diff --git a/src/services/mockSocketService.js b/src/services/mockSocketService.js index db29b810..a78faa23 100644 --- a/src/services/mockSocketService.js +++ b/src/services/mockSocketService.js @@ -310,6 +310,7 @@ class MockSocketService { this.reconnectAttempts = 0; this.customReconnectTimer = null; this.failConnection = false; // 是否模拟连接失败 + this.pushPaused = false; // 新增:暂停推送标志(保持连接) } /** @@ -414,6 +415,7 @@ class MockSocketService { // 清除所有定时器 this.intervals.forEach(interval => clearInterval(interval)); this.intervals = []; + this.pushPaused = false; // 重置暂停状态 const wasConnected = this.connected; this.connected = false; @@ -613,6 +615,12 @@ class MockSocketService { logger.info('mockSocketService', `Starting mock push: interval=${interval}ms, burst=${burstCount}`); const pushInterval = setInterval(() => { + // 检查是否暂停推送 + if (this.pushPaused) { + logger.info('mockSocketService', '⏸️ Mock push is paused, skipping this cycle...'); + return; + } + // 随机选择 1-burstCount 条消息 const count = Math.floor(Math.random() * burstCount) + 1; @@ -642,9 +650,34 @@ class MockSocketService { stopMockPush() { this.intervals.forEach(interval => clearInterval(interval)); this.intervals = []; + this.pushPaused = false; // 重置暂停状态 logger.info('mockSocketService', 'Mock push stopped'); } + /** + * 暂停自动推送(保持连接和定时器运行) + */ + pausePush() { + this.pushPaused = true; + logger.info('mockSocketService', '⏸️ Mock push paused (connection and intervals maintained)'); + } + + /** + * 恢复自动推送 + */ + resumePush() { + this.pushPaused = false; + logger.info('mockSocketService', '▶️ Mock push resumed'); + } + + /** + * 查询推送暂停状态 + * @returns {boolean} 是否已暂停 + */ + isPushPaused() { + return this.pushPaused; + } + /** * 手动触发一条测试消息 * @param {object} customData - 自定义消息数据(可选) @@ -836,6 +869,27 @@ if (process.env.NODE_ENV === 'development') { logger.info('mockSocketService', `Current reconnection attempts: ${attempts}`); return attempts; }, + + // 暂停自动推送(保持连接) + pausePush: () => { + mockSocketService.pausePush(); + logger.info('mockSocketService', '⏸️ Auto push paused'); + return true; + }, + + // 恢复自动推送 + resumePush: () => { + mockSocketService.resumePush(); + logger.info('mockSocketService', '▶️ Auto push resumed'); + return true; + }, + + // 查看推送暂停状态 + isPushPaused: () => { + const paused = mockSocketService.isPushPaused(); + logger.info('mockSocketService', `Push status: ${paused ? '⏸️ Paused' : '▶️ Active'}`); + return paused; + }, }; logger.info('mockSocketService', '💡 Mock Socket test functions available:'); @@ -845,6 +899,9 @@ if (process.env.NODE_ENV === 'development') { logger.info('mockSocketService', ' __mockSocket.isConnected() - 查看连接状态'); logger.info('mockSocketService', ' __mockSocket.reconnect() - 手动重连'); logger.info('mockSocketService', ' __mockSocket.getAttempts() - 查看重连次数'); + logger.info('mockSocketService', ' __mockSocket.pausePush() - ⏸️ 暂停自动推送(保持连接)'); + logger.info('mockSocketService', ' __mockSocket.resumePush() - ▶️ 恢复自动推送'); + logger.info('mockSocketService', ' __mockSocket.isPushPaused() - 查看推送状态'); } export default mockSocketService; diff --git a/src/services/socket/index.js b/src/services/socket/index.js index 99924555..8e7d49d3 100644 --- a/src/services/socket/index.js +++ b/src/services/socket/index.js @@ -78,10 +78,93 @@ if (typeof window !== 'undefined') { timestamp: new Date().toISOString(), userAgent: navigator.userAgent, url: window.location.href, + env: { + NODE_ENV: process.env.NODE_ENV, + REACT_APP_ENABLE_MOCK: process.env.REACT_APP_ENABLE_MOCK, + REACT_APP_USE_MOCK_SOCKET: process.env.REACT_APP_USE_MOCK_SOCKET, + REACT_APP_API_URL: process.env.REACT_APP_API_URL, + REACT_APP_ENV: process.env.REACT_APP_ENV, + }, }; console.log('[Socket Diagnostics]', diagnostics); return diagnostics; - } + }, + + // 手动订阅事件 + subscribe: (options = {}) => { + const { eventType = 'all', importance = 'all' } = options; + console.log(`[Socket Debug] Subscribing to events: type=${eventType}, importance=${importance}`); + + if (socket.subscribeToEvents) { + socket.subscribeToEvents({ + eventType, + importance, + onNewEvent: (event) => { + console.log('[Socket Debug] ✅ New event received:', event); + }, + onSubscribed: (data) => { + console.log('[Socket Debug] ✅ Subscription confirmed:', data); + }, + }); + } else { + console.error('[Socket Debug] ❌ subscribeToEvents method not available'); + } + }, + + // 测试连接质量 + testConnection: () => { + console.log('[Socket Debug] Testing connection...'); + const start = Date.now(); + + if (socket.emit) { + socket.emit('ping', { timestamp: start }, (response) => { + const latency = Date.now() - start; + console.log(`[Socket Debug] ✅ Connection OK - Latency: ${latency}ms`, response); + }); + } else { + console.error('[Socket Debug] ❌ Cannot test connection - socket.emit not available'); + } + }, + + // 检查配置是否正确 + checkConfig: () => { + const config = { + socketType: SOCKET_TYPE, + useMock, + envVars: { + REACT_APP_ENABLE_MOCK: process.env.REACT_APP_ENABLE_MOCK, + REACT_APP_USE_MOCK_SOCKET: process.env.REACT_APP_USE_MOCK_SOCKET, + NODE_ENV: process.env.NODE_ENV, + REACT_APP_API_URL: process.env.REACT_APP_API_URL, + }, + socketMethods: { + connect: typeof socket.connect, + disconnect: typeof socket.disconnect, + on: typeof socket.on, + emit: typeof socket.emit, + subscribeToEvents: typeof socket.subscribeToEvents, + }, + }; + + console.log('[Socket Debug] Configuration Check:', config); + + // 检查潜在问题 + const issues = []; + if (SOCKET_TYPE === 'MOCK' && process.env.NODE_ENV === 'production') { + issues.push('⚠️ WARNING: Using MOCK socket in production!'); + } + if (!socket.subscribeToEvents) { + issues.push('❌ ERROR: subscribeToEvents method missing'); + } + + if (issues.length > 0) { + console.warn('[Socket Debug] Issues found:', issues); + } else { + console.log('[Socket Debug] ✅ No issues found'); + } + + return { config, issues }; + }, }; console.log( @@ -92,6 +175,190 @@ if (typeof window !== 'undefined') { '%cTry: window.__SOCKET_DEBUG__.getStatus()', 'color: #2196F3;' ); + console.log( + '%c window.__SOCKET_DEBUG__.checkConfig() - 检查配置', + 'color: #2196F3;' + ); + console.log( + '%c window.__SOCKET_DEBUG__.subscribe() - 手动订阅事件', + 'color: #2196F3;' + ); + console.log( + '%c window.__SOCKET_DEBUG__.testConnection() - 测试连接', + 'color: #2196F3;' + ); + + // ========== 通知系统专用调试 API ========== + window.__NOTIFY_DEBUG__ = { + // 完整检查(配置+连接+订阅状态) + checkAll: () => { + console.log('\n==========【通知系统诊断】=========='); + + // 1. 检查 Socket 配置 + const socketCheck = window.__SOCKET_DEBUG__.checkConfig(); + console.log('\n✓ Socket 配置检查完成'); + + // 2. 检查连接状态 + const status = window.__SOCKET_DEBUG__.getStatus(); + console.log('\n✓ 连接状态:', status.connected ? '✅ 已连接' : '❌ 未连接'); + + // 3. 检查环境变量 + console.log('\n✓ API Base:', process.env.REACT_APP_API_URL || '(使用相对路径)'); + + // 4. 检查浏览器通知权限 + const browserPermission = Notification?.permission || 'unsupported'; + console.log('\n✓ 浏览器通知权限:', browserPermission); + + // 5. 汇总报告 + const report = { + timestamp: new Date().toISOString(), + socket: { + type: SOCKET_TYPE, + connected: status.connected, + reconnectAttempts: status.reconnectAttempts, + }, + env: socketCheck.config.envVars, + browserNotification: browserPermission, + issues: socketCheck.issues, + }; + + console.log('\n========== 诊断报告 =========='); + console.table(report); + + if (report.issues.length > 0) { + console.warn('\n⚠️ 发现问题:', report.issues); + } else { + console.log('\n✅ 系统正常,未发现问题'); + } + + // 提供修复建议 + if (!status.connected) { + console.log('\n💡 修复建议:'); + console.log(' 1. 检查网络连接'); + console.log(' 2. 尝试手动重连: __SOCKET_DEBUG__.reconnect()'); + console.log(' 3. 检查后端服务是否运行'); + } + + if (browserPermission === 'denied') { + console.log('\n💡 浏览器通知已被拒绝,请在浏览器设置中允许通知权限'); + } + + console.log('\n====================================\n'); + + return report; + }, + + // 手动订阅事件(简化版) + subscribe: (eventType = 'all', importance = 'all') => { + console.log(`\n[通知调试] 手动订阅事件: type=${eventType}, importance=${importance}`); + window.__SOCKET_DEBUG__.subscribe({ eventType, importance }); + }, + + // 模拟接收通知(用于测试UI) + testNotify: (type = 'announcement') => { + console.log('\n[通知调试] 模拟通知:', type); + + const mockNotifications = { + announcement: { + id: `test_${Date.now()}`, + type: 'announcement', + priority: 'important', + title: '🧪 测试公告通知', + content: '这是一条测试消息,用于验证通知系统是否正常工作', + publishTime: Date.now(), + pushTime: Date.now(), + }, + stock_alert: { + id: `test_${Date.now()}`, + type: 'stock_alert', + priority: 'urgent', + title: '🧪 测试股票预警', + content: '贵州茅台触发价格预警: 1850.00元 (+5.2%)', + publishTime: Date.now(), + pushTime: Date.now(), + }, + event_alert: { + id: `test_${Date.now()}`, + type: 'event_alert', + priority: 'important', + title: '🧪 测试事件动向', + content: 'AI大模型新政策发布,影响科技板块', + publishTime: Date.now(), + pushTime: Date.now(), + }, + analysis_report: { + id: `test_${Date.now()}`, + type: 'analysis_report', + priority: 'normal', + title: '🧪 测试分析报告', + content: '2024年Q1市场策略报告已发布', + publishTime: Date.now(), + pushTime: Date.now(), + }, + }; + + const notification = mockNotifications[type] || mockNotifications.announcement; + + // 触发 new_event 事件 + if (socket.emit) { + // 对于真实 Socket,模拟服务端推送(实际上客户端无法这样做,仅用于Mock模式) + console.warn('⚠️ 真实 Socket 无法模拟服务端推送,请使用 Mock 模式或等待真实推送'); + } + + // 直接触发事件监听器(如果是 Mock 模式) + if (SOCKET_TYPE === 'MOCK' && socket.emit) { + socket.emit('new_event', notification); + console.log('✅ 已触发 Mock 通知事件'); + } + + console.log('通知数据:', notification); + return notification; + }, + + // 导出完整诊断报告 + exportReport: () => { + const report = window.__NOTIFY_DEBUG__.checkAll(); + + // 生成可下载的 JSON + const blob = new Blob([JSON.stringify(report, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `notification-debug-${Date.now()}.json`; + a.click(); + URL.revokeObjectURL(url); + + console.log('✅ 诊断报告已导出'); + return report; + }, + + // 快捷帮助 + help: () => { + console.log('\n========== 通知系统调试 API =========='); + console.log('window.__NOTIFY_DEBUG__.checkAll() - 完整诊断检查'); + console.log('window.__NOTIFY_DEBUG__.subscribe() - 手动订阅事件'); + console.log('window.__NOTIFY_DEBUG__.testNotify(type) - 模拟通知 (announcement/stock_alert/event_alert/analysis_report)'); + console.log('window.__NOTIFY_DEBUG__.exportReport() - 导出诊断报告'); + console.log('\n========== Socket 调试 API =========='); + console.log('window.__SOCKET_DEBUG__.getStatus() - 获取连接状态'); + console.log('window.__SOCKET_DEBUG__.checkConfig() - 检查配置'); + console.log('window.__SOCKET_DEBUG__.reconnect() - 手动重连'); + console.log('====================================\n'); + }, + }; + + console.log( + '%c[Notify Debug] Notification Debug API available at window.__NOTIFY_DEBUG__', + 'color: #FF9800; font-weight: bold;' + ); + console.log( + '%cTry: window.__NOTIFY_DEBUG__.checkAll() - 完整诊断', + 'color: #FF9800;' + ); + console.log( + '%c window.__NOTIFY_DEBUG__.help() - 查看所有命令', + 'color: #FF9800;' + ); } export default socket;