diff --git a/main/xiaozhi-server/test/css/test_page.css b/main/xiaozhi-server/test/css/test_page.css index 3aac3df1..7ca6ef85 100644 --- a/main/xiaozhi-server/test/css/test_page.css +++ b/main/xiaozhi-server/test/css/test_page.css @@ -54,6 +54,82 @@ body { /* 移除底部padding,让模型可以延伸到页面底部 */ } +/* ==================== 模型加载区 ==================== */ +.model-container { + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 200px; + transform: translate(-50%, -50%); + user-select: none; +} + +.model-loading { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: none; + flex-direction: column; + justify-content: center; + align-items: center; + z-index: 999; + transition: opacity 0.5s ease-out, visibility 0.5s ease-out; + background-image: linear-gradient(transparent 50%, rgba(88, 101, 242, 0.05) 50%); + background-size: 100% 4px; + animation: scan 1.26s linear infinite; +} + +.loading-char-float { + font-size: 22px; + letter-spacing: 3px; + position: relative; +} + +.loading-char-float .main-char { + color: #f0f8ff; + text-shadow: 0 0 5px #5865f2, 0 0 10px rgba(88, 101, 242, 0.8); + display: inline-block; +} + +.loading-char-float .main-char span { + animation: char-float 1.26s ease-in-out infinite; + display: inline-block; +} + +.loading-char-float .shadow-char { + position: absolute; + top: 3px; + left: 0; + color: rgba(88, 101, 242, 0.3); + pointer-events: none; + animation: shadow-float 1.26s ease-in-out infinite; +} + +.loading-char-float .main-char span:nth-child(1) { animation-delay: 0s; } +.loading-char-float .main-char span:nth-child(2) { animation-delay: 0.11s; } +.loading-char-float .main-char span:nth-child(3) { animation-delay: 0.22s; } +.loading-char-float .main-char span:nth-child(4) { animation-delay: 0.33s; } +.loading-char-float .main-char span:nth-child(5) { animation-delay: 0.44s; } +.loading-char-float .main-char span:nth-child(6) { animation-delay: 0.55s; } + +@keyframes scan { + 0% { background-position: 0 0; } + 100% { background-position: 0 100px; } +} + +@keyframes char-float { + 0%, 100% { transform: translateY(0); opacity: 1; text-shadow: 0 0 5px #5865f2, 0 0 10px rgba(88, 101, 242, 0.8); } + 50% { transform: translateY(-5px); opacity: 0.9; text-shadow: 0 0 10px #5865f2, 0 0 20px rgba(88, 101, 242, 0.8); } +} + +@keyframes shadow-float { + 0%, 100% { transform: translateY(3px); opacity: 0.3; } + 50% { transform: translateY(8px); opacity: 0.15; } +} + /* ==================== Live2D显示区域 ==================== */ #live2d-stage { position: fixed; diff --git a/main/xiaozhi-server/test/js/app.js b/main/xiaozhi-server/test/js/app.js index b608f69d..518e49c4 100644 --- a/main/xiaozhi-server/test/js/app.js +++ b/main/xiaozhi-server/test/js/app.js @@ -37,9 +37,20 @@ class App { // 初始化Live2D await this.initLive2D(); + // 关闭加载loading + this.setModelLoadingStatus(false); + log('应用初始化完成', 'success'); } + // 设置model加载状态 + setModelLoadingStatus(isLoading) { + const modelLoading = document.getElementById('modelLoading'); + if (modelLoading) { + modelLoading.style.display = isLoading ? 'flex' : 'none'; + } + } + // 初始化Live2D async initLive2D() { try { @@ -83,6 +94,12 @@ if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => app.init()); } else { app.init(); + window.addEventListener('beforeunload', () => { + // 销毁定时器 + if (app.uiController && app.uiController.wsTimer) { + clearInterval(app.uiController.wsTimer); + } + }); } export default app; 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 new file mode 100644 index 00000000..9ab3f16b --- /dev/null +++ b/main/xiaozhi-server/test/js/ui/bg-image-load-detector.js @@ -0,0 +1,15 @@ +// 背景图加载检测 +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/js/ui/controller.js b/main/xiaozhi-server/test/js/ui/controller.js index 0bdbdec7..79409388 100644 --- a/main/xiaozhi-server/test/js/ui/controller.js +++ b/main/xiaozhi-server/test/js/ui/controller.js @@ -11,6 +11,7 @@ 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']; @@ -275,7 +276,7 @@ class UIController { this.currentBackgroundIndex = (this.currentBackgroundIndex + 1) % this.backgroundImages.length; const backgroundContainer = document.querySelector('.background-container'); if (backgroundContainer) { - backgroundContainer.style.backgroundImage = `url('../images/${this.backgroundImages[this.currentBackgroundIndex]}')`; + backgroundContainer.style.backgroundImage = `url('./images/${this.backgroundImages[this.currentBackgroundIndex]}')`; } } @@ -331,6 +332,20 @@ class UIController { this.addChatMessage('配置已保存', false); } + // 拨号成功后直接开始录音 + dialAndRecord() { + const recordBtn = document.getElementById('recordBtn'); + const wsHandler = getWebSocketHandler(); + this.wsTimer = setInterval(() => { + if (wsHandler.isConnected() && wsHandler.websocket.onopen) { + clearInterval(this.wsTimer); + this.wsTimer = null; + recordBtn.click(); + return; + } + }, 500); + } + // 处理连接按钮点击 async handleConnect() { console.log('handleConnect called'); @@ -415,6 +430,8 @@ class UIController { dialBtn.disabled = false; dialBtn.querySelector('.btn-text').textContent = '挂断'; dialBtn.classList.add('dial-active'); + + this.dialAndRecord(); } this.hideModal('settingsModal'); diff --git a/main/xiaozhi-server/test/test_page.html b/main/xiaozhi-server/test/test_page.html index 1bacc056..3d938c52 100644 --- a/main/xiaozhi-server/test/test_page.html +++ b/main/xiaozhi-server/test/test_page.html @@ -38,7 +38,7 @@
-