import { useChatStore, useTtsStore } from "@/stores"; // WebSocket export const useWebSocketStore = defineStore("websocket", () => { const websocket = ref(); const connected = ref(false); const chatStore = useChatStore(); const ttsStore = useTtsStore(); const router = useRouter(); const { onlineCount } = storeToRefs(chatStore); const onmessage = (e: MessageEvent) => { // 检查消息类型 if (e.data instanceof ArrayBuffer) { // 处理二进制音频数据(兜底处理,新版本应该不会用到) console.log("收到二进制音频数据,大小:", e.data.byteLength); // 可以选择忽略或者作为兜底处理 } else if (e.data instanceof Blob) { // 如果是Blob,转换为ArrayBuffer(兜底处理) e.data.arrayBuffer().then((buffer: ArrayBuffer) => { console.log("收到Blob音频数据,大小:", buffer.byteLength); }); } else if (typeof e.data === "string") { // 处理文本JSON消息 try { const data = JSON.parse(e.data); switch (data.type) { case "count": onlineCount.value = data.online_count; break; case "asr_result": if (router.currentRoute.value.path === "/") { chatStore.addMessageToHistory(data.result); } else if (router.currentRoute.value.path === "/voice") { // 在语音页面的处理 chatStore.addMessageToHistory(data.result, "user", "voice"); } else { console.warn(data); } break; // 新的TTS消息格式处理 case "tts_audio_data": // 新的音频数据格式,包含messageId和hex格式的音频数据 if (data.messageId && data.audioData) { console.log( `收到TTS音频数据 [${data.messageId}],hex长度:`, data.audioData.length ); try { // 将hex字符串转换为ArrayBuffer const bytes = data.audioData .match(/.{1,2}/g) ?.map((byte: string) => Number.parseInt(byte, 16)); if (bytes) { const buffer = new Uint8Array(bytes).buffer; console.log( `转换后的音频数据大小 [${data.messageId}]:`, buffer.byteLength ); ttsStore.handleAudioData(buffer, data.messageId); } else { console.error(`音频数据格式错误 [${data.messageId}]`); } } catch (error) { console.error(`音频数据转换失败 [${data.messageId}]:`, error); ttsStore.handleError( `音频数据转换失败: ${error}`, data.messageId ); } } else { console.error("tts_audio_data消息格式错误:", data); } break; case "tts_audio_complete": // TTS音频传输完成 if (data.messageId) { console.log(`TTS音频传输完成 [${data.messageId}]`); ttsStore.finishConversion(data.messageId); } else { console.log("TTS音频传输完成(无messageId)"); ttsStore.finishConversion(data.messageId); } break; case "tts_complete": // TTS会话结束 if (data.messageId) { console.log(`TTS会话结束 [${data.messageId}]`); } else { console.log("TTS会话结束"); } break; case "tts_error": // TTS错误 if (data.messageId) { console.error(`TTS错误 [${data.messageId}]:`, data.message); ttsStore.handleError(data.message, data.messageId); } else { console.error("TTS错误:", data.message); ttsStore.handleError(data.message, data.messageId || "unknown"); } break; case "llm_complete_response": // LLM部分响应 if (router.currentRoute.value.path === "/voice") { chatStore.addMessageToHistory(data.content, "assistant", "voice"); } break; default: console.log("未知消息类型:", data.type, data); } } catch (error) { console.error("JSON解析错误:", error, "原始数据:", e.data); } } else { console.warn("收到未知格式的消息:", typeof e.data, e.data); } }; const send = (data: string) => { if (websocket.value && websocket.value.readyState === WebSocket.OPEN) { websocket.value?.send(data); } else { console.warn("WebSocket未连接,无法发送消息:", data); } }; const sendBinary = (data: ArrayBuffer | Uint8Array) => { if (websocket.value && websocket.value.readyState === WebSocket.OPEN) { websocket.value?.send(data); } else { console.warn("WebSocket未连接,无法发送二进制数据"); } }; const close = () => { websocket.value?.close(); }; const connect = () => { const url = "ws://127.0.0.1:8000/websocket"; websocket.value = new WebSocket(url); websocket.value.onopen = () => { connected.value = true; console.log("WebSocket连接成功"); let pingIntervalId: NodeJS.Timeout | undefined; if (pingIntervalId) clearInterval(pingIntervalId); pingIntervalId = setInterval(() => { // 修改ping格式为JSON格式,与后端保持一致 send(JSON.stringify({ type: "ping" })); }, 30 * 1000); if (websocket.value) { websocket.value.onmessage = onmessage; websocket.value.onerror = (e: Event) => { console.error(`WebSocket错误:${(e as ErrorEvent).message}`); }; websocket.value.onclose = (e: CloseEvent) => { connected.value = false; console.log(`WebSocket连接关闭: ${e.code} ${e.reason}`); setTimeout(() => { console.log("尝试重新连接WebSocket..."); connect(); // 尝试重新连接 }, 1000); // 1秒后重试连接 }; } }; websocket.value.onerror = (e: Event) => { console.error("WebSocket连接错误:", e); }; }; return { websocket, connected, send, sendBinary, close, connect }; });