@siact/sime-x-vue 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sime-x-vue.mjs","sources":["../src/injection-key.ts","../src/types.ts","../src/components/sime-provider.vue","../src/components/voice-status.vue","../src/components/execution-status.vue","../src/lib/utils.ts","../src/components/sime-x.vue"],"sourcesContent":["import type { InjectionKey } from 'vue'\r\nimport type { AiChatbotXContext } from './types'\r\nimport { inject } from 'vue'\r\n\r\nexport const AiChatbotXKey: InjectionKey<AiChatbotXContext> = Symbol('sime-x')\r\n\r\nexport function injectStrict<T>(key: InjectionKey<T>): T\r\nexport function injectStrict<T>(key: InjectionKey<T>, defaultValue: T, treatDefaultAsFactory?: false): T\r\nexport function injectStrict<T>(key: InjectionKey<T>, defaultValue: T | (() => T), treatDefaultAsFactory: true): T\r\nexport function injectStrict<T>(key: InjectionKey<T>, defaultValue?: T | (() => T), treatDefaultAsFactory?: boolean): T {\r\n let result: T | undefined\r\n\r\n if (defaultValue === undefined) {\r\n result = inject(key) as T | undefined\r\n }\r\n else if (treatDefaultAsFactory === true) {\r\n result = inject(key, defaultValue as T | (() => T), true)\r\n }\r\n else {\r\n result = inject(key, defaultValue as T, false)\r\n }\r\n\r\n if (!result) {\r\n throw new Error(`Could not resolve ${key.description}`)\r\n }\r\n return result\r\n}\r\n","import type { CommandDefinition, DiscoveredCommand } from \"@siact/sime-bridge\";\r\n\r\nexport enum clientCommandKey {\r\n SET_THEME = \"SiMeAgent_setTheme\",\r\n APPEND_MESSAGE = \"SiMeAgent_appendMessage\",\r\n WAKE = \"SiMeAgent_wake\",\r\n TRANSITION = \"SiMeAgent_transition\",\r\n TRANSITION_END = \"SiMeAgent_transition_end\",\r\n START_NEW_CONVERSATION = \"SiMeAgent_startNewConversation\",\r\n RECOGNITION = 'SiMeAgent_recognition'\r\n}\r\n\r\nexport interface VoiceConfig {\r\n appId: string;\r\n apiKey: string;\r\n websocketUrl: string;\r\n}\r\n\r\nexport interface AiChatbotXContext {\r\n chatbotUrl: () => string;\r\n appId: () => string;\r\n appToken: () => string;\r\n voiceConfig: () => VoiceConfig;\r\n registerCommand: (cmd: CommandDefinition) => void;\r\n unregisterCommand: (name: string) => void;\r\n clientCommand: () => Promise<DiscoveredCommand[]>;\r\n hostCommads: () => Promise<DiscoveredCommand[]>;\r\n appendMessage: (message: string) => Promise<void>;\r\n setTheme: (theme: string) => Promise<void>;\r\n weak: () => Promise<void>;\r\n startListening: () => Promise<void>;\r\n stopListening: () => Promise<void>;\r\n toggleCollapse: () => Promise<void>;\r\n openDialog: () => Promise<void>;\r\n closeDialog: () => Promise<void>;\r\n registerVoiceMethods: (methods: {\r\n start: () => Promise<void>;\r\n stop: () => Promise<void>;\r\n toggleCollapse: () => Promise<void>;\r\n openDialog: () => Promise<void>;\r\n closeDialog: () => Promise<void>;\r\n }) => void;\r\n startNewConversation: () => Promise<void>;\r\n setIframeElement: (iframe: HTMLIFrameElement) => void;\r\n recognition: (message: string, commands: DiscoveredCommand[]) => Promise<any>;\r\n executeCommand: (commandName: string, args?: any[]) => Promise<any>;\r\n}\r\n","<template>\r\n <slot></slot>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { provide, shallowRef } from 'vue';\r\nimport { HostBridge, CommandDefinition } from '@siact/sime-bridge';\r\nimport { AiChatbotXKey } from '../injection-key';\r\nimport { clientCommandKey, VoiceConfig } from '../types';\r\n\r\nconst props = defineProps<{\r\n /** 项目名称 */\r\n project: string;\r\n /** 项目描述 */\r\n description?: string;\r\n /** 是否开启调试模式 */\r\n debug?: boolean;\r\n /** iframeUrl */\r\n chatbotUrl: string;\r\n /** appId */\r\n appId: string;\r\n /** appToken */\r\n appToken: string;\r\n /** 语音配置 */\r\n voiceConfig: VoiceConfig;\r\n}>();\r\n\r\nconst hostBridge = shallowRef<HostBridge>(new HostBridge());\r\n\r\nconst startListeningRef = shallowRef<() => Promise<void>>(async () => {});\r\nconst stopListeningRef = shallowRef<() => Promise<void>>(async () => {});\r\nconst toggleCollapseRef = shallowRef<() => Promise<void>>(async () => {});\r\nconst openDialogRef = shallowRef<() => Promise<void>>(async () => {});\r\nconst closeDialogRef = shallowRef<() => Promise<void>>(async () => {});\r\n\r\nprovide(AiChatbotXKey, {\r\n chatbotUrl: () => props.chatbotUrl,\r\n appId: () => props.appId,\r\n appToken: () => props.appToken,\r\n voiceConfig: () => props.voiceConfig,\r\n startListening: () => startListeningRef.value(),\r\n stopListening: () => stopListeningRef.value(),\r\n toggleCollapse: () => toggleCollapseRef.value(),\r\n openDialog: () => openDialogRef.value(),\r\n closeDialog: () => closeDialogRef.value(),\r\n registerVoiceMethods: (methods: {\r\n start: () => Promise<void>;\r\n stop: () => Promise<void>;\r\n toggleCollapse: () => Promise<void>;\r\n openDialog: () => Promise<void>;\r\n closeDialog: () => Promise<void>;\r\n }) => {\r\n startListeningRef.value = methods.start;\r\n stopListeningRef.value = methods.stop;\r\n toggleCollapseRef.value = methods.toggleCollapse;\r\n openDialogRef.value = methods.openDialog;\r\n closeDialogRef.value = methods.closeDialog;\r\n },\r\n clientCommand: () => hostBridge.value.clientCommands(),\r\n hostCommads: () => hostBridge.value.hostCommands(),\r\n registerCommand: (cmd: CommandDefinition) => {\r\n hostBridge.value.registerCommand(cmd);\r\n },\r\n unregisterCommand: (name) => {\r\n hostBridge.value.unregisterCommand(name);\r\n },\r\n async appendMessage(message) {\r\n await hostBridge.value.executeClientCommand(clientCommandKey.APPEND_MESSAGE, [message]);\r\n },\r\n async setTheme(theme) {\r\n await hostBridge.value.executeClientCommand(clientCommandKey.SET_THEME, [theme]);\r\n },\r\n async weak() {\r\n await hostBridge.value.executeClientCommand(clientCommandKey.WAKE);\r\n },\r\n async startNewConversation() {\r\n await hostBridge.value.executeClientCommand(clientCommandKey.START_NEW_CONVERSATION);\r\n },\r\n setIframeElement(iframe) {\r\n hostBridge.value.setIframe(iframe);\r\n },\r\n async recognition(message, commands) {\r\n return await hostBridge.value.executeClientCommand(clientCommandKey.RECOGNITION, [message, commands]);\r\n },\r\n async executeCommand(commandName, args = []) {\r\n return await hostBridge.value.executeCommand(commandName, args);\r\n },\r\n});\r\n</script>\r\n","<template>\r\n <transition name=\"voice-panel\">\r\n <!-- Main Container -->\r\n <div v-if=\"status === 'wake' || isTranscribing\" class=\"voice-status-wrapper\" :class=\"currentMode\">\r\n <!-- Visual Indicator Section -->\r\n <div class=\"indicator-container\">\r\n <!-- Ambient Glow (Background) -->\r\n <div class=\"ambient-glow\"></div>\r\n\r\n <!-- Animated Ripples -->\r\n <div class=\"ripple-layer\">\r\n <div class=\"ripple delay-1\"></div>\r\n <div class=\"ripple delay-2\"></div>\r\n <div class=\"ripple delay-3\"></div>\r\n </div>\r\n\r\n <!-- Core Icon Circle -->\r\n <div class=\"icon-core\">\r\n <!-- Unified Microphone Icon -->\r\n <svg\r\n class=\"mic-icon\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <!-- Microphone Capsule (Animates on voice) -->\r\n <rect x=\"9\" y=\"2\" width=\"6\" height=\"12\" rx=\"3\" class=\"mic-capsule\" />\r\n <!-- Stand/Base -->\r\n <path d=\"M5 10C5 13.866 8.13401 17 12 17C15.866 17 19 13.866 19 10\" class=\"mic-stand\" />\r\n <path d=\"M12 17V21M8 21H16\" class=\"mic-base\" />\r\n </svg>\r\n </div>\r\n </div>\r\n\r\n <!-- Content Section -->\r\n <div class=\"content-container\">\r\n <!-- Status Header -->\r\n <div class=\"status-header\">\r\n <span class=\"status-text\">{{ statusLabel }}</span>\r\n </div>\r\n\r\n <!-- Transcription Text (Animated Entry) -->\r\n <div class=\"text-window\" :class=\"{ 'has-text': !!transcriptionText }\">\r\n <transition name=\"fade-slide\" mode=\"out-in\">\r\n <p v-if=\"transcriptionText\" class=\"transcription-content\">\r\n {{ transcriptionText }}\r\n </p>\r\n <p v-else-if=\"status === 'wake'\" class=\"placeholder-text\">Listening...</p>\r\n </transition>\r\n </div>\r\n </div>\r\n </div>\r\n </transition>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from 'vue';\r\ntype VoiceStatus = 'wake' | 'listening' | 'standby';\r\n\r\nconst props = defineProps<{\r\n status: VoiceStatus;\r\n transcriptionText?: string;\r\n isTranscribing?: boolean;\r\n}>();\r\n\r\n// Determine the current visual mode\r\nconst currentMode = computed(() => {\r\n if (props.isTranscribing) return 'mode-transcribing';\r\n if (props.status === 'wake') return 'mode-wake';\r\n return 'mode-standby';\r\n});\r\n\r\n// Dynamic label text\r\nconst statusLabel = computed(() => {\r\n if (props.isTranscribing) return '正在聆听您的问题...';\r\n if (props.status === 'wake') return '您好,有什么可以帮助您的吗?';\r\n return 'Standby';\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n@use 'sass:color';\r\n\r\n/* --- Design Tokens --- */\r\n$c-wake: #10b981; // Emerald for Wake\r\n$c-transcribe: #3b82f6; // Blue for Transcribing\r\n$bg-glass: rgba(15, 23, 42, 0.85);\r\n$border-glass: rgba(255, 255, 255, 0.1);\r\n$ease-smooth: cubic-bezier(0.25, 0.8, 0.25, 1);\r\n$ease-elastic: cubic-bezier(0.34, 1.56, 0.64, 1);\r\n\r\n/* --- Main Container --- */\r\n.voice-status-wrapper {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 20px;\r\n padding: 24px;\r\n background: $bg-glass;\r\n backdrop-filter: blur(16px);\r\n -webkit-backdrop-filter: blur(16px);\r\n border: 1px solid $border-glass;\r\n border-radius: 24px;\r\n box-shadow:\r\n 0 10px 40px -10px rgba(0, 0, 0, 0.5),\r\n inset 0 1px 0 rgba(255, 255, 255, 0.1);\r\n transition: all 0.4s $ease-smooth;\r\n max-width: 480px;\r\n width: 100%;\r\n}\r\n\r\n/* --- Indicator Section --- */\r\n.indicator-container {\r\n position: relative;\r\n width: 64px;\r\n height: 64px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n}\r\n\r\n.ambient-glow {\r\n position: absolute;\r\n inset: -20px;\r\n border-radius: 50%;\r\n opacity: 0;\r\n filter: blur(20px);\r\n transition: all 0.5s ease;\r\n}\r\n\r\n.icon-core {\r\n position: relative;\r\n width: 52px;\r\n height: 52px;\r\n border-radius: 50%;\r\n background: rgba(255, 255, 255, 0.05);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border: 1px solid rgba(255, 255, 255, 0.1);\r\n z-index: 10;\r\n transition: all 0.4s $ease-elastic;\r\n overflow: hidden;\r\n\r\n .mic-icon {\r\n width: 24px;\r\n height: 24px;\r\n color: rgba(255, 255, 255, 0.9);\r\n transition: all 0.3s ease;\r\n\r\n .mic-capsule {\r\n transition: transform 0.2s ease;\r\n transform-origin: center center;\r\n }\r\n }\r\n}\r\n\r\n/* --- Ripple Effects --- */\r\n.ripple-layer {\r\n position: absolute;\r\n inset: 0;\r\n pointer-events: none;\r\n}\r\n\r\n.ripple {\r\n position: absolute;\r\n inset: 0;\r\n border-radius: 50%;\r\n border: 2px solid transparent;\r\n opacity: 0;\r\n}\r\n\r\n/* --- Content Section --- */\r\n.content-container {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n min-width: 0; /* Prevent flex text overflow */\r\n padding-top: 4px;\r\n}\r\n\r\n.status-header {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.status-dot {\r\n width: 6px;\r\n height: 6px;\r\n border-radius: 50%;\r\n background: currentColor;\r\n box-shadow: 0 0 8px currentColor;\r\n transition: color 0.3s ease;\r\n}\r\n\r\n.status-text {\r\n font-size: 13px;\r\n font-weight: 600;\r\n text-transform: uppercase;\r\n letter-spacing: 0.05em;\r\n color: rgba(255, 255, 255, 0.6);\r\n}\r\n\r\n.text-window {\r\n min-height: 24px;\r\n position: relative;\r\n}\r\n\r\n.transcription-content {\r\n font-size: 16px;\r\n line-height: 1.5;\r\n color: #fff;\r\n font-weight: 500;\r\n margin: 0;\r\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\r\n}\r\n\r\n.placeholder-text {\r\n font-size: 16px;\r\n color: rgba(255, 255, 255, 0.3);\r\n font-style: italic;\r\n margin: 0;\r\n}\r\n\r\n/* --- State: Wake --- */\r\n.mode-wake {\r\n border-color: rgba($c-wake, 0.3);\r\n\r\n .ambient-glow {\r\n background: $c-wake;\r\n opacity: 0.2;\r\n }\r\n\r\n .icon-core {\r\n background: linear-gradient(135deg, rgba($c-wake, 0.2), rgba($c-wake, 0.1));\r\n border-color: rgba($c-wake, 0.4);\r\n box-shadow: 0 0 15px rgba($c-wake, 0.2);\r\n\r\n .mic-icon {\r\n color: color.adjust($c-wake, $lightness: 10%);\r\n }\r\n }\r\n\r\n .status-dot {\r\n color: $c-wake;\r\n animation: pulse-dot 2s infinite;\r\n }\r\n\r\n .ripple {\r\n border-color: $c-wake;\r\n animation: ripple-out 3s infinite;\r\n\r\n &.delay-1 {\r\n animation-delay: 0s;\r\n }\r\n &.delay-2 {\r\n animation-delay: 1s;\r\n }\r\n &.delay-3 {\r\n animation-delay: 2s;\r\n }\r\n }\r\n}\r\n\r\n/* --- State: Transcribing --- */\r\n.mode-transcribing {\r\n border-color: rgba($c-transcribe, 0.3);\r\n\r\n .ambient-glow {\r\n background: $c-transcribe;\r\n opacity: 0.3;\r\n animation: glow-breathe 1.5s ease-in-out infinite alternate;\r\n }\r\n\r\n .icon-core {\r\n background: linear-gradient(135deg, rgba($c-transcribe, 0.3), rgba($c-transcribe, 0.1));\r\n border-color: rgba($c-transcribe, 0.5);\r\n box-shadow: 0 0 20px rgba($c-transcribe, 0.3);\r\n transform: scale(1.1);\r\n\r\n .mic-icon {\r\n color: #fff;\r\n\r\n .mic-capsule {\r\n animation: mic-bounce 0.6s ease-in-out infinite alternate;\r\n }\r\n }\r\n }\r\n\r\n .status-dot {\r\n color: $c-transcribe;\r\n }\r\n\r\n .ripple {\r\n border-color: $c-transcribe;\r\n animation: ripple-rapid 1.5s infinite;\r\n\r\n &.delay-1 {\r\n animation-delay: 0s;\r\n }\r\n &.delay-2 {\r\n animation-delay: 0.3s;\r\n }\r\n &.delay-3 {\r\n animation-delay: 0.6s;\r\n }\r\n }\r\n}\r\n\r\n/* --- Animations --- */\r\n@keyframes ripple-out {\r\n 0% {\r\n transform: scale(0.8);\r\n opacity: 0;\r\n border-width: 2px;\r\n }\r\n 20% {\r\n opacity: 0.5;\r\n }\r\n 100% {\r\n transform: scale(2.2);\r\n opacity: 0;\r\n border-width: 0px;\r\n }\r\n}\r\n\r\n@keyframes ripple-rapid {\r\n 0% {\r\n transform: scale(0.9);\r\n opacity: 0;\r\n }\r\n 50% {\r\n opacity: 0.4;\r\n }\r\n 100% {\r\n transform: scale(1.6);\r\n opacity: 0;\r\n }\r\n}\r\n\r\n@keyframes pulse-dot {\r\n 0%,\r\n 100% {\r\n opacity: 1;\r\n transform: scale(1);\r\n }\r\n 50% {\r\n opacity: 0.5;\r\n transform: scale(0.8);\r\n }\r\n}\r\n\r\n@keyframes glow-breathe {\r\n 0% {\r\n opacity: 0.2;\r\n transform: scale(0.9);\r\n }\r\n 100% {\r\n opacity: 0.4;\r\n transform: scale(1.1);\r\n }\r\n}\r\n\r\n@keyframes mic-bounce {\r\n 0% {\r\n transform: scaleY(1);\r\n }\r\n 100% {\r\n transform: scaleY(0.7);\r\n }\r\n}\r\n\r\n/* --- Vue Transitions --- */\r\n.voice-panel-enter-active,\r\n.voice-panel-leave-active {\r\n transition: all 0.4s $ease-elastic;\r\n}\r\n.voice-panel-enter-from,\r\n.voice-panel-leave-to {\r\n opacity: 0;\r\n transform: translateY(20px) scale(0.95);\r\n}\r\n\r\n.fade-slide-enter-active,\r\n.fade-slide-leave-active {\r\n transition: all 0.3s ease;\r\n}\r\n.fade-slide-enter-from {\r\n opacity: 0;\r\n transform: translateY(10px);\r\n}\r\n.fade-slide-leave-to {\r\n opacity: 0;\r\n transform: translateY(-10px);\r\n}\r\n</style>\r\n","<template>\r\n <transition name=\"exec-bubble\">\r\n <div v-if=\"visible\" class=\"execution-bubble\">\r\n <!-- 文本内容 -->\r\n <span class=\"exec-text\">{{ text || '执行中' }}</span>\r\n <!-- 三点加载动画 -->\r\n <div class=\"loading-dots\">\r\n <span class=\"dot\"></span>\r\n <span class=\"dot\"></span>\r\n <span class=\"dot\"></span>\r\n </div>\r\n </div>\r\n </transition>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\ndefineProps<{\r\n visible: boolean;\r\n text?: string;\r\n}>();\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n$c-exec: #a855f7;\r\n$c-exec-light: #c084fc;\r\n$bg-glass: rgba(15, 23, 42, 0.9);\r\n$ease-smooth: cubic-bezier(0.25, 0.8, 0.25, 1);\r\n\r\n.execution-bubble {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 12px 20px;\r\n background: $bg-glass;\r\n backdrop-filter: blur(16px);\r\n -webkit-backdrop-filter: blur(16px);\r\n border: 1px solid rgba($c-exec, 0.35);\r\n border-radius: 20px;\r\n box-shadow:\r\n 0 4px 20px rgba(0, 0, 0, 0.3),\r\n 0 0 20px -5px rgba($c-exec, 0.3),\r\n inset 0 1px 0 rgba(255, 255, 255, 0.08);\r\n}\r\n\r\n/* 文本样式 */\r\n.exec-text {\r\n font-size: 14px;\r\n font-weight: 500;\r\n color: rgba(255, 255, 255, 0.9);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: 300px;\r\n}\r\n\r\n/* 三点加载动画 */\r\n.loading-dots {\r\n display: flex;\r\n align-items: center;\r\n gap: 5px;\r\n margin-left: 10px;\r\n}\r\n\r\n.dot {\r\n width: 6px;\r\n height: 6px;\r\n border-radius: 50%;\r\n background: $c-exec-light;\r\n animation: dot-bounce 1.4s ease-in-out infinite;\r\n\r\n &:nth-child(1) {\r\n animation-delay: 0s;\r\n }\r\n &:nth-child(2) {\r\n animation-delay: 0.2s;\r\n }\r\n &:nth-child(3) {\r\n animation-delay: 0.4s;\r\n }\r\n}\r\n\r\n@keyframes dot-bounce {\r\n 0%,\r\n 80%,\r\n 100% {\r\n transform: scale(0.6);\r\n opacity: 0.4;\r\n }\r\n 40% {\r\n transform: scale(1);\r\n opacity: 1;\r\n box-shadow: 0 0 8px rgba($c-exec-light, 0.6);\r\n }\r\n}\r\n\r\n/* Vue 过渡动画 */\r\n.exec-bubble-enter-active {\r\n transition: all 0.3s $ease-smooth;\r\n}\r\n\r\n.exec-bubble-leave-active {\r\n transition: all 0.2s $ease-smooth;\r\n}\r\n\r\n.exec-bubble-enter-from {\r\n opacity: 0;\r\n transform: scale(0.8);\r\n}\r\n\r\n.exec-bubble-leave-to {\r\n opacity: 0;\r\n transform: scale(0.8);\r\n}\r\n</style>\r\n","import { DiscoveredCommand } from '@siact/sime-bridge'\r\n\r\nexport const ensureMicrophonePermission = async () => {\r\n // 检查浏览器环境\r\n if (typeof navigator === 'undefined' || typeof window === 'undefined') {\r\n console.log('当前环境不支持麦克风访问');\r\n return false;\r\n }\r\n\r\n // 检查 MediaDevices API 支持\r\n if (!navigator.mediaDevices?.getUserMedia || !navigator.mediaDevices?.enumerateDevices) {\r\n console.log('当前环境不支持麦克风访问');\r\n return false;\r\n }\r\n\r\n try {\r\n // 1. 首先枚举设备,检查是否有音频输入设备\r\n const devices = await navigator.mediaDevices.enumerateDevices();\r\n const audioInputDevices = devices.filter((device) => device.kind === 'audioinput');\r\n\r\n if (audioInputDevices.length === 0) {\r\n console.log('未检测到麦克风设备,请连接麦克风后重试。');\r\n return false;\r\n }\r\n\r\n // 2. 检查权限状态(如果浏览器支持)\r\n if ('permissions' in navigator && navigator.permissions?.query) {\r\n try {\r\n const status = await navigator.permissions.query({ name: 'microphone' as PermissionName });\r\n\r\n if (status.state === 'denied') {\r\n console.log('麦克风权限被禁用,请在浏览器设置中开启。');\r\n return false;\r\n }\r\n } catch (e) {\r\n // 某些浏览器可能不支持 microphone 权限查询,继续执行\r\n console.warn('Permission query not supported:', e);\r\n }\r\n }\r\n\r\n // 3. 尝试获取麦克风流以确认权限和设备可用性\r\n let stream: MediaStream | null = null;\r\n try {\r\n stream = await navigator.mediaDevices.getUserMedia({\r\n audio: {\r\n echoCancellation: true,\r\n noiseSuppression: true,\r\n autoGainControl: true,\r\n },\r\n });\r\n\r\n // 检查流是否有活动的音频轨道\r\n const audioTracks = stream.getAudioTracks();\r\n if (audioTracks.length === 0) {\r\n console.log('无法获取麦克风音频轨道。');\r\n return false;\r\n }\r\n\r\n // 检查音频轨道是否启用且可读\r\n const activeTrack = audioTracks[0];\r\n if (!activeTrack.enabled || activeTrack.readyState !== 'live') {\r\n console.log('麦克风设备不可用,请检查设备连接。');\r\n return false;\r\n }\r\n\r\n return true;\r\n } finally {\r\n // 确保释放流资源\r\n if (stream) {\r\n stream.getTracks().forEach((track) => track.stop());\r\n }\r\n }\r\n } catch (error: any) {\r\n console.error('Microphone permission check failed', error);\r\n\r\n // 根据错误类型提供更具体的提示\r\n if (error.name === 'NotFoundError' || error.name === 'DevicesNotFoundError') {\r\n console.log('未检测到麦克风设备,请连接麦克风后重试。');\r\n } else if (error.name === 'NotAllowedError' || error.name === 'PermissionDeniedError') {\r\n console.log('麦克风权限被拒绝,请在浏览器设置中允许访问。');\r\n } else if (error.name === 'NotReadableError' || error.name === 'TrackStartError') {\r\n console.log('麦克风被其他应用占用或无法访问。');\r\n } else {\r\n console.log('无法访问麦克风,请检查设备连接和浏览器权限。');\r\n }\r\n\r\n return false;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * 语音命令匹配函数\r\n * @param {string} userInput - 用户输入的原始语音文本\r\n * @param {Array} commandList - 命令列表对象数组\r\n * @param {number} threshold - 相似度阈值 (0-1),默认 0.5\r\n */\r\nexport function matchVoiceCommand(userInput: string, commandList: DiscoveredCommand[], threshold = 0.5) {\r\n if (!userInput || typeof userInput !== 'string') return null;\r\n\r\n // 1. 预处理:转小写、去空格、去标点、去语气词\r\n const cleanInput = userInput\r\n .trim()\r\n .toLowerCase()\r\n // 1. 去除所有标点符号及特殊字符\r\n .replace(/[,。?!;:、“”()()<>《》\\s\\.\\,\\?\\!]/g, '')\r\n // 2. 去除常见的前缀 (增加“给我”、“能不能”等)\r\n .replace(/^(请帮我|我想|帮我|麻烦|我要|你好|您好|帮我把|给我|能不能帮我|请问|那个)/g, '')\r\n // 3. 去除中间的动作虚词 (如“把...给...”)\r\n .replace(/给(?=(打开|开启|关闭|停止))/g, '')\r\n // 4. 去除常见的后缀 (增加“就可以了”、“就行”、“模式”)\r\n .replace(/(一下|了|吧|输出|就可以了|就行|模式|操作|功能)$/g, '');\r\n\r\n let bestMatch = null;\r\n let maxScore = 0;\r\n\r\n // 编辑距离算法 (Levenshtein Distance)\r\n const getSimilarity = (s1: string, s2: string) => {\r\n const [l1, l2] = [s1.length, s2.length];\r\n const matrix = Array.from({ length: l1 + 1 }, () => Array(l2 + 1).fill(0));\r\n for (let i = 0; i <= l1; i++) matrix[i][0] = i;\r\n for (let j = 0; j <= l2; j++) matrix[0][j] = j;\r\n\r\n for (let i = 1; i <= l1; i++) {\r\n for (let j = 1; j <= l2; j++) {\r\n const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;\r\n matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);\r\n }\r\n }\r\n return 1 - matrix[l1][l2] / Math.max(l1, l2);\r\n };\r\n\r\n // 2. 遍历命令列表进行比对\r\n for (const cmd of commandList) {\r\n const target = cmd.description.toLowerCase();\r\n let currentScore = 0;\r\n\r\n // 策略 A:直接包含 (如输入“帮我开启漫游吧”,描述是“开启漫游”)\r\n if (cleanInput.includes(target) || target.includes(cleanInput)) {\r\n // 计算包含关系的得分,越接近 1 分越高\r\n currentScore = Math.min(target.length, cleanInput.length) / Math.max(target.length, cleanInput.length);\r\n // 给予包含匹配更高的基础权重\r\n currentScore = 0.8 + currentScore * 0.2;\r\n }\r\n // 策略 B:模糊匹配 (处理同音字错误,如“开启慢游”)\r\n else {\r\n currentScore = getSimilarity(cleanInput, target);\r\n }\r\n\r\n // 更新最高分项\r\n if (currentScore > maxScore) {\r\n maxScore = currentScore;\r\n bestMatch = { ...cmd, confidence: maxScore };\r\n }\r\n }\r\n\r\n // 3. 结果过滤\r\n return maxScore >= threshold ? bestMatch : null;\r\n}","<template>\r\n <div class=\"sime-x\" :data-theme=\"currentTheme\">\r\n <!-- 悬浮按钮(最小化状态) -->\r\n <transition name=\"fade\">\r\n <div ref=\"fabRef\" class=\"assistant-fab\" @click=\"toggleDialog(true)\">\r\n <VoiceStatus\r\n v-if=\"!isProcessing\"\r\n class=\"voice-status\"\r\n :status=\"voiceStatus\"\r\n :transcription-text=\"transcriptionText\"\r\n :is-transcribing=\"isTranscribing\"\r\n style=\"width: 480px\"\r\n />\r\n <ExecutionStatus v-else class=\"voice-status\" :visible=\"isProcessing\" :text=\"transcriptionText\" />\r\n <div class=\"fab-avatar-wrapper\">\r\n <img\r\n :src=\"xLogo ? xLogo : '/sime.png'\"\r\n alt=\"assistant\"\r\n :style=\"{\r\n width: xSize?.width + 'px',\r\n }\"\r\n />\r\n <!-- 优化后的监听状态指示器 -->\r\n <transition name=\"indicator-fade\">\r\n <div v-if=\"voiceStatus === 'listening'\" class=\"listening-badge\">\r\n <div class=\"listening-waves\">\r\n <div class=\"wave wave-1\"></div>\r\n <div class=\"wave wave-2\"></div>\r\n <div class=\"wave wave-3\"></div>\r\n </div>\r\n <div class=\"listening-icon\">\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path\r\n d=\"M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z\"\r\n fill=\"currentColor\"\r\n />\r\n <path\r\n d=\"M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n </div>\r\n </transition>\r\n </div>\r\n <div class=\"fab-pulse\" :class=\"{ active: voiceStatus === 'listening' }\"></div>\r\n </div>\r\n </transition>\r\n\r\n <!-- 弹窗 -->\r\n <transition name=\"dialog-fade\">\r\n <div\r\n ref=\"dialogRef\"\r\n class=\"x-dialog-container\"\r\n :class=\"{\r\n collapsed: isCollapsed,\r\n 'is-hidden': !visible,\r\n 'position-ready': positionReady,\r\n }\"\r\n :style=\"{\r\n width: containerWidth + 'px',\r\n height: isCollapsed ? 'auto' : containerHeight + 'px',\r\n border: currentTheme === 'light' && !isCollapsed ? '1px solid var(--border-color)' : 'none',\r\n '--dialog-x': position.x + 'px',\r\n '--dialog-y': position.y + 'px',\r\n }\"\r\n @mousedown=\"startDrag\"\r\n >\r\n <div class=\"x-dialog-header\" @mousedown.stop=\"startDrag\">\r\n <div class=\"header-left\">\r\n <div class=\"logo-icon\">\r\n <img :src=\"xLogo ? xLogo : '/sime.png'\" alt=\"assistant\" class=\"logo\" />\r\n </div>\r\n <span class=\"title\">{{ xTitle }}</span>\r\n </div>\r\n <div class=\"actions\">\r\n <button class=\"action-btn theme-btn\" title=\"开启新对话\" @click=\"startNewConversation\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M12 5v14M5 12h14\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n </button>\r\n <button\r\n class=\"action-btn theme-btn\"\r\n :class=\"{\r\n active: voiceStatus !== 'standby',\r\n listening: voiceStatus === 'listening',\r\n woke: voiceStatus === 'wake',\r\n }\"\r\n @click.stop=\"() => toggleVoiceMode()\"\r\n :title=\"voiceButtonTooltip\"\r\n >\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path\r\n d=\"M12 15C13.6569 15 15 13.6569 15 12V7C15 5.34315 13.6569 4 12 4C10.3431 4 9 5.34315 9 7V12C9 13.6569 10.3431 15 12 15Z\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M18 11C18 14.3137 15.3137 17 12 17C8.68629 17 6 14.3137 6 11\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M12 19V17\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M9 21H15\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span class=\"voice-indicator\" v-if=\"voiceStatus !== 'standby'\"></span>\r\n </button>\r\n <button class=\"action-btn theme-btn\" @click.stop=\"cycleTheme\" :title=\"themeTooltip\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <circle cx=\"12\" cy=\"12\" r=\"7\" stroke=\"currentColor\" stroke-width=\"2\" />\r\n <path d=\"M12 5A7 7 0 1 1 12 19\" fill=\"currentColor\" />\r\n </svg>\r\n </button>\r\n <button class=\"action-btn collapse-btn\" @click.stop=\"toggleCollapse\" :title=\"isCollapsed ? '展开' : '折叠'\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path\r\n :d=\"isCollapsed ? 'M18 15L12 9L6 15' : 'M6 9L12 15L18 9'\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n <button class=\"action-btn minimize-btn\" @click.stop=\"toggleDialog(false)\" title=\"最小化\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M5 12H19\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div :class=\"['x-dialog-content', { 'is-hidden': isCollapsed }]\" :style=\"{ opacity: isCollapsed ? 0 : 1 }\">\r\n <iframe\r\n ref=\"iframeRef\"\r\n :src=\"chatbotUrl\"\r\n class=\"x-iframe\"\r\n allow=\"microphone\"\r\n frameborder=\"0\"\r\n @load=\"handleIframeLoad\"\r\n ></iframe>\r\n </div>\r\n </div>\r\n </transition>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, reactive, onBeforeUnmount, computed, nextTick, watch } from 'vue';\r\nimport VoiceStatus from './voice-status.vue';\r\nimport ExecutionStatus from './execution-status.vue';\r\nimport { injectStrict, AiChatbotXKey } from '../injection-key';\r\nimport { WakeWordDetectorStandalone, SpeechTranscriberStandalone } from 'web-voice-kit';\r\nimport { ensureMicrophonePermission, matchVoiceCommand } from '../lib/utils';\r\n\r\ninterface XSize {\r\n width: number;\r\n height: number;\r\n}\r\ninterface xDialogSize {\r\n width: number;\r\n height: number;\r\n}\r\n\r\nconst props = defineProps<{\r\n xLogo?: string;\r\n xSize?: XSize;\r\n xTitle?: string;\r\n xTheme?: 'light' | 'dark' | 'system';\r\n xDialogSize?: xDialogSize;\r\n wakeWords?: string[];\r\n modelPath?: string;\r\n}>();\r\n\r\nconst emit = defineEmits<{\r\n (e: 'start-transcribing'): void;\r\n (e: 'stop-transcribing'): void;\r\n}>();\r\n\r\nconst aiChatbotX = injectStrict(AiChatbotXKey);\r\n\r\nconst chatbotUrl = ref('');\r\nconst voiceStatus = ref<'wake' | 'listening' | 'standby'>('standby');\r\nconst transcriptionText = ref<string>('');\r\nconst isTranscribing = ref(false);\r\nconst isProcessing = ref(false);\r\nconst visible = ref(false);\r\nconst isCollapsed = ref(false);\r\nconst fabRef = ref<HTMLElement | null>(null);\r\nconst positionReady = ref(false);\r\n\r\nlet detector: WakeWordDetectorStandalone | null = null;\r\nlet transcriber: SpeechTranscriberStandalone | null = null;\r\n\r\nconst isInitializing = ref(false);\r\nconst initError = ref<string>('');\r\n\r\n// 获取系统主题\r\nconst getSystemTheme = (): 'light' | 'dark' => {\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n};\r\nconst currentTheme = ref<'light' | 'dark'>(props.xTheme === 'system' ? getSystemTheme() : props.xTheme || 'light');\r\n\r\n// 切换主题\r\nconst cycleTheme = async () => {\r\n currentTheme.value = currentTheme.value === 'light' ? 'dark' : 'light';\r\n aiChatbotX.setTheme(currentTheme.value);\r\n};\r\n\r\n// 开启新对话\r\nconst startNewConversation = () => {\r\n aiChatbotX.startNewConversation();\r\n};\r\n\r\nconst themeTooltip = computed(() => (currentTheme.value === 'light' ? '切换到深色模式' : '切换到浅色模式'));\r\n\r\nconst voiceButtonTooltip = computed(() => {\r\n if (isInitializing.value) return '初始化中...';\r\n if (initError.value) return `错误: ${initError.value}`;\r\n\r\n switch (voiceStatus.value) {\r\n case 'standby':\r\n return '开启语音监听';\r\n case 'listening':\r\n return '监听中,等待唤醒词...';\r\n case 'wake':\r\n return '已唤醒!';\r\n default:\r\n return '语音监听';\r\n }\r\n});\r\n\r\nif (props.xTheme === 'system') {\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n const handleThemeChange = (e: MediaQueryListEvent) => {\r\n currentTheme.value = e.matches ? 'dark' : 'light';\r\n };\r\n mediaQuery.addEventListener('change', handleThemeChange);\r\n onBeforeUnmount(() => {\r\n mediaQuery.removeEventListener('change', handleThemeChange);\r\n });\r\n}\r\n\r\n// 初始化语音监听器\r\nconst initVoiceDetector = () => {\r\n if (detector || isInitializing.value) return;\r\n\r\n isInitializing.value = true;\r\n initError.value = '';\r\n\r\n if (!props.modelPath) {\r\n initError.value = '未提供语音模型文件';\r\n isInitializing.value = false;\r\n return;\r\n }\r\n\r\n try {\r\n detector = new WakeWordDetectorStandalone({\r\n modelPath: props.modelPath,\r\n sampleRate: 16000,\r\n usePartial: true,\r\n autoReset: {\r\n enabled: true,\r\n resetDelayMs: 5000,\r\n },\r\n });\r\n\r\n const wakeWords = props.wakeWords || ['你好', '您好'];\r\n detector.setWakeWords(wakeWords);\r\n\r\n detector.onWake(() => {\r\n console.log('[VoiceDetector] 检测到唤醒词');\r\n voiceStatus.value = 'wake';\r\n transcriptionText.value = '';\r\n isTranscribing.value = false;\r\n // 唤醒后立即启动转写\r\n startTranscribing();\r\n });\r\n\r\n detector.onError((error: any) => {\r\n console.error('[VoiceDetector] 错误:', error);\r\n initError.value = error.message;\r\n voiceStatus.value = 'standby';\r\n isTranscribing.value = false;\r\n\r\n if (error.message.includes('permission')) {\r\n transcriptionText.value = '需要麦克风权限';\r\n } else if (error.message.includes('model')) {\r\n transcriptionText.value = '模型加载失败';\r\n } else {\r\n transcriptionText.value = '初始化失败';\r\n }\r\n\r\n setTimeout(() => {\r\n transcriptionText.value = '';\r\n }, 3000);\r\n });\r\n\r\n console.log('[VoiceDetector] 初始化成功');\r\n } catch (error) {\r\n console.error('[VoiceDetector] 初始化失败:', error);\r\n initError.value = error instanceof Error ? error.message : '初始化失败';\r\n voiceStatus.value = 'standby';\r\n isTranscribing.value = false;\r\n } finally {\r\n isInitializing.value = false;\r\n }\r\n};\r\n\r\n// 初始化转写器\r\nfunction initTranscriber() {\r\n if (transcriber) return;\r\n\r\n try {\r\n const { appId, apiKey, websocketUrl } = aiChatbotX.voiceConfig();\r\n if (!appId || !apiKey || !websocketUrl) {\r\n initError.value = '未配置语音配置';\r\n voiceStatus.value = 'standby';\r\n isTranscribing.value = false;\r\n return;\r\n }\r\n transcriber = new SpeechTranscriberStandalone({\r\n appId,\r\n apiKey,\r\n websocketUrl,\r\n autoStop: {\r\n enabled: true,\r\n silenceTimeoutMs: 3000,\r\n noSpeechTimeoutMs: 5000,\r\n maxDurationMs: 60000,\r\n },\r\n });\r\n\r\n transcriber.onResult((result) => {\r\n transcriptionText.value = result.transcript;\r\n });\r\n\r\n transcriber.onAutoStop(async () => {\r\n console.log('[Transcriber] Auto Stop');\r\n\r\n // 保存当前转写文本,用于后续处理\r\n const currentText = transcriptionText.value;\r\n\r\n // 停止转写\r\n await stopTranscribing();\r\n\r\n // 如果没有转写内容,直接返回后台监听\r\n if (!currentText || !currentText.trim()) {\r\n console.log('[Transcriber] No transcription text, returning to listening');\r\n transcriptionText.value = '';\r\n voiceStatus.value = 'listening';\r\n return;\r\n }\r\n\r\n // 进入处理中状态,显示优雅的等待动画\r\n isProcessing.value = true;\r\n transcriptionText.value = currentText; // 保持显示用户说的内容\r\n\r\n try {\r\n const commands = await aiChatbotX.hostCommads();\r\n const result = await aiChatbotX.recognition(currentText, commands);\r\n\r\n // 如果是命令类型,执行匹配的命令\r\n if (result?.data?.intent === 'command' && result?.data?.matchedCommands) {\r\n const matchedCommands = result.data.matchedCommands;\r\n\r\n for (const cmd of matchedCommands) {\r\n try {\r\n // 将参数对象转换为参数数组\r\n const args = cmd.parameters ? Object.values(cmd.parameters) : [];\r\n\r\n // 执行宿主命令\r\n const cmdResult = await aiChatbotX.executeCommand(cmd.name, args);\r\n console.log(`Command ${cmd.name} executed successfully:`, cmdResult);\r\n } catch (error) {\r\n console.error(`Failed to execute command ${cmd.name}:`, error);\r\n }\r\n }\r\n } else {\r\n aiChatbotX.appendMessage(currentText);\r\n toggleDialog(true);\r\n }\r\n } finally {\r\n // 处理完成,返回后台监听状态\r\n isProcessing.value = false;\r\n transcriptionText.value = '';\r\n voiceStatus.value = 'listening';\r\n }\r\n });\r\n\r\n transcriber.onError((error) => {\r\n console.error('[Transcriber] Error:', error);\r\n stopTranscribing();\r\n transcriptionText.value = '转写错误';\r\n setTimeout(() => {\r\n transcriptionText.value = '';\r\n voiceStatus.value = 'listening';\r\n }, 2000);\r\n });\r\n\r\n console.log('[Transcriber] 初始化成功');\r\n } catch (error) {\r\n console.error('[Transcriber] 初始化失败:', error);\r\n voiceStatus.value = 'standby';\r\n initError.value = error instanceof Error ? error.message : '转写初始化失败';\r\n }\r\n}\r\n\r\nconst startTranscribing = async () => {\r\n if (!transcriber) {\r\n initTranscriber();\r\n if (!transcriber) return;\r\n }\r\n\r\n try {\r\n emit('start-transcribing');\r\n await transcriber.start();\r\n isTranscribing.value = true;\r\n transcriptionText.value = '';\r\n } catch (error) {\r\n console.error('[Transcriber] 启动失败:', error);\r\n transcriptionText.value = '转写启动失败';\r\n setTimeout(() => {\r\n transcriptionText.value = '';\r\n }, 2000);\r\n }\r\n};\r\n\r\nconst stopTranscribing = async () => {\r\n if (transcriber && transcriber.isActive()) {\r\n try {\r\n await transcriber.stop();\r\n isTranscribing.value = false;\r\n emit('stop-transcribing');\r\n } catch (error) {\r\n console.error('[Transcriber] 停止失败:', error);\r\n }\r\n }\r\n};\r\n\r\nconst toggleVoiceMode = async (targetState?: boolean) => {\r\n const permission = await ensureMicrophonePermission();\r\n if (!permission) return;\r\n\r\n if (isInitializing.value) return;\r\n\r\n if (!detector) {\r\n await initVoiceDetector();\r\n if (!detector) return;\r\n }\r\n\r\n // 核心逻辑:如果传了参数,目标就是参数值;如果不传,目标就是当前状态的反值\r\n // 假设 \"listening\" 为开启状态,其余(如 \"standby\")为关闭状态\r\n const isCurrentlyListening = voiceStatus.value === 'listening';\r\n const shouldStart = targetState !== undefined ? targetState : !isCurrentlyListening;\r\n\r\n // 如果当前状态已经符合目标状态,直接返回(防止重复开启或关闭)\r\n if (shouldStart === isCurrentlyListening) return;\r\n\r\n try {\r\n if (shouldStart) {\r\n // 执行开启逻辑\r\n console.log('[VoiceDetector] 强制/自动启动监听...');\r\n await detector.start();\r\n voiceStatus.value = 'listening';\r\n transcriptionText.value = '';\r\n isTranscribing.value = false;\r\n } else {\r\n // 执行关闭逻辑\r\n console.log('[VoiceDetector] 强制/自动停止监听...');\r\n await detector.stop();\r\n stopTranscribing();\r\n voiceStatus.value = 'standby';\r\n transcriptionText.value = '';\r\n isTranscribing.value = false;\r\n }\r\n } catch (error) {\r\n console.error('[VoiceDetector] 操作失败:', error);\r\n voiceStatus.value = 'standby';\r\n transcriptionText.value = '操作失败';\r\n isTranscribing.value = false;\r\n\r\n setTimeout(() => {\r\n transcriptionText.value = '';\r\n }, 2000);\r\n }\r\n};\r\n\r\nconst position = reactive({ x: 0, y: 0 });\r\nconst containerWidth = ref(props.xDialogSize?.width || 420);\r\nconst containerHeight = ref(props.xDialogSize?.height || 600);\r\nconst isFirstOpen = ref(true);\r\n\r\nconst validatePosition = (x: number, y: number, width: number, height: number) => {\r\n const margin = 20;\r\n const viewportWidth = window.innerWidth;\r\n const viewportHeight = window.innerHeight;\r\n\r\n const maxX = viewportWidth - width - margin;\r\n const maxY = viewportHeight - height - margin;\r\n\r\n return {\r\n x: Math.max(margin, Math.min(x, maxX)),\r\n y: Math.max(margin, Math.min(y, maxY)),\r\n };\r\n};\r\n\r\nconst calculateInitialPosition = () => {\r\n if (!fabRef.value) return;\r\n\r\n const fabRect = fabRef.value.getBoundingClientRect();\r\n const dialogWidth = containerWidth.value;\r\n const dialogHeight = containerHeight.value;\r\n const viewportWidth = window.innerWidth;\r\n const viewportHeight = window.innerHeight;\r\n const margin = 20; // 增加间距,确保不遮挡\r\n const minMargin = 20; // 最小边距\r\n\r\n let x = 0;\r\n let y = 0;\r\n\r\n // 优先尝试在 FAB 左侧定位\r\n const leftX = fabRect.left - dialogWidth - margin;\r\n\r\n if (leftX >= minMargin) {\r\n // 左侧有足够空间\r\n x = leftX;\r\n // Y 轴对齐 FAB 顶部,但确保不超出视口\r\n y = fabRect.top;\r\n\r\n // 如果对话框底部超出视口,向上调整\r\n if (y + dialogHeight > viewportHeight - minMargin) {\r\n y = viewportHeight - dialogHeight - minMargin;\r\n }\r\n // 确保顶部不超出\r\n if (y < minMargin) {\r\n y = minMargin;\r\n }\r\n } else {\r\n // 左侧空间不足,尝试右侧\r\n const rightX = fabRect.right + margin;\r\n\r\n if (rightX + dialogWidth <= viewportWidth - minMargin) {\r\n // 右侧有足够空间\r\n x = rightX;\r\n y = fabRect.top;\r\n\r\n // Y 轴调整\r\n if (y + dialogHeight > viewportHeight - minMargin) {\r\n y = viewportHeight - dialogHeight - minMargin;\r\n }\r\n if (y < minMargin) {\r\n y = minMargin;\r\n }\r\n } else {\r\n // 左右都不够,居中显示,并确保不遮挡 FAB\r\n x = (viewportWidth - dialogWidth) / 2;\r\n\r\n // 尝试在 FAB 上方\r\n const aboveY = fabRect.top - dialogHeight - margin;\r\n if (aboveY >= minMargin) {\r\n y = aboveY;\r\n } else {\r\n // 在 FAB 下方\r\n const belowY = fabRect.bottom + margin;\r\n if (belowY + dialogHeight <= viewportHeight - minMargin) {\r\n y = belowY;\r\n } else {\r\n // 垂直居中\r\n y = (viewportHeight - dialogHeight) / 2;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // 最终验证位置\r\n const validated = validatePosition(x, y, dialogWidth, dialogHeight);\r\n position.x = validated.x;\r\n position.y = validated.y;\r\n};\r\n\r\nconst toggleCollapse = async () => {\r\n isCollapsed.value = !isCollapsed.value;\r\n\r\n nextTick(() => {\r\n const currentHeight = isCollapsed.value ? 60 : containerHeight.value;\r\n const validated = validatePosition(position.x, position.y, containerWidth.value, currentHeight);\r\n position.x = validated.x;\r\n position.y = validated.y;\r\n });\r\n};\r\n\r\nconst drag = reactive({\r\n isDragging: false,\r\n startX: 0,\r\n startY: 0,\r\n offsetX: 0,\r\n offsetY: 0,\r\n});\r\n\r\nconst startDrag = (e: MouseEvent) => {\r\n drag.isDragging = true;\r\n drag.startX = e.clientX;\r\n drag.startY = e.clientY;\r\n drag.offsetX = position.x;\r\n drag.offsetY = position.y;\r\n document.addEventListener('mousemove', onDrag);\r\n document.addEventListener('mouseup', stopDrag);\r\n};\r\n\r\nconst onDrag = (e: MouseEvent) => {\r\n if (!drag.isDragging) return;\r\n\r\n const newX = drag.offsetX + (e.clientX - drag.startX);\r\n const newY = drag.offsetY + (e.clientY - drag.startY);\r\n\r\n const validated = validatePosition(newX, newY, containerWidth.value, isCollapsed.value ? 60 : containerHeight.value);\r\n\r\n position.x = validated.x;\r\n position.y = validated.y;\r\n};\r\n\r\nconst stopDrag = () => {\r\n drag.isDragging = false;\r\n document.removeEventListener('mousemove', onDrag);\r\n document.removeEventListener('mouseup', stopDrag);\r\n};\r\n\r\nconst toggleDialog = async (state: boolean) => {\r\n if (state) {\r\n visible.value = true;\r\n positionReady.value = false;\r\n\r\n await nextTick();\r\n\r\n if (isFirstOpen.value) {\r\n calculateInitialPosition();\r\n isFirstOpen.value = false;\r\n } else {\r\n const validated = validatePosition(\r\n position.x,\r\n position.y,\r\n containerWidth.value,\r\n isCollapsed.value ? 60 : containerHeight.value,\r\n );\r\n position.x = validated.x;\r\n position.y = validated.y;\r\n }\r\n\r\n await nextTick();\r\n positionReady.value = true;\r\n } else {\r\n positionReady.value = false;\r\n visible.value = false;\r\n isCollapsed.value = false;\r\n }\r\n};\r\n\r\nconst handleIframeLoad = (event: Event) => {\r\n aiChatbotX.setIframeElement(event.target as HTMLIFrameElement);\r\n aiChatbotX.setTheme('dark');\r\n};\r\n\r\nwatch(\r\n () => [aiChatbotX.chatbotUrl()],\r\n ([url]) => {\r\n console.log('[AiChatbotX] 初始化', url);\r\n if (url) {\r\n chatbotUrl.value = `${url}/app/${aiChatbotX.appId()}?token=${aiChatbotX.appToken()}`;\r\n }\r\n },\r\n { immediate: true },\r\n);\r\n\r\nonBeforeUnmount(async () => {\r\n if (detector) {\r\n try {\r\n if (detector.isActive()) {\r\n await detector.stop();\r\n }\r\n detector = null;\r\n } catch (error) {\r\n console.error('[VoiceDetector] 清理失败:', error);\r\n }\r\n }\r\n if (transcriber) {\r\n try {\r\n if (transcriber.isActive()) {\r\n await transcriber.stop();\r\n }\r\n transcriber = null;\r\n } catch (error) {\r\n console.error('[Transcriber] 清理失败:', error);\r\n }\r\n }\r\n});\r\n\r\naiChatbotX?.registerVoiceMethods({\r\n start: () => toggleVoiceMode(true),\r\n stop: () => toggleVoiceMode(false),\r\n openDialog: () => toggleDialog(true),\r\n closeDialog: () => toggleDialog(false),\r\n toggleCollapse: () => toggleCollapse(),\r\n});\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.sime-x {\r\n --bg-primary: #ffffff;\r\n --bg-secondary: #f8fafc;\r\n --bg-header: #0f172a;\r\n --text-primary: #0f172a;\r\n --text-secondary: #64748b;\r\n --text-header: #ffffff;\r\n --border-color: #e2e8f0;\r\n --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);\r\n --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);\r\n --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.15);\r\n --accent-color: #3b82f6;\r\n --hover-bg: rgba(0, 0, 0, 0.05);\r\n\r\n &[data-theme='dark'] {\r\n --bg-primary: #1e293b;\r\n --bg-secondary: #0f172a;\r\n --bg-header: #0f172a;\r\n --text-primary: #f1f5f9;\r\n --text-secondary: #94a3b8;\r\n --text-header: #f1f5f9;\r\n --border-color: #334155;\r\n --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);\r\n --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);\r\n --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.5);\r\n --accent-color: #60a5fa;\r\n --hover-bg: rgba(255, 255, 255, 0.1);\r\n }\r\n}\r\n\r\n.is-hidden {\r\n height: 0;\r\n opacity: 0 !important;\r\n pointer-events: none !important;\r\n visibility: hidden !important;\r\n}\r\n\r\n.assistant-fab {\r\n position: relative;\r\n cursor: pointer;\r\n overflow: visible;\r\n filter: drop-shadow(var(--shadow-md));\r\n opacity: 1;\r\n pointer-events: auto;\r\n transition: all 0.3s ease;\r\n\r\n &:hover {\r\n transform: scale(1.05);\r\n }\r\n\r\n &:active {\r\n transform: scale(0.95);\r\n }\r\n\r\n .voice-status {\r\n position: absolute;\r\n right: 100%;\r\n margin-right: 20px;\r\n }\r\n\r\n img {\r\n display: block;\r\n position: relative;\r\n object-fit: contain;\r\n }\r\n\r\n .fab-pulse {\r\n position: absolute;\r\n inset: -4px;\r\n border-radius: 50%;\r\n border: 2px solid var(--accent-color);\r\n opacity: 0;\r\n }\r\n}\r\n\r\n@keyframes pulse {\r\n 0%,\r\n 100% {\r\n opacity: 0;\r\n transform: scale(1);\r\n }\r\n 50% {\r\n opacity: 0.5;\r\n transform: scale(1.1);\r\n }\r\n}\r\n\r\n.x-dialog-container {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n transform: translate(var(--dialog-x), var(--dialog-y));\r\n border-radius: 16px;\r\n display: flex;\r\n flex-direction: column;\r\n cursor: grab;\r\n overflow: hidden;\r\n z-index: 1100;\r\n opacity: 0;\r\n pointer-events: none;\r\n\r\n &.position-ready {\r\n opacity: 1;\r\n pointer-events: auto;\r\n }\r\n\r\n &:active {\r\n cursor: grabbing;\r\n }\r\n\r\n &.collapsed {\r\n .x-dialog-header {\r\n border-radius: 16px;\r\n }\r\n }\r\n\r\n .x-dialog-header {\r\n position: relative;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n background: var(--bg-header);\r\n padding: 12px 16px;\r\n cursor: move;\r\n user-select: none;\r\n border-bottom: 1px solid var(--border-color);\r\n\r\n .header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n\r\n .logo-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 36px;\r\n height: 36px;\r\n transition: transform 0.2s ease;\r\n\r\n .logo {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: contain;\r\n }\r\n }\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 15px;\r\n color: var(--text-header);\r\n letter-spacing: -0.01em;\r\n }\r\n }\r\n\r\n .actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n\r\n .action-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border: none;\r\n background: transparent;\r\n cursor: pointer;\r\n color: var(--text-secondary);\r\n transition: all 0.2s ease;\r\n border-radius: 8px;\r\n\r\n &:hover {\r\n color: var(--text-header);\r\n background: var(--hover-bg);\r\n transform: translateY(-1px);\r\n }\r\n\r\n &:active {\r\n transform: translateY(0);\r\n }\r\n\r\n svg {\r\n transition: transform 0.2s ease;\r\n }\r\n\r\n &.collapse-btn:hover svg {\r\n transform: scale(1.1);\r\n }\r\n }\r\n }\r\n }\r\n\r\n .voice-container {\r\n width: 100%;\r\n opacity: 1;\r\n pointer-events: auto;\r\n }\r\n\r\n .x-dialog-content {\r\n flex: 1;\r\n display: flex;\r\n overflow: hidden;\r\n background: var(--bg-secondary);\r\n opacity: 1;\r\n pointer-events: auto;\r\n }\r\n\r\n .x-iframe {\r\n flex: 1;\r\n width: 100%;\r\n height: 100%;\r\n border: none;\r\n }\r\n\r\n .resize-handle {\r\n position: absolute;\r\n bottom: 0;\r\n right: 0;\r\n width: 40px;\r\n height: 40px;\r\n cursor: nwse-resize;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--text-secondary);\r\n transition: all 0.2s ease;\r\n background: linear-gradient(135deg, transparent 50%, var(--bg-primary) 50%);\r\n border-bottom-right-radius: 16px;\r\n z-index: 10;\r\n\r\n &:hover {\r\n color: var(--accent-color);\r\n background: linear-gradient(135deg, transparent 50%, var(--hover-bg) 50%);\r\n }\r\n\r\n svg {\r\n width: 16px;\r\n height: 16px;\r\n transform: rotate(0deg);\r\n transition: transform 0.2s ease;\r\n }\r\n\r\n &:hover svg {\r\n transform: scale(1.2);\r\n }\r\n }\r\n}\r\n/* 语音按钮状态样式 */\r\n.action-btn.theme-btn {\r\n position: relative;\r\n transition: all 0.3s ease;\r\n}\r\n\r\n.action-btn.theme-btn.active {\r\n background: rgba(59, 130, 246, 0.1);\r\n color: #3b82f6;\r\n}\r\n\r\n.action-btn.theme-btn.listening {\r\n animation: pulse-listening 2s ease-in-out infinite;\r\n}\r\n\r\n.action-btn.theme-btn.woke {\r\n background: rgba(34, 197, 94, 0.2);\r\n color: #22c55e;\r\n animation: pulse-wake 0.6s ease-in-out;\r\n}\r\n\r\n@keyframes pulse-listening {\r\n 0%,\r\n 100% {\r\n box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4);\r\n }\r\n 50% {\r\n box-shadow: 0 0 0 8px rgba(59, 130, 246, 0);\r\n }\r\n}\r\n\r\n@keyframes pulse-wake {\r\n 0%,\r\n 100% {\r\n transform: scale(1);\r\n }\r\n 50% {\r\n transform: scale(1.1);\r\n }\r\n}\r\n\r\n/* 语音指示器 */\r\n.voice-indicator {\r\n position: absolute;\r\n top: 4px;\r\n right: 4px;\r\n width: 6px;\r\n height: 6px;\r\n border-radius: 50%;\r\n background: #3b82f6;\r\n}\r\n\r\n.action-btn.theme-btn.listening .voice-indicator {\r\n animation: blink 1.5s ease-in-out infinite;\r\n}\r\n\r\n.action-btn.theme-btn.woke .voice-indicator {\r\n background: #22c55e;\r\n animation: none;\r\n}\r\n\r\n@keyframes blink {\r\n 0%,\r\n 100% {\r\n opacity: 1;\r\n }\r\n 50% {\r\n opacity: 0.3;\r\n }\r\n}\r\n\r\n/* FAB 头像容器 */\r\n.fab-avatar-wrapper {\r\n position: relative;\r\n display: flex; /* 改用 flex 可以消除图片底部的行高间隙 */\r\n align-items: center;\r\n justify-content: center;\r\n width: fit-content; /* 宽度随内容自适应 */\r\n margin: 0 auto;\r\n}\r\n\r\n/* 2. 修正图片样式 */\r\n.fab-avatar-wrapper img {\r\n display: block;\r\n max-width: 100%;\r\n height: auto;\r\n /* 移除原本 style 里的 width/height 可能造成的拉伸,保持比例 */\r\n}\r\n\r\n/* 3. 优化徽章定位 */\r\n.listening-badge {\r\n position: absolute;\r\n /* 强制定位到容器边缘 */\r\n top: 0;\r\n right: 0;\r\n /* 使用 transform 偏移,让徽章中心点落在图片的右上角顶点上 */\r\n transform: translate(30%, -30%);\r\n\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 50%;\r\n background-color: rgba(0, 0, 0, 0.75); /* 稍微加深一点 */\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 10;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\r\n\r\n /* 继承你原有的动画 */\r\n animation: badge-float 5s ease-in-out infinite;\r\n pointer-events: none; /* 防止遮挡头像点击 */\r\n}\r\n\r\n/* 4. 调整声波扩散的基准 */\r\n.wave {\r\n position: absolute;\r\n /* 确保声波从徽章中心扩散,而不是从容器左上角 */\r\n inset: -2px;\r\n border-radius: 50%;\r\n border: 2px solid rgba(59, 130, 246, 0.6); /* 声波颜色建议跟主题色一致 */\r\n animation: wave-expand 3s ease-out infinite;\r\n}\r\n\r\n/* 优化后的监听状态徽章 */\r\n.listening-badge {\r\n position: absolute;\r\n top: -8px;\r\n right: -8px;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 50%;\r\n background-color: rgba(0, 0, 0, 0.651);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 10;\r\n animation: badge-float 5s ease-in-out infinite;\r\n}\r\n\r\n/* 徽章浮动动画 */\r\n@keyframes badge-float {\r\n 0%,\r\n 100% {\r\n transform: translateY(0) scale(1);\r\n }\r\n 50% {\r\n transform: translateY(-2px) scale(1.05);\r\n }\r\n}\r\n\r\n/* 声波容器 */\r\n.listening-waves {\r\n position: absolute;\r\n inset: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n/* 声波动画 */\r\n.wave {\r\n position: absolute;\r\n width: 100%;\r\n height: 100%;\r\n border-radius: 50%;\r\n border: 2px solid rgba(255, 255, 255, 0.6);\r\n animation: wave-expand 3s ease-out infinite;\r\n}\r\n\r\n.wave-1 {\r\n animation-delay: 0s;\r\n}\r\n\r\n.wave-2 {\r\n animation-delay: 0.6s;\r\n}\r\n\r\n.wave-3 {\r\n animation-delay: 1.2s;\r\n}\r\n\r\n@keyframes wave-expand {\r\n 0% {\r\n transform: scale(0.8);\r\n opacity: 0.8;\r\n }\r\n 100% {\r\n transform: scale(2.2);\r\n opacity: 0;\r\n }\r\n}\r\n\r\n/* 麦克风图标 */\r\n.listening-icon {\r\n position: relative;\r\n width: 24px;\r\n height: 24px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: #ffffff;\r\n z-index: 1;\r\n animation: icon-pulse 2.5s ease-in-out infinite;\r\n}\r\n\r\n@keyframes icon-pulse {\r\n 0%,\r\n 100% {\r\n transform: scale(1);\r\n }\r\n 50% {\r\n transform: scale(1.1);\r\n }\r\n}\r\n\r\n/* 徽章淡入淡出动画 */\r\n.indicator-fade-enter-active {\r\n transition: all 1s cubic-bezier(0.34, 1.56, 0.64, 1);\r\n}\r\n\r\n.indicator-fade-leave-active {\r\n transition: all 1s ease;\r\n}\r\n\r\n.indicator-fade-enter-from {\r\n opacity: 0;\r\n transform: scale(0.3) rotate(-180deg);\r\n}\r\n\r\n.indicator-fade-leave-to {\r\n opacity: 0;\r\n transform: scale(0.5) rotate(180deg);\r\n}\r\n\r\n/* FAB 脉冲效果 */\r\n.fab-pulse {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n border-radius: 50%;\r\n pointer-events: none;\r\n}\r\n\r\n.fab-pulse.active {\r\n animation: fab-pulse 2s ease-in-out infinite;\r\n}\r\n\r\n@keyframes fab-pulse {\r\n 0%,\r\n 100% {\r\n box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4);\r\n }\r\n 50% {\r\n box-shadow: 0 0 0 20px rgba(59, 130, 246, 0);\r\n }\r\n}\r\n\r\n/* 深色模式适配 */\r\n[data-theme='dark'] .action-btn.theme-btn.active {\r\n background: rgba(59, 130, 246, 0.2);\r\n}\r\n\r\n[data-theme='dark'] .action-btn.theme-btn.woke {\r\n background: rgba(34, 197, 94, 0.3);\r\n}\r\n</style>\r\n"],"names":["clientCommandKey","_renderSlot","_createBlock","_Transition","_createElementBlock","_normalizeClass","_createElementVNode","_hoisted_1","_hoisted_2","_hoisted_3","_toDisplayString","_createVNode","_hoisted_4","_hoisted_5","_openBlock","_normalizeStyle"],"mappings":"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"}