From 4b347be9f5a6da12fe79430afd609b0f492e503e Mon Sep 17 00:00:00 2001 From: ittoview Date: Sun, 1 Mar 2026 15:27:19 +0000 Subject: [PATCH] =?UTF-8?q?feat(=E7=BB=83=E4=B9=A0):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E7=BC=93=E5=AD=98=E5=92=8C=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BD=93=E9=AA=8C=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 localStorage 缓存答题进度,支持切换页面后继续 - 修复暗色主题下输入框文字不可见问题 - 添加"想不起来"提示按钮,引导用户查看答案 - 添加清除进度按钮,方便重新开始练习 via [HAPI](https://hapi.run) Co-Authored-By: HAPI --- src/components/practice/InputArea.tsx | 1 + src/pages/ProcessPracticePage.tsx | 70 +++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/components/practice/InputArea.tsx b/src/components/practice/InputArea.tsx index a3b8c37..92c0562 100644 --- a/src/components/practice/InputArea.tsx +++ b/src/components/practice/InputArea.tsx @@ -128,6 +128,7 @@ export function InputArea({ 'w-10 h-12 text-center text-2xl font-medium', 'bg-transparent border-b-2 transition-all duration-200', 'focus:outline-none', + 'text-gray-900 dark:text-gray-100', isComposing && 'border-gray-300 dark:border-gray-600 opacity-70', !isComposing && !char && 'border-gray-400 dark:border-gray-500', !isComposing && isCorrect && 'border-green-500', diff --git a/src/pages/ProcessPracticePage.tsx b/src/pages/ProcessPracticePage.tsx index 06e14c4..1c99491 100644 --- a/src/pages/ProcessPracticePage.tsx +++ b/src/pages/ProcessPracticePage.tsx @@ -16,12 +16,32 @@ export default function ProcessPracticePage() { // 生成格子顺序 const [cellSequence] = useState(() => generateCellSequence()) + // 从 localStorage 加载答题进度 + const loadProgress = useCallback(() => { + try { + const saved = localStorage.getItem('practice-progress') + if (saved) { + const data = JSON.parse(saved) + return { + answeredCells: new Map(data.answeredCells || []), + currentCellId: data.currentCellId || cellSequence[0]?.id || null, + } + } + } catch (e) { + console.error('加载进度失败:', e) + } + return { + answeredCells: new Map(), + currentCellId: cellSequence[0]?.id || null, + } + }, [cellSequence]) + // 答题状态 const [answeredCells, setAnsweredCells] = useState>( - new Map() + () => loadProgress().answeredCells ) const [currentCellId, setCurrentCellId] = useState( - cellSequence[0]?.id || null + () => loadProgress().currentCellId ) // 输入状态 @@ -55,6 +75,21 @@ export default function ProcessPracticePage() { latestInputRef.current = userInput }, [userInput]) + // 保存答题进度到 localStorage + useEffect(() => { + try { + localStorage.setItem( + 'practice-progress', + JSON.stringify({ + answeredCells: Array.from(answeredCells.entries()), + currentCellId, + }) + ) + } catch (e) { + console.error('保存进度失败:', e) + } + }, [answeredCells, currentCellId]) + // 切换到指定格子 const switchToCell = useCallback( (cell: CellInfo) => { @@ -283,6 +318,15 @@ export default function ProcessPracticePage() { const answeredCount = answeredCells.size const totalCount = cellSequence.length + // 清除进度 + const handleClearProgress = useCallback(() => { + if (confirm('确定要清除所有答题进度吗?')) { + setAnsweredCells(new Map()) + setCurrentCellId(cellSequence[0]?.id || null) + localStorage.removeItem('practice-progress') + } + }, [cellSequence]) + return (
{/* 顶部进度条 */} @@ -292,8 +336,16 @@ export default function ProcessPracticePage() {

过程背诵练习

-
- 进度:{answeredCount} / {totalCount} +
+
+ 进度:{answeredCount} / {totalCount} +
+
@@ -341,6 +393,16 @@ export default function ProcessPracticePage() { onCompositionEnd={handleCompositionEnd} onPaste={handlePaste} /> + + {/* 提示按钮 */} +
+ +
{/* 辅助信息区域 */}