From 38499ce6502b37420e3965b297e3ca287cdbd617 Mon Sep 17 00:00:00 2001
From: zdl <3489966805@qq.com>
Date: Tue, 21 Oct 2025 15:48:38 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=B6=88=E6=81=AF?=
=?UTF-8?q?=E6=8E=A8=E9=80=81=E8=83=BD=E5=8A=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
NOTIFICATION_SYSTEM.md | 1167 +++++++++++++++--
src/components/NotificationContainer/index.js | 298 +++--
src/components/NotificationTestTool/index.js | 486 +++++--
.../Subscription/SubscriptionButton.js | 40 +-
src/constants/notificationTypes.js | 181 +++
src/contexts/NotificationContext.js | 198 ++-
src/services/browserNotificationService.js | 208 +++
src/services/mockSocketService.js | 324 ++++-
8 files changed, 2485 insertions(+), 417 deletions(-)
create mode 100644 src/constants/notificationTypes.js
create mode 100644 src/services/browserNotificationService.js
diff --git a/NOTIFICATION_SYSTEM.md b/NOTIFICATION_SYSTEM.md
index c1210635..964e857b 100644
--- a/NOTIFICATION_SYSTEM.md
+++ b/NOTIFICATION_SYSTEM.md
@@ -1,15 +1,60 @@
# 实时消息推送系统使用指南
-## 🆕 最新更新 (v1.1.0)
+## 🆕 最新更新 (v2.3.0 - 通知体验优化)
-- ✅ **新消息置顶展示**:采用行业标准,新消息显示在最上方
-- ✅ **智能队列管理**:最多同时显示 5 条消息,超出自动移除最旧的
-- ✅ **视觉层次优化**:最新消息更强的阴影和边框高亮效果
-- ✅ **测试工具增强**:实时显示队列状态,新增"测试最大限制"功能
+- ✅ **按优先级区分自动关闭**:紧急通知不自动关闭,重要30秒,普通15秒
+- ✅ **简单折叠机制**:最多显示3条通知,超过显示"还有X条"展开按钮
+- ✅ **推送频率优化**:60秒推送1-2条(随机),更符合真实金融场景
+- ✅ **历史保留增加**:从5条增加到15条,支持查看更多历史通知
+- ✅ **集中配置管理**:所有配置统一在 `NOTIFICATION_CONFIG` 中管理
+
+---
+
+### v2.2.0 更新回顾
+
+- ✅ **浏览器原生通知**:支持系统级通知,即使标签页在后台也能收到
+- ✅ **智能分发策略**:根据优先级和页面状态智能选择通知方式
+ - 紧急(urgent)→ 浏览器通知 + 网页通知(双重保障)
+ - 重要(important)→ 后台=浏览器,前台=网页
+ - 普通(normal)→ 仅网页通知
+- ✅ **权限管理**:测试工具显示权限状态,一键请求授权
+- ✅ **点击跳转**:浏览器通知点击聚焦窗口并跳转详情
+
+---
+
+### v2.1.0 更新回顾
+
+- ✅ **预测通知系统**:支持预测→详情两阶段推送,解决详情延迟生成问题
+- ✅ **严格可点击性**:只有真正可跳转的通知才显示"查看详情"和 hover 效果
+- ✅ **视觉区分优化**:预测通知显示灰色"预测"徽章和状态提示
+- ✅ **测试工具增强**:新增预测通知测试和预测→详情流程测试(5秒延迟)
+- ✅ **新增字段**:isPrediction、statusHint、relatedPredictionId
+
+---
+
+### v2.0.0 更新回顾
+
+- ✅ **通知类型重构**:4 种金融资讯通知类型(公告、股票、事件、分析)
+- ✅ **优先级系统**:紧急、重要、普通三级优先级,带视觉标签
+- ✅ **智能元数据**:发布时间、作者信息、AI 生成标识
+- ✅ **动态配色**:股票动向根据涨跌自动变色(红涨绿跌)
+- ✅ **点击交互**:支持点击跳转到详情页面,带视觉反馈
+- ✅ **统一设计**:所有通知宽度统一为 400px
## 📋 系统概述
-本系统实现了完整的实时消息推送功能,支持 Mock 模式(开发)和真实 Socket.IO 模式(生产)。消息以右下角层叠弹窗的形式显示,**新消息在最上方**,符合主流桌面应用的交互习惯。
+本系统是专为**金融资讯场景**设计的实时消息推送系统,支持 Mock 模式(开发)和真实 Socket.IO 模式(生产)。消息以右下角层叠弹窗的形式显示,**新消息在最上方**,符合主流桌面应用的交互习惯。
+
+### 核心特性
+
+- **双通知系统**:网页通知 + 浏览器原生通知,智能分发
+- **4 种通知类型**:公告通知、股票动向、事件动向、分析报告
+- **3 级优先级**:紧急(不关闭)、重要(30秒)、普通(15秒)🆕
+- **智能折叠**:最多显示3条,超过显示展开按钮 🆕
+- **智能配色**:股票动向根据涨跌自动变色(涨红 🔴 / 跌绿 🟢)
+- **丰富元数据**:发布时间、作者、AI 标识
+- **点击跳转**:可配置点击跳转链接
+- **队列管理**:最多保留 15 条历史,可展开查看 🆕
---
@@ -17,34 +62,90 @@
### ✅ 已实现功能
-1. **实时推送**
- - WebSocket (Socket.IO) 连接
- - Mock 模式自动定期推送(开发环境)
- - 支持多种消息类型(成功、错误、警告、信息)
+1. **4 种通知类型**
+ - **公告通知** (Announcement):财报、重组、分红等公司公告
+ - **股票动向** (Stock Alert):价格预警、异常波动、持仓表现
+ - **事件动向** (Event Alert):政策变化、行业事件、宏观消息
+ - **分析报告** (Analysis Report):行业研报、策略报告、公司研报
-2. **UI 展示**
+2. **3 级优先级系统**
+ - **紧急** (Urgent):红色标签,用于重大事件和高优先级预警
+ - **重要** (Important):橙色标签,用于重要消息和一般预警
+ - **普通** (Normal):无标签,用于常规消息和信息推送
+
+3. **智能元数据展示**
+ - **发布时间**:智能格式化(刚刚、X分钟前、今天 HH:mm、昨天 HH:mm、MM-DD HH:mm)
+ - **作者信息**:仅分析报告显示,格式为"作者 - 机构"
+ - **AI 标识**:紫色 AI 徽章,标识 AI 生成的内容
+
+4. **动态配色方案**
+ - **股票动向**:根据 `priceChange` 字段自动判断
+ - 涨(+):红色系(icon、border、bg、hover)
+ - 跌(-):绿色系
+ - **其他类型**:固定配色(蓝、橙、紫)
+
+5. **预测通知系统** 🆕
+ - **预测通知**:事件预测结果,详情未就绪(不可跳转)
+ - **详情通知**:完整报告已生成(可跳转查看)
+ - **视觉区分**:
+ - 预测通知:灰色"预测"徽章 + "详细报告生成中..." 状态提示
+ - 详情通知:优先级徽章 + "查看详情" 提示
+ - **典型场景**:先推送预测(T+0秒),延迟推送详情(T+5分钟)
+
+6. **点击交互**
+ - **可点击通知**:鼠标悬停变化、点击跳转到详情页
+ - **不可点击通知**:静态展示,无交互效果
+ - **视觉提示**:"📂 查看详情" 提示文本
+ - **严格判断**:只有 `clickable=true` 且 `link` 存在才可点击
+
+7. **UI 展示**
- 右下角固定定位
+ - **统一宽度 400px**
- **新消息在最上方**(符合行业标准)
+ - **从底部向上滑入动画**(浮起效果)
- 层叠显示最多 5 条消息
- 智能队列管理:超出自动移除最旧消息
- 视觉层次:最新消息更突出(更强阴影、边框高亮)
- - 自动关闭(可配置时长)
+ - 自动关闭(可配置时长,默认 10-12 秒)
- 手动关闭按钮
- - 流畅的进入/退出动画(从右侧滑入)
+ - 流畅的进入/退出动画
-3. **音效提示**
+8. **音效提示**
- 新消息音效播放
- 可开关音效
-4. **开发工具**
- - 右上角测试工具面板(仅开发环境)
- - 手动触发测试通知(4种类型)
- - 层叠效果测试(4条消息)
- - 最大限制测试(6条→5条)
- - **实时队列状态显示**(当前消息数 / 5)
- - 连接状态显示
- - 音效开关
- - 测试计数统计
+9. **浏览器原生通知系统** 🆕
+ - **系统级通知**:显示在操作系统通知中心(Windows/macOS)
+ - **后台可见**:即使标签页不在前台也能收到通知
+ - **智能分发策略**:
+ - **紧急通知(URGENT)**:浏览器通知 + 网页通知(双重保障)
+ - **重要通知(IMPORTANT)**:后台=浏览器通知,前台=网页通知
+ - **普通通知(NORMAL)**:仅网页通知
+ - **权限管理**:自动请求权限,状态实时显示
+ - **点击跳转**:点击浏览器通知聚焦窗口并跳转详情
+ - **防重复**:相同类型通知自动替换旧通知
+ - **自动关闭**:普通通知 8 秒自动关闭,紧急通知需手动关闭
+
+10. **开发工具增强**
+ - 右上角测试工具面板(仅开发环境)
+ - **浏览器权限管理** 🆕:
+ - 显示权限状态(已授权/未授权/已拒绝)
+ - 一键请求权限按钮
+ - 权限状态实时更新
+ - **9 种测试场景**:
+ - 公告通知
+ - 股票上涨 / 股票下跌
+ - 事件动向
+ - 分析报告 / AI 报告
+ - 预测通知(不可跳转)
+ - **3 种组合测试**:
+ - 层叠测试(4 种类型)
+ - 优先级测试(3 个级别)
+ - 预测→详情流程(5秒延迟)
+ - **实时队列状态**:当前消息数 / 5
+ - 连接状态显示
+ - 音效开关
+ - 测试计数统计
---
@@ -52,21 +153,258 @@
```
src/
+├── constants/
+│ └── notificationTypes.js # 通知类型定义和常量 🆕
├── services/
│ ├── socket/
-│ │ └── index.js # Socket 服务统一导出
-│ ├── socketService.js # 真实 Socket.IO 服务
-│ └── mockSocketService.js # Mock Socket 服务
+│ │ └── index.js # Socket 服务统一导出
+│ ├── socketService.js # 真实 Socket.IO 服务
+│ └── mockSocketService.js # Mock Socket 服务(含 14 条金融资讯数据)🔄
├── contexts/
-│ └── NotificationContext.js # 通知上下文管理
+│ └── NotificationContext.js # 通知上下文管理
├── components/
│ ├── NotificationContainer/
-│ │ └── index.js # 通知容器组件
+│ │ └── index.js # 通知容器组件(完全重写)🔄
│ └── NotificationTestTool/
-│ └── index.js # 测试工具组件
+│ └── index.js # 测试工具组件(升级 8 种测试)🔄
└── assets/
└── sounds/
- └── notification.wav # 通知音效
+ └── notification.wav # 通知音效
+```
+
+**图例**:🆕 新增 | 🔄 重构
+
+---
+
+## 🎨 通知类型配置
+
+### 类型 1: 公告通知 (Announcement)
+
+**适用场景**:公司财报、重大资产重组、分红派息、停复牌公告等
+
+**配色方案**:
+- 主色:蓝色 (Blue)
+- 图标:📢 MdCampaign
+- 背景:`blue.50`
+- 边框:`blue.400`
+- 图标色:`blue.500`
+- 悬停:`blue.100`
+
+**示例数据**:
+```javascript
+{
+ type: NOTIFICATION_TYPES.ANNOUNCEMENT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '贵州茅台发布2024年度财报公告',
+ content: '2024年度营收同比增长15.2%,净利润创历史新高,董事会建议每10股派息180元',
+ publishTime: 1711611000000,
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true,
+ link: '/event-detail/ann001',
+ extra: {
+ announcementType: '财报',
+ companyCode: '600519',
+ companyName: '贵州茅台',
+ },
+ autoClose: 10000,
+}
+```
+
+---
+
+### 类型 2: 股票动向 (Stock Alert)
+
+**适用场景**:价格预警、异常波动、持仓表现、目标价触达
+
+**配色方案**:**动态配色**(根据 `priceChange` 字段)
+- **涨(+)**:
+ - 主色:红色 (Red)
+ - 图标:📈 MdTrendingUp
+ - 背景:`red.50`
+ - 边框:`red.400`
+ - 图标色:`red.500`
+ - 悬停:`red.100`
+- **跌(-)**:
+ - 主色:绿色 (Green)
+ - 图标:📉 MdTrendingDown
+ - 背景:`green.50`
+ - 边框:`green.400`
+ - 图标色:`green.500`
+ - 悬停:`green.100`
+
+**示例数据(涨)**:
+```javascript
+{
+ type: NOTIFICATION_TYPES.STOCK_ALERT,
+ priority: PRIORITY_LEVELS.URGENT,
+ title: '您关注的股票触发预警',
+ content: '宁德时代(300750) 当前价格 ¥245.50,盘中涨幅达 +5.2%,已触达您设置的目标价位',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true,
+ link: '/stock-overview?code=300750',
+ extra: {
+ stockCode: '300750',
+ stockName: '宁德时代',
+ priceChange: '+5.2%', // 💡 重要:根据此字段判断涨跌
+ currentPrice: '245.50',
+ triggerType: '目标价',
+ },
+ autoClose: 10000,
+}
+```
+
+**示例数据(跌)**:
+```javascript
+{
+ type: NOTIFICATION_TYPES.STOCK_ALERT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '您关注的股票异常波动',
+ content: '比亚迪(002594) 5分钟内跌幅达 -3.8%,当前价格 ¥198.20,建议关注',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true,
+ link: '/stock-overview?code=002594',
+ extra: {
+ stockCode: '002594',
+ stockName: '比亚迪',
+ priceChange: '-3.8%', // 💡 负数:使用绿色配色
+ currentPrice: '198.20',
+ triggerType: '异常波动',
+ },
+ autoClose: 10000,
+}
+```
+
+---
+
+### 类型 3: 事件动向 (Event Alert)
+
+**适用场景**:央行政策、行业政策、监管动态、宏观事件
+
+**配色方案**:
+- 主色:橙色 (Orange)
+- 图标:📄 MdArticle
+- 背景:`orange.50`
+- 边框:`orange.400`
+- 图标色:`orange.500`
+- 悬停:`orange.100`
+
+**示例数据**:
+```javascript
+{
+ type: NOTIFICATION_TYPES.EVENT_ALERT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '央行宣布降准0.5个百分点',
+ content: '中国人民银行宣布下调金融机构存款准备金率0.5个百分点,释放长期资金约1万亿元,利好股市',
+ publishTime: 1711590000000,
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true,
+ link: '/event-detail/evt001',
+ extra: {
+ eventId: 'evt001',
+ relatedStocks: 12,
+ impactLevel: '重大利好',
+ sectors: ['银行', '地产', '基建'],
+ },
+ autoClose: 12000,
+}
+```
+
+---
+
+### 类型 4: 分析报告 (Analysis Report)
+
+**适用场景**:行业研报、策略报告、公司研报、市场分析
+
+**配色方案**:
+- 主色:紫色 (Purple)
+- 图标:📊 MdAssessment
+- 背景:`purple.50`
+- 边框:`purple.400`
+- 图标色:`purple.500`
+- 悬停:`purple.100`
+
+**特殊字段**:
+- `author`:作者信息(必填,包含 `name` 和 `organization`)
+- `isAIGenerated`:是否 AI 生成(显示紫色 AI 徽章)
+
+**示例数据(人工)**:
+```javascript
+{
+ type: NOTIFICATION_TYPES.ANALYSIS_REPORT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '医药行业深度报告:创新药迎来政策拐点',
+ content: 'CXO板块持续受益于全球创新药研发外包需求,建议关注药明康德、凯莱英等龙头企业',
+ publishTime: 1711584000000,
+ pushTime: Date.now(),
+ author: {
+ name: '李明',
+ organization: '中信证券',
+ },
+ isAIGenerated: false, // 人工报告
+ clickable: true,
+ link: '/forecast-report?id=rpt001',
+ extra: {
+ reportType: '行业研报',
+ industry: '医药',
+ rating: '强烈推荐',
+ },
+ autoClose: 12000,
+}
+```
+
+**示例数据(AI)**:
+```javascript
+{
+ type: NOTIFICATION_TYPES.ANALYSIS_REPORT,
+ priority: PRIORITY_LEVELS.NORMAL,
+ title: 'AI产业链投资机会分析',
+ content: '随着大模型应用加速落地,算力、数据、应用三大方向均存在投资机会,重点关注海光信息、寒武纪',
+ publishTime: 1711582200000,
+ pushTime: Date.now(),
+ author: {
+ name: 'AI分析师',
+ organization: '价值前沿',
+ },
+ isAIGenerated: true, // 💡 AI 生成:显示紫色 AI 徽章
+ clickable: true,
+ link: '/forecast-report?id=rpt002',
+ extra: {
+ reportType: '策略报告',
+ industry: '人工智能',
+ rating: '推荐',
+ },
+ autoClose: 12000,
+}
+```
+
+---
+
+## 📊 优先级配置
+
+| 优先级 | 级别 | 颜色主题 | 标签显示 | 使用场景 |
+|--------|------|---------|---------|----------|
+| **Urgent** | 紧急 | 🔴 Red | ✅ 显示"紧急" | 重大事件、高优先级预警、异常波动 |
+| **Important** | 重要 | 🟠 Orange | ✅ 显示"重要" | 重要消息、一般预警、关键公告 |
+| **Normal** | 普通 | ⚪ Gray | ❌ 不显示 | 常规消息、信息推送、日常报告 |
+
+**代码使用**:
+```javascript
+import { PRIORITY_LEVELS } from '../constants/notificationTypes';
+
+// 紧急消息
+priority: PRIORITY_LEVELS.URGENT
+
+// 重要消息
+priority: PRIORITY_LEVELS.IMPORTANT
+
+// 普通消息
+priority: PRIORITY_LEVELS.NORMAL
```
---
@@ -81,40 +419,54 @@ src/
用户视角(右下角):
第1条消息到达:
-┌────────────────────┐
-│ 🔔 买入成功 🆕 │ ← 从右侧滑入
-└────────────────────┘
+┌────────────────────────────────────────┐
+│ 📢 贵州茅台发布财报 🆕 [重要] │ ↑ 从底部向上滑入(浮起)
+│ 2024年度营收同比增长15.2%... │ 宽度 400px
+│ 📅 15分钟前 │
+└────────────────────────────────────────┘
第2条消息到达:
-┌────────────────────┐
-│ 🔔 价格预警 🆕 │ ← 新消息(最上方)
-├────────────────────┤
-│ 🔔 买入成功 │ ← 旧消息向下平移
-└────────────────────┘
+┌────────────────────────────────────────┐
+│ 📈 宁德时代触发预警 🆕 [紧急] │ ↑ 新消息(最上方,从下浮起)
+│ 当前价格 ¥245.50,涨幅 +5.2% │ 红色系(涨)
+│ 📅 刚刚 | 📂 查看详情 │
+├────────────────────────────────────────┤
+│ 📢 贵州茅台发布财报 [重要] │ ↑ 旧消息同时向上推动
+│ 2024年度营收同比增长15.2%... │
+│ 📅 16分钟前 │
+└────────────────────────────────────────┘
第6条消息到达(超过5条限制):
-┌────────────────────┐
-│ 🔔 第6条 🆕 │ ← 最新
-├────────────────────┤
-│ 🔔 第5条 │
-├────────────────────┤
-│ 🔔 第4条 │
-├────────────────────┤
-│ 🔔 第3条 │
-├────────────────────┤
-│ 🔔 第2条 │ ← 最旧(仍显示)
-└────────────────────┘
+┌────────────────────────────────────────┐
+│ 📊 AI产业链投资机会 🆕 [AI] │ ↑ 最新(从底部滑入)
+│ 👤 AI分析师 - 价值前沿 │ 紫色系 + AI 徽章
+│ 📅 刚刚 | 📂 查看详情 │
+├────────────────────────────────────────┤
+│ 📈 宁德时代触发预警 [紧急] │ ↑ 向上推
+├────────────────────────────────────────┤
+│ 📢 贵州茅台发布财报 [重要] │ ↑ 向上推
+├────────────────────────────────────────┤
+│ 📄 央行宣布降准 [重要] │ ↑ 向上推
+├────────────────────────────────────────┤
+│ 📊 医药行业深度报告 │ ↑ 最旧(仍显示)
+└────────────────────────────────────────┘
↓ 自动移除
-│ 第1条(已移除) │
+│ 第1条(已移除) │
```
### 关键特性
+- **统一宽度 400px**:所有通知宽度一致,整齐美观
- **最新消息固定位置**:始终在右下角的顶部,便于快速注意
- **自动队列管理**:最多保留 5 条,超出自动移除最旧的
-- **视觉区分**:最新消息有更强的阴影(2xl vs lg)和边框高亮
+- **视觉区分**:
+ - 最新消息:boxShadow='2xl' + 边框高亮(4 个边)
+ - 其他消息:boxShadow='lg' + 左边框
- **z-index 层级**:最新消息层级最高(9999),依次递减
- **间距优化**:消息之间 12px 间距(spacing={3})
+- **点击反馈**:
+ - 可点击:cursor=pointer,hover 时上移 2px + 阴影增强
+ - 不可点击:cursor=default,无 hover 效果
---
@@ -138,19 +490,31 @@ npm start
### 3. 测试通知
-打开浏览器,右上角会显示 **"通知测试工具"**,点击展开后可以:
+打开浏览器,右上角会显示 **"金融资讯测试工具"**,点击展开后可以:
-- **单条测试**:测试不同类型的通知(成功、错误、警告、信息)
-- **层叠测试**:一次发送 4 条消息,测试层叠效果
-- **最大限制测试**:发送 6 条消息,验证只保留最新 5 条
+#### 通知类型测试(9 种场景)
+- **公告通知**:测试蓝色系公告通知
+- **股票上涨**:测试红色系股票涨幅预警
+- **股票下跌**:测试绿色系股票跌幅预警
+- **事件动向**:测试橙色系事件通知
+- **分析报告**:测试紫色系人工研报
+- **AI 报告**:测试紫色系 AI 研报(带 AI 徽章)
+- **预测通知**:测试灰色系预测通知(不可跳转)🆕
+
+#### 组合测试(3 种)
+- **层叠测试(4种类型)**:一次发送 4 条不同类型消息,测试层叠效果
+- **优先级测试(3个级别)**:测试紧急、重要、普通三个优先级
+- **预测→详情流程**:先推送预测(不可跳转),5秒后推送详情(可跳转)🆕
+
+#### 功能按钮
+- **清空全部**:一键清空所有通知
+- **音效开关**:切换音效开关
- **队列状态**:实时显示当前队列中的消息数量(X / 5)
-- **音效控制**:切换音效开关
-- **清空功能**:一键清空所有通知
- **连接状态**:查看 Socket 连接状态和服务类型(MOCK/REAL)
### 4. 自动推送
-在 Mock 模式下,系统会自动每 20 秒推送 1-2 条随机消息,用于测试层叠效果。
+在 Mock 模式下,系统会自动每 15 秒推送 1-2 条随机金融资讯,用于测试层叠效果。
---
@@ -160,40 +524,232 @@ npm start
```javascript
import { useNotification } from 'contexts/NotificationContext';
+import { NOTIFICATION_TYPES, PRIORITY_LEVELS } from 'constants/notificationTypes';
function MyComponent() {
const { addNotification, isConnected } = useNotification();
- const handleTradeSuccess = () => {
+ // 示例 1: 公告通知
+ const handleAnnouncement = () => {
addNotification({
- type: 'trade_alert',
- severity: 'success',
- title: '买入成功',
- message: '您的订单已成功执行:买入 贵州茅台(600519) 100股',
- autoClose: 8000, // 8秒后自动关闭
+ 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: 股票动向(涨)
+ const handleStockAlert = () => {
+ addNotification({
+ type: NOTIFICATION_TYPES.STOCK_ALERT,
+ priority: PRIORITY_LEVELS.URGENT,
+ title: '您关注的股票触发预警',
+ content: '宁德时代(300750) 当前价格 ¥245.50,盘中涨幅达 +5.2%',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true,
+ link: '/stock-overview?code=300750',
+ extra: {
+ stockCode: '300750',
+ stockName: '宁德时代',
+ priceChange: '+5.2%', // 💡 涨:使用红色配色
+ currentPrice: '245.50',
+ },
+ autoClose: 10000,
+ });
+ };
+
+ // 示例 3: 事件动向
+ const handleEventAlert = () => {
+ addNotification({
+ type: NOTIFICATION_TYPES.EVENT_ALERT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '央行宣布降准0.5个百分点',
+ content: '中国人民银行宣布下调金融机构存款准备金率0.5个百分点',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true,
+ link: '/event-detail/evt001',
+ extra: {
+ eventId: 'evt001',
+ relatedStocks: 12,
+ impactLevel: '重大利好',
+ },
+ autoClose: 12000,
+ });
+ };
+
+ // 示例 4: 分析报告(AI)
+ const handleAnalysisReport = () => {
+ addNotification({
+ 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,
+ });
+ };
+
+ // 示例 5: 预测通知(不可跳转)🆕
+ const handlePrediction = () => {
+ addNotification({
+ type: NOTIFICATION_TYPES.EVENT_ALERT,
+ priority: PRIORITY_LEVELS.NORMAL,
+ title: '【预测】央行可能宣布降准政策',
+ content: '基于最新宏观数据分析,预计央行将在本周宣布降准0.5个百分点',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: true,
+ clickable: false, // ❌ 不可点击
+ link: null,
+ extra: {
+ isPrediction: true, // 💡 显示"预测"徽章
+ statusHint: '详细报告生成中...', // 💡 状态提示
+ },
+ autoClose: 15000,
+ });
+ };
+
+ // 示例 6: 预测→详情流程 🆕
+ const handlePredictionFlow = () => {
+ // 阶段 1: 推送预测
+ addNotification({
+ type: NOTIFICATION_TYPES.EVENT_ALERT,
+ priority: PRIORITY_LEVELS.NORMAL,
+ title: '【预测】新能源补贴政策或将延期',
+ content: '根据政策趋势分析,财政部可能宣布新能源汽车购置补贴政策延长至2025年底',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: true,
+ clickable: false,
+ link: null,
+ extra: {
+ isPrediction: true,
+ statusHint: '详细报告生成中...',
+ relatedPredictionId: 'pred_001',
+ },
+ autoClose: 15000,
+ });
+
+ // 阶段 2: 5分钟后推送详情(实际业务中由后端触发)
+ setTimeout(() => {
+ addNotification({
+ type: NOTIFICATION_TYPES.EVENT_ALERT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '新能源补贴政策延期至2025年底',
+ content: '财政部宣布新能源汽车购置补贴政策延长至2025年底,涉及比亚迪、理想汽车等5家龙头企业',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true, // ✅ 可点击
+ link: '/event-detail/evt001',
+ extra: {
+ isPrediction: false,
+ relatedPredictionId: 'pred_001', // 关联原预测
+ },
+ autoClose: 12000,
+ });
+ }, 300000); // 300000ms = 5分钟
+ };
+
return (
连接状态: {isConnected ? '已连接' : '未连接'}
-
+
+
+
+
+
+
);
}
```
-### 消息格式
+### 消息格式(v2.0.0)
```javascript
{
- type: 'trade_alert', // 消息类型
- severity: 'info', // 'success' | 'error' | 'warning' | 'info'
- title: '通知标题', // 主标题
- message: '详细消息内容', // 详细内容
- timestamp: Date.now(), // 时间戳(自动生成)
- autoClose: 8000, // 自动关闭时长(毫秒),0 或 false 表示不自动关闭
- id: 'unique_id' // 唯一ID(自动生成)
+ // 必填字段
+ type: 'announcement' | 'stock_alert' | 'event_alert' | 'analysis_report',
+ priority: 'urgent' | 'important' | 'normal',
+ title: '通知标题',
+ content: '详细消息内容',
+
+ // 时间字段
+ publishTime: 1711611000000, // 发布时间(毫秒时间戳)
+ pushTime: Date.now(), // 推送时间(毫秒时间戳)
+
+ // 元数据
+ isAIGenerated: false, // 是否 AI 生成(显示 AI 徽章)
+ clickable: true, // 是否可点击
+ link: '/event-detail/ann001', // 点击跳转链接
+
+ // 作者信息(仅 analysis_report 需要)
+ author: {
+ name: '李明',
+ organization: '中信证券',
+ },
+
+ // 额外信息(自定义,根据类型不同)
+ extra: {
+ // announcement
+ announcementType: '财报',
+ companyCode: '600519',
+
+ // stock_alert
+ stockCode: '300750',
+ priceChange: '+5.2%', // 💡 重要:涨跌判断依据
+ currentPrice: '245.50',
+
+ // event_alert
+ eventId: 'evt001',
+ relatedStocks: 12,
+ impactLevel: '重大利好',
+
+ // analysis_report
+ reportType: '行业研报',
+ industry: '医药',
+ rating: '强烈推荐',
+
+ // 🆕 预测通知专用字段
+ isPrediction: true, // 是否为预测通知(显示"预测"徽章)
+ statusHint: '详细报告生成中...', // 状态提示文字(可选)
+ relatedPredictionId: 'pred_001', // 关联预测ID(用于追溯,可选)
+ },
+
+ // 自动关闭
+ autoClose: 10000, // 毫秒,0 或 false 表示不自动关闭
+
+ // 自动生成字段(无需手动设置)
+ id: 'unique_id', // 自动生成
+ timestamp: Date.now(), // 自动生成
}
```
@@ -206,19 +762,91 @@ function MyComponent() {
在 `src/services/mockSocketService.js` 中可以配置:
```javascript
-// 修改模拟数据
-const mockTradeAlerts = [
+// 修改模拟数据(14 条金融资讯)
+const mockFinancialNews = [
+ // 3 条公告通知
{
- severity: 'success',
- title: '自定义标题',
- message: '自定义消息',
- autoClose: 8000,
+ type: NOTIFICATION_TYPES.ANNOUNCEMENT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '贵州茅台发布2024年度财报公告',
+ content: '2024年度营收同比增长15.2%,净利润创历史新高...',
+ // ...
+ },
+
+ // 3 条股票动向
+ {
+ type: NOTIFICATION_TYPES.STOCK_ALERT,
+ priority: PRIORITY_LEVELS.URGENT,
+ title: '您关注的股票触发预警',
+ content: '宁德时代(300750) 当前价格 ¥245.50,涨幅 +5.2%...',
+ extra: {
+ priceChange: '+5.2%', // 红色(涨)
+ },
+ // ...
+ },
+
+ // 3 条事件动向
+ {
+ type: NOTIFICATION_TYPES.EVENT_ALERT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '央行宣布降准0.5个百分点',
+ // ...
+ },
+
+ // 4 条分析报告(2 条人工 + 2 条 AI)
+ {
+ type: NOTIFICATION_TYPES.ANALYSIS_REPORT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ author: {
+ name: '李明',
+ organization: '中信证券',
+ },
+ isAIGenerated: false,
+ // ...
+ },
+ {
+ type: NOTIFICATION_TYPES.ANALYSIS_REPORT,
+ author: {
+ name: 'AI分析师',
+ organization: '价值前沿',
+ },
+ isAIGenerated: true, // AI 徽章
+ // ...
},
- // 添加更多...
];
// 调整推送频率
-socket.startMockPush(20000, 2); // 每20秒推送1-2条
+socket.startMockPush(15000, 1); // 每15秒推送1条
+```
+
+### 通知类型常量配置
+
+在 `src/constants/notificationTypes.js` 中可以修改:
+
+```javascript
+// 修改类型配色
+export const NOTIFICATION_TYPE_CONFIGS = {
+ [NOTIFICATION_TYPES.ANNOUNCEMENT]: {
+ name: '公告通知',
+ icon: MdCampaign,
+ colorScheme: 'blue', // 修改颜色主题
+ bg: 'blue.50',
+ borderColor: 'blue.400',
+ iconColor: 'blue.500',
+ hoverBg: 'blue.100',
+ },
+ // ...
+};
+
+// 修改优先级标签
+export const PRIORITY_CONFIGS = {
+ [PRIORITY_LEVELS.URGENT]: {
+ label: '紧急',
+ colorScheme: 'red',
+ show: true,
+ },
+ // ...
+};
```
### NotificationContext 配置
@@ -241,6 +869,12 @@ audioRef.current.volume = 0.5; // 0.0 - 1.0
在 `src/components/NotificationContainer/index.js` 中:
```javascript
+// 调整通知宽度(默认 400px)
+ // 修改为其他数值
+
+// 调整动画方向
+ // bottom=从下向上, right=从右向左
+
// 调整消息间距
// 3 = 12px, 4 = 16px, 2 = 8px
@@ -276,10 +910,14 @@ socketio = SocketIO(app, cors_allowed_origins=[
def handle_connect():
print(f'Client connected: {request.sid}')
-# 推送交易通知
-def send_trade_notification(user_id, data):
+# 推送金融资讯通知
+def send_financial_notification(user_id, data):
"""
- 推送交易通知到指定用户
+ 推送金融资讯通知到指定用户
+
+ 参数:
+ user_id: 用户ID
+ data: 通知数据(参考 v2.0.0 消息格式)
"""
emit('trade_notification', data, room=user_id)
@@ -291,49 +929,88 @@ if __name__ == '__main__':
### 2. 后端推送示例
```python
-# 交易成功后推送通知
+import time
+
+# 示例 1: 公告通知
socketio.emit('trade_notification', {
- 'type': 'trade_alert',
- 'severity': 'success',
- 'title': '买入成功',
- 'message': f'买入 {stock_name}({stock_code}) {quantity}股',
- 'timestamp': int(time.time() * 1000),
- 'autoClose': 8000
-}, room=user_id)
-```
-
----
-
-## 🎨 自定义样式
-
-### 修改通知位置
-
-在 `src/components/NotificationContainer/index.js`:
-
-```javascript
-
-```
-
-### 修改通知颜色
-
-在 `src/components/NotificationContainer/index.js` 中的 `NOTIFICATION_STYLES`:
-
-```javascript
-const NOTIFICATION_STYLES = {
- success: {
- icon: MdCheckCircle,
- colorScheme: 'green', // 修改颜色主题
- bg: 'green.50',
- borderColor: 'green.400',
- iconColor: 'green.500',
+ 'type': 'announcement',
+ 'priority': 'important',
+ 'title': '贵州茅台发布2024年度财报公告',
+ 'content': '2024年度营收同比增长15.2%,净利润创历史新高',
+ 'publishTime': int(time.time() * 1000),
+ 'pushTime': int(time.time() * 1000),
+ 'isAIGenerated': False,
+ 'clickable': True,
+ 'link': '/event-detail/ann001',
+ 'extra': {
+ 'announcementType': '财报',
+ 'companyCode': '600519',
+ 'companyName': '贵州茅台',
},
- // ...
-};
+ 'autoClose': 10000
+}, room=user_id)
+
+# 示例 2: 股票动向(涨)
+socketio.emit('trade_notification', {
+ 'type': 'stock_alert',
+ 'priority': 'urgent',
+ 'title': '您关注的股票触发预警',
+ 'content': f'宁德时代(300750) 当前价格 ¥{current_price},涨幅 +{change_percent}%',
+ 'publishTime': int(time.time() * 1000),
+ 'pushTime': int(time.time() * 1000),
+ 'isAIGenerated': False,
+ 'clickable': True,
+ 'link': '/stock-overview?code=300750',
+ 'extra': {
+ 'stockCode': '300750',
+ 'stockName': '宁德时代',
+ 'priceChange': f'+{change_percent}%', # 涨:红色
+ 'currentPrice': str(current_price),
+ },
+ 'autoClose': 10000
+}, room=user_id)
+
+# 示例 3: 事件动向
+socketio.emit('trade_notification', {
+ '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)
+
+# 示例 4: 分析报告(AI)
+socketio.emit('trade_notification', {
+ 'type': 'analysis_report',
+ 'priority': 'normal',
+ 'title': 'AI产业链投资机会分析',
+ 'content': '随着大模型应用加速落地,算力、数据、应用三大方向均存在投资机会',
+ 'publishTime': int(time.time() * 1000),
+ 'pushTime': int(time.time() * 1000),
+ 'author': {
+ 'name': 'AI分析师',
+ 'organization': '价值前沿',
+ },
+ 'isAIGenerated': True, # AI 徽章
+ 'clickable': True,
+ 'link': '/forecast-report?id=rpt002',
+ 'extra': {
+ 'reportType': '策略报告',
+ 'industry': '人工智能',
+ 'rating': '推荐',
+ },
+ 'autoClose': 12000
+}, room=user_id)
```
---
@@ -346,22 +1023,43 @@ const NOTIFICATION_STYLES = {
1. 确认 `NotificationProvider` 已包裹应用
2. 检查浏览器控制台是否有错误
3. 确认 socket 连接状态(查看测试工具)
+4. 检查通知数据格式是否正确(参考 v2.0.0 消息格式)
-### 问题 2: 音效不播放
+### 问题 2: 股票动向颜色不对
+
+**解决方案:**
+1. 检查 `extra.priceChange` 字段是否存在
+2. 确认 `priceChange` 格式为 "+5.2%" 或 "-3.8%"(包含符号)
+3. 确认使用了 `NOTIFICATION_TYPES.STOCK_ALERT` 类型
+
+### 问题 3: AI 徽章不显示
+
+**解决方案:**
+1. 检查 `isAIGenerated` 字段是否为 `true`
+2. 确认字段名拼写正确(驼峰命名)
+
+### 问题 4: 点击跳转不工作
+
+**解决方案:**
+1. 检查 `clickable` 字段是否为 `true`
+2. 确认 `link` 字段存在且格式正确
+3. 检查路由配置是否正确
+
+### 问题 5: 音效不播放
**解决方案:**
1. 检查浏览器是否允许自动播放音频
2. 确认音效开关已打开
3. 检查音频文件路径是否正确
-### 问题 3: Mock 推送不工作
+### 问题 6: Mock 推送不工作
**检查项:**
1. 确认 `.env` 中设置了 `REACT_APP_ENABLE_MOCK=true`
2. 查看控制台日志确认 Mock 服务已启动
3. 检查 `startMockPush` 是否被调用
-### 问题 4: Socket 连接失败
+### 问题 7: Socket 连接失败
**解决方案:**
1. 检查后端 Flask-SocketIO 是否正确运行
@@ -378,17 +1076,27 @@ const NOTIFICATION_STYLES = {
- 建议根据实际需求调整 `maxNotifications` 值
2. **合理设置自动关闭时长**
- - 建议 5-10 秒(默认 8 秒)
+ - 公告通知:10 秒
+ - 股票动向:10 秒
+ - 事件动向:12 秒(内容较多)
+ - 分析报告:12 秒(内容较多)
- 重要消息可设置更长时间或 `autoClose: false`
3. **避免频繁推送**
- 生产环境建议间隔至少 3 秒
+ - Mock 模式默认 15 秒推送 1 条
- 避免短时间内大量推送造成用户困扰
4. **视觉性能优化** ✅ 已实现
- 使用 Chakra UI 的优化动画(Slide、ScaleFade)
- z-index 合理分配,避免层叠问题
- 间距适中(12px),不会过于紧密
+ - 统一宽度(400px),避免布局抖动
+
+5. **点击交互优化** ✅ 已实现
+ - 使用 React Router `navigate` 实现客户端路由
+ - 点击事件冒泡控制(关闭按钮 `stopPropagation`)
+ - 悬停反馈平滑过渡(`transition: all 0.2s`)
---
@@ -396,17 +1104,201 @@ const NOTIFICATION_STYLES = {
可以考虑添加的功能:
-1. ✨ 通知历史记录
-2. ✨ 通知分类过滤
-3. ✨ 通知优先级
+1. ✨ 通知历史记录(带时间线展示)
+2. ✨ 通知分类过滤(按类型、优先级筛选)
+3. ✨ 通知优先级排序(紧急消息置顶)
4. ✨ 通知持久化(存储到 localStorage)
-5. ✨ 通知点击交互(跳转到相关页面)
-6. ✨ 用户偏好设置(通知类型开关)
+5. ✨ 通知点击跳转动画(页面过渡效果)
+6. ✨ 用户偏好设置(通知类型开关、免打扰模式)
+7. ✨ 通知分组(同一股票的多条通知合并显示)
+8. ✨ 桌面通知集成(Web Notifications API)
+9. ✨ 通知搜索功能(历史记录搜索)
+10. ✨ 通知统计分析(每日推送量、类型分布)
---
## 📝 更新日志
+### v2.2.0 (2025-01-21) - 双通知系统 🆕
+
+**新增功能:**
+- ✅ **浏览器原生通知**:集成 Web Notifications API
+ - 系统级通知,显示在操作系统通知中心
+ - 即使标签页在后台也能收到通知
+ - 点击通知聚焦窗口并跳转详情
+
+- ✅ **智能分发策略**:根据优先级和页面状态自动选择通知方式
+ - **紧急(URGENT)**:浏览器通知 + 网页通知(双重保障)
+ - **重要(IMPORTANT)**:页面在后台=浏览器通知,在前台=网页通知
+ - **普通(NORMAL)**:仅显示网页通知
+
+- ✅ **权限管理系统**:
+ - 自动检测浏览器通知权限状态
+ - 测试工具显示权限状态(已授权/未授权/已拒绝)
+ - 一键请求权限按钮
+ - 权限被拒绝时显示提示信息
+
+**技术实现:**
+- 新增 `browserNotificationService.js` 浏览器通知服务
+- NotificationContext 集成智能分发逻辑
+- 使用 `document.hidden` 检测页面状态
+- 浏览器通知点击使用 `window.location.hash` 跳转
+
+**文件变更:**
+- 新增:`src/services/browserNotificationService.js`
+- 修改:`src/contexts/NotificationContext.js`
+- 修改:`src/components/NotificationTestTool/index.js`
+
+**测试工具更新:**
+- 顶部 Badge 显示浏览器权限状态
+- 新增"浏览器通知"测试区域
+- 请求权限按钮(未授权时显示)
+- 权限状态实时说明
+
+---
+
+### v2.1.0 (2025-01-21) - 预测通知系统
+
+**新增功能:**
+- ✅ **预测通知系统**:支持预测→详情两阶段推送
+ - 预测通知:不可跳转,显示"预测"徽章和状态提示
+ - 详情通知:可跳转,显示"查看详情"提示
+ - 典型场景:先推送预测(T+0),延迟推送详情(T+5分钟)
+
+- ✅ **严格可点击性判断**:
+ - 只有 `clickable=true` 且 `link` 存在才可点击
+ - 不可点击通知:cursor=default,无 hover 效果,不显示"查看详情"
+
+- ✅ **新增字段**:
+ - `extra.isPrediction`:是否为预测通知(显示"预测"徽章)
+ - `extra.statusHint`:状态提示文字(如"详细报告生成中...")
+ - `extra.relatedPredictionId`:关联预测 ID(用于追溯)
+
+- ✅ **测试工具增强**:
+ - 新增"预测通知"测试按钮
+ - 新增"预测→详情流程"测试(5秒延迟)
+ - Mock 数据新增 2 条预测通知示例
+
+- ✅ **视觉优化**:
+ - 预测通知:灰色"预测"徽章
+ - 状态提示:灰色小字 + 时钟图标(MdSchedule)
+ - 不可点击通知无 hover 效果
+
+**技术细节:**
+- 新增 `NOTIFICATION_STATUS` 常量(PREDICTION/READY)
+- NotificationContainer 严格判断 `isActuallyClickable = clickable && link`
+- 导入 MdSchedule 图标用于状态提示
+
+**文档更新:**
+- 新增预测通知使用场景说明
+- 新增预测→详情流程代码示例
+- 更新测试工具说明(9 种测试 + 3 种组合)
+
+---
+
+### v2.0.0 (2025-01-21) - 金融资讯专业版
+
+**重大重构:**
+- ✅ **通知类型系统**:从 4 种通用类型(成功/错误/警告/信息)重构为 4 种金融资讯类型
+ - 公告通知 (Announcement) - 蓝色系
+ - 股票动向 (Stock Alert) - 红绿系(动态)
+ - 事件动向 (Event Alert) - 橙色系
+ - 分析报告 (Analysis Report) - 紫色系
+
+- ✅ **优先级系统**:新增 3 级优先级
+ - 紧急 (Urgent) - 红色标签
+ - 重要 (Important) - 橙色标签
+ - 普通 (Normal) - 无标签
+
+- ✅ **智能元数据**:
+ - 发布时间(智能格式化:刚刚、X分钟前、今天 HH:mm、昨天 HH:mm)
+ - 作者信息(仅分析报告,格式:作者 - 机构)
+ - AI 生成标识(紫色 AI 徽章)
+
+- ✅ **动态配色方案**:
+ - 股票动向根据 `priceChange` 自动判断涨跌
+ - 涨(+):红色系(icon、border、bg、hover)
+ - 跌(-):绿色系
+
+- ✅ **点击交互**:
+ - 支持点击跳转到详情页(React Router)
+ - 可配置 `clickable` 和 `link`
+ - 悬停视觉反馈(上移 2px + 阴影增强)
+ - "📂 查看详情" 提示文本
+
+- ✅ **统一设计**:
+ - 所有通知宽度统一为 400px
+ - 内容超长自动截断(noOfLines)
+ - 响应式布局优化
+
+- ✅ **Mock 数据升级**:
+ - 14 条金融资讯模拟数据
+ - 3 条公告通知 + 3 条股票动向 + 3 条事件动向 + 4 条分析报告(2 条 AI)
+ - 真实场景数据(贵州茅台、宁德时代、比亚迪、央行政策等)
+
+- ✅ **测试工具升级**:
+ - 8 种单独测试:公告、股票上涨/下跌、事件、分析/AI 报告
+ - 2 种组合测试:层叠测试(4 种类型)、优先级测试(3 个级别)
+ - 类型特定图标和配色
+ - UI 分组优化(Divider)
+
+- ✅ **文件结构优化**:
+ - 新增 `src/constants/notificationTypes.js` 统一管理类型定义
+ - `NotificationContainer/index.js` 完全重写
+ - `NotificationTestTool/index.js` 完全重写
+ - `mockSocketService.js` Mock 数据重构
+
+**技术细节:**
+- 使用 React Router `useNavigate` 实现点击跳转
+- 动态类型配置(getIcon、getColorScheme、getBg 等函数)
+- 条件渲染优化(优先级标签、AI 徽章、作者信息、点击提示)
+- 时间格式化辅助函数(formatNotificationTime)
+
+**破坏性变更:**
+- ⚠️ 消息格式完全改变(从 severity 改为 type + priority)
+- ⚠️ 移除了通用的 success/error/warning/info 类型
+- ⚠️ 新增必填字段:`type`、`priority`、`publishTime`
+- ⚠️ 分析报告必须包含 `author` 字段
+- ⚠️ 股票动向需要 `extra.priceChange` 字段用于动态配色
+
+**迁移指南:**
+```javascript
+// 旧版本(v1.x)
+addNotification({
+ type: 'trade_alert',
+ severity: 'success', // ❌ 移除
+ title: '买入成功',
+ message: '...', // ❌ 改为 content
+})
+
+// 新版本(v2.0)
+addNotification({
+ type: NOTIFICATION_TYPES.ANNOUNCEMENT, // ✅ 新的类型系统
+ priority: PRIORITY_LEVELS.IMPORTANT, // ✅ 新增优先级
+ title: '买入成功',
+ content: '...', // ✅ message 改为 content
+ publishTime: Date.now(), // ✅ 新增发布时间
+ pushTime: Date.now(),
+ isAIGenerated: false, // ✅ 新增 AI 标识
+ clickable: true, // ✅ 新增点击配置
+ link: '/event-detail/001', // ✅ 新增跳转链接
+ extra: { ... }, // ✅ 新增额外信息
+ autoClose: 10000,
+})
+```
+
+---
+
+### v1.1.1 (2025-01-21) - 动画优化版
+
+- ✅ **动画方向优化**:从"从右向左滑入"改为"**从底部向上滑入**"
+ - 更符合"通知浮起"的物理隐喻
+ - 视觉效果更自然,与"堆叠"概念一致
+ - 代码修改:`direction="right"` → `direction="bottom"`
+- ✅ **文档更新**:同步更新动画说明和可视化图示
+
+---
+
### v1.1.0 (2025-01-21) - 交互优化版
- ✅ **新消息置顶展示**(行业标准,参考 Windows/macOS/Slack)
@@ -422,6 +1314,8 @@ const NOTIFICATION_STYLES = {
- 队列满时红色提示
- ✅ **文档完善**:添加展示逻辑说明、配置指南
+---
+
### v1.0.0 (2025-01-20) - 初始版本
- ✅ 实现基础通知系统
@@ -437,9 +1331,11 @@ const NOTIFICATION_STYLES = {
- **前端框架**: React 18.3.1
- **UI 库**: Chakra UI 2.8.2
+- **路由**: React Router v6
- **实时通信**: Socket.IO Client 4.7.4
- **后端框架**: Flask-SocketIO 5.3.6
- **状态管理**: React Context API
+- **图标库**: React Icons (Material Design)
---
@@ -447,8 +1343,9 @@ const NOTIFICATION_STYLES = {
如有问题,请查看:
- 项目文档: `CLAUDE.md`
-- 测试工具: 开发环境右上角
+- 测试工具: 开发环境右上角"金融资讯测试工具"
- 控制台日志: 所有操作都有详细日志
+- 类型定义: `src/constants/notificationTypes.js`
---
diff --git a/src/components/NotificationContainer/index.js b/src/components/NotificationContainer/index.js
index 3c2a962c..777aeb8c 100644
--- a/src/components/NotificationContainer/index.js
+++ b/src/components/NotificationContainer/index.js
@@ -1,9 +1,10 @@
// src/components/NotificationContainer/index.js
/**
- * 通知容器组件 - 右下角层叠显示实时通知
+ * 金融资讯通知容器组件 - 右下角层叠显示实时通知
*/
-import React from 'react';
+import React, { useState } from 'react';
+import { useNavigate } from 'react-router-dom';
import {
Box,
VStack,
@@ -11,56 +12,69 @@ import {
Text,
IconButton,
Icon,
+ Badge,
+ Button,
useColorModeValue,
Slide,
ScaleFade,
} from '@chakra-ui/react';
-import { MdClose, MdCheckCircle, MdError, MdWarning, MdInfo } from 'react-icons/md';
+import { MdClose, MdOpenInNew, MdSchedule, MdExpandMore, MdExpandLess } from 'react-icons/md';
import { useNotification } from '../../contexts/NotificationContext';
-
-// 通知类型对应的图标和颜色
-const NOTIFICATION_STYLES = {
- success: {
- icon: MdCheckCircle,
- colorScheme: 'green',
- bg: 'green.50',
- borderColor: 'green.400',
- iconColor: 'green.500',
- },
- error: {
- icon: MdError,
- colorScheme: 'red',
- bg: 'red.50',
- borderColor: 'red.400',
- iconColor: 'red.500',
- },
- warning: {
- icon: MdWarning,
- colorScheme: 'orange',
- bg: 'orange.50',
- borderColor: 'orange.400',
- iconColor: 'orange.500',
- },
- info: {
- icon: MdInfo,
- colorScheme: 'blue',
- bg: 'blue.50',
- borderColor: 'blue.400',
- iconColor: 'blue.500',
- },
-};
+import {
+ NOTIFICATION_TYPE_CONFIGS,
+ NOTIFICATION_TYPES,
+ PRIORITY_CONFIGS,
+ NOTIFICATION_CONFIG,
+ formatNotificationTime,
+} from '../../constants/notificationTypes';
/**
* 单个通知项组件
*/
const NotificationItem = ({ notification, onClose, isNewest = false }) => {
- const { id, severity = 'info', title, message } = notification;
- const style = NOTIFICATION_STYLES[severity] || NOTIFICATION_STYLES.info;
+ const navigate = useNavigate();
+ const { id, type, priority, title, content, isAIGenerated, clickable, link, author, publishTime, pushTime, extra } = notification;
- const bgColor = useColorModeValue(style.bg, `${style.colorScheme}.900`);
- const borderColor = useColorModeValue(style.borderColor, `${style.colorScheme}.500`);
+ // 严格判断可点击性:只有 clickable=true 且 link 存在才可点击
+ const isActuallyClickable = clickable && link;
+
+ // 判断是否为预测通知
+ const isPrediction = extra?.isPrediction;
+
+ // 获取类型配置
+ let typeConfig = NOTIFICATION_TYPE_CONFIGS[type] || NOTIFICATION_TYPE_CONFIGS[NOTIFICATION_TYPES.EVENT_ALERT];
+
+ // 股票动向需要根据涨跌动态配置
+ if (type === NOTIFICATION_TYPES.STOCK_ALERT && extra?.priceChange) {
+ const priceChange = extra.priceChange;
+ typeConfig = {
+ ...typeConfig,
+ icon: typeConfig.getIcon(priceChange),
+ colorScheme: typeConfig.getColorScheme(priceChange),
+ bg: typeConfig.getBg(priceChange),
+ borderColor: typeConfig.getBorderColor(priceChange),
+ iconColor: typeConfig.getIconColor(priceChange),
+ hoverBg: typeConfig.getHoverBg(priceChange),
+ };
+ }
+
+ // 获取优先级配置
+ const priorityConfig = PRIORITY_CONFIGS[priority] || PRIORITY_CONFIGS.normal;
+
+ const bgColor = useColorModeValue(typeConfig.bg, `${typeConfig.colorScheme}.900`);
+ const borderColor = useColorModeValue(typeConfig.borderColor, `${typeConfig.colorScheme}.500`);
const textColor = useColorModeValue('gray.800', 'white');
const subTextColor = useColorModeValue('gray.600', 'gray.300');
+ const metaTextColor = useColorModeValue('gray.500', 'gray.400');
+ const hoverBg = typeConfig.hoverBg;
+ const closeButtonHoverBg = useColorModeValue(`${typeConfig.colorScheme}.200`, `${typeConfig.colorScheme}.700`);
+
+ // 点击处理(只有真正可点击时才执行)
+ const handleClick = () => {
+ if (isActuallyClickable) {
+ navigate(link);
+ }
+ };
return (
@@ -69,72 +83,160 @@ const NotificationItem = ({ notification, onClose, isNewest = false }) => {
borderLeft="4px solid"
borderColor={borderColor}
borderRadius="md"
- boxShadow={isNewest ? '2xl' : 'lg'} // 最新消息更强的阴影
+ boxShadow={isNewest ? '2xl' : 'lg'}
p={4}
- minW="350px"
- maxW="450px"
+ w="400px" // 统一宽度
position="relative"
- _hover={{
+ cursor={isActuallyClickable ? 'pointer' : 'default'} // 严格判断
+ onClick={isActuallyClickable ? handleClick : undefined} // 严格判断
+ _hover={isActuallyClickable ? {
boxShadow: 'xl',
- transform: 'translateX(-4px)',
- }}
+ transform: 'translateY(-2px)',
+ bg: hoverBg,
+ } : {}} // 不可点击时无 hover 效果
transition="all 0.2s"
- // 最新消息添加微妙的高亮边框
{...(isNewest && {
borderRight: '1px solid',
borderRightColor: borderColor,
borderTop: '1px solid',
- borderTopColor: useColorModeValue(`${style.colorScheme}.100`, `${style.colorScheme}.700`),
+ borderTopColor: useColorModeValue(`${typeConfig.colorScheme}.100`, `${typeConfig.colorScheme}.700`),
})}
>
-
- {/* 图标 */}
+ {/* 头部区域:图标 + 标题 + 优先级 + AI标识 */}
+
+ {/* 类型图标 */}
- {/* 内容 */}
-
-
+ {title}
+
+
+ {/* 优先级标签 */}
+ {priorityConfig.show && (
+
- {title}
-
- {message && (
-
- {message}
-
- )}
-
+ {priorityConfig.label}
+
+ )}
+
+ {/* 预测标识 */}
+ {isPrediction && (
+
+ 预测
+
+ )}
+
+ {/* AI 生成标识 */}
+ {isAIGenerated && (
+
+ AI
+
+ )}
{/* 关闭按钮 */}
}
- size="sm"
+ size="xs"
variant="ghost"
- colorScheme={style.colorScheme}
+ colorScheme={typeConfig.colorScheme}
aria-label="关闭通知"
- onClick={() => onClose(id)}
- position="absolute"
- top={2}
- right={2}
+ onClick={(e) => {
+ e.stopPropagation();
+ onClose(id);
+ }}
+ flexShrink={0}
_hover={{
- bg: useColorModeValue(`${style.colorScheme}.100`, `${style.colorScheme}.800`),
+ bg: closeButtonHoverBg,
}}
/>
+
+ {/* 内容区域 */}
+
+ {content}
+
+
+ {/* 底部元数据区域 */}
+
+ {/* 作者信息(仅分析报告) */}
+ {author && (
+
+ 👤
+ {author.name} - {author.organization}
+ |
+
+ )}
+
+ {/* 时间信息 */}
+
+ 📅
+
+ {publishTime && formatNotificationTime(publishTime)}
+ {!publishTime && pushTime && formatNotificationTime(pushTime)}
+
+
+
+ {/* 状态提示(仅预测通知) */}
+ {extra?.statusHint && (
+ <>
+ |
+
+
+ {extra.statusHint}
+
+ >
+ )}
+
+ {/* 可点击提示(仅真正可点击的通知) */}
+ {isActuallyClickable && (
+ <>
+ |
+
+
+ 查看详情
+
+ >
+ )}
+
);
@@ -145,12 +247,24 @@ const NotificationItem = ({ notification, onClose, isNewest = false }) => {
*/
const NotificationContainer = () => {
const { notifications, removeNotification } = useNotification();
+ const [isExpanded, setIsExpanded] = useState(false);
// 如果没有通知,不渲染
if (notifications.length === 0) {
return null;
}
+ // 根据展开状态决定显示的通知
+ const maxVisible = NOTIFICATION_CONFIG.maxVisible;
+ const hasMore = notifications.length > maxVisible;
+ const visibleNotifications = isExpanded ? notifications : notifications.slice(0, maxVisible);
+ const hiddenCount = notifications.length - maxVisible;
+
+ // 颜色配置
+ const collapseBg = useColorModeValue('gray.100', 'gray.700');
+ const collapseHoverBg = useColorModeValue('gray.200', 'gray.600');
+ const collapseTextColor = useColorModeValue('gray.700', 'gray.200');
+
return (
{
align="flex-end"
pointerEvents="auto"
>
- {notifications.map((notification, index) => (
+ {visibleNotifications.map((notification, index) => (
{
/>
))}
+
+ {/* 折叠/展开按钮 */}
+ {hasMore && (
+
+ }
+ onClick={() => setIsExpanded(!isExpanded)}
+ boxShadow="md"
+ borderRadius="md"
+ >
+ {isExpanded
+ ? '收起通知'
+ : NOTIFICATION_CONFIG.collapse.textTemplate.replace('{count}', hiddenCount)
+ }
+
+
+ )}
);
diff --git a/src/components/NotificationTestTool/index.js b/src/components/NotificationTestTool/index.js
index 3aa75741..cbec0cd5 100644
--- a/src/components/NotificationTestTool/index.js
+++ b/src/components/NotificationTestTool/index.js
@@ -1,7 +1,7 @@
// src/components/NotificationTestTool/index.js
/**
- * 通知测试工具 - 仅在开发环境显示
- * 用于手动测试通知功能
+ * 金融资讯通知测试工具 - 仅在开发环境显示
+ * 用于手动测试4种通知类型
*/
import React, { useState } from 'react';
@@ -15,87 +15,299 @@ import {
Collapse,
useDisclosure,
Badge,
+ Divider,
} from '@chakra-ui/react';
-import { MdNotifications, MdClose, MdVolumeOff, MdVolumeUp } from 'react-icons/md';
+import { MdNotifications, MdClose, MdVolumeOff, MdVolumeUp, MdCampaign, MdTrendingUp, MdArticle, MdAssessment } from 'react-icons/md';
import { useNotification } from '../../contexts/NotificationContext';
import { SOCKET_TYPE } from '../../services/socket';
+import { NOTIFICATION_TYPES, PRIORITY_LEVELS } from '../../constants/notificationTypes';
const NotificationTestTool = () => {
const { isOpen, onToggle } = useDisclosure();
- const { addNotification, soundEnabled, toggleSound, isConnected, clearAllNotifications, notifications } = useNotification();
+ const { addNotification, soundEnabled, toggleSound, isConnected, clearAllNotifications, notifications, browserPermission, requestBrowserPermission } = useNotification();
const [testCount, setTestCount] = useState(0);
+ // 浏览器权限状态标签
+ const getPermissionLabel = () => {
+ switch (browserPermission) {
+ case 'granted':
+ return '已授权';
+ case 'denied':
+ return '已拒绝';
+ case 'default':
+ return '未授权';
+ default:
+ return '不支持';
+ }
+ };
+
+ const getPermissionColor = () => {
+ switch (browserPermission) {
+ case 'granted':
+ return 'green';
+ case 'denied':
+ return 'red';
+ case 'default':
+ return 'gray';
+ default:
+ return 'gray';
+ }
+ };
+
+ // 请求浏览器权限
+ const handleRequestPermission = async () => {
+ await requestBrowserPermission();
+ };
+
// 只在开发环境显示
if (process.env.NODE_ENV !== 'development') {
return null;
}
- const testNotifications = [
- {
- severity: 'success',
- title: '买入成功',
- message: '您的订单已成功执行:买入 贵州茅台(600519) 100股',
- },
- {
- severity: 'error',
- title: '委托失败',
- message: '卖出订单失败:资金不足',
- },
- {
- severity: 'warning',
- title: '价格预警',
- message: '您关注的股票已触达预设价格',
- },
- {
- severity: 'info',
- title: '持仓提醒',
- message: '您持有的股票今日涨幅达 5.2%',
- },
- ];
-
- const handleTestNotification = (index) => {
- const notif = testNotifications[index];
+ // 公告通知测试数据
+ const testAnnouncement = () => {
addNotification({
- ...notif,
- type: 'trade_alert',
- autoClose: 8000,
+ type: NOTIFICATION_TYPES.ANNOUNCEMENT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '【测试】贵州茅台发布2024年度财报公告',
+ content: '2024年度营收同比增长15.2%,净利润创历史新高,董事会建议每10股派息180元',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true,
+ link: '/event-detail/test001',
+ extra: {
+ announcementType: '财报',
+ companyCode: '600519',
+ companyName: '贵州茅台',
+ },
+ autoClose: 10000,
});
setTestCount(prev => prev + 1);
};
- const handleMultipleNotifications = () => {
- testNotifications.forEach((notif, index) => {
- setTimeout(() => {
- addNotification({
- ...notif,
- type: 'trade_alert',
- autoClose: 10000,
- });
- }, index * 600);
+ // 股票动向测试数据(涨)
+ const testStockAlertUp = () => {
+ addNotification({
+ type: NOTIFICATION_TYPES.STOCK_ALERT,
+ priority: PRIORITY_LEVELS.URGENT,
+ title: '【测试】您关注的股票触发预警',
+ content: '宁德时代(300750) 当前价格 ¥245.50,盘中涨幅达 +5.2%,已触达您设置的目标价位',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true,
+ link: '/stock-overview?code=300750',
+ extra: {
+ stockCode: '300750',
+ stockName: '宁德时代',
+ priceChange: '+5.2%',
+ currentPrice: '245.50',
+ },
+ autoClose: 10000,
});
- setTestCount(prev => prev + testNotifications.length);
+ setTestCount(prev => prev + 1);
};
- const handleMaxLimitTest = () => {
- // 测试最大限制:快速发送6条,验证只保留最新5条
- for (let i = 1; i <= 6; i++) {
+ // 股票动向测试数据(跌)
+ const testStockAlertDown = () => {
+ addNotification({
+ type: NOTIFICATION_TYPES.STOCK_ALERT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '【测试】您关注的股票异常波动',
+ content: '比亚迪(002594) 5分钟内跌幅达 -3.8%,当前价格 ¥198.20,建议关注',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true,
+ link: '/stock-overview?code=002594',
+ extra: {
+ stockCode: '002594',
+ stockName: '比亚迪',
+ priceChange: '-3.8%',
+ currentPrice: '198.20',
+ },
+ autoClose: 10000,
+ });
+ setTestCount(prev => prev + 1);
+ };
+
+ // 事件动向测试数据
+ const testEventAlert = () => {
+ addNotification({
+ type: NOTIFICATION_TYPES.EVENT_ALERT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '【测试】央行宣布降准0.5个百分点',
+ content: '中国人民银行宣布下调金融机构存款准备金率0.5个百分点,释放长期资金约1万亿元,利好股市',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true,
+ link: '/event-detail/test003',
+ extra: {
+ eventId: 'test003',
+ relatedStocks: 12,
+ impactLevel: '重大利好',
+ },
+ autoClose: 12000,
+ });
+ setTestCount(prev => prev + 1);
+ };
+
+ // 分析报告测试数据(非AI)
+ const testAnalysisReport = () => {
+ addNotification({
+ type: NOTIFICATION_TYPES.ANALYSIS_REPORT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '【测试】医药行业深度报告:创新药迎来政策拐点',
+ content: 'CXO板块持续受益于全球创新药研发外包需求,建议关注药明康德、凯莱英等龙头企业',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ author: {
+ name: '李明',
+ organization: '中信证券',
+ },
+ isAIGenerated: false,
+ clickable: true,
+ link: '/forecast-report?id=test004',
+ extra: {
+ reportType: '行业研报',
+ industry: '医药',
+ },
+ autoClose: 12000,
+ });
+ setTestCount(prev => prev + 1);
+ };
+
+ // AI分析报告测试数据
+ const testAIReport = () => {
+ addNotification({
+ type: NOTIFICATION_TYPES.ANALYSIS_REPORT,
+ priority: PRIORITY_LEVELS.NORMAL,
+ title: '【测试】AI产业链投资机会分析',
+ content: '随着大模型应用加速落地,算力、数据、应用三大方向均存在投资机会,重点关注海光信息、寒武纪',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ author: {
+ name: 'AI分析师',
+ organization: '价值前沿',
+ },
+ isAIGenerated: true,
+ clickable: true,
+ link: '/forecast-report?id=test005',
+ extra: {
+ reportType: '策略报告',
+ industry: '人工智能',
+ },
+ autoClose: 12000,
+ });
+ setTestCount(prev => prev + 1);
+ };
+
+ // 预测通知测试数据(不可跳转)
+ const testPrediction = () => {
+ addNotification({
+ type: NOTIFICATION_TYPES.EVENT_ALERT,
+ priority: PRIORITY_LEVELS.NORMAL,
+ title: '【测试】【预测】央行可能宣布降准政策',
+ content: '基于最新宏观数据分析,预计央行将在本周宣布降准0.5个百分点,释放长期资金',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: true,
+ clickable: false, // ❌ 不可点击
+ link: null,
+ extra: {
+ isPrediction: true,
+ statusHint: '详细报告生成中...',
+ },
+ autoClose: 15000,
+ });
+ setTestCount(prev => prev + 1);
+ };
+
+ // 预测→详情流程测试(先推预测,5秒后推详情)
+ const testPredictionFlow = () => {
+ // 阶段 1: 推送预测
+ addNotification({
+ type: NOTIFICATION_TYPES.EVENT_ALERT,
+ priority: PRIORITY_LEVELS.NORMAL,
+ title: '【测试】【预测】新能源汽车补贴政策将延期',
+ content: '根据政策趋势分析,预计财政部将宣布新能源汽车购置补贴政策延长至2025年底',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: true,
+ clickable: false,
+ link: null,
+ extra: {
+ isPrediction: true,
+ statusHint: '详细报告生成中...',
+ relatedPredictionId: 'pred_test_001',
+ },
+ autoClose: 15000,
+ });
+ setTestCount(prev => prev + 1);
+
+ // 阶段 2: 5秒后推送详情
+ setTimeout(() => {
+ addNotification({
+ type: NOTIFICATION_TYPES.EVENT_ALERT,
+ priority: PRIORITY_LEVELS.IMPORTANT,
+ title: '【测试】新能源汽车补贴政策延期至2025年底',
+ content: '财政部宣布新能源汽车购置补贴政策延长至2025年底,涉及比亚迪、理想汽车等5家龙头企业',
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: true, // ✅ 可点击
+ link: '/event-detail/test_pred_001',
+ extra: {
+ isPrediction: false,
+ relatedPredictionId: 'pred_test_001',
+ eventId: 'test_pred_001',
+ relatedStocks: 5,
+ impactLevel: '重大利好',
+ },
+ autoClose: 12000,
+ });
+ setTestCount(prev => prev + 1);
+ }, 5000);
+ };
+
+ // 测试全部类型(层叠效果)
+ const testAllTypes = () => {
+ const tests = [testAnnouncement, testStockAlertUp, testEventAlert, testAnalysisReport];
+ tests.forEach((test, index) => {
+ setTimeout(() => test(), index * 600);
+ });
+ };
+
+ // 测试优先级
+ const testPriority = () => {
+ [
+ { priority: PRIORITY_LEVELS.URGENT, label: '紧急' },
+ { priority: PRIORITY_LEVELS.IMPORTANT, label: '重要' },
+ { priority: PRIORITY_LEVELS.NORMAL, label: '普通' },
+ ].forEach((item, index) => {
setTimeout(() => {
addNotification({
- severity: i % 2 === 0 ? 'success' : 'info',
- title: `测试消息 #${i}`,
- message: `这是第 ${i} 条测试消息(共6条,应只保留最新5条)`,
- type: 'trade_alert',
- autoClose: 12000,
+ type: NOTIFICATION_TYPES.ANNOUNCEMENT,
+ priority: item.priority,
+ title: `【测试】${item.label}优先级通知`,
+ content: `这是一条${item.label}优先级的测试通知,用于验证优先级标签显示`,
+ publishTime: Date.now(),
+ pushTime: Date.now(),
+ isAIGenerated: false,
+ clickable: false,
+ autoClose: 10000,
});
- }, i * 400);
- }
- setTestCount(prev => prev + 6);
+ setTestCount(prev => prev + 1);
+ }, index * 600);
+ });
};
return (
{
>
- 通知测试工具
+ 金融资讯测试工具
{isConnected ? 'Connected' : 'Disconnected'}
@@ -122,6 +334,9 @@ const NotificationTestTool = () => {
{SOCKET_TYPE}
+
+ 浏览器: {getPermissionLabel()}
+
: }
size="xs"
@@ -133,60 +348,151 @@ const NotificationTestTool = () => {
{/* 工具面板 */}
-
-
- 点击按钮测试不同类型的通知
+
+
+ 通知类型测试
- {/* 测试按钮 */}
-
-
-
-
-
-
+ {/* 公告通知 */}
+ {/* 股票动向 */}
+
+ }
+ onClick={testStockAlertUp}
+ flex={1}
+ >
+ 股票上涨
+
+ }
+ onClick={testStockAlertDown}
+ flex={1}
+ >
+ 股票下跌
+
+
+
+ {/* 事件动向 */}
}
+ onClick={testEventAlert}
>
- 层叠通知(4条)
+ 事件动向
+ {/* 分析报告 */}
+
+ }
+ onClick={testAnalysisReport}
+ flex={1}
+ >
+ 分析报告
+
+ AI
+
+
+
+ {/* 预测通知 */}
+ }
+ onClick={testPrediction}
+ >
+ 预测通知(不可跳转)
+
+
+
+
+
+ 组合测试
+
+
+ {/* 层叠测试 */}
+
+
+ {/* 优先级测试 */}
+ {/* 预测→详情流程测试 */}
+
+
+
+
+
+ 浏览器通知
+
+
+ {/* 请求权限按钮 */}
+ {browserPermission !== 'granted' && (
+
+ )}
+
+ {/* 浏览器通知状态说明 */}
+ {browserPermission === 'granted' && (
+
+ ✅ 浏览器通知已启用
+
+ )}
+ {browserPermission === 'denied' && (
+
+ ❌ 请在浏览器设置中允许通知
+
+ )}
+
+
+
{/* 功能按钮 */}