From 36ea5c5e13a58bc0b63ab8b5a0a1b3abced758ab Mon Sep 17 00:00:00 2001 From: 3030332422 <3030332422@qq.com> Date: Wed, 15 Apr 2026 17:53:51 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/js/core/network/wakeword-bridge.js | 18 +++++ main/xiaozhi-server/test/js/ui/controller.js | 67 ++++++++++++++++--- 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/main/xiaozhi-server/test/js/core/network/wakeword-bridge.js b/main/xiaozhi-server/test/js/core/network/wakeword-bridge.js index cf521cad..ea4087a8 100644 --- a/main/xiaozhi-server/test/js/core/network/wakeword-bridge.js +++ b/main/xiaozhi-server/test/js/core/network/wakeword-bridge.js @@ -6,6 +6,7 @@ let reconnectTimer = null; let reconnectAttempts = 0; let shouldReconnect = true; let wakewordRequestSeq = 0; +let onNextBridgeConnectedCallback = null; const pendingWakewordRequests = new Map(); @@ -53,6 +54,11 @@ function tryConnect() { if (message.type === 'bridge_connected') { log('本地唤醒监听已就绪', 'info'); + if (onNextBridgeConnectedCallback) { + const cb = onNextBridgeConnectedCallback; + onNextBridgeConnectedCallback = null; + cb(message); + } return; } @@ -125,6 +131,7 @@ export function stopWakewordBridgeListener() { return; } + wakewordSocket.onclose = null; wakewordSocket.close(); wakewordSocket = null; } @@ -162,6 +169,17 @@ export function requestWakewordBridge(type, payload = {}, timeout = 5000) { }); } +export function getWakewordBridgeUrl() { + if (wakewordSocket && wakewordSocket.url) { + return wakewordSocket.url; + } + return buildWakewordBridgeUrl(); +} + +export function onNextBridgeConnected(callback) { + onNextBridgeConnectedCallback = callback; +} + function buildWakewordBridgeUrl() { const configured = localStorage.getItem('xz_tester_wakewordWsUrl'); if (configured && configured.trim()) { diff --git a/main/xiaozhi-server/test/js/ui/controller.js b/main/xiaozhi-server/test/js/ui/controller.js index 42c69d7d..b71ababc 100644 --- a/main/xiaozhi-server/test/js/ui/controller.js +++ b/main/xiaozhi-server/test/js/ui/controller.js @@ -2,7 +2,7 @@ import { loadConfig, saveConfig } from '../config/manager.js?v=0205'; import { getAudioPlayer } from '../core/audio/player.js?v=0205'; import { getAudioRecorder } from '../core/audio/recorder.js?v=0205'; -import { requestWakewordBridge } from '../core/network/wakeword-bridge.js?v=0205'; +import { requestWakewordBridge, stopWakewordBridgeListener, startWakewordBridgeListener, getWakewordBridgeUrl, onNextBridgeConnected } from '../core/network/wakeword-bridge.js?v=0205'; import { getWebSocketHandler } from '../core/network/websocket.js?v=0205'; import { log } from '../utils/logger.js?v=0205'; @@ -544,6 +544,7 @@ class UIController { async handleApplyWakeword() { const wakewordEnabledInput = document.getElementById('wakewordEnabled'); const wakewordListInput = document.getElementById('wakewordList'); + const wakewordWsUrlInput = document.getElementById('wakewordWsUrl'); if (!wakewordEnabledInput || !wakewordListInput) { return; } @@ -571,17 +572,63 @@ class UIController { } try { - const response = await requestWakewordBridge('set_wakeword_config', payload); - this.applyWakewordConfig(response.payload || payload); - - const shouldRestart = window.confirm('唤醒词已保存。是否现在重启唤醒词服务以立即生效?'); - if (!shouldRestart) { - this.addChatMessage('唤醒词配置已保存,可稍后手动重启服务后生效。', false); - return; + // 保存地址到 localStorage + if (wakewordWsUrlInput && wakewordWsUrlInput.value.trim()) { + localStorage.setItem('xz_tester_wakewordWsUrl', wakewordWsUrlInput.value.trim()); } - await requestWakewordBridge('restart_wakeword_service'); - this.addChatMessage('唤醒词配置已保存,唤醒词服务正在重启。', false); + // 比较新地址和当前连接地址 + const newWsUrl = localStorage.getItem('xz_tester_wakewordWsUrl'); + const currentWsUrl = getWakewordBridgeUrl(); + const urlChanged = newWsUrl !== currentWsUrl; + + if (urlChanged) { + // 地址变了,先确认 + const shouldRestart = window.confirm('地址已变更,是否继续?(将断开旧连接并重新连接)'); + if (!shouldRestart) { + // 恢复 localStorage 里的旧地址 + localStorage.setItem('xz_tester_wakewordWsUrl', currentWsUrl); + this.addChatMessage('已取消地址变更。', false); + return; + } + + // 断开旧连接 + stopWakewordBridgeListener(); + + // 启动新连接(自动用新地址) + startWakewordBridgeListener(); + + // 等 bridge_connected + await new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + reject(new Error('连接新服务器超时')); + }, 5000); + + onNextBridgeConnected(() => { + clearTimeout(timeout); + resolve(); + }); + }); + + // 发配置和重启 + await requestWakewordBridge('set_wakeword_config', payload); + this.applyWakewordConfig(payload); + await requestWakewordBridge('restart_wakeword_service'); + this.addChatMessage('唤醒词配置已保存,唤醒词服务正在重启。', false); + } else { + // 地址没变:直接在当前连接操作 + const response = await requestWakewordBridge('set_wakeword_config', payload); + this.applyWakewordConfig(response.payload || payload); + + const shouldRestart = window.confirm('唤醒词已保存。是否现在重启唤醒词服务以立即生效?'); + if (!shouldRestart) { + this.addChatMessage('唤醒词配置已保存,可稍后手动重启服务后生效。', false); + return; + } + + await requestWakewordBridge('restart_wakeword_service'); + this.addChatMessage('唤醒词配置已保存,唤醒词服务正在重启。', false); + } } catch (error) { this.addChatMessage(`应用唤醒词失败: ${error.message}`, false); } finally {