主要更新: - 合并 ENHANCED_FEATURES_GUIDE.md 到 NOTIFICATION_SYSTEM.md - 移除过时的 Mock 模式和测试工具引用 - 更新所有调试工具为 window.__DEBUG__ - 完善增强功能文档(智能桌面通知、性能监控、历史记录) - 重新组织文档结构为 10 个清晰的部分 - 更新所有代码示例与最新代码保持一致 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
56 KiB
实时消息推送系统 - 完整技术文档
版本: v3.0.0 更新日期: 2025-11-17 文档类型: 用户指南 + 完整技术规格
🎯 重要说明:
- 本文档已合并原
ENHANCED_FEATURES_GUIDE.md的内容- 所有 API 引用和代码示例已更新至最新版本
- 调试工具统一使用
window.__DEBUG__
📑 目录
👤 第一部分:用户快速指南
🚀 第二部分:快速入门(开发者)
🏗️ 第三部分:系统架构
🧩 第四部分:核心组件详解
🔄 第五部分:设计流程
🎨 第六部分:通知类型与配置
✨ 第七部分:增强功能详解
🧪 第八部分:测试指南
🐛 第九部分:故障排查
📏 第十部分:最佳实践
附录
👤 第一部分:用户快速指南
适用人群: 普通用户、测试人员、客服人员 阅读时间: 5 分钟
🔌 连接状态查看
方法 1: 页面顶部状态横幅
当系统出现连接问题时,页面顶部会显示状态横幅:
| 状态 | 显示内容 | 颜色 | 说明 |
|---|---|---|---|
| ✅ 已连接 | 无横幅 | - | 正常工作,无需操作 |
| ⚠️ 断开连接 | "⚠️ 连接已断开" | 橙色 | 正在尝试重连 |
| 🔄 重连中 | "🔄 正在重连... (第 X 次)" | 蓝色 | 自动重连进行中 |
| ❌ 连接失败 | "❌ 连接失败,请检查网络" | 红色 | 需要手动干预 |
| ✓ 已重连 | "✓ 已重新连接" | 绿色 | 重连成功,2秒后自动消失 |
操作:
- 横幅可手动关闭(点击 ✕ 按钮)
- 关闭后会记住状态,重连成功后自动清除
方法 2: 浏览器控制台查看
- 按
F12打开开发者工具 - 切换到
Console标签 - 输入以下命令:
// 查看连接状态
__DEBUG__.socket.getStatus()
// 输出示例:
{
connected: true,
socketId: "abc123...",
reconnectAttempts: 0
}
🔧 手动操作指南
1. 手动重连
当连接失败时,可以手动触发重连:
浏览器控制台 (F12 → Console):
// 手动重连
__DEBUG__.socket.reconnect()
刷新页面(最简单):
- 按
Ctrl+R(Windows) 或Cmd+R(Mac) - 或点击浏览器刷新按钮
2. 查看连接日志
// 查看最近的 Socket 日志
__DEBUG__.socket.getLogs()
// 导出所有日志到文件
__DEBUG__.exportAll()
3. 检查浏览器通知权限
// 查看通知权限状态
window.browserNotificationService.getPermissionStatus()
// 返回值:
// "granted" - 已授权
// "denied" - 已拒绝
// "default" - 未询问
如何授予权限:
- 点击浏览器地址栏左侧的🔒图标
- 找到"通知"设置
- 选择"允许"
🆘 常见问题解决
问题 1: 收不到通知
可能原因:
- ❌ 浏览器通知权限未授予
- ❌ Socket 连接断开
- ❌ 浏览器标签页处于后台(网页通知需要标签页在前台)
解决步骤:
- 检查连接状态(参见上面"连接状态查看")
- 检查通知权限:
window.browserNotificationService.getPermissionStatus() - 如果是
"denied",需要在浏览器设置中允许通知 - 如果是
"default",刷新页面会自动请求权限
问题 2: 连接一直断开
排查步骤:
- 检查网络连接:打开其他网站,确认网络正常
- 查看重连次数:
__DEBUG__.socket.getStatus() - 查看错误日志:
__DEBUG__.socket.getLogs() - 手动重连:
__DEBUG__.socket.reconnect() - 刷新页面:
Ctrl+R或Cmd+R
问题 3: 通知太多/太少
无法控制通知数量(由后端推送决定),但可以:
- 清空所有通知: 点击通知容器右上角"清空全部"按钮
- 关闭单个通知: 点击通知右上角 ✕ 按钮
- 关闭音效: 点击通知容器右上角🔊图标
问题 4: 页面卡顿
可能原因: 通知历史过多
解决方法:
- 点击"清空全部"按钮清空历史通知
- 系统会自动限制最多显示 15 条通知
- 如仍卡顿,刷新页面
💻 可用调试命令
使用方法: 打开浏览器控制台 (
F12→Console),输入以下命令
Socket 连接调试
// 1. 查看连接状态
__DEBUG__.socket.getStatus()
// 2. 手动重连
__DEBUG__.socket.reconnect()
// 3. 查看 Socket 日志
__DEBUG__.socket.getLogs()
// 4. 导出 Socket 日志
__DEBUG__.socket.exportLogs()
通知权限调试
// 1. 查看权限状态
window.browserNotificationService.getPermissionStatus()
// 返回: "granted" | "denied" | "default"
// 2. 请求权限
window.browserNotificationService.requestPermission()
// 3. 检查是否支持通知
window.browserNotificationService.isSupported()
// 返回: true | false
综合调试
// 1. 系统诊断(检查所有状态)
__DEBUG__.diagnose()
// 2. 查看所有统计信息
__DEBUG__.printStats()
// 3. 导出所有日志
__DEBUG__.exportAll()
// 4. 清空所有日志
__DEBUG__.clearAll()
// 5. 显示帮助信息
__DEBUG__.help()
🚀 第二部分:快速入门(开发者)
📋 系统概述
本系统是专为金融资讯场景设计的实时消息推送系统,基于 Socket.IO 实现 WebSocket 实时通信。消息以右下角层叠弹窗的形式显示,新消息在最上方,符合主流桌面应用的交互习惯。
核心特性
- 双通知系统:网页通知 + 浏览器原生通知,智能分发
- 4 种通知类型:公告通知、股票动向、事件动向、分析报告
- 3 级优先级:紧急(不关闭)、重要(30秒)、普通(15秒)
- 智能折叠:最多显示3条,超过显示展开按钮
- 智能配色:股票动向根据涨跌自动变色(涨红 🔴 / 跌绿 🟢)
- 丰富元数据:发布时间、作者、AI 标识
- 点击跳转:可配置点击跳转链接
- 队列管理:最多保留 15 条历史,可展开查看
- 性能监控:自动追踪到达率、点击率、响应时间
- 历史记录:持久化存储、筛选、搜索、导出功能
技术亮点
- WebSocket 实时通信:Socket.IO + 指数退避重连策略
- 双重去重机制:Socket层去重 + 显示层去重
- 智能权限引导:渐进式权限请求,避免打扰用户
- 无障碍支持:完整的 ARIA 属性,键盘导航
- 性能优化:React.memo、useMemo、useCallback,GPU 加速动画
🏃 快速开始
1. 启动项目
# 开发环境
npm start
# 或使用真实后端
npm run start:real
2. 验证连接
打开浏览器控制台 (F12 → Console),查看连接状态:
// 查看 Socket 连接状态
__DEBUG__.socket.getStatus()
// 预期输出:
// { connected: true, socketId: "...", reconnectAttempts: 0 }
3. 测试通知
等待后端推送通知,或使用后端 API 手动触发(参见后端集成)。
💻 代码使用
在组件中使用
import { useNotification } from 'contexts/NotificationContext';
import { NOTIFICATION_TYPES, PRIORITY_LEVELS } from 'constants/notificationTypes';
function MyComponent() {
const { addNotification, isConnected } = useNotification();
const handleAnnouncement = () => {
addNotification({
type: NOTIFICATION_TYPES.ANNOUNCEMENT,
priority: PRIORITY_LEVELS.IMPORTANT,
title: '贵州茅台发布2024年度财报公告',
content: '2024年度营收同比增长15.2%',
publishTime: Date.now(),
pushTime: Date.now(),
isAIGenerated: false,
clickable: true,
link: '/event-detail/ann001',
autoClose: 10000,
});
};
return (
<div>
<p>连接状态: {isConnected ? '已连接' : '未连接'}</p>
<button onClick={handleAnnouncement}>发送公告</button>
</div>
);
}
🏗️ 第三部分:系统架构
整体架构图
graph TB
subgraph "前端应用"
A[App.js] --> B[AppProviders]
B --> C[NotificationProvider<br/>NotificationContext]
C --> D[NotificationContainer<br/>通知容器UI]
end
subgraph "通知系统核心"
C --> F[socketService<br/>Socket.IO连接]
C --> J[browserNotificationService<br/>浏览器通知]
C --> K[notificationHistoryService<br/>历史记录]
C --> L[notificationMetricsService<br/>性能监控]
end
subgraph "后端服务"
F --> M[Flask Backend<br/>Socket.IO Server]
M --> N[(ClickHouse<br/>事件数据)]
M --> O[(MySQL<br/>用户数据)]
end
subgraph "数据存储"
K --> P[(localStorage<br/>历史记录)]
L --> Q[(localStorage<br/>性能指标)]
end
style C fill:#f9f,stroke:#333,stroke-width:3px
style D fill:#bbf,stroke:#333,stroke-width:2px
style F fill:#bfb,stroke:#333,stroke-width:2px
📚 技术栈
前端技术栈
- React 18.3.1: 并发渲染、Suspense、自动批处理
- Chakra UI 2.8.2: 可访问性优先、主题定制、响应式设计
- Socket.IO Client 4.7.4: WebSocket实时通信、自动重连
- React Router v6: 客户端路由、编程式导航
- Framer Motion: 流畅动画、布局动画
- React Icons: Material Design 图标
后端技术栈
- Flask + Flask-SocketIO: Python WebSocket服务器
- ClickHouse: 时序数据分析(事件数据、性能指标)
- MySQL/PostgreSQL: 用户数据、订阅关系
- Redis + Celery: 消息队列、异步任务
数据流向
sequenceDiagram
participant B as 后端服务器
participant S as Socket Service
participant C as NotificationContext
participant D as 通知分发器
participant W as 网页通知
participant N as 浏览器通知
participant H as History Service
participant M as Metrics Service
B->>S: 推送事件数据
S->>S: Socket层去重检查
S->>C: 触发 new_event
C->>C: 适配后端格式→前端格式
C->>C: 显示层去重检查
C->>D: 分发通知
alt 页面在前台
D->>W: 显示网页通知
W->>H: 保存历史记录
W->>M: 记录性能指标
else 页面在后台
D->>N: 显示浏览器通知
N->>H: 保存历史记录
N->>M: 记录性能指标
end
Note over W,N: 用户点击通知
W->>M: 追踪点击事件
W->>C: 导航到详情页
双重通知策略
系统根据通知优先级和页面可见性智能选择通知方式:
| 优先级 | 页面在前台 | 页面在后台 |
|---|---|---|
| 紧急 (Urgent) | 网页通知 + 浏览器通知 | 网页通知 + 浏览器通知 |
| 重要 (Important) | 网页通知 | 浏览器通知 |
| 普通 (Normal) | 网页通知 | 网页通知 |
设计理念:
- 紧急通知:双重保障,确保用户不会错过
- 重要通知:根据用户注意力分配渠道(前台看得到网页,后台需要系统通知)
- 普通通知:避免过度打扰,仅网页内显示
🧩 第四部分:核心组件详解
📦 核心组件清单
| 组件名 | 类型 | 职责 | 文件路径 |
|---|---|---|---|
| NotificationContext | React Context | 通知系统核心逻辑、状态管理 | src/contexts/NotificationContext.js |
| NotificationContainer | React Component | 通知UI容器、动画、交互 | src/components/NotificationContainer/index.js |
| socketService | Service Class | WebSocket连接管理 | src/services/socketService.js |
| browserNotificationService | Service Class | 浏览器通知API封装 | src/services/browserNotificationService.js |
| notificationHistoryService | Service Class | 历史记录持久化 | src/services/notificationHistoryService.js |
| notificationMetricsService | Service Class | 性能监控埋点 | src/services/notificationMetricsService.js |
| notificationTypes | Constants | 类型定义、配置常量 | src/constants/notificationTypes.js |
| useEventNotifications | Custom Hook | 事件订阅Hook | src/hooks/useEventNotifications.js |
1. NotificationContext - 通知上下文
职责:通知系统的大脑,管理所有状态和业务逻辑。
核心功能:
- WebSocket 连接管理(连接、断开、重连)
- 通知队列管理(添加、移除、去重)
- 权限管理(浏览器通知权限请求)
- 通知分发(网页/浏览器通知智能选择)
- 音效播放
- 性能监控埋点
主要API:
const {
notifications, // 当前通知队列
isConnected, // Socket连接状态
soundEnabled, // 音效开关状态
browserPermission, // 浏览器通知权限状态
connectionStatus, // 详细连接状态
addNotification, // 添加通知
removeNotification, // 移除通知
clearAllNotifications, // 清空所有通知
toggleSound, // 切换音效
requestBrowserPermission, // 请求浏览器通知权限
trackNotificationClick, // 追踪通知点击
retryConnection, // 手动重连
showWelcomeGuide, // 显示欢迎引导
showCommunityGuide, // 显示社区功能引导
showFirstFollowGuide, // 显示首次关注引导
} = useNotification();
关键实现细节:
-
双重去重机制:
// Socket层去重(避免重复接收) const processedEventIds = useRef(new Set()); // 显示层去重(避免重复显示) const isDuplicate = notifications.some(n => n.id === notificationId); -
智能分发策略:
const isPageHidden = document.hidden; if (isPageHidden) { sendBrowserNotification(notification); // 后台:浏览器通知 } else { addWebNotification(notification); // 前台:网页通知 } -
渐进式权限引导:
// 登录后显示欢迎引导 showWelcomeGuide(); // 首次关注事件时显示引导 showFirstFollowGuide();
源码位置: src/contexts/NotificationContext.js
2. NotificationContainer - 通知容器UI
职责:通知的可视化展示,处理动画、交互、无障碍。
核心功能:
- 通知列表渲染(最多显示3条)
- 折叠/展开功能
- 通知动画(Framer Motion)
- 点击跳转
- 无障碍支持(ARIA、键盘导航)
主要组件:
<NotificationContainer>
<VStack spacing={3}>
{/* 可见通知 */}
{visibleNotifications.map(notification => (
<NotificationItem
notification={notification}
onClose={removeNotification}
isNewest={index === 0} // 最新通知特殊样式
/>
))}
{/* 折叠按钮 */}
{hasMore && (
<Button onClick={() => setIsExpanded(!isExpanded)}>
{isExpanded ? '收起' : `还有 ${hiddenCount} 条通知`}
</Button>
)}
</VStack>
</NotificationContainer>
关键实现细节:
-
优先级视觉表现:
// 紧急通知:粗边框 + 深色背景 + 脉冲动画 borderWidth: priority === URGENT ? '6px' : '2px' animation: priority === URGENT ? pulseAnimation : undefined -
严格可点击性判断:
const isActuallyClickable = clickable && link; // 两者都必须为true cursor: isActuallyClickable ? 'pointer' : 'default' -
性能优化:
// React.memo 自定义比较函数 React.memo(NotificationItem, (prevProps, nextProps) => { return prevProps.notification.id === nextProps.notification.id && prevProps.isNewest === nextProps.isNewest; });
源码位置: src/components/NotificationContainer/index.js
3. SocketService - WebSocket服务
职责:管理Socket.IO连接,处理断线重连,事件订阅。
核心功能:
- Socket.IO 连接管理
- 指数退避重连策略
- 事件订阅/取消订阅
- 消息发送/接收
重连策略:
// 指数退避延迟
getReconnectionDelay(attempt) {
const delays = [60000, 120000, 240000]; // 1min, 2min, 4min
const index = Math.min(attempt - 1, delays.length - 1);
return delays[index];
}
// 无限重试
this.maxReconnectAttempts = Infinity;
主要API:
// 连接管理
socket.connect();
socket.disconnect();
socket.reconnect();
socket.isConnected();
// 事件监听
socket.on('event_name', callback);
socket.off('event_name');
// 事件订阅(金融资讯专用)
socket.subscribeToEvents({ eventType, importance, onNewEvent });
socket.unsubscribeFromEvents({ eventType });
源码位置: src/services/socketService.js
其他核心组件
4. browserNotificationService - 浏览器通知服务
核心方法:
// 检查支持性
browserNotificationService.isSupported();
// 获取权限状态
browserNotificationService.getPermissionStatus(); // 'granted' | 'denied' | 'default'
// 请求权限
await browserNotificationService.requestPermission();
// 发送通知
const notification = browserNotificationService.sendNotification({
title: '通知标题',
body: '通知内容',
tag: 'unique_tag',
requireInteraction: false,
data: { link: '/detail' },
autoClose: 8000,
});
// 设置点击处理
notification.onclick = () => {
window.focus();
window.location.hash = link;
notification.close();
};
源码位置: src/services/browserNotificationService.js
5. notificationHistoryService - 历史记录服务
核心功能:
- localStorage持久化(最多500条)
- 筛选(类型、优先级、日期范围、阅读状态)
- 搜索(关键词匹配)
- 导出(JSON/CSV)
- 统计分析
主要API:
// 保存通知
notificationHistoryService.saveNotification(notification);
// 获取历史记录(带筛选)
const { records, total, page, totalPages } = notificationHistoryService.getHistory({
type: 'event_alert',
priority: 'urgent',
readStatus: 'unread',
startDate: Date.now() - 7 * 24 * 60 * 60 * 1000,
page: 1,
pageSize: 20,
});
// 搜索
const results = notificationHistoryService.searchHistory('央行');
// 导出
notificationHistoryService.downloadJSON();
notificationHistoryService.downloadCSV();
// 统计
const stats = notificationHistoryService.getStats();
// { total, read, unread, clicked, clickRate, byType, byPriority }
源码位置: src/services/notificationHistoryService.js
6. notificationMetricsService - 性能监控服务
追踪指标:
- 总发送数、总接收数
- 点击率、关闭率
- 平均响应时间(从接收到点击的时间)
- 每小时推送分布
- 每日数据趋势(最近30天)
主要API:
// 追踪事件
notificationMetricsService.trackReceived(notification);
notificationMetricsService.trackClicked(notification);
notificationMetricsService.trackDismissed(notification);
// 获取统计
const summary = notificationMetricsService.getSummary();
// {
// totalReceived, totalClicked, totalDismissed,
// clickRate, avgResponseTime, deliveryRate
// }
const byType = notificationMetricsService.getByType();
// { announcement: { received, clicked, dismissed, clickRate }, ... }
const dailyData = notificationMetricsService.getDailyData(7); // 最近7天
// [ { date: '2025-01-01', received, clicked, dismissed, clickRate }, ... ]
// 导出
const json = notificationMetricsService.exportToJSON();
const csv = notificationMetricsService.exportToCSV();
源码位置: src/services/notificationMetricsService.js
🔄 第五部分:设计流程
📡 消息推送完整流程
1. 初始化流程
graph LR
A[App启动] --> B[AppProviders挂载]
B --> C[NotificationProvider初始化]
C --> D[连接socketService]
D --> E[注册事件监听器]
E --> F[触发connect事件]
F --> G[更新连接状态]
G --> H[检查浏览器通知权限]
H --> I[加载历史记录]
I --> J[初始化完成]
代码实现 (src/contexts/NotificationContext.js):
useEffect(() => {
// 1. 注册事件监听器
socket.on('connect', handleConnect);
socket.on('disconnect', handleDisconnect);
socket.on('connect_error', handleConnectError);
socket.on('new_event', handleNewEvent);
// 2. 连接Socket
socket.connect();
// 3. 清理函数
return () => {
socket.off('connect');
socket.off('disconnect');
socket.off('new_event');
socket.disconnect();
};
}, []);
2. 消息接收与适配
graph TB
A[后端推送事件] --> B{Socket层去重}
B -->|已存在| C[忽略]
B -->|新事件| D[触发 new_event]
D --> E{数据格式检测}
E -->|前端格式| F[直接使用]
E -->|后端格式| G[格式适配]
G --> H[映射重要性<br/>S/A→urgent/important<br/>B/C→normal]
H --> I[构建通知对象]
I --> J[生成跳转链接<br/>/event-detail/id]
J --> K[添加元数据]
K --> L{显示层去重}
L -->|已存在| M[忽略]
L -->|新通知| N[添加到队列]
后端事件格式 → 前端通知格式 适配器:
const adaptEventToNotification = (event) => {
// 检测格式
if (event.priority || event.type === NOTIFICATION_TYPES.ANNOUNCEMENT) {
return event; // 已经是前端格式
}
// 重要性映射
let priority = PRIORITY_LEVELS.NORMAL;
if (event.importance === 'S') priority = PRIORITY_LEVELS.URGENT;
else if (event.importance === 'A') priority = PRIORITY_LEVELS.IMPORTANT;
// 构建通知对象
return {
id: event.id,
type: NOTIFICATION_TYPES.EVENT_ALERT,
priority: priority,
title: event.title,
content: event.description || event.content,
publishTime: new Date(event.created_at).getTime(),
pushTime: Date.now(),
isAIGenerated: event.is_ai_generated || false,
clickable: true,
link: `/event-detail/${event.id}`,
autoClose: NOTIFICATION_CONFIG.autoCloseDuration[priority],
extra: {
eventId: event.id,
eventType: event.event_type,
importance: event.importance,
keywords: event.keywords || [],
},
};
};
源码位置: src/contexts/NotificationContext.js
3. 通知分发策略
graph TB
A[收到新通知] --> B{检查浏览器权限}
B -->|default| C[自动请求权限]
B -->|denied| D[显示设置指引]
B -->|granted| E{检查页面可见性}
E -->|document.hidden=true<br/>页面在后台| F[发送浏览器通知]
E -->|document.hidden=false<br/>页面在前台| G[显示网页通知]
F --> H[browserNotificationService]
H --> I[创建系统通知]
I --> J[设置点击处理]
J --> K[保存到历史]
K --> L[记录性能指标]
G --> M[addWebNotification]
M --> N[添加到通知队列]
N --> O[播放音效]
O --> P{自动关闭时长}
P -->|0| Q[不自动关闭]
P -->|>0| R[延迟关闭]
R --> K
代码实现 (src/contexts/NotificationContext.js):
const isPageHidden = document.hidden;
if (isPageHidden) {
// 后台:浏览器通知
logger.info('NotificationContext', 'Page hidden: sending browser notification');
sendBrowserNotification(newNotification);
} else {
// 前台:网页通知
logger.info('NotificationContext', 'Page visible: sending web notification');
addWebNotification(newNotification);
}
4. 性能监控埋点
系统自动追踪以下事件:
// 通知接收时
notificationMetricsService.trackReceived(notification);
// 通知点击时
notificationMetricsService.trackClicked(notification);
// 自动计算响应时间 = 点击时间 - 接收时间
// 通知关闭时
notificationMetricsService.trackDismissed(notification);
性能指标计算:
// 点击率
clickRate = (totalClicked / totalReceived) * 100
// 平均响应时间
avgResponseTime = totalResponseTime / totalClicked
// 到达率(假设sent=received)
deliveryRate = (totalReceived / totalSent) * 100
数据存储:
- localStorage 持久化
- 最多保留 30 天数据
- 自动清理过期数据
🎨 第六部分:通知类型与配置
🎯 通知类型配置
类型 1: 公告通知 (Announcement)
适用场景:公司财报、重大资产重组、分红派息、停复牌公告
配色方案:
- 主色:蓝色 (Blue)
- 图标:📢 MdCampaign
- 背景:
blue.50/ 暗色:rgba(59, 130, 246, 0.15)
示例:
{
type: NOTIFICATION_TYPES.ANNOUNCEMENT,
priority: PRIORITY_LEVELS.IMPORTANT,
title: '贵州茅台发布2024年度财报公告',
content: '2024年度营收同比增长15.2%,净利润创历史新高',
publishTime: Date.now(),
pushTime: Date.now(),
isAIGenerated: false,
clickable: true,
link: '/event-detail/ann001',
extra: {
announcementType: '财报',
companyCode: '600519',
},
autoClose: 10000,
}
类型 2: 股票动向 (Stock Alert)
适用场景:价格预警、异常波动、持仓表现
动态配色(根据 extra.priceChange 字段):
- 涨(+):红色系 🔴
- 跌(-):绿色系 🟢
示例(涨):
{
type: NOTIFICATION_TYPES.STOCK_ALERT,
priority: PRIORITY_LEVELS.URGENT,
title: '您关注的股票触发预警',
content: '宁德时代(300750) 当前价格 ¥245.50,涨幅 +5.2%',
publishTime: Date.now(),
pushTime: Date.now(),
clickable: true,
link: '/stock-overview?code=300750',
extra: {
stockCode: '300750',
stockName: '宁德时代',
priceChange: '+5.2%', // 💡 重要:根据此字段判断涨跌
currentPrice: '245.50',
},
autoClose: 10000,
}
类型 3: 事件动向 (Event Alert)
适用场景:央行政策、行业政策、监管动态、宏观事件
配色方案:
- 主色:橙色 (Orange)
- 图标:📄 MdArticle
示例:
{
type: NOTIFICATION_TYPES.EVENT_ALERT,
priority: PRIORITY_LEVELS.IMPORTANT,
title: '央行宣布降准0.5个百分点',
content: '中国人民银行宣布下调金融机构存款准备金率0.5个百分点',
publishTime: Date.now(),
pushTime: Date.now(),
clickable: true,
link: '/event-detail/evt001',
extra: {
eventId: 'evt001',
relatedStocks: 12,
impactLevel: '重大利好',
},
autoClose: 12000,
}
类型 4: 分析报告 (Analysis Report)
适用场景:行业研报、策略报告、公司研报
特殊字段:
author:作者信息(必填)isAIGenerated:是否 AI 生成(显示紫色 AI 徽章)
示例(AI):
{
type: NOTIFICATION_TYPES.ANALYSIS_REPORT,
priority: PRIORITY_LEVELS.NORMAL,
title: 'AI产业链投资机会分析',
content: '随着大模型应用加速落地,算力、数据、应用三大方向均存在投资机会',
publishTime: Date.now(),
pushTime: Date.now(),
author: {
name: 'AI分析师',
organization: '价值前沿',
},
isAIGenerated: true, // 💡 显示 AI 徽章
clickable: true,
link: '/forecast-report?id=rpt002',
extra: {
reportType: '策略报告',
industry: '人工智能',
},
autoClose: 12000,
}
📊 优先级配置
| 优先级 | 标签 | 边框 | 自动关闭 | 使用场景 |
|---|---|---|---|---|
| urgent | 🔴 紧急 | 6px粗边框 + 脉冲动画 | ❌ 不自动关闭 | 重大事件、高优先级预警 |
| important | 🟠 重要 | 4px中等边框 | 30秒 | 重要消息、一般预警 |
| normal | - | 2px细边框 | 15秒 | 常规消息、信息推送 |
配置代码:
export const PRIORITY_CONFIGS = {
[PRIORITY_LEVELS.URGENT]: {
label: '紧急',
colorScheme: 'red',
show: false,
borderWidth: '6px',
bgOpacity: 0.25,
},
[PRIORITY_LEVELS.IMPORTANT]: {
label: '重要',
colorScheme: 'orange',
show: false,
borderWidth: '4px',
bgOpacity: 0.15,
},
[PRIORITY_LEVELS.NORMAL]: {
label: '',
colorScheme: 'gray',
show: false,
borderWidth: '2px',
bgOpacity: 0.08,
},
};
环境配置
API 配置
在 .env 文件中配置后端地址:
# 开发环境
REACT_APP_API_URL=http://49.232.185.254:5001
# 生产环境
REACT_APP_API_URL=
# 空字符串表示使用相对路径
Socket 连接配置
Socket 服务会自动读取 REACT_APP_API_URL 并连接到后端:
// src/services/socketService.js
const API_BASE_URL = getApiBase();
this.socket = io(API_BASE_URL, {
transports: ['websocket', 'polling'],
reconnection: false, // 使用自定义重连策略
timeout: 20000,
withCredentials: true,
});
✨ 第七部分:增强功能详解
🔔 功能 1:智能桌面通知
功能说明
首次收到重要/紧急通知时,自动请求浏览器通知权限,确保用户不错过关键信息。
工作原理
// 在 NotificationContext 中的逻辑
if (priority === URGENT || priority === IMPORTANT) {
if (browserPermission === 'default' && !hasRequestedPermission) {
// 首次遇到重要通知,自动请求权限
await requestBrowserPermission();
setHasRequestedPermission(true); // 避免重复请求
}
}
权限状态
- granted: 已授权,可以发送桌面通知
- denied: 已拒绝,无法发送桌面通知
- default: 未请求,首次重要通知时会自动请求
使用示例
自动触发(推荐)
// 无需任何代码,系统自动处理
// 首次收到重要/紧急通知时会自动弹出权限请求
手动请求
import { useNotification } from 'contexts/NotificationContext';
function SettingsPage() {
const { requestBrowserPermission, browserPermission } = useNotification();
return (
<div>
<p>当前状态: {browserPermission}</p>
<button onClick={requestBrowserPermission}>
开启桌面通知
</button>
</div>
);
}
通知分发策略
| 优先级 | 页面在前台 | 页面在后台 |
|---|---|---|
| 紧急 | 桌面通知 + 网页通知 | 桌面通知 + 网页通知 |
| 重要 | 网页通知 | 桌面通知 |
| 普通 | 网页通知 | 网页通知 |
📊 功能 2:性能监控
功能说明
追踪通知推送的各项指标,包括:
- 到达率: 发送 vs 接收
- 点击率: 点击 vs 接收
- 响应时间: 收到通知到点击的平均时间
- 类型分布: 各类型通知的数量和效果
- 时段分布: 每小时推送量
API 参考
获取汇总统计
import { notificationMetricsService } from 'services/notificationMetricsService';
const summary = notificationMetricsService.getSummary();
console.log(summary);
/* 输出:
{
totalSent: 100,
totalReceived: 98,
totalClicked: 45,
totalDismissed: 53,
avgResponseTime: 5200, // 毫秒
clickRate: '45.92', // 百分比
deliveryRate: '98.00' // 百分比
}
*/
获取按类型统计
const byType = notificationMetricsService.getByType();
console.log(byType);
/* 输出:
{
announcement: { sent: 20, received: 20, clicked: 15, dismissed: 5, clickRate: '75.00' },
stock_alert: { sent: 30, received: 30, clicked: 20, dismissed: 10, clickRate: '66.67' },
event_alert: { sent: 40, received: 38, clicked: 10, dismissed: 28, clickRate: '26.32' },
analysis_report: { sent: 10, received: 10, clicked: 0, dismissed: 10, clickRate: '0.00' }
}
*/
获取每日数据
const dailyData = notificationMetricsService.getDailyData(7); // 最近 7 天
console.log(dailyData);
/* 输出:
[
{ date: '2025-01-15', sent: 15, received: 14, clicked: 6, dismissed: 8, clickRate: '42.86' },
{ date: '2025-01-16', sent: 20, received: 20, clicked: 10, dismissed: 10, clickRate: '50.00' },
...
]
*/
导出数据
// 导出为 JSON
const json = notificationMetricsService.exportToJSON();
console.log(json);
// 导出为 CSV
const csv = notificationMetricsService.exportToCSV();
console.log(csv);
在控制台查看实时指标
打开浏览器控制台,执行:
// 查看汇总
import { notificationMetricsService } from './services/notificationMetricsService.js';
console.table(notificationMetricsService.getSummary());
// 查看按类型分布
console.table(notificationMetricsService.getByType());
// 查看最近 7 天数据
console.table(notificationMetricsService.getDailyData(7));
📜 功能 3:历史记录
功能说明
持久化存储所有接收到的通知,支持:
- 查询和筛选
- 搜索关键词
- 标记已读/已点击
- 批量删除
- 导出(JSON/CSV)
API 参考
获取历史记录(支持筛选和分页)
import { notificationHistoryService } from 'services/notificationHistoryService';
const result = notificationHistoryService.getHistory({
type: 'event_alert', // 可选:筛选类型
priority: 'urgent', // 可选:筛选优先级
readStatus: 'unread', // 可选:'read' | 'unread' | 'all'
startDate: Date.now() - 7 * 24 * 60 * 60 * 1000, // 可选:开始日期
endDate: Date.now(), // 可选:结束日期
page: 1, // 页码
pageSize: 20, // 每页数量
});
console.log(result);
/* 输出:
{
records: [...], // 当前页的记录
total: 150, // 总记录数
page: 1, // 当前页
pageSize: 20, // 每页数量
totalPages: 8 // 总页数
}
*/
搜索历史记录
const results = notificationHistoryService.searchHistory('降准');
console.log(results); // 返回标题/内容中包含"降准"的所有记录
标记已读/已点击
// 标记已读
notificationHistoryService.markAsRead('notification_id');
// 标记已点击
notificationHistoryService.markAsClicked('notification_id');
删除记录
// 删除单条
notificationHistoryService.deleteRecord('notification_id');
// 批量删除
notificationHistoryService.deleteRecords(['id1', 'id2', 'id3']);
// 清空所有
notificationHistoryService.clearHistory();
获取统计数据
const stats = notificationHistoryService.getStats();
console.log(stats);
/* 输出:
{
total: 500, // 总记录数
read: 320, // 已读数
unread: 180, // 未读数
clicked: 150, // 已点击数
clickRate: '30.00', // 点击率
byType: { // 按类型统计
announcement: 100,
stock_alert: 150,
event_alert: 200,
analysis_report: 50
},
byPriority: { // 按优先级统计
urgent: 50,
important: 200,
normal: 250
}
}
*/
导出历史记录
// 导出为 JSON 字符串
const json = notificationHistoryService.exportToJSON({
type: 'event_alert' // 可选:只导出特定类型
});
// 导出为 CSV 字符串
const csv = notificationHistoryService.exportToCSV();
// 直接下载 JSON 文件
notificationHistoryService.downloadJSON();
// 直接下载 CSV 文件
notificationHistoryService.downloadCSV();
数据结构
每条历史记录包含:
{
id: 'notif_123', // 通知 ID
notification: { // 完整通知对象
type: 'event_alert',
priority: 'urgent',
title: '...',
content: '...',
...
},
receivedAt: 1737459600000, // 接收时间戳
readAt: 1737459650000, // 已读时间戳(null 表示未读)
clickedAt: null, // 已点击时间戳(null 表示未点击)
}
存储限制
- 最大数量: 500 条(超过后自动删除最旧的)
- 存储位置: localStorage
- 容量估算: 约 2-5MB(取决于通知内容长度)
🧪 第八部分:测试指南
🧪 测试快速指南
开发环境测试
# 启动开发服务器
npm start
关键检查:
// 1. 验证连接
__DEBUG__.socket.getStatus()
// 预期: { connected: true, socketId: "..." }
// 2. 系统诊断
__DEBUG__.diagnose()
生产环境测试
// 一键诊断
__DEBUG__.diagnose()
// 导出报告
__DEBUG__.exportAll()
调试工具速查
| 工具 | 适用环境 | 主要功能 |
|---|---|---|
__DEBUG__.socket |
所有环境 | 连接状态、配置检查、手动重连 |
__DEBUG__.api |
所有环境 | API 日志、错误追踪 |
__DEBUG__ |
所有环境 | 完整诊断、导出报告、性能监控 |
常用命令:
// 完整诊断
__DEBUG__.diagnose()
// 查看帮助
__DEBUG__.help()
// 查看连接状态
__DEBUG__.socket.getStatus()
// 手动重连
__DEBUG__.socket.reconnect()
✅ 手动测试清单
功能测试
1. 通知显示测试
- 公告通知显示正确(蓝色系、图标、内容)
- 股票上涨通知显示为红色系(+图标、红边框)
- 股票下跌通知显示为绿色系(-图标、绿边框)
- 事件动向通知显示正确(橙色系)
- 分析报告(人工)显示正确(紫色系、作者信息)
- 分析报告(AI)显示AI徽章
2. 优先级测试
- 紧急通知:红色标签、粗边框、脉冲动画、不自动关闭
- 重要通知:橙色标签、中等边框、30秒自动关闭
- 普通通知:无标签、细边框、15秒自动关闭
3. 交互测试
- 点击可点击通知跳转到正确页面
- 点击不可点击通知无反应
- 点击关闭按钮关闭通知
- 音效开关正常工作
- 清空全部按钮清空所有通知
4. 折叠展开测试
- 通知数 ≤ 3 时不显示展开按钮
- 通知数 > 3 时显示"还有X条通知"按钮
- 点击展开显示所有通知
- 点击收起恢复显示前3条
5. 队列管理测试
- 最多显示15条历史通知
- 超过15条自动移除最旧的
- 新通知在最上方
- z-index层级正确(最新最高)
浏览器通知测试
6. 权限管理测试
- 首次访问显示权限状态为"default"
- 点击请求权限按钮弹出浏览器授权对话框
- 授权后状态变为"granted"
- 拒绝后状态变为"denied",显示设置指引
7. 浏览器通知显示测试
- 权限授予后,切换到其他标签页,收到通知时显示系统通知
- 点击浏览器通知聚焦窗口并跳转到详情页
- 普通通知8秒后自动关闭
- 紧急通知需手动关闭
Socket连接测试
8. 连接测试
- 启动后显示"Connected"状态
- 后端推送消息能正确接收
- 断线后自动重连(1分钟→2分钟→4分钟)
- 网络恢复时自动重连
- 标签页重新聚焦时自动重连
- 重连成功后显示"✓ 已重新连接" 2秒后消失
UI测试
9. 响应式测试
- 移动端(< 480px):宽度 = 屏宽-32px,精简显示
- 小屏(480-768px):宽度 = 360px
- 平板(768-992px):宽度 = 380px
- 桌面(> 992px):宽度 = 400px
10. 动画测试
- 新通知从底部向上滑入(浮起效果)
- 关闭通知向右滑出消失
- 紧急通知边框脉冲动画流畅
- 折叠/展开动画流畅无卡顿
11. 无障碍测试
- Tab键可以聚焦到可点击通知
- 聚焦时显示蓝色轮廓线
- Enter/Space键可以打开详情
- 关闭按钮可键盘操作(Tab + Enter)
性能测试
12. 性能指标测试
- 发送10条通知,打开控制台查看性能指标
- 点击5条通知,检查点击率计算正确
- 检查平均响应时间计算正确
- 导出JSON/CSV文件正常
13. 历史记录测试
- 收到通知后自动保存到历史记录
- 筛选功能正常(类型、优先级、日期范围、阅读状态)
- 搜索功能返回正确结果
- 分页功能正常
- 统计数据准确
- 导出JSON/CSV正常
跨浏览器测试
14. 兼容性测试
- Chrome: 所有功能正常
- Edge: 所有功能正常
- Firefox: 所有功能正常
- Safari: 所有功能正常(注意浏览器通知权限)
- 移动端Chrome: 响应式布局正确
- 移动端Safari: 响应式布局正确
🧪 自动化测试用例
单元测试
NotificationContext 测试
describe('NotificationContext', () => {
test('应该正确初始化默认状态', () => {
const { result } = renderHook(() => useNotification(), {
wrapper: NotificationProvider,
});
expect(result.current.notifications).toEqual([]);
expect(result.current.soundEnabled).toBe(true);
});
test('应该正确添加通知', () => {
const { result } = renderHook(() => useNotification(), {
wrapper: NotificationProvider,
});
act(() => {
result.current.addNotification({
type: 'announcement',
priority: 'important',
title: '测试通知',
content: '内容',
});
});
expect(result.current.notifications).toHaveLength(1);
expect(result.current.notifications[0].title).toBe('测试通知');
});
// 更多测试用例...
});
notificationHistoryService 测试
describe('notificationHistoryService', () => {
beforeEach(() => {
localStorage.clear();
});
test('应该保存通知到历史记录', () => {
const notification = {
id: 'test001',
type: 'announcement',
title: '测试',
content: '内容',
};
notificationHistoryService.saveNotification(notification);
const { records } = notificationHistoryService.getHistory();
expect(records).toHaveLength(1);
expect(records[0].notification.id).toBe('test001');
});
// 更多测试用例...
});
集成测试
describe('通知系统集成测试', () => {
test('完整流程:从接收到显示到点击', async () => {
render(
<NotificationProvider>
<NotificationContainer />
</NotificationProvider>
);
// 1. 模拟接收通知
act(() => {
socket.emit('new_event', mockEventData);
});
// 2. 验证通知显示
await waitFor(() => {
expect(screen.getByText('测试通知')).toBeInTheDocument();
});
// 3. 模拟点击
const notification = screen.getByText('测试通知').closest('[role="status"]');
fireEvent.click(notification);
// 4. 验证导航
expect(mockNavigate).toHaveBeenCalledWith('/event-detail/test001');
// 5. 验证性能指标
const stats = notificationMetricsService.getSummary();
expect(stats.totalClicked).toBe(1);
});
});
🐛 第九部分:故障排查
🔧 故障排除
问题 1: 通知不显示
检查项:
- 确认
NotificationProvider已包裹应用 - 检查浏览器控制台是否有错误
- 确认 socket 连接状态(使用
__DEBUG__.socket.getStatus()) - 检查通知数据格式是否正确
问题 2: 股票动向颜色不对
解决方案:
- 检查
extra.priceChange字段是否存在 - 确认格式为 "+5.2%" 或 "-3.8%"(包含符号)
- 确认使用了
NOTIFICATION_TYPES.STOCK_ALERT类型
问题 3: AI 徽章不显示
解决方案:
- 检查
isAIGenerated字段是否为true - 确认字段名拼写正确(驼峰命名)
问题 4: 浏览器通知不工作
解决方案:
- 检查浏览器通知权限是否已授予
- macOS: 关闭"专注模式"或"勿扰模式"
- Chrome: 检查
chrome://settings/content/notifications - 退出全屏模式(某些浏览器全屏时不显示通知)
- 无痕/隐私模式特别说明:
- Chrome 无痕模式:可以授权,但关闭窗口后权限会被清除
- Safari 隐私模式:通知权限被永久拒绝,无法更改
- 建议:使用普通浏览器窗口以获得完整体验
快速诊断:
// 在浏览器控制台运行
console.log('Permission:', Notification.permission); // 'granted' | 'denied' | 'default'
console.log('Supported:', 'Notification' in window); // true | false
// 完整诊断
__DEBUG__.diagnose();
问题 5: Socket 连接失败
解决方案:
- 检查后端 Flask-SocketIO 是否正确运行
- 确认 CORS 配置正确
- 检查
src/utils/apiConfig.js中的 API 地址 - 查看控制台日志确认错误信息
使用调试工具:
// 查看连接状态
__DEBUG__.socket.getStatus()
// 查看错误日志
__DEBUG__.socket.getLogs()
// 手动重连
__DEBUG__.socket.reconnect()
调试工具
window.DEBUG - 主调试工具
可用命令:
// 系统诊断
__DEBUG__.diagnose() // 检查所有系统状态
__DEBUG__.printStats() // 打印所有统计信息
__DEBUG__.performance() // 性能监控
// 日志管理
__DEBUG__.exportAll() // 导出所有日志
__DEBUG__.clearAll() // 清空所有日志
// 帮助信息
__DEBUG__.help() // 显示帮助信息
window.DEBUG.socket - Socket 调试
可用命令:
// 连接管理
__DEBUG__.socket.getStatus() // 获取连接状态
__DEBUG__.socket.reconnect() // 手动重连
// 日志管理
__DEBUG__.socket.getLogs() // 获取所有 Socket 日志
__DEBUG__.socket.clearLogs() // 清空日志
__DEBUG__.socket.exportLogs() // 导出日志
window.DEBUG.api - API 调试
可用命令:
// 日志查询
__DEBUG__.api.getLogs() // 获取所有 API 日志
__DEBUG__.api.getRecentErrors() // 获取最近的错误
// 测试请求
__DEBUG__.api.testRequest('GET', '/api/endpoint')
// 日志管理
__DEBUG__.api.exportLogs() // 导出日志
__DEBUG__.api.clearLogs() // 清空日志
日志分析
正常日志流程
1. [NotificationContext] Initializing socket connection...
2. [NotificationContext] Socket connected
3. [NotificationContext] Received new event { id: 'evt001', title: '...' }
4. [NotificationContext] Adding notification { id: 'evt001', type: 'event_alert' }
5. [NotificationContext] Page visible: sending web notification
异常日志排查
ERROR: Socket connect_error
→ 检查后端是否运行,网络是否通畅
WARN: Duplicate notification ignored at socket level
→ 正常,去重机制工作正常
ERROR: Browser permission not granted
→ 用户未授权浏览器通知,提示用户授权
📏 第十部分:最佳实践
📏 开发规范
1. 添加新通知类型
步骤:
- 在
src/constants/notificationTypes.js添加类型定义 - 添加类型配置(图标、颜色、样式)
- 在
NotificationContainer中添加渲染逻辑 - 使用控制台命令测试
- 更新文档
示例:
// 1. 添加类型
export const NOTIFICATION_TYPES = {
// ...现有类型
MARKET_NEWS: 'market_news', // 新增
};
// 2. 添加配置
export const NOTIFICATION_TYPE_CONFIGS = {
// ...现有配置
[NOTIFICATION_TYPES.MARKET_NEWS]: {
name: '市场快讯',
icon: MdNewspaper,
colorScheme: 'teal',
bg: 'teal.50',
borderColor: 'teal.400',
iconColor: 'teal.500',
hoverBg: 'teal.100',
},
};
2. 自定义通知组件
如需完全自定义通知样式:
import { useNotification } from 'contexts/NotificationContext';
function CustomNotification({ notification }) {
const { removeNotification, trackNotificationClick } = useNotification();
const handleClick = () => {
trackNotificationClick(notification.id);
// 自定义导航逻辑
removeNotification(notification.id, true);
};
return (
<Box onClick={handleClick}>
{/* 自定义样式 */}
</Box>
);
}
3. 扩展性能监控
添加自定义指标:
// 在 notificationMetricsService 中添加新方法
trackCustomEvent(notification, eventType, data) {
// 自定义追踪逻辑
}
// 使用
notificationMetricsService.trackCustomEvent(notification, 'share', {
platform: 'wechat',
});
⚡ 性能优化建议
1. 队列管理优化 ✅ 已实现
- 系统自动限制最多 15 条历史记录
- 超出自动移除最旧的,避免内存泄漏
- 建议根据实际需求调整
NOTIFICATION_CONFIG.maxHistory
2. 合理设置自动关闭时长
| 类型 | 建议时长 | 理由 |
|---|---|---|
| 公告通知 | 10秒 | 内容较简短 |
| 股票动向 | 10秒 | 需要快速响应 |
| 事件动向 | 12秒 | 内容较多 |
| 分析报告 | 12秒 | 内容较多 |
| 紧急通知 | 不关闭 | 需要用户确认 |
3. 避免频繁推送
- 生产环境建议间隔至少 3 秒
- 避免短时间内大量推送造成用户困扰
4. React 性能优化 ✅ 已实现
// 1. React.memo 优化
const NotificationItem = React.memo(NotificationItemComponent, (prev, next) => {
return prev.notification.id === next.notification.id
&& prev.isNewest === next.isNewest;
});
// 2. useMemo 缓存计算
const colors = useMemo(() => ({
bg: priorityBgColor,
border: borderColor,
// ...
}), [priorityBgColor, borderColor, ...]);
// 3. useCallback 优化事件处理
const handleClick = useCallback(() => {
trackNotificationClick(id);
navigate(link);
}, [id, link, trackNotificationClick, navigate]);
// 4. GPU 加速动画
willChange="transform, opacity"
5. 动画性能优化 ✅ 已实现
- 只对新增通知应用动画
- 使用 Framer Motion 的 GPU 加速
- 展开15条通知时禁用动画(避免卡顿)
- 性能提升 90%+
6. localStorage 优化
// 定期清理过期数据
notificationHistoryService.cleanup(100);
// 限制最大存储数量
MAX_HISTORY_SIZE = 500;
🔒 安全注意事项
1. XSS 防护
// ✅ 正确:使用 React 自动转义
<Text>{notification.title}</Text>
// ❌ 错误:使用 dangerouslySetInnerHTML
<Text dangerouslySetInnerHTML={{ __html: notification.title }} />
2. 链接验证
// 跳转前验证链接合法性
const isValidLink = (link) => {
return link && link.startsWith('/'); // 只允许内部链接
};
if (isActuallyClickable && isValidLink(link)) {
navigate(link);
}
3. 敏感信息保护
// 不要在通知中显示敏感信息
// ❌ 错误
content: `您的密码是:${password}`
// ✅ 正确
content: '密码修改成功,请重新登录'
4. localStorage 安全
// 不要存储敏感数据到 localStorage
// ❌ 错误
localStorage.setItem('user_token', token);
// ✅ 正确:使用 httpOnly Cookie 或 sessionStorage
附录
🌐 后端集成(生产环境)
Flask-SocketIO 配置
from flask_socketio import SocketIO, emit
# 初始化 SocketIO
socketio = SocketIO(app, cors_allowed_origins=[
"http://localhost:3000",
"https://valuefrontier.cn"
])
# 推送金融资讯通知
def send_financial_notification(user_id, data):
"""
推送金融资讯通知到指定用户
参数:
user_id: 用户ID
data: 通知数据(参考通知类型配置)
"""
socketio.emit('new_event', data, room=user_id)
# 启动服务器
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0', port=5001)
后端推送示例
import time
# 推送事件动向
socketio.emit('new_event', {
'type': 'event_alert',
'priority': 'important',
'title': '央行宣布降准0.5个百分点',
'content': '中国人民银行宣布下调金融机构存款准备金率0.5个百分点',
'publishTime': int(time.time() * 1000),
'pushTime': int(time.time() * 1000),
'isAIGenerated': False,
'clickable': True,
'link': '/event-detail/evt001',
'extra': {
'eventId': 'evt001',
'relatedStocks': 12,
'impactLevel': '重大利好',
},
'autoClose': 12000
}, room=user_id)
📝 更新日志
v3.0.0 (2025-11-17) - 文档合并与更新
- ✅ 合并 ENHANCED_FEATURES_GUIDE.md 内容
- ✅ 移除过时的 Mock 模式引用
- ✅ 更新所有调试工具引用(统一使用
window.__DEBUG__) - ✅ 更新代码示例与最新代码一致
- ✅ 完善增强功能文档(智能桌面通知、性能监控、历史记录)
- ✅ 更新测试指南
v2.11.0 (2025-01-07) - Socket 连接优化
- ✅ 指数退避重连策略
- ✅ 连接状态横幅优化
- ✅ 手动关闭状态持久化
v2.10.0 (2025-01-06) - 按钮加载态
- ✅ 点击"查看详情"显示 loading spinner
- ✅ 防重复点击机制
v2.9.0 (2025-01-05) - 头部简化
- ✅ AI 和预测标识移到底部
v2.8.0 (2025-01-04) - 无障碍支持
- ✅ 完整的 ARIA 属性
- ✅ 键盘导航支持
v2.7.0 (2025-01-03) - 智能动画
- ✅ 只对新增通知应用动画
- ✅ 性能提升 90%+
v2.0.0 (2024-12-27) - 金融资讯专业版
- ✅ 4种金融资讯通知类型
- ✅ 3级优先级系统
- ✅ 智能元数据、动态配色
📁 文件结构
src/
├── constants/
│ └── notificationTypes.js # 通知类型定义和常量
├── services/
│ ├── socket/
│ │ └── index.js # Socket 服务统一导出
│ ├── socketService.js # Socket.IO 服务
│ ├── browserNotificationService.js # 浏览器通知服务
│ ├── notificationHistoryService.js # 历史记录服务
│ └── notificationMetricsService.js # 性能监控服务
├── contexts/
│ └── NotificationContext.js # 通知上下文管理
├── components/
│ └── NotificationContainer/
│ └── index.js # 通知容器组件
├── hooks/
│ └── useEventNotifications.js # 事件订阅 Hook
├── devtools/
│ ├── index.js # 调试工具统一入口
│ ├── socketDebugger.js # Socket 调试工具
│ └── apiDebugger.js # API 调试工具
└── assets/
└── sounds/
└── notification.wav # 通知音效
📞 支持
如有问题,请查看:
- 用户快速指南: 本文档开头的用户快速指南
- 项目文档:
CLAUDE.md - 调试命令: 浏览器控制台使用
__DEBUG__.help()查看所有可用命令 - 控制台日志: 所有操作都有详细日志
- 类型定义:
src/constants/notificationTypes.js
祝你使用愉快! 🎉