import { getAiChatSocket } from './AiChatSocket' import { getActivitySocket } from './ActivitySocket' /** * 全局 WebSocket 管理器 * 统一管理多个服务的 WebSocket 连接 */ class GlobalSocketManager { constructor() { this.sockets = {} // serviceName -> SocketManager this.token = null this.isAllConnected = false this._initialized = false // 防止重复 init 导致监听器累积 // 保存监听器引用,用于 cleanup this._aiChatConnectHandler = null this._aiChatErrorHandler = null this._activityConnectHandler = null this._activityErrorHandler = null } /** * 初始化所有连接(幂等,重复调用会先清理旧监听器再重连) */ init(token) { this.token = token // 总是先清理旧监听器再注册新的,防止累积。 // 注意:closeAll() 会清空 this.sockets,所以 cleanup 必须通过单例 getter 获取 socket 引用。 this._cleanupListeners() this._initialized = true this._initAiChat() this._initActivity() // Future: this._initNotification() } async _initAiChat() { const aiChat = getAiChatSocket() this._aiChatConnectHandler = () => console.log('AI Chat connected') this._aiChatErrorHandler = (err) => console.error('AI Chat error:', err) aiChat.on('connect', this._aiChatConnectHandler) aiChat.on('error', this._aiChatErrorHandler) await aiChat.connect(this.token) this.sockets['ai_chat'] = aiChat } async _initActivity() { const activity = getActivitySocket() this._activityConnectHandler = () => console.log('Activity socket connected') this._activityErrorHandler = (err) => console.error('Activity socket error:', err) activity.on('connect', this._activityConnectHandler) activity.on('error', this._activityErrorHandler) if (this.token) { await activity.connect(this.token) } this.sockets['activity'] = activity } /** * 清理之前注册的监听器,防止每次 init() 累积。 * 通过单例 getter 获取 socket 引用(而非 this.sockets), * 因为 closeAll() 会清空 this.sockets 但单例仍存活。 */ _cleanupListeners() { try { const aiChat = getAiChatSocket() if (this._aiChatConnectHandler) { aiChat.off('connect', this._aiChatConnectHandler) aiChat.off('error', this._aiChatErrorHandler) } } catch (e) { /* singleton not yet created, skip */ } try { const activity = getActivitySocket() if (this._activityConnectHandler) { activity.off('connect', this._activityConnectHandler) activity.off('error', this._activityErrorHandler) } } catch (e) { /* singleton not yet created, skip */ } } getSocket(serviceName) { return this.sockets[serviceName] } closeAll() { Object.values(this.sockets).forEach(socket => socket.close()) this.sockets = {} this._initialized = false // 关闭后允许下次 init() 重新注册监听器 } } let globalInstance = null export function getGlobalSocket() { if (!globalInstance) { globalInstance = new GlobalSocketManager() } return globalInstance } export default GlobalSocketManager