feat: 添加消息推送能力
This commit is contained in:
@@ -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 (
|
||||
<Box
|
||||
position="fixed"
|
||||
top={4}
|
||||
top="316px"
|
||||
right={4}
|
||||
zIndex={9998}
|
||||
bg="white"
|
||||
@@ -114,7 +326,7 @@ const NotificationTestTool = () => {
|
||||
>
|
||||
<MdNotifications size={20} />
|
||||
<Text fontSize="sm" fontWeight="bold">
|
||||
通知测试工具
|
||||
金融资讯测试工具
|
||||
</Text>
|
||||
<Badge colorScheme={isConnected ? 'green' : 'red'} ml="auto">
|
||||
{isConnected ? 'Connected' : 'Disconnected'}
|
||||
@@ -122,6 +334,9 @@ const NotificationTestTool = () => {
|
||||
<Badge colorScheme="purple">
|
||||
{SOCKET_TYPE}
|
||||
</Badge>
|
||||
<Badge colorScheme={getPermissionColor()}>
|
||||
浏览器: {getPermissionLabel()}
|
||||
</Badge>
|
||||
<IconButton
|
||||
icon={isOpen ? <MdClose /> : <MdNotifications />}
|
||||
size="xs"
|
||||
@@ -133,60 +348,151 @@ const NotificationTestTool = () => {
|
||||
|
||||
{/* 工具面板 */}
|
||||
<Collapse in={isOpen} animateOpacity>
|
||||
<VStack p={4} spacing={3} align="stretch" minW="250px">
|
||||
<Text fontSize="xs" color="gray.600">
|
||||
点击按钮测试不同类型的通知
|
||||
<VStack p={4} spacing={3} align="stretch" minW="280px">
|
||||
<Text fontSize="xs" color="gray.600" fontWeight="bold">
|
||||
通知类型测试
|
||||
</Text>
|
||||
|
||||
{/* 测试按钮 */}
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="green"
|
||||
onClick={() => handleTestNotification(0)}
|
||||
>
|
||||
成功通知
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="red"
|
||||
onClick={() => handleTestNotification(1)}
|
||||
>
|
||||
错误通知
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="orange"
|
||||
onClick={() => handleTestNotification(2)}
|
||||
>
|
||||
警告通知
|
||||
</Button>
|
||||
|
||||
{/* 公告通知 */}
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="blue"
|
||||
onClick={() => handleTestNotification(3)}
|
||||
leftIcon={<MdCampaign />}
|
||||
onClick={testAnnouncement}
|
||||
>
|
||||
信息通知
|
||||
公告通知
|
||||
</Button>
|
||||
|
||||
{/* 股票动向 */}
|
||||
<HStack spacing={2}>
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="red"
|
||||
leftIcon={<MdTrendingUp />}
|
||||
onClick={testStockAlertUp}
|
||||
flex={1}
|
||||
>
|
||||
股票上涨
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="green"
|
||||
leftIcon={<MdTrendingUp style={{ transform: 'rotate(180deg)' }} />}
|
||||
onClick={testStockAlertDown}
|
||||
flex={1}
|
||||
>
|
||||
股票下跌
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
{/* 事件动向 */}
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="purple"
|
||||
onClick={handleMultipleNotifications}
|
||||
colorScheme="orange"
|
||||
leftIcon={<MdArticle />}
|
||||
onClick={testEventAlert}
|
||||
>
|
||||
层叠通知(4条)
|
||||
事件动向
|
||||
</Button>
|
||||
|
||||
{/* 分析报告 */}
|
||||
<HStack spacing={2}>
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="purple"
|
||||
leftIcon={<MdAssessment />}
|
||||
onClick={testAnalysisReport}
|
||||
flex={1}
|
||||
>
|
||||
分析报告
|
||||
</Button>
|
||||
<Badge colorScheme="purple" alignSelf="center">AI</Badge>
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="purple"
|
||||
variant="outline"
|
||||
onClick={testAIReport}
|
||||
flex={1}
|
||||
>
|
||||
AI报告
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
{/* 预测通知 */}
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="gray"
|
||||
leftIcon={<MdArticle />}
|
||||
onClick={testPrediction}
|
||||
>
|
||||
预测通知(不可跳转)
|
||||
</Button>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Text fontSize="xs" color="gray.600" fontWeight="bold">
|
||||
组合测试
|
||||
</Text>
|
||||
|
||||
{/* 层叠测试 */}
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="teal"
|
||||
onClick={testAllTypes}
|
||||
>
|
||||
层叠测试(4种类型)
|
||||
</Button>
|
||||
|
||||
{/* 优先级测试 */}
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="pink"
|
||||
onClick={handleMaxLimitTest}
|
||||
onClick={testPriority}
|
||||
>
|
||||
测试最大限制(6条→5条)
|
||||
优先级测试(3个级别)
|
||||
</Button>
|
||||
|
||||
{/* 预测→详情流程测试 */}
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="cyan"
|
||||
onClick={testPredictionFlow}
|
||||
>
|
||||
预测→详情流程(5秒延迟)
|
||||
</Button>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Text fontSize="xs" color="gray.600" fontWeight="bold">
|
||||
浏览器通知
|
||||
</Text>
|
||||
|
||||
{/* 请求权限按钮 */}
|
||||
{browserPermission !== 'granted' && (
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme={browserPermission === 'denied' ? 'red' : 'blue'}
|
||||
onClick={handleRequestPermission}
|
||||
isDisabled={browserPermission === 'denied'}
|
||||
>
|
||||
{browserPermission === 'denied' ? '权限已拒绝' : '请求浏览器权限'}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* 浏览器通知状态说明 */}
|
||||
{browserPermission === 'granted' && (
|
||||
<Text fontSize="xs" color="green.500">
|
||||
✅ 浏览器通知已启用
|
||||
</Text>
|
||||
)}
|
||||
{browserPermission === 'denied' && (
|
||||
<Text fontSize="xs" color="red.500">
|
||||
❌ 请在浏览器设置中允许通知
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<Divider />
|
||||
|
||||
{/* 功能按钮 */}
|
||||
<HStack spacing={2}>
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user