From d5686fed9d802d38b1b2e574d9d61d7fc73a3b12 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Mon, 10 Nov 2025 15:17:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=80=9A=E7=9F=A5=E5=8E=BB=E9=99=A4moc?= =?UTF-8?q?k=E7=8E=AF=E5=A2=83=E5=B9=B2=E6=89=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/contexts/NotificationContext.js | 143 ++++++++++++++-------------- 1 file changed, 72 insertions(+), 71 deletions(-) diff --git a/src/contexts/NotificationContext.js b/src/contexts/NotificationContext.js index 3a22f5e0..a6816ebc 100644 --- a/src/contexts/NotificationContext.js +++ b/src/contexts/NotificationContext.js @@ -589,6 +589,65 @@ 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...'); @@ -605,51 +664,8 @@ export const NotificationProvider = ({ children }) => { logger.info('NotificationContext', 'Socket connected', { wasDisconnected }); console.log('%c[NotificationContext] ✅ Socket connected', 'color: #4CAF50; font-weight: bold;'); - // ========== ✅ 连接成功后注册业务事件监听器 ========== - 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); - - // ========== Socket层去重检查 ========== - const eventId = data.id || `${data.type}_${data.publishTime}`; - - if (processedEventIds.current.has(eventId)) { - logger.debug('NotificationContext', 'Duplicate event ignored at socket level', { eventId }); - return; // 重复事件,直接忽略 - } - - // 记录已处理的事件ID - processedEventIds.current.add(eventId); - - // 限制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层去重检查结束 ========== - - // 使用适配器转换事件格式 - 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;'); - // ========== 业务事件监听器注册完成 ========== + // ✅ 调用统一的业务监听器注册函数 + registerBusinessListeners(); // 如果之前断开过,显示 RECONNECTED 状态2秒后自动消失 if (wasDisconnected) { @@ -669,32 +685,6 @@ 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) => { @@ -740,6 +730,17 @@ 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');