// Socket.IO 客户端管理 import type { Socket } from 'socket.io-client'; import { io } from 'socket.io-client'; import type { ClientToServerEvents, ServerToClientEvents, WatchRoomConfig, } from '@/types/watch-room'; export type WatchRoomSocket = Socket; class WatchRoomSocketManager { private socket: WatchRoomSocket | null = null; private config: WatchRoomConfig | null = null; private heartbeatInterval: NodeJS.Timeout | null = null; async connect(config: WatchRoomConfig): Promise { if (this.socket?.connected) { return this.socket; } this.config = config; const socketOptions = { transports: ['websocket', 'polling'] as ('websocket' | 'polling')[], reconnection: true, reconnectionDelay: 1000, reconnectionDelayMax: 5000, reconnectionAttempts: 5, }; if (config.serverType === 'internal') { // 内部服务器 - 连接到同一个域名的Socket.IO服务器 this.socket = io({ ...socketOptions, path: '/socket.io', // 使用服务器配置的path }); } else { // 外部服务器 if (!config.externalServerUrl) { throw new Error('External server URL is required'); } this.socket = io(config.externalServerUrl, { ...socketOptions, auth: { token: config.externalServerAuth, }, extraHeaders: config.externalServerAuth ? { Authorization: `Bearer ${config.externalServerAuth}`, } : undefined, }); } // 设置事件监听 this.setupEventListeners(); // 开始心跳 this.startHeartbeat(); return new Promise((resolve, reject) => { if (!this.socket) { reject(new Error('Socket not initialized')); return; } this.socket.on('connect', () => { // eslint-disable-next-line no-console console.log('[WatchRoom] Connected to server'); if (this.socket) { resolve(this.socket); } }); this.socket.on('connect_error', (error) => { // eslint-disable-next-line no-console console.error('[WatchRoom] Connection error:', error); reject(error); }); }); } disconnect() { if (this.heartbeatInterval) { clearInterval(this.heartbeatInterval); this.heartbeatInterval = null; } if (this.socket) { this.socket.disconnect(); this.socket = null; } } getSocket(): WatchRoomSocket | null { return this.socket; } isConnected(): boolean { return this.socket?.connected ?? false; } private setupEventListeners() { if (!this.socket) return; this.socket.on('connect', () => { // eslint-disable-next-line no-console console.log('[WatchRoom] Socket connected'); }); this.socket.on('disconnect', (reason) => { // eslint-disable-next-line no-console console.log('[WatchRoom] Socket disconnected:', reason); }); this.socket.on('error', (error) => { // eslint-disable-next-line no-console console.error('[WatchRoom] Socket error:', error); }); } private startHeartbeat() { if (this.heartbeatInterval) { clearInterval(this.heartbeatInterval); } this.heartbeatInterval = setInterval(() => { if (this.socket?.connected) { this.socket.emit('heartbeat'); } }, 5000); // 每5秒发送一次心跳 } } // 单例实例 export const watchRoomSocketManager = new WatchRoomSocketManager();