// src/services/socket/index.js /** * Socket 服务统一导出 * 根据环境变量自动选择使用 Mock 或真实 Socket.IO 服务 */ import { mockSocketService } from '../mockSocketService'; import { socketService } from '../socketService'; // 判断是否使用 Mock const useMock = process.env.REACT_APP_ENABLE_MOCK === 'true' || process.env.REACT_APP_USE_MOCK_SOCKET === 'true'; // 根据环境选择服务 export const socket = useMock ? mockSocketService : socketService; // 同时导出两个服务,方便测试和调试 export { mockSocketService, socketService }; // 导出服务类型标识 export const SOCKET_TYPE = useMock ? 'MOCK' : 'REAL'; // 打印当前使用的服务类型 console.log( `%c[Socket Service] Using ${SOCKET_TYPE} Socket Service`, `color: ${useMock ? '#FF9800' : '#4CAF50'}; font-weight: bold; font-size: 12px;` ); // ========== 暴露调试 API 到全局 ========== if (typeof window !== 'undefined') { // 暴露 Socket 类型到全局 window.SOCKET_TYPE = SOCKET_TYPE; // 暴露调试 API window.__SOCKET_DEBUG__ = { // 获取当前连接状态 getStatus: () => { const isConnected = socket.connected || false; return { type: SOCKET_TYPE, connected: isConnected, reconnectAttempts: socket.getReconnectAttempts?.() || 0, maxReconnectAttempts: socket.getMaxReconnectAttempts?.() || Infinity, service: useMock ? 'mockSocketService' : 'socketService', }; }, // 手动重连 reconnect: () => { console.log('[Socket Debug] Manual reconnect triggered'); if (socket.reconnect) { socket.reconnect(); } else { socket.disconnect(); socket.connect(); } }, // 断开连接 disconnect: () => { console.log('[Socket Debug] Manual disconnect triggered'); socket.disconnect(); }, // 连接 connect: () => { console.log('[Socket Debug] Manual connect triggered'); socket.connect(); }, // 获取服务实例 (仅用于调试) getService: () => socket, // 导出诊断信息 exportDiagnostics: () => { const status = window.__SOCKET_DEBUG__.getStatus(); const diagnostics = { ...status, 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( '%c[Socket Debug] Debug API available at window.__SOCKET_DEBUG__', 'color: #2196F3; font-weight: bold;' ); console.log( '%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;