From: root Date: Fri, 26 Jun 2026 14:40:41 +0000 (+0800) Subject: 学习模式: 朗读期间禁止进入闪记模式 X-Git-Url: http://acesimba.cloud/gitweb/?a=commitdiff_plain;h=38618b218bcedc77914664b6a47eb510c9b4b7ab;p=words.git 学习模式: 朗读期间禁止进入闪记模式 - 新增 isSpeaking 状态,朗读期间为 true - 键盘 Enter 监听在 isSpeaking 时直接 return - 进入闪记按钮 disabled={isSpeaking},文案切换为朗读中,请稍候... - 两遍音频全部播完(或播放失败)才 setIsSpeaking(false) --- diff --git a/frontend/src/components/StudyMode.js b/frontend/src/components/StudyMode.js index 75c69ad..1edaa74 100644 --- a/frontend/src/components/StudyMode.js +++ b/frontend/src/components/StudyMode.js @@ -13,21 +13,32 @@ function StudyMode() { const [phase, setPhase] = useState('learning'); // learning, flashcard, correction const [userInput, setUserInput] = useState(""); const [correctionInput, setCorrectionInput] = useState(""); + const [isSpeaking, setIsSpeaking] = useState(false); const hasSpokenRef = useRef(null); const transitioningRef = useRef(false); const currentWord = words[currentIndex]; // 朗读逻辑:通过后端 TTS 代理(有道美式发音)播放两遍,间隔 500ms + // 朗读期间 isSpeaking=true,阻止进入闪记模式 const speak = useCallback((text) => { if (!text) return; const url = `${API_BASE}/api/tts/${encodeURIComponent(text)}`; + setIsSpeaking(true); + const finish = () => setIsSpeaking(false); const audio1 = new Audio(url); - audio1.play().catch(err => console.error("TTS play failed:", err)); + audio1.play().catch(err => { + console.error("TTS play failed:", err); + finish(); + }); audio1.onended = () => { setTimeout(() => { const audio2 = new Audio(url); - audio2.play().catch(err => console.error("TTS play failed:", err)); + audio2.play().catch(err => { + console.error("TTS play failed:", err); + finish(); + }); + audio2.onended = finish; }, 500); }; }, []); @@ -47,17 +58,18 @@ function StudyMode() { } }, [currentIndex, currentWord, phase, speak]); - // 全局键盘监听:在学习模式下按回车进入闪记 + // 全局键盘监听:在学习模式下按回车进入闪记(朗读中禁用) useEffect(() => { const handleGlobalKeyDown = (event) => { if (transitioningRef.current) return; + if (isSpeaking) return; if (phase === 'learning' && event.key === 'Enter') { setPhase('flashcard'); } }; window.addEventListener('keydown', handleGlobalKeyDown); return () => window.removeEventListener('keydown', handleGlobalKeyDown); - }, [phase]); + }, [phase, isSpeaking]); const handleNext = async () => { transitioningRef.current = true; @@ -145,8 +157,12 @@ function StudyMode() {
{currentWord.word_root &&

词根: {currentWord.word_root}

} {currentWord.affix &&

组成: {currentWord.affix}

} -