From 43ddc0135cdba9ef694fb9cc77d399aa84f0db25 Mon Sep 17 00:00:00 2001 From: lww155 <756794909@qq.com> Date: Thu, 22 Jan 2026 15:39:40 +0800 Subject: [PATCH 1/4] =?UTF-8?q?update:=20=E5=8E=BB=E9=99=A4=E6=9C=AA?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/js/core/audio/opus-codec.js | 4 --- .../test/js/core/network/ota-connector.js | 3 --- main/xiaozhi-server/test/js/ui/dom-helper.js | 25 ------------------- 3 files changed, 32 deletions(-) delete mode 100644 main/xiaozhi-server/test/js/ui/dom-helper.js diff --git a/main/xiaozhi-server/test/js/core/audio/opus-codec.js b/main/xiaozhi-server/test/js/core/audio/opus-codec.js index 8fb856f2..254e8c24 100644 --- a/main/xiaozhi-server/test/js/core/audio/opus-codec.js +++ b/main/xiaozhi-server/test/js/core/audio/opus-codec.js @@ -1,5 +1,4 @@ import { log } from '../../utils/logger.js'; -import { updateScriptStatus } from '../../ui/dom-helper.js' // 检查Opus库是否已加载 @@ -15,7 +14,6 @@ export function checkOpusLoaded() { // 使用Module.instance对象替换全局Module对象 window.ModuleInstance = Module.instance; log('Opus库加载成功(使用Module.instance)', 'success'); - updateScriptStatus('Opus库加载成功', 'success'); // 3秒后隐藏状态 const statusElement = document.getElementById('scriptStatus'); @@ -27,7 +25,6 @@ export function checkOpusLoaded() { if (typeof Module._opus_decoder_get_size === 'function') { window.ModuleInstance = Module; log('Opus库加载成功(使用全局Module)', 'success'); - updateScriptStatus('Opus库加载成功', 'success'); // 3秒后隐藏状态 const statusElement = document.getElementById('scriptStatus'); @@ -38,7 +35,6 @@ export function checkOpusLoaded() { throw new Error('Opus解码函数未找到,可能Module结构不正确'); } catch (err) { log(`Opus库加载失败,请检查libopus.js文件是否存在且正确: ${err.message}`, 'error'); - updateScriptStatus('Opus库加载失败,请检查libopus.js文件是否存在且正确', 'error'); } } diff --git a/main/xiaozhi-server/test/js/core/network/ota-connector.js b/main/xiaozhi-server/test/js/core/network/ota-connector.js index 4c626cf7..2372c767 100644 --- a/main/xiaozhi-server/test/js/core/network/ota-connector.js +++ b/main/xiaozhi-server/test/js/core/network/ota-connector.js @@ -1,4 +1,3 @@ -import { otaStatusStyle } from '../../ui/dom-helper.js'; import { log } from '../../utils/logger.js'; // WebSocket 连接 @@ -103,10 +102,8 @@ async function sendOTA(otaUrl, config) { if (!res.ok) throw new Error(`${res.status} ${res.statusText}`); const result = await res.json(); - otaStatusStyle(true) return result; // 返回完整的响应数据 } catch (err) { - otaStatusStyle(false) return null; // 失败返回null } } \ No newline at end of file diff --git a/main/xiaozhi-server/test/js/ui/dom-helper.js b/main/xiaozhi-server/test/js/ui/dom-helper.js deleted file mode 100644 index 07e3151b..00000000 --- a/main/xiaozhi-server/test/js/ui/dom-helper.js +++ /dev/null @@ -1,25 +0,0 @@ -// ota 是否连接成功,修改成对应的样式 -export function otaStatusStyle(flan) { - const otaStatusElement = document.getElementById('otaStatus'); - if (otaStatusElement) { - if (flan) { - otaStatusElement.textContent = 'OTA已连接'; - otaStatusElement.style.color = 'green'; - } else { - otaStatusElement.textContent = 'OTA未连接'; - otaStatusElement.style.color = 'red'; - } - } -} - -// 更新Opus库状态显示 -export function updateScriptStatus(message, type) { - const statusElement = document.getElementById('scriptStatus'); - if (statusElement) { - statusElement.textContent = message; - statusElement.className = `script-status ${type}`; - statusElement.style.display = 'block'; - statusElement.style.width = 'auto'; - } -} - From 9d9ca1475d69821008fc619665ec004a6f66677e Mon Sep 17 00:00:00 2001 From: lww155 <756794909@qq.com> Date: Thu, 22 Jan 2026 15:54:26 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E8=AF=B7=E6=B1=82ota=E4=B8=8E=E9=87=8D=E5=A4=8D=E5=BB=BA?= =?UTF-8?q?=E7=AB=8B=E8=BF=9E=E6=8E=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/xiaozhi-server/test/js/app.js | 13 ----- .../test/js/core/network/websocket.js | 4 +- main/xiaozhi-server/test/js/ui/controller.js | 54 ++++--------------- 3 files changed, 11 insertions(+), 60 deletions(-) diff --git a/main/xiaozhi-server/test/js/app.js b/main/xiaozhi-server/test/js/app.js index 96f6afc0..76819a6f 100644 --- a/main/xiaozhi-server/test/js/app.js +++ b/main/xiaozhi-server/test/js/app.js @@ -40,9 +40,6 @@ class App { // 关闭加载loading this.setModelLoadingStatus(false); - // 绑定页面卸载事件 - this.bindUnload(); - log('应用初始化完成', 'success'); } @@ -84,16 +81,6 @@ class App { modelLoading.style.display = isLoading ? 'flex' : 'none'; } } - - // 绑定页面卸载事件 - bindUnload() { - window.addEventListener('beforeunload', () => { - // 销毁定时器 - if (this.uiController && this.uiController.wsTimer) { - clearInterval(this.uiController.wsTimer); - } - }); - } } // 创建并启动应用 diff --git a/main/xiaozhi-server/test/js/core/network/websocket.js b/main/xiaozhi-server/test/js/core/network/websocket.js index 187a57e4..c35b5300 100644 --- a/main/xiaozhi-server/test/js/core/network/websocket.js +++ b/main/xiaozhi-server/test/js/core/network/websocket.js @@ -5,6 +5,7 @@ import { getConfig, saveConnectionUrls } from '../../config/manager.js'; import { getAudioPlayer } from '../audio/player.js'; import { getAudioRecorder } from '../audio/recorder.js'; import { getMcpTools, executeMcpTool, setWebSocket as setMcpWebSocket } from '../mcp/tools.js'; +import { uiController } from '../../ui/controller.js' // WebSocket处理器类 export class WebSocketHandler { @@ -17,7 +18,6 @@ export class WebSocketHandler { this.onChatMessage = null; // 新增:聊天消息回调 this.currentSessionId = null; this.isRemoteSpeaking = false; - this.isEstablishConnection = false; // 新增:是否已建立连接 } // 发送hello握手消息 @@ -74,7 +74,7 @@ export class WebSocketHandler { handleTextMessage(message) { if (message.type === 'hello') { log(`服务器回应:${JSON.stringify(message, null, 2)}`, 'success'); - this.isEstablishConnection = true; + uiController.startAIChatSession(); } else if (message.type === 'tts') { this.handleTTSMessage(message); } else if (message.type === 'audio') { diff --git a/main/xiaozhi-server/test/js/ui/controller.js b/main/xiaozhi-server/test/js/ui/controller.js index 6cf2def7..1d22f32f 100644 --- a/main/xiaozhi-server/test/js/ui/controller.js +++ b/main/xiaozhi-server/test/js/ui/controller.js @@ -1,5 +1,5 @@ // UI控制模块 -import { loadConfig, saveConfig, getConfig } from '../config/manager.js'; +import { loadConfig, saveConfig } from '../config/manager.js'; import { getAudioRecorder } from '../core/audio/recorder.js'; import { getWebSocketHandler } from '../core/network/websocket.js'; import { getAudioPlayer } from '../core/audio/player.js'; @@ -11,7 +11,6 @@ class UIController { this.visualizerCanvas = null; this.visualizerContext = null; this.audioStatsTimer = null; - this.wsTimer = null; this.currentBackgroundIndex = 0; this.backgroundImages = ['1.png', '2.png', '3.png']; @@ -93,6 +92,7 @@ class UIController { if (isConnected) { wsHandler.disconnect(); this.updateDialButton(false); + this.addChatMessage('已断开连接,期待下次再见~😉', false); } else { // 检查OTA地址是否已填写 const otaUrlInput = document.getElementById('otaUrl'); @@ -347,30 +347,9 @@ class UIController { this.addChatMessage('配置已保存', false); } - // 处理未绑定设备事件 - handleUnboundDevice() { - const dialBtn = document.getElementById('dialBtn'); - if (dialBtn) { - dialBtn.click(); - } - } - - // 拨号成功后直接开始录音 - dialAndRecord() { - const recordBtn = document.getElementById('recordBtn'); - const wsHandler = getWebSocketHandler(); - this.wsTimer = setInterval(() => { - if (wsHandler.isConnected() && wsHandler.websocket.onopen) { - clearInterval(this.wsTimer); - this.wsTimer = null; - if (wsHandler.isEstablishConnection) { - recordBtn.click(); - } else { - this.handleUnboundDevice(); - } - return; - } - }, 500); + // 连接成功后开始对话 + startAIChatSession() { + this.addChatMessage('连接成功,开始聊天吧~🙂', false); } // 处理连接按钮点击 @@ -412,21 +391,12 @@ class UIController { } try { - // 获取配置信息 - const config = getConfig(); - // 导入OTA连接器 - const { webSocketConnect } = await import('../core/network/ota-connector.js'); + // 获取WebSocket处理器 + const wsHandler = getWebSocketHandler(); + const isConnected = await wsHandler.connect(); - // 建立OTA连接 - const websocket = await webSocketConnect(otaUrl, config); - - if (websocket) { - // 获取WebSocket处理器 - const wsHandler = getWebSocketHandler(); - - // 设置WebSocket连接 - wsHandler.websocket = websocket; + if (isConnected) { // 设置连接状态回调 wsHandler.onConnectionStateChange = (isConnected) => { @@ -462,16 +432,10 @@ class UIController { dialBtn.disabled = false; dialBtn.querySelector('.btn-text').textContent = '挂断'; dialBtn.classList.add('dial-active'); - - this.dialAndRecord(); } this.hideModal('settingsModal'); - // 自动尝试建立WebSocket连接 - setTimeout(() => { - wsHandler.connect(); - }, 1000); } else { throw new Error('OTA连接失败'); } From 3e7bc0606aaab5e528c8efd2c775e83eec8d9446 Mon Sep 17 00:00:00 2001 From: lww155 <756794909@qq.com> Date: Thu, 22 Jan 2026 16:16:09 +0800 Subject: [PATCH 3/4] =?UTF-8?q?update:=20=E4=BC=98=E5=8C=96=E8=83=8C?= =?UTF-8?q?=E6=99=AF=E5=8A=A0=E8=BD=BD=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/js/ui/background-load.js | 27 +++++++++++++++++++ .../test/js/ui/bg-image-load-detector.js | 15 ----------- main/xiaozhi-server/test/test_page.html | 4 +-- 3 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 main/xiaozhi-server/test/js/ui/background-load.js delete mode 100644 main/xiaozhi-server/test/js/ui/bg-image-load-detector.js diff --git a/main/xiaozhi-server/test/js/ui/background-load.js b/main/xiaozhi-server/test/js/ui/background-load.js new file mode 100644 index 00000000..b956f731 --- /dev/null +++ b/main/xiaozhi-server/test/js/ui/background-load.js @@ -0,0 +1,27 @@ +// 背景图加载检测 +(function() { + const backgroundContainer = document.getElementById('backgroundContainer'); + + // 提取背景图片URL + let bgImageUrl = window.getComputedStyle(backgroundContainer).backgroundImage; + const urlMatch = bgImageUrl && bgImageUrl.match(/url\(["']?(.*?)["']?\)/); + + if (!urlMatch || !urlMatch[1]) { + console.warn('未提取到有效的背景图片URL'); + return; + } + + bgImageUrl = urlMatch[1]; + + const bgImage = new Image(); + bgImage.onerror = function() { + console.error('背景图片加载失败:', bgImageUrl); + }; + + // 加载成功显示模型加载 + bgImage.onload = function() { + modelLoading.style.display = 'flex'; + }; + + bgImage.src = bgImageUrl; +})(); \ No newline at end of file diff --git a/main/xiaozhi-server/test/js/ui/bg-image-load-detector.js b/main/xiaozhi-server/test/js/ui/bg-image-load-detector.js deleted file mode 100644 index 9ab3f16b..00000000 --- a/main/xiaozhi-server/test/js/ui/bg-image-load-detector.js +++ /dev/null @@ -1,15 +0,0 @@ -// 背景图加载检测 -const backgroundContainer = document.getElementById('backgroundContainer'); -// 提取背景图片URL -let bgImageUrl = window.getComputedStyle(backgroundContainer).backgroundImage; -const urlMatch = bgImageUrl.match(/url\(["']?(.*?)["']?\)/); -bgImageUrl = urlMatch[1]; -const bgImage = new Image(); -bgImage.src = bgImageUrl; -// 加载完成后显示模型加载 -bgImage.onload = function () { - const modelLoading = document.getElementById('modelLoading'); - if (modelLoading) { - modelLoading.style.display = 'flex'; - } -} \ No newline at end of file diff --git a/main/xiaozhi-server/test/test_page.html b/main/xiaozhi-server/test/test_page.html index d11d9d42..e92a3ea9 100644 --- a/main/xiaozhi-server/test/test_page.html +++ b/main/xiaozhi-server/test/test_page.html @@ -236,8 +236,8 @@ - - + + From e1dd27270887a26a704395f0202b056ec287ea00 Mon Sep 17 00:00:00 2001 From: lww155 <756794909@qq.com> Date: Thu, 22 Jan 2026 17:23:27 +0800 Subject: [PATCH 4/4] =?UTF-8?q?update:=20=E5=85=B3=E9=97=AD=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E6=A1=86=E6=97=B6=E4=BF=9D=E5=AD=98=E9=85=8D=E7=BD=AE?= =?UTF-8?q?,=20=E9=98=BB=E6=AD=A2=E6=8C=89=E9=92=AE=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E5=86=92=E6=B3=A1,=20=E8=B0=83=E6=95=B4=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/xiaozhi-server/test/js/config/manager.js | 7 ++-- .../test/js/core/network/ota-connector.js | 2 +- main/xiaozhi-server/test/js/ui/controller.js | 35 +++++-------------- main/xiaozhi-server/test/test_page.html | 6 ++-- 4 files changed, 16 insertions(+), 34 deletions(-) diff --git a/main/xiaozhi-server/test/js/config/manager.js b/main/xiaozhi-server/test/js/config/manager.js index 9bc33122..e3d31843 100644 --- a/main/xiaozhi-server/test/js/config/manager.js +++ b/main/xiaozhi-server/test/js/config/manager.js @@ -58,10 +58,9 @@ export function saveConfig() { // 获取配置值 export function getConfig() { - // 从DOM获取值 - const deviceMac = document.getElementById('deviceMac')?.value.trim() || ''; - const deviceName = document.getElementById('deviceName')?.value.trim() || ''; - const clientId = document.getElementById('clientId')?.value.trim() || ''; + const deviceMac = localStorage.getItem('xz_tester_deviceMac'); + const deviceName = localStorage.getItem('xz_tester_deviceName'); + const clientId = localStorage.getItem('xz_tester_clientId'); return { deviceId: deviceMac, // 使用MAC地址作为deviceId diff --git a/main/xiaozhi-server/test/js/core/network/ota-connector.js b/main/xiaozhi-server/test/js/core/network/ota-connector.js index 2372c767..e254887a 100644 --- a/main/xiaozhi-server/test/js/core/network/ota-connector.js +++ b/main/xiaozhi-server/test/js/core/network/ota-connector.js @@ -83,7 +83,7 @@ async function sendOTA(otaUrl, config) { }, ota: { label: 'xiaozhi-web-test' }, board: { - type: 'xiaozhi-web-test', + type: config.deviceName, ssid: 'xiaozhi-web-test', rssi: 0, channel: 0, diff --git a/main/xiaozhi-server/test/js/ui/controller.js b/main/xiaozhi-server/test/js/ui/controller.js index 1d22f32f..664e27c2 100644 --- a/main/xiaozhi-server/test/js/ui/controller.js +++ b/main/xiaozhi-server/test/js/ui/controller.js @@ -152,8 +152,12 @@ class UIController { const closeButtons = document.querySelectorAll('.close-btn'); closeButtons.forEach(btn => { btn.addEventListener('click', (e) => { + e.stopPropagation(); const modal = e.target.closest('.modal'); if (modal) { + if (modal.id === 'settingsModal') { + saveConfig(); + } this.hideModal(modal.id); } }); @@ -172,23 +176,19 @@ class UIController { modals.forEach(modal => { modal.addEventListener('click', (e) => { if (e.target === modal) { + if (modal.id === 'settingsModal') { + saveConfig(); + } this.hideModal(modal.id); } }); }); - // 保存配置按钮 - const saveConfigBtn = document.getElementById('saveConfigBtn'); - if (saveConfigBtn) { - saveConfigBtn.addEventListener('click', () => { - this.saveConfig(); - }); - } - // 添加MCP工具按钮 const addMCPToolBtn = document.getElementById('addMCPToolBtn'); if (addMCPToolBtn) { - addMCPToolBtn.addEventListener('click', () => { + addMCPToolBtn.addEventListener('click', (e) => { + e.stopPropagation(); this.addMCPTool(); }); } @@ -330,23 +330,6 @@ class UIController { } } - // 保存配置 - saveConfig() { - const config = { - serverUrl: document.getElementById('serverUrl').value, - serverPort: document.getElementById('serverPort').value, - audioDevice: document.getElementById('audioDevice').value, - audioSampleRate: document.getElementById('audioSampleRate').value, - audioChannels: document.getElementById('audioChannels').value - }; - - saveConfig(config); - this.hideModal('settingsModal'); - - // 显示保存成功消息 - this.addChatMessage('配置已保存', false); - } - // 连接成功后开始对话 startAIChatSession() { this.addChatMessage('连接成功,开始聊天吧~🙂', false); diff --git a/main/xiaozhi-server/test/test_page.html b/main/xiaozhi-server/test/test_page.html index e92a3ea9..9a3bf04e 100644 --- a/main/xiaozhi-server/test/test_page.html +++ b/main/xiaozhi-server/test/test_page.html @@ -133,7 +133,7 @@
- +
@@ -143,7 +143,7 @@
- +
@@ -237,7 +237,7 @@ - +