- 移动42个文档文件到 docs/ 目录 - 更新 .gitignore 允许 docs/ 下的 .md 文件 - 删除根目录下的重复文档文件 📁 文档分类: - StockDetailPanel 重构文档(3个) - PostHog 集成文档(6个) - 系统架构和API文档(33个) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
15 KiB
15 KiB
通知系统增强功能 - 使用指南
📋 概述
本指南介绍通知系统的三大增强功能:
- 智能桌面通知 - 自动请求权限,系统级通知
- 性能监控 - 追踪推送效果,数据驱动优化
- 历史记录 - 持久化存储,随时查询
🎯 功能 1:智能桌面通知
功能说明
首次收到重要/紧急通知时,自动请求浏览器通知权限,确保用户不错过关键信息。
工作原理
// 在 NotificationContext 中的逻辑
if (priority === URGENT || priority === IMPORTANT) {
if (browserPermission === 'default' && !hasRequestedPermission) {
// 首次遇到重要通知,自动请求权限
await requestBrowserPermission();
setHasRequestedPermission(true); // 避免重复请求
}
}
权限状态
- granted: 已授权,可以发送桌面通知
- denied: 已拒绝,无法发送桌面通知
- default: 未请求,首次重要通知时会自动请求
使用示例
自动触发(推荐)
// 无需任何代码,系统自动处理
// 首次收到重要/紧急通知时会自动弹出权限请求
手动请求
import { useNotification } from 'contexts/NotificationContext';
function SettingsPage() {
const { requestBrowserPermission, browserPermission } = useNotification();
return (
<div>
<p>当前状态: {browserPermission}</p>
<button onClick={requestBrowserPermission}>
开启桌面通知
</button>
</div>
);
}
通知分发策略
| 优先级 | 页面在前台 | 页面在后台 |
|---|---|---|
| 紧急 | 桌面通知 + 网页通知 | 桌面通知 + 网页通知 |
| 重要 | 网页通知 | 桌面通知 |
| 普通 | 网页通知 | 网页通知 |
测试步骤
-
清除已保存的权限状态
localStorage.removeItem('browser_notification_requested'); -
刷新页面
-
触发一个重要/紧急通知
- Mock 模式:等待自动推送
- Real 模式:创建测试事件
-
观察权限请求弹窗
- 浏览器会弹出通知权限请求
- 点击"允许"授权
-
验证桌面通知
- 切换到其他标签页
- 收到重要通知时应该看到桌面通知
📊 功能 2:性能监控
功能说明
追踪通知推送的各项指标,包括:
- 到达率: 发送 vs 接收
- 点击率: 点击 vs 接收
- 响应时间: 收到通知到点击的平均时间
- 类型分布: 各类型通知的数量和效果
- 时段分布: 每小时推送量
API 参考
获取汇总统计
import { notificationMetricsService } from 'services/notificationMetricsService';
const summary = notificationMetricsService.getSummary();
console.log(summary);
/* 输出:
{
totalSent: 100,
totalReceived: 98,
totalClicked: 45,
totalDismissed: 53,
avgResponseTime: 5200, // 毫秒
clickRate: '45.92', // 百分比
deliveryRate: '98.00' // 百分比
}
*/
获取按类型统计
const byType = notificationMetricsService.getByType();
console.log(byType);
/* 输出:
{
announcement: { sent: 20, received: 20, clicked: 15, dismissed: 5, clickRate: '75.00' },
stock_alert: { sent: 30, received: 30, clicked: 20, dismissed: 10, clickRate: '66.67' },
event_alert: { sent: 40, received: 38, clicked: 10, dismissed: 28, clickRate: '26.32' },
analysis_report: { sent: 10, received: 10, clicked: 0, dismissed: 10, clickRate: '0.00' }
}
*/
获取按优先级统计
const byPriority = notificationMetricsService.getByPriority();
console.log(byPriority);
/* 输出:
{
urgent: { sent: 10, received: 10, clicked: 9, dismissed: 1, clickRate: '90.00' },
important: { sent: 40, received: 39, clicked: 25, dismissed: 14, clickRate: '64.10' },
normal: { sent: 50, received: 49, clicked: 11, dismissed: 38, clickRate: '22.45' }
}
*/
获取每日数据
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' },
...
]
*/
获取完整指标
const allMetrics = notificationMetricsService.getAllMetrics();
console.log(allMetrics);
导出数据
// 导出为 JSON
const json = notificationMetricsService.exportToJSON();
console.log(json);
// 导出为 CSV
const csv = notificationMetricsService.exportToCSV();
console.log(csv);
重置指标
notificationMetricsService.reset();
在控制台查看实时指标
打开浏览器控制台,执行:
// 引入服务
import { notificationMetricsService } from './services/notificationMetricsService.js';
// 查看汇总
console.table(notificationMetricsService.getSummary());
// 查看按类型分布
console.table(notificationMetricsService.getByType());
// 查看最近 7 天数据
console.table(notificationMetricsService.getDailyData(7));
监控埋点(自动)
监控服务已自动集成到 NotificationContext,无需手动调用:
- trackReceived: 收到通知时自动调用
- trackClicked: 点击通知时自动调用
- trackDismissed: 关闭通知时自动调用
可视化展示(可选)
你可以基于监控数据创建仪表板:
import { notificationMetricsService } from 'services/notificationMetricsService';
import { PieChart, LineChart } from 'recharts';
function MetricsDashboard() {
const summary = notificationMetricsService.getSummary();
const dailyData = notificationMetricsService.getDailyData(7);
const byType = notificationMetricsService.getByType();
return (
<div>
{/* 汇总卡片 */}
<StatsCard title="总推送数" value={summary.totalSent} />
<StatsCard title="点击率" value={`${summary.clickRate}%`} />
<StatsCard title="平均响应时间" value={`${summary.avgResponseTime}ms`} />
{/* 类型分布饼图 */}
<PieChart data={Object.entries(byType).map(([type, data]) => ({
name: type,
value: data.received
}))} />
{/* 每日趋势折线图 */}
<LineChart data={dailyData} />
</div>
);
}
📜 功能 3:历史记录
功能说明
持久化存储所有接收到的通知,支持:
- 查询和筛选
- 搜索关键词
- 标记已读/已点击
- 批量删除
- 导出(JSON/CSV)
API 参考
获取历史记录(支持筛选和分页)
import { notificationHistoryService } from 'services/notificationHistoryService';
const result = notificationHistoryService.getHistory({
type: 'event_alert', // 可选:筛选类型
priority: 'urgent', // 可选:筛选优先级
readStatus: 'unread', // 可选:'read' | 'unread' | 'all'
startDate: Date.now() - 7 * 24 * 60 * 60 * 1000, // 可选:开始日期
endDate: Date.now(), // 可选:结束日期
page: 1, // 页码
pageSize: 20, // 每页数量
});
console.log(result);
/* 输出:
{
records: [...], // 当前页的记录
total: 150, // 总记录数
page: 1, // 当前页
pageSize: 20, // 每页数量
totalPages: 8 // 总页数
}
*/
搜索历史记录
const results = notificationHistoryService.searchHistory('降准');
console.log(results); // 返回标题/内容中包含"降准"的所有记录
标记已读/已点击
// 标记已读
notificationHistoryService.markAsRead('notification_id');
// 标记已点击
notificationHistoryService.markAsClicked('notification_id');
删除记录
// 删除单条
notificationHistoryService.deleteRecord('notification_id');
// 批量删除
notificationHistoryService.deleteRecords(['id1', 'id2', 'id3']);
// 清空所有
notificationHistoryService.clearHistory();
获取统计数据
const stats = notificationHistoryService.getStats();
console.log(stats);
/* 输出:
{
total: 500, // 总记录数
read: 320, // 已读数
unread: 180, // 未读数
clicked: 150, // 已点击数
clickRate: '30.00', // 点击率
byType: { // 按类型统计
announcement: 100,
stock_alert: 150,
event_alert: 200,
analysis_report: 50
},
byPriority: { // 按优先级统计
urgent: 50,
important: 200,
normal: 250
}
}
*/
导出历史记录
// 导出为 JSON 字符串
const json = notificationHistoryService.exportToJSON({
type: 'event_alert' // 可选:只导出特定类型
});
// 导出为 CSV 字符串
const csv = notificationHistoryService.exportToCSV();
// 直接下载 JSON 文件
notificationHistoryService.downloadJSON();
// 直接下载 CSV 文件
notificationHistoryService.downloadCSV();
在控制台使用
打开浏览器控制台,执行:
// 引入服务
import { notificationHistoryService } from './services/notificationHistoryService.js';
// 查看所有历史
console.table(notificationHistoryService.getHistory().records);
// 搜索
const results = notificationHistoryService.searchHistory('央行');
console.table(results);
// 查看统计
console.table(notificationHistoryService.getStats());
// 导出并下载
notificationHistoryService.downloadJSON();
数据结构
每条历史记录包含:
{
id: 'notif_123', // 通知 ID
notification: { // 完整通知对象
type: 'event_alert',
priority: 'urgent',
title: '...',
content: '...',
...
},
receivedAt: 1737459600000, // 接收时间戳
readAt: 1737459650000, // 已读时间戳(null 表示未读)
clickedAt: null, // 已点击时间戳(null 表示未点击)
}
存储限制
- 最大数量: 500 条(超过后自动删除最旧的)
- 存储位置: localStorage
- 容量估算: 约 2-5MB(取决于通知内容长度)
🔧 技术细节
文件结构
src/
├── services/
│ ├── browserNotificationService.js [已存在] 浏览器通知服务
│ ├── notificationMetricsService.js [新建] 性能监控服务
│ └── notificationHistoryService.js [新建] 历史记录服务
├── contexts/
│ └── NotificationContext.js [修改] 集成所有功能
└── components/
└── NotificationContainer/
└── index.js [修改] 添加点击追踪
修改清单
| 文件 | 修改内容 | 状态 |
|---|---|---|
NotificationContext.js |
添加智能权限请求、监控埋点、历史保存 | ✅ 已完成 |
NotificationContainer/index.js |
添加点击追踪 | ✅ 已完成 |
notificationMetricsService.js |
性能监控服务 | ✅ 已创建 |
notificationHistoryService.js |
历史记录服务 | ✅ 已创建 |
数据流
用户收到通知
↓
NotificationContext.addWebNotification()
├─ notificationMetricsService.trackReceived() [监控埋点]
├─ notificationHistoryService.saveNotification() [历史保存]
├─ 首次重要通知 → requestBrowserPermission() [智能权限]
└─ 显示网页通知或桌面通知
用户点击通知
↓
NotificationContainer.handleClick()
├─ notificationMetricsService.trackClicked() [监控埋点]
├─ notificationHistoryService.markAsClicked() [历史标记]
└─ 跳转到目标页面
用户关闭通知
↓
NotificationContext.removeNotification()
└─ notificationMetricsService.trackDismissed() [监控埋点]
🧪 测试步骤
1. 测试智能桌面通知
# 1. 清除已保存的权限状态
localStorage.removeItem('browser_notification_requested');
# 2. 刷新页面
# 3. 等待或触发一个重要/紧急通知
# 4. 观察浏览器弹出权限请求
# 5. 授权后验证桌面通知功能
2. 测试性能监控
// 在控制台执行
import { notificationMetricsService } from './services/notificationMetricsService.js';
// 查看实时统计
console.table(notificationMetricsService.getSummary());
// 模拟推送几条通知,再次查看
console.table(notificationMetricsService.getAllMetrics());
// 导出数据
console.log(notificationMetricsService.exportToJSON());
3. 测试历史记录
// 在控制台执行
import { notificationHistoryService } from './services/notificationHistoryService.js';
// 查看历史
console.table(notificationHistoryService.getHistory().records);
// 搜索
console.table(notificationHistoryService.searchHistory('降准'));
// 查看统计
console.table(notificationHistoryService.getStats());
// 导出
notificationHistoryService.downloadJSON();
📈 数据导出示例
导出性能监控数据
import { notificationMetricsService } from 'services/notificationMetricsService';
// 导出 JSON
const json = notificationMetricsService.exportToJSON();
// 复制到剪贴板或保存
// 导出 CSV
const csv = notificationMetricsService.exportToCSV();
// 可以在 Excel 中打开
导出历史记录
import { notificationHistoryService } from 'services/notificationHistoryService';
// 导出最近 7 天的事件动向通知
const json = notificationHistoryService.exportToJSON({
type: 'event_alert',
startDate: Date.now() - 7 * 24 * 60 * 60 * 1000
});
// 直接下载为文件
notificationHistoryService.downloadJSON({
type: 'event_alert'
});
⚠️ 注意事项
1. localStorage 容量限制
- 大多数浏览器限制为 5-10MB
- 建议定期清理历史记录和监控数据
- 使用导出功能备份数据
2. 浏览器兼容性
- 桌面通知: 需要 HTTPS 或 localhost
- localStorage: 所有现代浏览器支持
- 权限请求: 需要用户交互(不能自动授权)
3. 隐私和数据安全
- 所有数据存储在本地(localStorage)
- 不会上传到服务器
- 用户可以随时清空数据
4. 性能影响
- 监控埋点非常轻量,几乎无性能影响
- 历史记录保存异步进行,不阻塞 UI
- 数据查询在客户端完成,不增加服务器负担
🎉 总结
已实现的功能
✅ 智能桌面通知
- 首次重要通知时自动请求权限
- 智能分发策略(前台/后台)
- localStorage 持久化权限状态
✅ 性能监控
- 到达率、点击率、响应时间追踪
- 按类型、优先级、时段统计
- 数据导出(JSON/CSV)
✅ 历史记录
- 持久化存储(最多 500 条)
- 筛选、搜索、分页
- 已读/已点击标记
- 数据导出(JSON/CSV)
未实现的功能(备份,待上线)
⏸️ 历史记录页面 UI(代码已备份,随时可上线) ⏸️ 监控仪表板 UI(可选,暂未实现)
下一步建议
- 用户设置页面: 允许用户自定义通知偏好
- 声音提示: 为紧急通知添加音效
- 数据同步: 将历史和监控数据同步到服务器
- 高级筛选: 添加更多筛选维度(如关键词、股票代码等)
文档版本: v1.0 最后更新: 2025-01-21 维护者: Claude Code