# 实时消息推送系统 - 完整技术文档 > **版本**: v3.0.0 > **更新日期**: 2025-11-17 > **文档类型**: 用户指南 + 完整技术规格 > > 🎯 **重要说明**: > - 本文档已合并原 `ENHANCED_FEATURES_GUIDE.md` 的内容 > - 所有 API 引用和代码示例已更新至最新版本 > - 调试工具统一使用 `window.__DEBUG__` --- ## 📑 目录 ### 👤 第一部分:用户快速指南 1. [连接状态查看](#-连接状态查看) 2. [手动操作指南](#-手动操作指南) 3. [常见问题解决](#-常见问题解决) 4. [可用调试命令](#-可用调试命令) ### 🚀 第二部分:快速入门(开发者) 5. [系统简介](#-系统概述) 6. [核心特性](#核心特性) 7. [5分钟快速开始](#-快速开始) 8. [基础使用示例](#-代码使用) ### 🏗️ 第三部分:系统架构 9. [整体架构设计](#-系统架构设计) 10. [技术栈选型](#-技术栈) 11. [数据流向](#数据流向) 12. [双重通知策略](#双重通知策略) ### 🧩 第四部分:核心组件详解 13. [组件清单](#-核心组件清单) 14. [NotificationContext](#1-notificationcontext---通知上下文) 15. [NotificationContainer](#2-notificationcontainer---通知容器ui) 16. [SocketService](#3-socketservice---websocket服务) 17. [其他核心组件](#其他核心组件) ### 🔄 第五部分:设计流程 18. [消息推送完整流程](#-消息推送完整流程) 19. [初始化流程](#1-初始化流程) 20. [消息接收与适配](#2-消息接收与适配) 21. [通知分发策略](#3-通知分发策略) 22. [性能监控埋点](#4-性能监控埋点) ### 🎨 第六部分:通知类型与配置 23. [通知类型配置](#-通知类型配置) 24. [优先级配置](#-优先级配置) 25. [环境配置](#环境配置) ### ✨ 第七部分:增强功能详解 26. [智能桌面通知](#-功能-1智能桌面通知) 27. [性能监控](#-功能-2性能监控) 28. [历史记录](#-功能-3历史记录) ### 🧪 第八部分:测试指南 29. [测试快速指南](#-测试快速指南) 30. [手动测试清单](#-手动测试清单) 31. [自动化测试](#-自动化测试用例) ### 🐛 第九部分:故障排查 32. [常见问题FAQ](#-故障排除) 33. [调试工具](#调试工具) 34. [日志分析](#日志分析) ### 📏 第十部分:最佳实践 35. [开发规范](#-开发规范) 36. [性能优化](#-性能优化建议) 37. [安全注意事项](#安全注意事项) ### 附录 38. [后端集成](#-后端集成生产环境) 39. [更新日志](#-更新日志) 40. [文件结构](#-文件结构) --- ## 👤 第一部分:用户快速指南 > **适用人群**: 普通用户、测试人员、客服人员 > **阅读时间**: 5 分钟 ### 🔌 连接状态查看 #### **方法 1: 页面顶部状态横幅** 当系统出现连接问题时,页面顶部会显示状态横幅: | 状态 | 显示内容 | 颜色 | 说明 | |------|----------|------|------| | ✅ 已连接 | 无横幅 | - | 正常工作,无需操作 | | ⚠️ 断开连接 | "⚠️ 连接已断开" | 橙色 | 正在尝试重连 | | 🔄 重连中 | "🔄 正在重连... (第 X 次)" | 蓝色 | 自动重连进行中 | | ❌ 连接失败 | "❌ 连接失败,请检查网络" | 红色 | 需要手动干预 | | ✓ 已重连 | "✓ 已重新连接" | 绿色 | 重连成功,2秒后自动消失 | **操作**: - 横幅可手动关闭(点击 ✕ 按钮) - 关闭后会记住状态,重连成功后自动清除 #### **方法 2: 浏览器控制台查看** 1. 按 `F12` 打开开发者工具 2. 切换到 `Console` 标签 3. 输入以下命令: ```javascript // 查看连接状态 __DEBUG__.socket.getStatus() // 输出示例: { connected: true, socketId: "abc123...", reconnectAttempts: 0 } ``` --- ### 🔧 手动操作指南 #### **1. 手动重连** 当连接失败时,可以手动触发重连: **浏览器控制台** (`F12` → `Console`): ```javascript // 手动重连 __DEBUG__.socket.reconnect() ``` **刷新页面**(最简单): - 按 `Ctrl+R` (Windows) 或 `Cmd+R` (Mac) - 或点击浏览器刷新按钮 #### **2. 查看连接日志** ```javascript // 查看最近的 Socket 日志 __DEBUG__.socket.getLogs() // 导出所有日志到文件 __DEBUG__.exportAll() ``` #### **3. 检查浏览器通知权限** ```javascript // 查看通知权限状态 window.browserNotificationService.getPermissionStatus() // 返回值: // "granted" - 已授权 // "denied" - 已拒绝 // "default" - 未询问 ``` **如何授予权限**: 1. 点击浏览器地址栏左侧的🔒图标 2. 找到"通知"设置 3. 选择"允许" --- ### 🆘 常见问题解决 #### **问题 1: 收不到通知** **可能原因**: - ❌ 浏览器通知权限未授予 - ❌ Socket 连接断开 - ❌ 浏览器标签页处于后台(网页通知需要标签页在前台) **解决步骤**: 1. 检查连接状态(参见上面"连接状态查看") 2. 检查通知权限: ```javascript window.browserNotificationService.getPermissionStatus() ``` 3. 如果是 `"denied"`,需要在浏览器设置中允许通知 4. 如果是 `"default"`,刷新页面会自动请求权限 #### **问题 2: 连接一直断开** **排查步骤**: 1. **检查网络连接**:打开其他网站,确认网络正常 2. **查看重连次数**: ```javascript __DEBUG__.socket.getStatus() ``` 3. **查看错误日志**: ```javascript __DEBUG__.socket.getLogs() ``` 4. **手动重连**: ```javascript __DEBUG__.socket.reconnect() ``` 5. **刷新页面**:`Ctrl+R` 或 `Cmd+R` #### **问题 3: 通知太多/太少** **无法控制通知数量**(由后端推送决定),但可以: - **清空所有通知**: 点击通知容器右上角"清空全部"按钮 - **关闭单个通知**: 点击通知右上角 ✕ 按钮 - **关闭音效**: 点击通知容器右上角🔊图标 #### **问题 4: 页面卡顿** **可能原因**: 通知历史过多 **解决方法**: 1. 点击"清空全部"按钮清空历史通知 2. 系统会自动限制最多显示 15 条通知 3. 如仍卡顿,刷新页面 --- ### 💻 可用调试命令 > **使用方法**: 打开浏览器控制台 (`F12` → `Console`),输入以下命令 #### **Socket 连接调试** ```javascript // 1. 查看连接状态 __DEBUG__.socket.getStatus() // 2. 手动重连 __DEBUG__.socket.reconnect() // 3. 查看 Socket 日志 __DEBUG__.socket.getLogs() // 4. 导出 Socket 日志 __DEBUG__.socket.exportLogs() ``` #### **通知权限调试** ```javascript // 1. 查看权限状态 window.browserNotificationService.getPermissionStatus() // 返回: "granted" | "denied" | "default" // 2. 请求权限 window.browserNotificationService.requestPermission() // 3. 检查是否支持通知 window.browserNotificationService.isSupported() // 返回: true | false ``` #### **综合调试** ```javascript // 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. 启动项目 ```bash # 开发环境 npm start # 或使用真实后端 npm run start:real ``` #### 2. 验证连接 打开浏览器控制台 (`F12` → `Console`),查看连接状态: ```javascript // 查看 Socket 连接状态 __DEBUG__.socket.getStatus() // 预期输出: // { connected: true, socketId: "...", reconnectAttempts: 0 } ``` #### 3. 测试通知 等待后端推送通知,或使用后端 API 手动触发(参见[后端集成](#-后端集成生产环境))。 --- ### 💻 代码使用 #### 在组件中使用 ```javascript 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 (

连接状态: {isConnected ? '已连接' : '未连接'}

); } ``` --- ## 🏗️ 第三部分:系统架构 ### 整体架构图 ```mermaid graph TB subgraph "前端应用" A[App.js] --> B[AppProviders] B --> C[NotificationProvider
NotificationContext] C --> D[NotificationContainer
通知容器UI] end subgraph "通知系统核心" C --> F[socketService
Socket.IO连接] C --> J[browserNotificationService
浏览器通知] C --> K[notificationHistoryService
历史记录] C --> L[notificationMetricsService
性能监控] end subgraph "后端服务" F --> M[Flask Backend
Socket.IO Server] M --> N[(ClickHouse
事件数据)] M --> O[(MySQL
用户数据)] end subgraph "数据存储" K --> P[(localStorage
历史记录)] L --> Q[(localStorage
性能指标)] 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**: 消息队列、异步任务 ### 数据流向 ```mermaid 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**: ```javascript const { notifications, // 当前通知队列 isConnected, // Socket连接状态 soundEnabled, // 音效开关状态 browserPermission, // 浏览器通知权限状态 connectionStatus, // 详细连接状态 addNotification, // 添加通知 removeNotification, // 移除通知 clearAllNotifications, // 清空所有通知 toggleSound, // 切换音效 requestBrowserPermission, // 请求浏览器通知权限 trackNotificationClick, // 追踪通知点击 retryConnection, // 手动重连 showWelcomeGuide, // 显示欢迎引导 showCommunityGuide, // 显示社区功能引导 showFirstFollowGuide, // 显示首次关注引导 } = useNotification(); ``` **关键实现细节**: 1. **双重去重机制**: ```javascript // Socket层去重(避免重复接收) const processedEventIds = useRef(new Set()); // 显示层去重(避免重复显示) const isDuplicate = notifications.some(n => n.id === notificationId); ``` 2. **智能分发策略**: ```javascript const isPageHidden = document.hidden; if (isPageHidden) { sendBrowserNotification(notification); // 后台:浏览器通知 } else { addWebNotification(notification); // 前台:网页通知 } ``` 3. **渐进式权限引导**: ```javascript // 登录后显示欢迎引导 showWelcomeGuide(); // 首次关注事件时显示引导 showFirstFollowGuide(); ``` **源码位置**: `src/contexts/NotificationContext.js` --- ### 2. NotificationContainer - 通知容器UI **职责**:通知的可视化展示,处理动画、交互、无障碍。 **核心功能**: - 通知列表渲染(最多显示3条) - 折叠/展开功能 - 通知动画(Framer Motion) - 点击跳转 - 无障碍支持(ARIA、键盘导航) **主要组件**: ```jsx {/* 可见通知 */} {visibleNotifications.map(notification => ( ))} {/* 折叠按钮 */} {hasMore && ( )} ``` **关键实现细节**: 1. **优先级视觉表现**: ```javascript // 紧急通知:粗边框 + 深色背景 + 脉冲动画 borderWidth: priority === URGENT ? '6px' : '2px' animation: priority === URGENT ? pulseAnimation : undefined ``` 2. **严格可点击性判断**: ```javascript const isActuallyClickable = clickable && link; // 两者都必须为true cursor: isActuallyClickable ? 'pointer' : 'default' ``` 3. **性能优化**: ```javascript // 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 连接管理 - 指数退避重连策略 - 事件订阅/取消订阅 - 消息发送/接收 **重连策略**: ```javascript // 指数退避延迟 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**: ```javascript // 连接管理 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 - 浏览器通知服务 **核心方法**: ```javascript // 检查支持性 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**: ```javascript // 保存通知 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**: ```javascript // 追踪事件 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. 初始化流程 ```mermaid 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): ```javascript 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. 消息接收与适配 ```mermaid graph TB A[后端推送事件] --> B{Socket层去重} B -->|已存在| C[忽略] B -->|新事件| D[触发 new_event] D --> E{数据格式检测} E -->|前端格式| F[直接使用] E -->|后端格式| G[格式适配] G --> H[映射重要性
S/A→urgent/important
B/C→normal] H --> I[构建通知对象] I --> J[生成跳转链接
/event-detail/id] J --> K[添加元数据] K --> L{显示层去重} L -->|已存在| M[忽略] L -->|新通知| N[添加到队列] ``` **后端事件格式** → **前端通知格式** 适配器: ```javascript 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. 通知分发策略 ```mermaid graph TB A[收到新通知] --> B{检查浏览器权限} B -->|default| C[自动请求权限] B -->|denied| D[显示设置指引] B -->|granted| E{检查页面可见性} E -->|document.hidden=true
页面在后台| F[发送浏览器通知] E -->|document.hidden=false
页面在前台| 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): ```javascript 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. 性能监控埋点 系统自动追踪以下事件: ```javascript // 通知接收时 notificationMetricsService.trackReceived(notification); // 通知点击时 notificationMetricsService.trackClicked(notification); // 自动计算响应时间 = 点击时间 - 接收时间 // 通知关闭时 notificationMetricsService.trackDismissed(notification); ``` **性能指标计算**: ```javascript // 点击率 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)` **示例**: ```javascript { 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` 字段): - **涨(+)**:红色系 🔴 - **跌(-)**:绿色系 🟢 **示例(涨)**: ```javascript { 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 **示例**: ```javascript { 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)**: ```javascript { 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秒 | 常规消息、信息推送 | **配置代码**: ```javascript 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` 文件中配置后端地址: ```bash # 开发环境 REACT_APP_API_URL=http://49.232.185.254:5001 # 生产环境 REACT_APP_API_URL= # 空字符串表示使用相对路径 ``` ### Socket 连接配置 Socket 服务会自动读取 `REACT_APP_API_URL` 并连接到后端: ```javascript // 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:智能桌面通知 #### 功能说明 首次收到重要/紧急通知时,自动请求浏览器通知权限,确保用户不错过关键信息。 #### 工作原理 ```javascript // 在 NotificationContext 中的逻辑 if (priority === URGENT || priority === IMPORTANT) { if (browserPermission === 'default' && !hasRequestedPermission) { // 首次遇到重要通知,自动请求权限 await requestBrowserPermission(); setHasRequestedPermission(true); // 避免重复请求 } } ``` #### 权限状态 - **granted**: 已授权,可以发送桌面通知 - **denied**: 已拒绝,无法发送桌面通知 - **default**: 未请求,首次重要通知时会自动请求 #### 使用示例 **自动触发**(推荐) ```javascript // 无需任何代码,系统自动处理 // 首次收到重要/紧急通知时会自动弹出权限请求 ``` **手动请求** ```javascript import { useNotification } from 'contexts/NotificationContext'; function SettingsPage() { const { requestBrowserPermission, browserPermission } = useNotification(); return (

当前状态: {browserPermission}

); } ``` #### 通知分发策略 | 优先级 | 页面在前台 | 页面在后台 | |-------|----------|----------| | 紧急 | 桌面通知 + 网页通知 | 桌面通知 + 网页通知 | | 重要 | 网页通知 | 桌面通知 | | 普通 | 网页通知 | 网页通知 | --- ### 📊 功能 2:性能监控 #### 功能说明 追踪通知推送的各项指标,包括: - **到达率**: 发送 vs 接收 - **点击率**: 点击 vs 接收 - **响应时间**: 收到通知到点击的平均时间 - **类型分布**: 各类型通知的数量和效果 - **时段分布**: 每小时推送量 #### API 参考 ##### 获取汇总统计 ```javascript 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' // 百分比 } */ ``` ##### 获取按类型统计 ```javascript 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' } } */ ``` ##### 获取每日数据 ```javascript 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' }, ... ] */ ``` ##### 导出数据 ```javascript // 导出为 JSON const json = notificationMetricsService.exportToJSON(); console.log(json); // 导出为 CSV const csv = notificationMetricsService.exportToCSV(); console.log(csv); ``` #### 在控制台查看实时指标 打开浏览器控制台,执行: ```javascript // 查看汇总 import { notificationMetricsService } from './services/notificationMetricsService.js'; console.table(notificationMetricsService.getSummary()); // 查看按类型分布 console.table(notificationMetricsService.getByType()); // 查看最近 7 天数据 console.table(notificationMetricsService.getDailyData(7)); ``` --- ### 📜 功能 3:历史记录 #### 功能说明 持久化存储所有接收到的通知,支持: - 查询和筛选 - 搜索关键词 - 标记已读/已点击 - 批量删除 - 导出(JSON/CSV) #### API 参考 ##### 获取历史记录(支持筛选和分页) ```javascript 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 // 总页数 } */ ``` ##### 搜索历史记录 ```javascript const results = notificationHistoryService.searchHistory('降准'); console.log(results); // 返回标题/内容中包含"降准"的所有记录 ``` ##### 标记已读/已点击 ```javascript // 标记已读 notificationHistoryService.markAsRead('notification_id'); // 标记已点击 notificationHistoryService.markAsClicked('notification_id'); ``` ##### 删除记录 ```javascript // 删除单条 notificationHistoryService.deleteRecord('notification_id'); // 批量删除 notificationHistoryService.deleteRecords(['id1', 'id2', 'id3']); // 清空所有 notificationHistoryService.clearHistory(); ``` ##### 获取统计数据 ```javascript 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 } } */ ``` ##### 导出历史记录 ```javascript // 导出为 JSON 字符串 const json = notificationHistoryService.exportToJSON({ type: 'event_alert' // 可选:只导出特定类型 }); // 导出为 CSV 字符串 const csv = notificationHistoryService.exportToCSV(); // 直接下载 JSON 文件 notificationHistoryService.downloadJSON(); // 直接下载 CSV 文件 notificationHistoryService.downloadCSV(); ``` #### 数据结构 每条历史记录包含: ```javascript { id: 'notif_123', // 通知 ID notification: { // 完整通知对象 type: 'event_alert', priority: 'urgent', title: '...', content: '...', ... }, receivedAt: 1737459600000, // 接收时间戳 readAt: 1737459650000, // 已读时间戳(null 表示未读) clickedAt: null, // 已点击时间戳(null 表示未点击) } ``` #### 存储限制 - **最大数量**: 500 条(超过后自动删除最旧的) - **存储位置**: localStorage - **容量估算**: 约 2-5MB(取决于通知内容长度) --- ## 🧪 第八部分:测试指南 ### 🧪 测试快速指南 #### 开发环境测试 ```bash # 启动开发服务器 npm start ``` **关键检查**: ```javascript // 1. 验证连接 __DEBUG__.socket.getStatus() // 预期: { connected: true, socketId: "..." } // 2. 系统诊断 __DEBUG__.diagnose() ``` #### 生产环境测试 **访问**: https://valuefrontier.cn ```javascript // 一键诊断 __DEBUG__.diagnose() // 导出报告 __DEBUG__.exportAll() ``` #### 调试工具速查 | 工具 | 适用环境 | 主要功能 | |------|---------|---------| | `__DEBUG__.socket` | 所有环境 | 连接状态、配置检查、手动重连 | | `__DEBUG__.api` | 所有环境 | API 日志、错误追踪 | | `__DEBUG__` | 所有环境 | 完整诊断、导出报告、性能监控 | **常用命令**: ```javascript // 完整诊断 __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 测试 ```javascript 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 测试 ```javascript 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'); }); // 更多测试用例... }); ``` #### 集成测试 ```javascript describe('通知系统集成测试', () => { test('完整流程:从接收到显示到点击', async () => { render( ); // 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: 通知不显示 **检查项**: 1. 确认 `NotificationProvider` 已包裹应用 2. 检查浏览器控制台是否有错误 3. 确认 socket 连接状态(使用 `__DEBUG__.socket.getStatus()`) 4. 检查通知数据格式是否正确 #### 问题 2: 股票动向颜色不对 **解决方案**: 1. 检查 `extra.priceChange` 字段是否存在 2. 确认格式为 "+5.2%" 或 "-3.8%"(包含符号) 3. 确认使用了 `NOTIFICATION_TYPES.STOCK_ALERT` 类型 #### 问题 3: AI 徽章不显示 **解决方案**: 1. 检查 `isAIGenerated` 字段是否为 `true` 2. 确认字段名拼写正确(驼峰命名) #### 问题 4: 浏览器通知不工作 **解决方案**: 1. 检查浏览器通知权限是否已授予 2. macOS: 关闭"专注模式"或"勿扰模式" 3. Chrome: 检查 `chrome://settings/content/notifications` 4. 退出全屏模式(某些浏览器全屏时不显示通知) 5. **无痕/隐私模式特别说明**: - Chrome 无痕模式:可以授权,但关闭窗口后权限会被清除 - Safari 隐私模式:通知权限被永久拒绝,无法更改 - 建议:使用普通浏览器窗口以获得完整体验 **快速诊断**: ```javascript // 在浏览器控制台运行 console.log('Permission:', Notification.permission); // 'granted' | 'denied' | 'default' console.log('Supported:', 'Notification' in window); // true | false // 完整诊断 __DEBUG__.diagnose(); ``` #### 问题 5: Socket 连接失败 **解决方案**: 1. 检查后端 Flask-SocketIO 是否正确运行 2. 确认 CORS 配置正确 3. 检查 `src/utils/apiConfig.js` 中的 API 地址 4. 查看控制台日志确认错误信息 **使用调试工具**: ```javascript // 查看连接状态 __DEBUG__.socket.getStatus() // 查看错误日志 __DEBUG__.socket.getLogs() // 手动重连 __DEBUG__.socket.reconnect() ``` --- ### 调试工具 #### window.__DEBUG__ - 主调试工具 **可用命令**: ```javascript // 系统诊断 __DEBUG__.diagnose() // 检查所有系统状态 __DEBUG__.printStats() // 打印所有统计信息 __DEBUG__.performance() // 性能监控 // 日志管理 __DEBUG__.exportAll() // 导出所有日志 __DEBUG__.clearAll() // 清空所有日志 // 帮助信息 __DEBUG__.help() // 显示帮助信息 ``` #### window.__DEBUG__.socket - Socket 调试 **可用命令**: ```javascript // 连接管理 __DEBUG__.socket.getStatus() // 获取连接状态 __DEBUG__.socket.reconnect() // 手动重连 // 日志管理 __DEBUG__.socket.getLogs() // 获取所有 Socket 日志 __DEBUG__.socket.clearLogs() // 清空日志 __DEBUG__.socket.exportLogs() // 导出日志 ``` #### window.__DEBUG__.api - API 调试 **可用命令**: ```javascript // 日志查询 __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. 添加新通知类型 **步骤**: 1. 在 `src/constants/notificationTypes.js` 添加类型定义 2. 添加类型配置(图标、颜色、样式) 3. 在 `NotificationContainer` 中添加渲染逻辑 4. 使用控制台命令测试 5. 更新文档 **示例**: ```javascript // 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. 自定义通知组件 如需完全自定义通知样式: ```javascript import { useNotification } from 'contexts/NotificationContext'; function CustomNotification({ notification }) { const { removeNotification, trackNotificationClick } = useNotification(); const handleClick = () => { trackNotificationClick(notification.id); // 自定义导航逻辑 removeNotification(notification.id, true); }; return ( {/* 自定义样式 */} ); } ``` #### 3. 扩展性能监控 添加自定义指标: ```javascript // 在 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 性能优化 ✅ 已实现 ```javascript // 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 优化 ```javascript // 定期清理过期数据 notificationHistoryService.cleanup(100); // 限制最大存储数量 MAX_HISTORY_SIZE = 500; ``` --- ### 🔒 安全注意事项 #### 1. XSS 防护 ```javascript // ✅ 正确:使用 React 自动转义 {notification.title} // ❌ 错误:使用 dangerouslySetInnerHTML ``` #### 2. 链接验证 ```javascript // 跳转前验证链接合法性 const isValidLink = (link) => { return link && link.startsWith('/'); // 只允许内部链接 }; if (isActuallyClickable && isValidLink(link)) { navigate(link); } ``` #### 3. 敏感信息保护 ```javascript // 不要在通知中显示敏感信息 // ❌ 错误 content: `您的密码是:${password}` // ✅ 正确 content: '密码修改成功,请重新登录' ``` #### 4. localStorage 安全 ```javascript // 不要存储敏感数据到 localStorage // ❌ 错误 localStorage.setItem('user_token', token); // ✅ 正确:使用 httpOnly Cookie 或 sessionStorage ``` --- ## 附录 ### 🌐 后端集成(生产环境) #### Flask-SocketIO 配置 ```python 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) ``` #### 后端推送示例 ```python 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` --- **祝你使用愉快!** 🎉