diff --git a/src/renderer/src/assets/asr-server/index.html b/src/renderer/src/assets/asr-server/index.html index ac0531d0ce..c049cb2b21 100644 --- a/src/renderer/src/assets/asr-server/index.html +++ b/src/renderer/src/assets/asr-server/index.html @@ -64,6 +64,9 @@ startRecognition(); } else if (data.type === 'stop') { stopRecognition(); + } else if (data.type === 'reset') { + // 强制重置语音识别 + forceResetRecognition(); } else { console.warn('[Browser Page] Received unknown command type:', data.type); } @@ -362,6 +365,30 @@ updateStatus("识别未运行。"); } } + + function forceResetRecognition() { + console.log('[Browser Page] Force resetting recognition...'); + updateStatus("强制重置语音识别..."); + + // 先尝试停止当前的识别 + if (recognition) { + try { + recognition.stop(); + } catch (e) { + console.error('[Browser Page] Error stopping recognition during reset:', e); + } + } + + // 强制设置为null,丢弃所有后续结果 + recognition = null; + + // 通知服务器已重置 + if (ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'status', message: 'reset_complete' })); + } + + updateStatus("语音识别已重置,等待新指令。"); + } diff --git a/src/renderer/src/assets/asr-server/server.js b/src/renderer/src/assets/asr-server/server.js index 7b3d77d9f2..677124ce97 100644 --- a/src/renderer/src/assets/asr-server/server.js +++ b/src/renderer/src/assets/asr-server/server.js @@ -124,6 +124,13 @@ wss.on('connection', (ws) => { } else { console.log('[Server] Cannot relay STOP: Browser not connected') } + } else if (data.type === 'reset' && ws === electronConnection) { + if (browserConnection && browserConnection.readyState === WebSocket.OPEN) { + console.log('[Server] Relaying RESET command to browser') + browserConnection.send(JSON.stringify({ type: 'reset' })) + } else { + console.log('[Server] Cannot relay RESET: Browser not connected') + } } // 浏览器发送识别结果 else if (data.type === 'result' && ws === browserConnection) { diff --git a/src/renderer/src/components/VoiceCallButton.tsx b/src/renderer/src/components/VoiceCallButton.tsx new file mode 100644 index 0000000000..00d784b4ed --- /dev/null +++ b/src/renderer/src/components/VoiceCallButton.tsx @@ -0,0 +1,55 @@ +import React, { useState } from 'react'; +import { Button, Tooltip } from 'antd'; +import { PhoneOutlined, LoadingOutlined } from '@ant-design/icons'; +import { useTranslation } from 'react-i18next'; +import VoiceCallModal from './VoiceCallModal'; +import { VoiceCallService } from '../services/VoiceCallService'; + +interface Props { + disabled?: boolean; + style?: React.CSSProperties; +} + +const VoiceCallButton: React.FC = ({ disabled = false, style }) => { + const { t } = useTranslation(); + const [isModalVisible, setIsModalVisible] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const handleClick = async () => { + if (disabled || isLoading) return; + + setIsLoading(true); + try { + // 初始化语音服务 + await VoiceCallService.initialize(); + setIsModalVisible(true); + } catch (error) { + console.error('Failed to initialize voice call:', error); + window.message.error(t('voice_call.initialization_failed')); + } finally { + setIsLoading(false); + } + }; + + return ( + <> + +