# 实时消息推送系统 - 完整技术文档
> **版本**: 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`
---
**祝你使用愉快!** 🎉