From 08bd8dd4dc44706d2e61967321236a038fc43a1b Mon Sep 17 00:00:00 2001 From: ittoview Date: Sun, 1 Mar 2026 16:12:50 +0000 Subject: [PATCH] =?UTF-8?q?fix(=E7=BB=83=E4=B9=A0):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=BA=95=E9=83=A8=E5=8C=BA=E5=9F=9F=E5=B8=83=E5=B1=80=E5=92=8C?= =?UTF-8?q?=E7=84=A6=E7=82=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 动态计算底部固定区域高度,避免固定值导致的空白或遮挡 - 底部区域适配侧边栏宽度,不再被左侧菜单遮挡 - 答案隐藏后自动恢复输入框焦点 - 增加辅助信息显示高度(max-h-48) via [HAPI](https://hapi.run) Co-Authored-By: HAPI --- src/pages/ProcessPracticePage.tsx | 88 ++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/src/pages/ProcessPracticePage.tsx b/src/pages/ProcessPracticePage.tsx index 1c99491..d7c8107 100644 --- a/src/pages/ProcessPracticePage.tsx +++ b/src/pages/ProcessPracticePage.tsx @@ -9,10 +9,14 @@ import { import { PracticeMatrix } from '@/components/practice/PracticeMatrix' import { InputArea } from '@/components/practice/InputArea' import { HintInfo } from '@/components/practice/HintInfo' +import { useAppStore } from '@/stores/useAppStore' +import { clsx } from 'clsx' type CharStatus = 'pending' | 'correct' | 'error' export default function ProcessPracticePage() { + const sidebarOpen = useAppStore((s) => s.sidebarOpen) + // 生成格子顺序 const [cellSequence] = useState(() => generateCellSequence()) @@ -60,6 +64,8 @@ export default function ProcessPracticePage() { } | null>(null) const [inputLocked, setInputLocked] = useState(false) const latestInputRef = useRef([]) + const bottomAreaRef = useRef(null) + const [bottomHeight, setBottomHeight] = useState(0) // 初始化输入框 useEffect(() => { @@ -90,6 +96,19 @@ export default function ProcessPracticePage() { } }, [answeredCells, currentCellId]) + // 动态计算底部固定区域高度 + useEffect(() => { + const updateBottomHeight = () => { + if (bottomAreaRef.current) { + setBottomHeight(bottomAreaRef.current.offsetHeight) + } + } + + updateBottomHeight() + window.addEventListener('resize', updateBottomHeight) + return () => window.removeEventListener('resize', updateBottomHeight) + }, [userInput.length]) // 当输入框数量变化时重新计算 + // 切换到指定格子 const switchToCell = useCallback( (cell: CellInfo) => { @@ -251,6 +270,14 @@ export default function ProcessPracticePage() { setShowAnswerForCell(null) setInputLocked(false) announceToScreenReader('答案已隐藏') + + // 恢复焦点到第一个输入框 + setTimeout(() => { + const firstInput = document.querySelector( + '.practice-input-area input' + ) as HTMLInputElement + firstInput?.focus() + }, 100) } }, [showAnswerForCell]) @@ -262,6 +289,14 @@ export default function ProcessPracticePage() { if (remainingTime <= 0) { setShowAnswerForCell(null) setInputLocked(false) + + // 恢复焦点 + setTimeout(() => { + const firstInput = document.querySelector( + '.practice-input-area input' + ) as HTMLInputElement + firstInput?.focus() + }, 100) return } @@ -269,6 +304,14 @@ export default function ProcessPracticePage() { setShowAnswerForCell(null) setInputLocked(false) announceToScreenReader('答案已自动隐藏') + + // 恢复焦点 + setTimeout(() => { + const firstInput = document.querySelector( + '.practice-input-area input' + ) as HTMLInputElement + firstInput?.focus() + }, 100) }, remainingTime) return () => clearTimeout(timer) @@ -362,7 +405,7 @@ export default function ProcessPracticePage() { {/* 主内容区域 */} -
+
{/* 矩阵区域 */}
{/* 底部固定区域 */} -
+
{/* 输入区域 */}
- +
+ - {/* 提示按钮 */} -
+ {/* 查看答案按钮 */}
{/* 辅助信息区域 */} -
+