Files
vf_react/docs/NOTIFICATION_SYSTEM.md
zdl 678eb6838e docs: 合并并更新通知系统文档至 v3.0.0
主要更新:
- 合并 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>
2025-11-17 18:40:05 +08:00

2200 lines
56 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 实时消息推送系统 - 完整技术文档
> **版本**: 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、useCallbackGPU 加速动画
---
### 🏃 快速开始
#### 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 (
<div>
<p>连接状态: {isConnected ? '已连接' : '未连接'}</p>
<button onClick={handleAnnouncement}>发送公告</button>
</div>
);
}
```
---
## 🏗️ 第三部分:系统架构
### 整体架构图
```mermaid
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**: 消息队列、异步任务
### 数据流向
```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
<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>
```
**关键实现细节**
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[映射重要性<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[添加到队列]
```
**后端事件格式** → **前端通知格式** 适配器:
```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<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):
```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 (
<div>
<p>当前状态: {browserPermission}</p>
<button onClick={requestBrowserPermission}>
开启桌面通知
</button>
</div>
);
}
```
#### 通知分发策略
| 优先级 | 页面在前台 | 页面在后台 |
|-------|----------|----------|
| 紧急 | 桌面通知 + 网页通知 | 桌面通知 + 网页通知 |
| 重要 | 网页通知 | 桌面通知 |
| 普通 | 网页通知 | 网页通知 |
---
### 📊 功能 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(
<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: 通知不显示
**检查项**
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 (
<Box onClick={handleClick}>
{/* 自定义样式 */}
</Box>
);
}
```
#### 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 自动转义
<Text>{notification.title}</Text>
// ❌ 错误:使用 dangerouslySetInnerHTML
<Text dangerouslySetInnerHTML={{ __html: notification.title }} />
```
#### 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`
---
**祝你使用愉快!** 🎉