diff --git a/src/contexts/NotificationContext.js b/src/contexts/NotificationContext.js index a6816ebc..518ec9c5 100644 --- a/src/contexts/NotificationContext.js +++ b/src/contexts/NotificationContext.js @@ -589,65 +589,6 @@ export const NotificationProvider = ({ children }) => { return newNotification.id; }, [notifications, toast, sendBrowserNotification, addWebNotification, browserPermission, hasRequestedPermission, requestBrowserPermission]); - /** - * 注册业务事件监听器并订阅 - */ - const registerBusinessListeners = useCallback(() => { - console.log('%c[NotificationContext] Registering business event listeners...', 'color: #673AB7;'); - - // 移除旧监听器(避免重复注册) - socket.off('new_event'); - socket.off('system_notification'); - - // 监听新事件推送 - socket.on('new_event', (data) => { - logger.info('NotificationContext', 'Received new event', data); - - const eventId = data.id || `${data.type}_${data.publishTime}`; - if (processedEventIds.current.has(eventId)) { - logger.debug('NotificationContext', 'Duplicate event ignored at socket level', { eventId }); - return; - } - - processedEventIds.current.add(eventId); - - if (processedEventIds.current.size > MAX_PROCESSED_IDS) { - const idsArray = Array.from(processedEventIds.current); - processedEventIds.current = new Set(idsArray.slice(-MAX_PROCESSED_IDS)); - logger.debug('NotificationContext', 'Cleaned up old processed event IDs', { - kept: MAX_PROCESSED_IDS - }); - } - - const notification = adaptEventToNotification(data); - addNotification(notification); - }); - - socket.on('system_notification', (data) => { - logger.info('NotificationContext', 'Received system notification', data); - addNotification(data); - }); - - console.log('%c[NotificationContext] ✅ Business event listeners registered', 'color: #4CAF50; font-weight: bold;'); - - // 执行订阅(仅生产环境逻辑) - console.log('%c[NotificationContext] 🔔 订阅事件推送...', 'color: #FF9800; font-weight: bold;'); - - if (socket.subscribeToEvents) { - socket.subscribeToEvents({ - eventType: 'all', - importance: 'all', - onSubscribed: (data) => { - console.log('%c[NotificationContext] ✅ 订阅成功!', 'color: #4CAF50; font-weight: bold;'); - console.log('[NotificationContext] 订阅确认:', data); - logger.info('NotificationContext', 'Events subscribed', data); - }, - }); - } else { - console.error('[NotificationContext] ❌ socket.subscribeToEvents 方法不可用'); - } - }, [adaptEventToNotification, addNotification]); - // 连接到 Socket 服务 useEffect(() => { logger.info('NotificationContext', 'Initializing socket connection...'); @@ -662,10 +603,7 @@ export const NotificationProvider = ({ children }) => { setIsConnected(true); setReconnectAttempt(0); logger.info('NotificationContext', 'Socket connected', { wasDisconnected }); - console.log('%c[NotificationContext] ✅ Socket connected', 'color: #4CAF50; font-weight: bold;'); - - // ✅ 调用统一的业务监听器注册函数 - registerBusinessListeners(); + console.log('%c[NotificationContext] ✅ Received connect event, updating state to connected', 'color: #4CAF50; font-weight: bold;'); // 如果之前断开过,显示 RECONNECTED 状态2秒后自动消失 if (wasDisconnected) { @@ -685,6 +623,32 @@ export const NotificationProvider = ({ children }) => { } else { setConnectionStatus(CONNECTION_STATUS.CONNECTED); } + + // 如果使用 mock,可以启动定期推送 + if (SOCKET_TYPE === 'MOCK') { + // 启动模拟推送:使用配置的间隔和数量 + const { interval, maxBatch } = NOTIFICATION_CONFIG.mockPush; + socket.startMockPush(interval, maxBatch); + logger.info('NotificationContext', 'Mock push started', { interval, maxBatch }); + } else { + // ✅ 真实模式下,订阅事件推送 + console.log('%c[NotificationContext] 🔔 订阅事件推送...', 'color: #FF9800; font-weight: bold;'); + + if (socket.subscribeToEvents) { + socket.subscribeToEvents({ + eventType: 'all', + importance: 'all', + onSubscribed: (data) => { + console.log('%c[NotificationContext] ✅ 订阅成功!', 'color: #4CAF50; font-weight: bold;'); + console.log('[NotificationContext] 订阅确认:', data); + logger.info('NotificationContext', 'Events subscribed', data); + }, + // ⚠️ 不需要 onNewEvent 回调,因为 NotificationContext 已经通过 socket.on('new_event') 监听 + }); + } else { + console.warn('[NotificationContext] ⚠️ socket.subscribeToEvents 方法不可用'); + } + } }); socket.on('disconnect', (reason) => { @@ -718,7 +682,61 @@ export const NotificationProvider = ({ children }) => { }); }); - console.log('%c[NotificationContext] ✅ Connection event listeners registered', 'color: #4CAF50; font-weight: bold;'); + // 监听新事件推送(统一事件名) + socket.on('new_event', (data) => { + console.log('\n%c════════════════════════════════════════', 'color: #FF9800; font-weight: bold;'); + console.log('%c[NotificationContext] 📨 收到 new_event 事件!', 'color: #FF9800; font-weight: bold;'); + console.log('%c════════════════════════════════════════', 'color: #FF9800; font-weight: bold;'); + console.log('[NotificationContext] 原始事件数据:', data); + console.log('[NotificationContext] 事件 ID:', data?.id); + console.log('[NotificationContext] 事件标题:', data?.title); + console.log('[NotificationContext] 事件类型:', data?.event_type || data?.type); + console.log('[NotificationContext] 事件重要性:', data?.importance); + + logger.info('NotificationContext', 'Received new event', data); + + // ========== Socket层去重检查 ========== + const eventId = data.id || `${data.type}_${data.publishTime}`; + + if (processedEventIds.current.has(eventId)) { + logger.debug('NotificationContext', 'Duplicate event ignored at socket level', { eventId }); + console.warn('[NotificationContext] ⚠️ 重复事件,已忽略:', eventId); + console.log('%c════════════════════════════════════════\n', 'color: #FF9800; font-weight: bold;'); + return; // 重复事件,直接忽略 + } + + // 记录已处理的事件ID + processedEventIds.current.add(eventId); + console.log('[NotificationContext] ✓ 事件已记录,防止重复处理'); + + // 限制Set大小,避免内存泄漏 + if (processedEventIds.current.size > MAX_PROCESSED_IDS) { + const idsArray = Array.from(processedEventIds.current); + processedEventIds.current = new Set(idsArray.slice(-MAX_PROCESSED_IDS)); + logger.debug('NotificationContext', 'Cleaned up old processed event IDs', { + kept: MAX_PROCESSED_IDS + }); + } + // ========== Socket层去重检查结束 ========== + + // 使用适配器转换事件格式 + console.log('[NotificationContext] 正在转换事件格式...'); + const notification = adaptEventToNotification(data); + console.log('[NotificationContext] 转换后的通知对象:', notification); + + console.log('[NotificationContext] 准备添加通知到队列...'); + addNotification(notification); + console.log('[NotificationContext] ✅ 通知已添加到队列'); + console.log('%c════════════════════════════════════════\n', 'color: #FF9800; font-weight: bold;'); + }); + + // 保留系统通知监听(兼容性) + socket.on('system_notification', (data) => { + logger.info('NotificationContext', 'Received system notification', data); + addNotification(data); + }); + + console.log('%c[NotificationContext] ✅ All event listeners registered', 'color: #4CAF50; font-weight: bold;'); // ✅ 第二步: 获取最大重连次数 const maxAttempts = socket.getMaxReconnectAttempts?.() || Infinity; @@ -730,17 +748,6 @@ export const NotificationProvider = ({ children }) => { socket.connect(); console.log('%c[NotificationContext] socket.connect() completed', 'color: #673AB7;'); - // ✅ 第四步: 检查 Socket 是否已连接(处理连接先于监听器注册的情况) - if (socket.connected) { - console.log('%c[NotificationContext] ⚡ Socket 已连接,手动触发订阅逻辑', 'color: #FF9800; font-weight: bold;'); - // Socket 已经连接,手动调用业务监听器注册 - registerBusinessListeners(); - setIsConnected(true); - setConnectionStatus(CONNECTION_STATUS.CONNECTED); - } else { - console.log('%c[NotificationContext] Socket 未连接,等待 connect 事件触发...', 'color: #9E9E9E;'); - } - // 清理函数 return () => { logger.info('NotificationContext', 'Cleaning up socket connection');