import type { ChatMessage } from '@/types/api' export interface WebSocketMessage { request_type?: string clientId?: string data?: ChatMessage } export type MessageHandler = (message: ChatMessage) => void export type SignalHandler = (message: ChatMessage) => void class WebSocketManager { private ws: WebSocket | null = null private clientId: string | null = null private userId: string | null = null private messageHandlers: MessageHandler[] = [] private signalHandlers: SignalHandler[] = [] private reconnectAttempts = 0 private maxReconnectAttempts = 5 private reconnectDelay = 3000 /** * 连接WebSocket */ connect(userId: string): Promise { return new Promise((resolve, reject) => { if (this.ws?.readyState === WebSocket.OPEN) { resolve() return } this.userId = userId const wsUrl = `ws://localhost:12080/ws?user_id=${userId}` try { this.ws = new WebSocket(wsUrl) this.ws.onopen = () => { console.log('✅ WebSocket connected') this.reconnectAttempts = 0 resolve() } this.ws.onmessage = (event) => { try { // 处理可能的多行JSON或消息分割 const data = event.data.toString().trim() const lines = data.split('\n').filter(line => line.trim()) for (const line of lines) { try { const payload: WebSocketMessage = JSON.parse(line) // 接收clientId if (payload.clientId) { this.clientId = payload.clientId } // 处理接收消息 if (payload.request_type === 'receive_message' && payload.data) { this.handleMessage(payload.data) } } catch (e) { // Ignore single line parse error } } } catch (error) { console.error('WebSocket message parse error:', error) } } this.ws.onerror = (error) => { console.error('WebSocket error:', error) reject(error) } this.ws.onclose = () => { console.log('WebSocket closed') this.ws = null this.attemptReconnect() } } catch (error) { reject(error) } }) } /** * 断开连接 */ disconnect() { if (this.ws) { this.ws.close() this.ws = null } this.clientId = null this.userId = null this.messageHandlers = [] this.signalHandlers = [] } /** * 获取ClientID */ getClientId(): string | null { return this.clientId } /** * 添加普通消息处理器 */ onMessage(handler: MessageHandler) { this.messageHandlers.push(handler) } /** * 移除普通消息处理器 */ offMessage(handler: MessageHandler) { const index = this.messageHandlers.indexOf(handler) if (index > -1) { this.messageHandlers.splice(index, 1) } } /** * 添加信令处理器 (WebRTC用) */ onSignal(handler: SignalHandler) { this.signalHandlers.push(handler) } /** * 移除信令处理器 */ offSignal(handler: SignalHandler) { const index = this.signalHandlers.indexOf(handler) if (index > -1) { this.signalHandlers.splice(index, 1) } } /** * 内部处理接收到的消息 */ private handleMessage(message: ChatMessage) { // 信令消息(message_type = 6)- 路由到signalHandlers if (message.message_type === 6) { this.signalHandlers.forEach(handler => handler(message)) return } // 普通消息 - 路由到messageHandlers this.messageHandlers.forEach(handler => handler(message)) } /** * 尝试重连 */ private attemptReconnect() { if (this.reconnectAttempts >= this.maxReconnectAttempts) { return } if (!this.userId) { return } this.reconnectAttempts++ setTimeout(() => { if (this.userId) { this.connect(this.userId).catch(console.error) } }, this.reconnectDelay) } } export const wsManager = new WebSocketManager()