pref: 删除NotificationTestTool 组件, notificationDebugger.js 调试工具删除完成
This commit is contained in:
@@ -9,7 +9,6 @@ import { logger } from '../utils/logger';
|
|||||||
// Global Components
|
// Global Components
|
||||||
import AuthModalManager from './Auth/AuthModalManager';
|
import AuthModalManager from './Auth/AuthModalManager';
|
||||||
import NotificationContainer from './NotificationContainer';
|
import NotificationContainer from './NotificationContainer';
|
||||||
import NotificationTestTool from './NotificationTestTool';
|
|
||||||
import ConnectionStatusBar from './ConnectionStatusBar';
|
import ConnectionStatusBar from './ConnectionStatusBar';
|
||||||
import ScrollToTop from './ScrollToTop';
|
import ScrollToTop from './ScrollToTop';
|
||||||
|
|
||||||
@@ -71,7 +70,6 @@ function ConnectionStatusBarWrapper() {
|
|||||||
* - ScrollToTop: 路由切换时自动滚动到顶部
|
* - ScrollToTop: 路由切换时自动滚动到顶部
|
||||||
* - AuthModalManager: 认证弹窗管理器
|
* - AuthModalManager: 认证弹窗管理器
|
||||||
* - NotificationContainer: 通知容器
|
* - NotificationContainer: 通知容器
|
||||||
* - NotificationTestTool: 通知测试工具 (仅开发环境)
|
|
||||||
* - BytedeskWidget: Bytedesk在线客服 (条件性显示,在/和/home页隐藏)
|
* - BytedeskWidget: Bytedesk在线客服 (条件性显示,在/和/home页隐藏)
|
||||||
*/
|
*/
|
||||||
export function GlobalComponents() {
|
export function GlobalComponents() {
|
||||||
@@ -92,9 +90,6 @@ export function GlobalComponents() {
|
|||||||
{/* 通知容器 */}
|
{/* 通知容器 */}
|
||||||
<NotificationContainer />
|
<NotificationContainer />
|
||||||
|
|
||||||
{/* 通知测试工具 (仅开发环境) */}
|
|
||||||
<NotificationTestTool />
|
|
||||||
|
|
||||||
{/* Bytedesk在线客服 - 根据路径条件性显示 */}
|
{/* Bytedesk在线客服 - 根据路径条件性显示 */}
|
||||||
{showBytedesk && (
|
{showBytedesk && (
|
||||||
<BytedeskWidget
|
<BytedeskWidget
|
||||||
|
|||||||
@@ -1,663 +0,0 @@
|
|||||||
// src/components/NotificationTestTool/index.js
|
|
||||||
/**
|
|
||||||
* 金融资讯通知测试工具 - 仅在开发环境显示
|
|
||||||
* 用于手动测试4种通知类型
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
VStack,
|
|
||||||
HStack,
|
|
||||||
Text,
|
|
||||||
IconButton,
|
|
||||||
Collapse,
|
|
||||||
useDisclosure,
|
|
||||||
Badge,
|
|
||||||
Divider,
|
|
||||||
Alert,
|
|
||||||
AlertIcon,
|
|
||||||
AlertTitle,
|
|
||||||
AlertDescription,
|
|
||||||
Code,
|
|
||||||
UnorderedList,
|
|
||||||
ListItem,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import { MdNotifications, MdClose, MdVolumeOff, MdVolumeUp, MdCampaign, MdTrendingUp, MdArticle, MdAssessment, MdWarning } from 'react-icons/md';
|
|
||||||
import { useNotification } from '../../contexts/NotificationContext';
|
|
||||||
import { NOTIFICATION_TYPES, PRIORITY_LEVELS } from '../../constants/notificationTypes';
|
|
||||||
|
|
||||||
const NotificationTestTool = () => {
|
|
||||||
// 只在开发环境显示 - 必须在所有 Hooks 调用之前检查
|
|
||||||
if (process.env.NODE_ENV !== 'development') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { isOpen, onToggle } = useDisclosure();
|
|
||||||
const { addNotification, soundEnabled, toggleSound, isConnected, clearAllNotifications, notifications, browserPermission, requestBrowserPermission } = useNotification();
|
|
||||||
const [testCount, setTestCount] = useState(0);
|
|
||||||
|
|
||||||
// 测试状态
|
|
||||||
const [isTestingNotification, setIsTestingNotification] = useState(false);
|
|
||||||
const [testCountdown, setTestCountdown] = useState(0);
|
|
||||||
const [notificationShown, setNotificationShown] = useState(null); // null | true | false
|
|
||||||
|
|
||||||
// 系统环境检测
|
|
||||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
||||||
const [isMacOS, setIsMacOS] = useState(false);
|
|
||||||
|
|
||||||
// 故障排查面板
|
|
||||||
const { isOpen: isTroubleshootOpen, onToggle: onTroubleshootToggle } = useDisclosure();
|
|
||||||
|
|
||||||
// 检测系统环境
|
|
||||||
useEffect(() => {
|
|
||||||
// 检测是否为 macOS
|
|
||||||
const platform = navigator.platform.toLowerCase();
|
|
||||||
setIsMacOS(platform.includes('mac'));
|
|
||||||
|
|
||||||
// 检测全屏状态
|
|
||||||
const checkFullscreen = () => {
|
|
||||||
setIsFullscreen(!!document.fullscreenElement);
|
|
||||||
};
|
|
||||||
document.addEventListener('fullscreenchange', checkFullscreen);
|
|
||||||
checkFullscreen();
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener('fullscreenchange', checkFullscreen);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// 倒计时逻辑
|
|
||||||
useEffect(() => {
|
|
||||||
if (testCountdown > 0) {
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
setTestCountdown(testCountdown - 1);
|
|
||||||
}, 1000);
|
|
||||||
return () => clearTimeout(timer);
|
|
||||||
} else if (testCountdown === 0 && isTestingNotification) {
|
|
||||||
// 倒计时结束,询问用户
|
|
||||||
setIsTestingNotification(false);
|
|
||||||
|
|
||||||
// 延迟一下再询问,确保用户有时间看到通知
|
|
||||||
setTimeout(() => {
|
|
||||||
const sawNotification = window.confirm('您是否看到了浏览器桌面通知?\n\n点击"确定"表示看到了\n点击"取消"表示没看到');
|
|
||||||
setNotificationShown(sawNotification);
|
|
||||||
|
|
||||||
if (!sawNotification) {
|
|
||||||
// 没看到通知,展开故障排查面板
|
|
||||||
if (!isTroubleshootOpen) {
|
|
||||||
onTroubleshootToggle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
}, [testCountdown, isTestingNotification, isTroubleshootOpen, onTroubleshootToggle]);
|
|
||||||
|
|
||||||
// 浏览器权限状态标签
|
|
||||||
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();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 公告通知测试数据
|
|
||||||
const testAnnouncement = () => {
|
|
||||||
addNotification({
|
|
||||||
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 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);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// 预测通知测试数据(不可跳转)
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
position="fixed"
|
|
||||||
top="116px"
|
|
||||||
right={4}
|
|
||||||
zIndex={9998}
|
|
||||||
bg="white"
|
|
||||||
borderRadius="md"
|
|
||||||
boxShadow="lg"
|
|
||||||
overflow="hidden"
|
|
||||||
>
|
|
||||||
{/* 折叠按钮 */}
|
|
||||||
<HStack
|
|
||||||
p={2}
|
|
||||||
bg="blue.500"
|
|
||||||
color="white"
|
|
||||||
cursor="pointer"
|
|
||||||
onClick={onToggle}
|
|
||||||
spacing={2}
|
|
||||||
>
|
|
||||||
<MdNotifications size={20} />
|
|
||||||
<Text fontSize="sm" fontWeight="bold">
|
|
||||||
金融资讯测试工具
|
|
||||||
</Text>
|
|
||||||
<Badge colorScheme={isConnected ? 'green' : 'red'} ml="auto">
|
|
||||||
{isConnected ? 'Connected' : 'Disconnected'}
|
|
||||||
</Badge>
|
|
||||||
<Badge colorScheme="purple">
|
|
||||||
REAL
|
|
||||||
</Badge>
|
|
||||||
<Badge colorScheme={getPermissionColor()}>
|
|
||||||
浏览器: {getPermissionLabel()}
|
|
||||||
</Badge>
|
|
||||||
<IconButton
|
|
||||||
icon={isOpen ? <MdClose /> : <MdNotifications />}
|
|
||||||
size="xs"
|
|
||||||
variant="ghost"
|
|
||||||
colorScheme="whiteAlpha"
|
|
||||||
aria-label={isOpen ? '关闭' : '打开'}
|
|
||||||
/>
|
|
||||||
</HStack>
|
|
||||||
|
|
||||||
{/* 工具面板 */}
|
|
||||||
<Collapse in={isOpen} animateOpacity>
|
|
||||||
<VStack p={4} spacing={3} align="stretch" minW="280px">
|
|
||||||
<Text fontSize="xs" color="gray.600" fontWeight="bold">
|
|
||||||
通知类型测试
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
{/* 公告通知 */}
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
colorScheme="blue"
|
|
||||||
leftIcon={<MdCampaign />}
|
|
||||||
onClick={testAnnouncement}
|
|
||||||
>
|
|
||||||
公告通知
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{/* 事件动向 */}
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
colorScheme="orange"
|
|
||||||
leftIcon={<MdArticle />}
|
|
||||||
onClick={testEventAlert}
|
|
||||||
>
|
|
||||||
事件动向
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{/* 分析报告 */}
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
colorScheme="purple"
|
|
||||||
leftIcon={<MdAssessment />}
|
|
||||||
onClick={testAnalysisReport}
|
|
||||||
>
|
|
||||||
分析报告
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{/* 预测通知 */}
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
colorScheme="gray"
|
|
||||||
leftIcon={<MdArticle />}
|
|
||||||
onClick={testPrediction}
|
|
||||||
>
|
|
||||||
预测通知(不可跳转)
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
<Text fontSize="xs" color="gray.600" fontWeight="bold">
|
|
||||||
组合测试
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
{/* 预测→详情流程测试 */}
|
|
||||||
<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' && (
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
colorScheme="green"
|
|
||||||
leftIcon={<MdNotifications />}
|
|
||||||
onClick={() => {
|
|
||||||
console.log('测试浏览器通知按钮被点击');
|
|
||||||
console.log('Notification support:', 'Notification' in window);
|
|
||||||
console.log('Notification permission:', Notification?.permission);
|
|
||||||
console.log('Platform:', navigator.platform);
|
|
||||||
console.log('Fullscreen:', !!document.fullscreenElement);
|
|
||||||
|
|
||||||
// 直接使用原生 Notification API 测试
|
|
||||||
if (!('Notification' in window)) {
|
|
||||||
alert('您的浏览器不支持桌面通知');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Notification.permission !== 'granted') {
|
|
||||||
alert('浏览器通知权限未授予\n当前权限状态:' + Notification.permission);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置状态
|
|
||||||
setNotificationShown(null);
|
|
||||||
setIsTestingNotification(true);
|
|
||||||
setTestCountdown(8); // 8秒倒计时
|
|
||||||
|
|
||||||
try {
|
|
||||||
console.log('正在创建浏览器通知...');
|
|
||||||
const notification = new Notification('【测试】浏览器通知测试', {
|
|
||||||
body: '如果您看到这条系统级通知,说明浏览器通知功能正常工作',
|
|
||||||
icon: '/logo192.png',
|
|
||||||
badge: '/badge.png',
|
|
||||||
tag: 'test_notification_' + Date.now(),
|
|
||||||
requireInteraction: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('浏览器通知创建成功:', notification);
|
|
||||||
|
|
||||||
// 监听通知显示(成功显示)
|
|
||||||
notification.onshow = () => {
|
|
||||||
console.log('✅ 浏览器通知已显示(onshow 事件触发)');
|
|
||||||
setNotificationShown(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听通知错误
|
|
||||||
notification.onerror = (error) => {
|
|
||||||
console.error('❌ 浏览器通知错误:', error);
|
|
||||||
setNotificationShown(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听通知关闭
|
|
||||||
notification.onclose = () => {
|
|
||||||
console.log('浏览器通知已关闭');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 8秒后自动关闭
|
|
||||||
setTimeout(() => {
|
|
||||||
notification.close();
|
|
||||||
console.log('浏览器通知已自动关闭');
|
|
||||||
}, 8000);
|
|
||||||
|
|
||||||
// 点击通知时聚焦窗口
|
|
||||||
notification.onclick = () => {
|
|
||||||
console.log('浏览器通知被点击');
|
|
||||||
window.focus();
|
|
||||||
notification.close();
|
|
||||||
setNotificationShown(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
setTestCount(prev => prev + 1);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('创建浏览器通知失败:', error);
|
|
||||||
alert('创建浏览器通知失败:' + error.message);
|
|
||||||
setIsTestingNotification(false);
|
|
||||||
setNotificationShown(false);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
isLoading={isTestingNotification}
|
|
||||||
loadingText={`等待通知... ${testCountdown}s`}
|
|
||||||
>
|
|
||||||
{isTestingNotification ? `等待通知... ${testCountdown}s` : '测试浏览器通知(直接)'}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 浏览器通知状态说明 */}
|
|
||||||
{browserPermission === 'granted' && (
|
|
||||||
<Text fontSize="xs" color="green.500">
|
|
||||||
✅ 浏览器通知已启用
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
{browserPermission === 'denied' && (
|
|
||||||
<Text fontSize="xs" color="red.500">
|
|
||||||
❌ 请在浏览器设置中允许通知
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 实时权限状态 */}
|
|
||||||
<HStack spacing={2} justify="center">
|
|
||||||
<Text fontSize="xs" color="gray.500">
|
|
||||||
实际权限:
|
|
||||||
</Text>
|
|
||||||
<Badge
|
|
||||||
colorScheme={
|
|
||||||
('Notification' in window && Notification.permission === 'granted') ? 'green' :
|
|
||||||
('Notification' in window && Notification.permission === 'denied') ? 'red' : 'gray'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{('Notification' in window) ? Notification.permission : '不支持'}
|
|
||||||
</Badge>
|
|
||||||
</HStack>
|
|
||||||
|
|
||||||
{/* 环境警告 */}
|
|
||||||
{isFullscreen && (
|
|
||||||
<Alert status="warning" size="sm" borderRadius="md">
|
|
||||||
<AlertIcon />
|
|
||||||
<Box fontSize="xs">
|
|
||||||
<Text fontWeight="bold">全屏模式</Text>
|
|
||||||
<Text>某些浏览器在全屏模式下不显示通知</Text>
|
|
||||||
</Box>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{isMacOS && notificationShown === false && (
|
|
||||||
<Alert status="error" size="sm" borderRadius="md">
|
|
||||||
<AlertIcon />
|
|
||||||
<Box fontSize="xs">
|
|
||||||
<Text fontWeight="bold">未检测到通知显示</Text>
|
|
||||||
<Text>可能是专注模式阻止了通知</Text>
|
|
||||||
</Box>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
{/* 故障排查面板 */}
|
|
||||||
<VStack spacing={2} align="stretch">
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
colorScheme="orange"
|
|
||||||
leftIcon={<MdWarning />}
|
|
||||||
onClick={onTroubleshootToggle}
|
|
||||||
>
|
|
||||||
{isTroubleshootOpen ? '收起' : '故障排查指南'}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Collapse in={isTroubleshootOpen} animateOpacity>
|
|
||||||
<VStack spacing={3} align="stretch" p={3} bg="orange.50" borderRadius="md">
|
|
||||||
<Text fontSize="xs" fontWeight="bold" color="orange.800">
|
|
||||||
如果看不到浏览器通知,请检查:
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
{/* macOS 专注模式 */}
|
|
||||||
{isMacOS && (
|
|
||||||
<Alert status="warning" size="sm">
|
|
||||||
<AlertIcon />
|
|
||||||
<Box fontSize="xs">
|
|
||||||
<AlertTitle fontSize="xs">macOS 专注模式</AlertTitle>
|
|
||||||
<AlertDescription>
|
|
||||||
<UnorderedList spacing={1} mt={1}>
|
|
||||||
<ListItem>点击右上角控制中心</ListItem>
|
|
||||||
<ListItem>关闭「专注模式」或「勿扰模式」</ListItem>
|
|
||||||
<ListItem>或者:系统设置 → 专注模式 → 关闭</ListItem>
|
|
||||||
</UnorderedList>
|
|
||||||
</AlertDescription>
|
|
||||||
</Box>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* macOS 系统通知设置 */}
|
|
||||||
{isMacOS && (
|
|
||||||
<Alert status="info" size="sm">
|
|
||||||
<AlertIcon />
|
|
||||||
<Box fontSize="xs">
|
|
||||||
<AlertTitle fontSize="xs">macOS 系统通知设置</AlertTitle>
|
|
||||||
<AlertDescription>
|
|
||||||
<UnorderedList spacing={1} mt={1}>
|
|
||||||
<ListItem>系统设置 → 通知</ListItem>
|
|
||||||
<ListItem>找到 <Code fontSize="xs">Google Chrome</Code> 或 <Code fontSize="xs">Microsoft Edge</Code></ListItem>
|
|
||||||
<ListItem>确保「允许通知」已开启</ListItem>
|
|
||||||
<ListItem>通知样式设置为「横幅」或「提醒」</ListItem>
|
|
||||||
</UnorderedList>
|
|
||||||
</AlertDescription>
|
|
||||||
</Box>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Chrome 浏览器设置 */}
|
|
||||||
<Alert status="info" size="sm">
|
|
||||||
<AlertIcon />
|
|
||||||
<Box fontSize="xs">
|
|
||||||
<AlertTitle fontSize="xs">Chrome 浏览器设置</AlertTitle>
|
|
||||||
<AlertDescription>
|
|
||||||
<UnorderedList spacing={1} mt={1}>
|
|
||||||
<ListItem>地址栏输入: <Code fontSize="xs">chrome://settings/content/notifications</Code></ListItem>
|
|
||||||
<ListItem>确保「网站可以请求发送通知」已开启</ListItem>
|
|
||||||
<ListItem>检查本站点是否在「允许」列表中</ListItem>
|
|
||||||
</UnorderedList>
|
|
||||||
</AlertDescription>
|
|
||||||
</Box>
|
|
||||||
</Alert>
|
|
||||||
|
|
||||||
{/* 全屏模式提示 */}
|
|
||||||
{isFullscreen && (
|
|
||||||
<Alert status="warning" size="sm">
|
|
||||||
<AlertIcon />
|
|
||||||
<Box fontSize="xs">
|
|
||||||
<AlertTitle fontSize="xs">退出全屏模式</AlertTitle>
|
|
||||||
<AlertDescription>
|
|
||||||
按 <Code fontSize="xs">ESC</Code> 键退出全屏,然后重新测试
|
|
||||||
</AlertDescription>
|
|
||||||
</Box>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 测试结果反馈 */}
|
|
||||||
{notificationShown === true && (
|
|
||||||
<Alert status="success" size="sm">
|
|
||||||
<AlertIcon />
|
|
||||||
<Text fontSize="xs">✅ 通知功能正常!</Text>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
</VStack>
|
|
||||||
</Collapse>
|
|
||||||
</VStack>
|
|
||||||
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
{/* 功能按钮 */}
|
|
||||||
<HStack spacing={2}>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
colorScheme="gray"
|
|
||||||
onClick={clearAllNotifications}
|
|
||||||
flex={1}
|
|
||||||
>
|
|
||||||
清空全部
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<IconButton
|
|
||||||
size="sm"
|
|
||||||
icon={soundEnabled ? <MdVolumeUp /> : <MdVolumeOff />}
|
|
||||||
colorScheme={soundEnabled ? 'blue' : 'gray'}
|
|
||||||
onClick={toggleSound}
|
|
||||||
aria-label="切换音效"
|
|
||||||
/>
|
|
||||||
</HStack>
|
|
||||||
|
|
||||||
{/* 统计信息 */}
|
|
||||||
<VStack spacing={1}>
|
|
||||||
<HStack justify="space-between" w="full">
|
|
||||||
<Text fontSize="xs" color="gray.500">
|
|
||||||
当前队列:
|
|
||||||
</Text>
|
|
||||||
<Badge colorScheme={notifications.length >= 5 ? 'red' : 'blue'}>
|
|
||||||
{notifications.length} / 5
|
|
||||||
</Badge>
|
|
||||||
</HStack>
|
|
||||||
<Text fontSize="xs" color="gray.400" textAlign="center">
|
|
||||||
已测试: {testCount} 条通知
|
|
||||||
</Text>
|
|
||||||
</VStack>
|
|
||||||
</VStack>
|
|
||||||
</Collapse>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NotificationTestTool;
|
|
||||||
@@ -10,20 +10,17 @@
|
|||||||
* 全局 API:
|
* 全局 API:
|
||||||
* - window.__DEBUG__ - 调试 API 主对象
|
* - window.__DEBUG__ - 调试 API 主对象
|
||||||
* - window.__DEBUG__.api - API 调试工具
|
* - window.__DEBUG__.api - API 调试工具
|
||||||
* - window.__DEBUG__.notification - 通知调试工具
|
|
||||||
* - window.__DEBUG__.socket - Socket 调试工具
|
* - window.__DEBUG__.socket - Socket 调试工具
|
||||||
* - window.__DEBUG__.help() - 显示帮助信息
|
* - window.__DEBUG__.help() - 显示帮助信息
|
||||||
* - window.__DEBUG__.exportAll() - 导出所有日志
|
* - window.__DEBUG__.exportAll() - 导出所有日志
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { apiDebugger } from './apiDebugger';
|
import { apiDebugger } from './apiDebugger';
|
||||||
import { notificationDebugger } from './notificationDebugger';
|
|
||||||
import { socketDebugger } from './socketDebugger';
|
import { socketDebugger } from './socketDebugger';
|
||||||
|
|
||||||
class DebugToolkit {
|
class DebugToolkit {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.api = apiDebugger;
|
this.api = apiDebugger;
|
||||||
this.notification = notificationDebugger;
|
|
||||||
this.socket = socketDebugger;
|
this.socket = socketDebugger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +44,6 @@ class DebugToolkit {
|
|||||||
|
|
||||||
// 初始化各个调试工具
|
// 初始化各个调试工具
|
||||||
this.api.init();
|
this.api.init();
|
||||||
this.notification.init();
|
|
||||||
this.socket.init();
|
this.socket.init();
|
||||||
|
|
||||||
// 暴露到全局
|
// 暴露到全局
|
||||||
@@ -69,22 +65,13 @@ class DebugToolkit {
|
|||||||
console.log(' __DEBUG__.api.exportLogs() - 导出 API 日志');
|
console.log(' __DEBUG__.api.exportLogs() - 导出 API 日志');
|
||||||
console.log(' __DEBUG__.api.testRequest(method, endpoint, data) - 测试 API 请求');
|
console.log(' __DEBUG__.api.testRequest(method, endpoint, data) - 测试 API 请求');
|
||||||
console.log('');
|
console.log('');
|
||||||
console.log('%c2️⃣ 通知调试:', 'color: #9C27B0; font-weight: bold;');
|
console.log('%c2️⃣ Socket 调试:', 'color: #00BCD4; font-weight: bold;');
|
||||||
console.log(' __DEBUG__.notification.getLogs() - 获取所有通知日志');
|
|
||||||
console.log(' __DEBUG__.notification.forceNotification() - 发送测试浏览器通知');
|
|
||||||
console.log(' __DEBUG__.notification.testWebNotification(type, priority) - 测试网页通知 🆕');
|
|
||||||
console.log(' __DEBUG__.notification.testAllNotificationTypes() - 测试所有类型 🆕');
|
|
||||||
console.log(' __DEBUG__.notification.testAllNotificationPriorities() - 测试所有优先级 🆕');
|
|
||||||
console.log(' __DEBUG__.notification.checkPermission() - 检查通知权限');
|
|
||||||
console.log(' __DEBUG__.notification.exportLogs() - 导出通知日志');
|
|
||||||
console.log('');
|
|
||||||
console.log('%c3️⃣ Socket 调试:', 'color: #00BCD4; font-weight: bold;');
|
|
||||||
console.log(' __DEBUG__.socket.getLogs() - 获取所有 Socket 日志');
|
console.log(' __DEBUG__.socket.getLogs() - 获取所有 Socket 日志');
|
||||||
console.log(' __DEBUG__.socket.getStatus() - 获取连接状态');
|
console.log(' __DEBUG__.socket.getStatus() - 获取连接状态');
|
||||||
console.log(' __DEBUG__.socket.reconnect() - 手动重连');
|
console.log(' __DEBUG__.socket.reconnect() - 手动重连');
|
||||||
console.log(' __DEBUG__.socket.exportLogs() - 导出 Socket 日志');
|
console.log(' __DEBUG__.socket.exportLogs() - 导出 Socket 日志');
|
||||||
console.log('');
|
console.log('');
|
||||||
console.log('%c4️⃣ 通用命令:', 'color: #4CAF50; font-weight: bold;');
|
console.log('%c3️⃣ 通用命令:', 'color: #4CAF50; font-weight: bold;');
|
||||||
console.log(' __DEBUG__.help() - 显示帮助信息');
|
console.log(' __DEBUG__.help() - 显示帮助信息');
|
||||||
console.log(' __DEBUG__.exportAll() - 导出所有日志');
|
console.log(' __DEBUG__.exportAll() - 导出所有日志');
|
||||||
console.log(' __DEBUG__.printStats() - 打印所有统计信息');
|
console.log(' __DEBUG__.printStats() - 打印所有统计信息');
|
||||||
@@ -113,7 +100,6 @@ class DebugToolkit {
|
|||||||
const allLogs = {
|
const allLogs = {
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
api: this.api.getLogs(),
|
api: this.api.getLogs(),
|
||||||
notification: this.notification.getLogs(),
|
|
||||||
socket: this.socket.getLogs(),
|
socket: this.socket.getLogs(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -138,15 +124,11 @@ class DebugToolkit {
|
|||||||
console.log('\n%c[API 统计]', 'color: #2196F3; font-weight: bold;');
|
console.log('\n%c[API 统计]', 'color: #2196F3; font-weight: bold;');
|
||||||
const apiStats = this.api.printStats();
|
const apiStats = this.api.printStats();
|
||||||
|
|
||||||
console.log('\n%c[通知统计]', 'color: #9C27B0; font-weight: bold;');
|
|
||||||
const notificationStats = this.notification.printStats();
|
|
||||||
|
|
||||||
console.log('\n%c[Socket 统计]', 'color: #00BCD4; font-weight: bold;');
|
console.log('\n%c[Socket 统计]', 'color: #00BCD4; font-weight: bold;');
|
||||||
const socketStats = this.socket.printStats();
|
const socketStats = this.socket.printStats();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
api: apiStats,
|
api: apiStats,
|
||||||
notification: notificationStats,
|
|
||||||
socket: socketStats,
|
socket: socketStats,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -157,7 +139,6 @@ class DebugToolkit {
|
|||||||
clearAll() {
|
clearAll() {
|
||||||
console.log('[Debug Toolkit] Clearing all logs...');
|
console.log('[Debug Toolkit] Clearing all logs...');
|
||||||
this.api.clearLogs();
|
this.api.clearLogs();
|
||||||
this.notification.clearLogs();
|
|
||||||
this.socket.clearLogs();
|
this.socket.clearLogs();
|
||||||
console.log('[Debug Toolkit] ✅ All logs cleared');
|
console.log('[Debug Toolkit] ✅ All logs cleared');
|
||||||
}
|
}
|
||||||
@@ -169,15 +150,11 @@ class DebugToolkit {
|
|||||||
console.log('\n%c=== 🔍 系统诊断 ===', 'color: #FF9800; font-weight: bold; font-size: 16px;');
|
console.log('\n%c=== 🔍 系统诊断 ===', 'color: #FF9800; font-weight: bold; font-size: 16px;');
|
||||||
|
|
||||||
// 1. Socket 状态
|
// 1. Socket 状态
|
||||||
console.log('\n%c[1/3] Socket 状态', 'color: #00BCD4; font-weight: bold;');
|
console.log('\n%c[1/2] Socket 状态', 'color: #00BCD4; font-weight: bold;');
|
||||||
const socketStatus = this.socket.getStatus();
|
const socketStatus = this.socket.getStatus();
|
||||||
|
|
||||||
// 2. 通知权限
|
// 2. API 错误
|
||||||
console.log('\n%c[2/3] 通知权限', 'color: #9C27B0; font-weight: bold;');
|
console.log('\n%c[2/2] 最近的 API 错误', 'color: #F44336; font-weight: bold;');
|
||||||
const notificationStatus = this.notification.checkPermission();
|
|
||||||
|
|
||||||
// 3. API 错误
|
|
||||||
console.log('\n%c[3/3] 最近的 API 错误', 'color: #F44336; font-weight: bold;');
|
|
||||||
const recentErrors = this.api.getRecentErrors(5);
|
const recentErrors = this.api.getRecentErrors(5);
|
||||||
if (recentErrors.length > 0) {
|
if (recentErrors.length > 0) {
|
||||||
console.table(
|
console.table(
|
||||||
@@ -193,11 +170,10 @@ class DebugToolkit {
|
|||||||
console.log('✅ 没有 API 错误');
|
console.log('✅ 没有 API 错误');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 汇总报告
|
// 3. 汇总报告
|
||||||
const report = {
|
const report = {
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
socket: socketStatus,
|
socket: socketStatus,
|
||||||
notification: notificationStatus,
|
|
||||||
apiErrors: recentErrors.length,
|
apiErrors: recentErrors.length,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,204 +0,0 @@
|
|||||||
// src/debug/notificationDebugger.js
|
|
||||||
/**
|
|
||||||
* 通知系统调试工具
|
|
||||||
* 扩展现有的 window.__NOTIFY_DEBUG__,添加更多生产环境调试能力
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { browserNotificationService } from '@services/browserNotificationService';
|
|
||||||
|
|
||||||
class NotificationDebugger {
|
|
||||||
constructor() {
|
|
||||||
this.eventLog = [];
|
|
||||||
this.maxLogSize = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化调试工具
|
|
||||||
*/
|
|
||||||
init() {
|
|
||||||
console.log('%c[Notification Debugger] Initialized', 'color: #FF9800; font-weight: bold;');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 记录通知事件
|
|
||||||
*/
|
|
||||||
logEvent(eventType, data) {
|
|
||||||
const logEntry = {
|
|
||||||
type: eventType,
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
data,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.eventLog.unshift(logEntry);
|
|
||||||
if (this.eventLog.length > this.maxLogSize) {
|
|
||||||
this.eventLog = this.eventLog.slice(0, this.maxLogSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`%c[Notification Event] ${eventType}`,
|
|
||||||
'color: #9C27B0; font-weight: bold;',
|
|
||||||
data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有事件日志
|
|
||||||
*/
|
|
||||||
getLogs() {
|
|
||||||
return this.eventLog;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清空日志
|
|
||||||
*/
|
|
||||||
clearLogs() {
|
|
||||||
this.eventLog = [];
|
|
||||||
console.log('[Notification Debugger] Logs cleared');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出日志
|
|
||||||
*/
|
|
||||||
exportLogs() {
|
|
||||||
const blob = new Blob([JSON.stringify(this.eventLog, null, 2)], {
|
|
||||||
type: 'application/json',
|
|
||||||
});
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
const a = document.createElement('a');
|
|
||||||
a.href = url;
|
|
||||||
a.download = `notification-logs-${Date.now()}.json`;
|
|
||||||
a.click();
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
console.log('[Notification Debugger] Logs exported');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 强制发送浏览器通知(测试用)
|
|
||||||
*/
|
|
||||||
forceNotification(options = {}) {
|
|
||||||
const defaultOptions = {
|
|
||||||
title: '🧪 测试通知',
|
|
||||||
body: `测试时间: ${new Date().toLocaleString()}`,
|
|
||||||
tag: `test_${Date.now()}`,
|
|
||||||
requireInteraction: false,
|
|
||||||
autoClose: 5000,
|
|
||||||
};
|
|
||||||
|
|
||||||
const finalOptions = { ...defaultOptions, ...options };
|
|
||||||
|
|
||||||
console.log('[Notification Debugger] Sending test notification:', finalOptions);
|
|
||||||
|
|
||||||
const notification = browserNotificationService.sendNotification(finalOptions);
|
|
||||||
|
|
||||||
if (notification) {
|
|
||||||
console.log('[Notification Debugger] ✅ Notification sent successfully');
|
|
||||||
} else {
|
|
||||||
console.error('[Notification Debugger] ❌ Failed to send notification');
|
|
||||||
}
|
|
||||||
|
|
||||||
return notification;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查通知权限状态
|
|
||||||
*/
|
|
||||||
checkPermission() {
|
|
||||||
const permission = browserNotificationService.getPermissionStatus();
|
|
||||||
const isSupported = browserNotificationService.isSupported();
|
|
||||||
|
|
||||||
const status = {
|
|
||||||
supported: isSupported,
|
|
||||||
permission,
|
|
||||||
canSend: isSupported && permission === 'granted',
|
|
||||||
};
|
|
||||||
|
|
||||||
console.table(status);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求通知权限
|
|
||||||
*/
|
|
||||||
async requestPermission() {
|
|
||||||
console.log('[Notification Debugger] Requesting notification permission...');
|
|
||||||
const result = await browserNotificationService.requestPermission();
|
|
||||||
console.log(`[Notification Debugger] Permission result: ${result}`);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印事件统计
|
|
||||||
*/
|
|
||||||
printStats() {
|
|
||||||
const stats = {
|
|
||||||
total: this.eventLog.length,
|
|
||||||
byType: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.eventLog.forEach((log) => {
|
|
||||||
stats.byType[log.type] = (stats.byType[log.type] || 0) + 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('=== Notification Stats ===');
|
|
||||||
console.table(stats.byType);
|
|
||||||
console.log(`Total events: ${stats.total}`);
|
|
||||||
|
|
||||||
return stats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 按类型过滤日志
|
|
||||||
*/
|
|
||||||
getLogsByType(eventType) {
|
|
||||||
return this.eventLog.filter((log) => log.type === eventType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取最近的事件
|
|
||||||
*/
|
|
||||||
getRecentEvents(count = 10) {
|
|
||||||
return this.eventLog.slice(0, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试网页通知(需要 window.__TEST_NOTIFICATION__ 可用)
|
|
||||||
*/
|
|
||||||
testWebNotification(type = 'event_alert', priority = 'normal') {
|
|
||||||
if (typeof window !== 'undefined' && window.__TEST_NOTIFICATION__) {
|
|
||||||
console.log('[Notification Debugger] 调用测试 API');
|
|
||||||
window.__TEST_NOTIFICATION__.testWebNotification(type, priority);
|
|
||||||
} else {
|
|
||||||
console.error('[Notification Debugger] ❌ window.__TEST_NOTIFICATION__ 不可用');
|
|
||||||
console.error('💡 请确保:');
|
|
||||||
console.error(' 1. REACT_APP_ENABLE_DEBUG=true');
|
|
||||||
console.error(' 2. NotificationContext 已加载');
|
|
||||||
console.error(' 3. 页面已刷新');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试所有通知类型
|
|
||||||
*/
|
|
||||||
testAllNotificationTypes() {
|
|
||||||
if (typeof window !== 'undefined' && window.__TEST_NOTIFICATION__) {
|
|
||||||
window.__TEST_NOTIFICATION__.testAllTypes();
|
|
||||||
} else {
|
|
||||||
console.error('[Notification Debugger] ❌ window.__TEST_NOTIFICATION__ 不可用');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试所有优先级
|
|
||||||
*/
|
|
||||||
testAllNotificationPriorities() {
|
|
||||||
if (typeof window !== 'undefined' && window.__TEST_NOTIFICATION__) {
|
|
||||||
window.__TEST_NOTIFICATION__.testAllPriorities();
|
|
||||||
} else {
|
|
||||||
console.error('[Notification Debugger] ❌ window.__TEST_NOTIFICATION__ 不可用');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出单例
|
|
||||||
export const notificationDebugger = new NotificationDebugger();
|
|
||||||
export default notificationDebugger;
|
|
||||||
Reference in New Issue
Block a user