import React, { useState, useEffect, useRef } from 'react'; interface VoiceInputProps { onTranscript: (text: string) => void; isProcessing: boolean; isFullWidth?: boolean; } const VoiceInput: React.FC = ({ onTranscript, isProcessing, isFullWidth = false }) => { const [isListening, setIsListening] = useState(false); const recognitionRef = useRef(null); const timerRef = useRef(null); const isStartingRef = useRef(false); useEffect(() => { if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; recognitionRef.current = new SpeechRecognition(); recognitionRef.current.continuous = false; recognitionRef.current.lang = 'zh-CN'; recognitionRef.current.interimResults = false; recognitionRef.current.onresult = (event: any) => { const transcript = event.results[0][0].transcript; if (transcript) onTranscript(transcript); }; recognitionRef.current.onerror = (event: any) => { if (event.error === 'network') { alert("语音识别网络连接失败。请检查网络或尝试切换浏览器(推荐 Chrome/Edge)。"); } console.error('Speech recognition error', event.error); }; recognitionRef.current.onend = () => { setIsListening(false); isStartingRef.current = false; }; } }, [onTranscript]); const startListening = (e: React.PointerEvent) => { if (e.cancelable) e.preventDefault(); if (isProcessing || isListening || isStartingRef.current) return; if (recognitionRef.current) { try { isStartingRef.current = true; recognitionRef.current.start(); setIsListening(true); } catch (err) { console.error("Failed to start recognition", err); // 如果 start 失败,立即重置状态,否则会锁死 isStartingRef.current = false; setIsListening(false); } } else { alert("您的浏览器不支持语音识别,请使用 Chrome 或 Edge。"); } }; const stopListening = () => { // 仅在识别引擎正在运行时尝试停止 // 不要在这里重置 isListening 和 isStartingRef,等待 onend 回调 if (isListening) { try { recognitionRef.current?.stop(); } catch (err) { console.error("Failed to stop recognition", err); } } }; return (
{isListening && isFullWidth && (
正在录音...
)}
); }; export default VoiceInput;