diff --git a/src/pages/PerformanceDomainPracticePage.tsx b/src/pages/PerformanceDomainPracticePage.tsx index 56cf79e..74c4b81 100644 --- a/src/pages/PerformanceDomainPracticePage.tsx +++ b/src/pages/PerformanceDomainPracticePage.tsx @@ -208,6 +208,7 @@ export default function PerformanceDomainPracticePage() { const accuracyBase = progress.correctCount + progress.wrongCount const accuracy = accuracyBase > 0 ? Math.round((progress.correctCount / accuracyBase) * 100) : 0 const progressPercent = progress.totalCount > 0 ? (completedCount / progress.totalCount) * 100 : 0 + const completedIdSet = useMemo(() => new Set(progress.completedIds), [progress.completedIds]) useEffect(() => { try { @@ -311,37 +312,87 @@ export default function PerformanceDomainPracticePage() { const isCorrectSelected = isAnswerShown && isSelected && answerState?.isCorrect const isWrongSelected = isAnswerShown && isSelected && !answerState?.isCorrect const shouldHighlightCorrect = isAnswerShown && isCorrectDomain + const getKindProgress = (kind: QuestionKind) => { + const ids = questionBank + .filter((question) => question.domainId === domain.id && question.kind === kind) + .map((question) => question.id) + const completed = ids.filter((id) => completedIdSet.has(id)).length + return { + completed, + total: ids.length, + percent: ids.length > 0 ? (completed / ids.length) * 100 : 0, + } + } + const expectedGoalProgress = getKindProgress('expectedGoal') + const keyPointProgress = getKindProgress('keyPoint') + const currentKindProgress = currentQuestion?.kind === 'expectedGoal' + ? expectedGoalProgress + : keyPointProgress + const currentKindDone = currentKindProgress.total > 0 && currentKindProgress.completed >= currentKindProgress.total + const optionDisabled = isAnswerShown || currentKindDone return ( handleSelect(domain.id)} - disabled={isAnswerShown} + disabled={optionDisabled} className={clsx( - 'relative flex min-h-[84px] items-center gap-3 rounded-xl border bg-white p-3 text-left shadow-sm transition-colors dark:bg-gray-800', + 'relative flex min-h-[128px] flex-col gap-3 rounded-xl border bg-white p-3 text-left shadow-sm transition-colors dark:bg-gray-800', 'border-gray-100 hover:border-indigo-200 hover:bg-indigo-50/40 dark:border-gray-700 dark:hover:border-indigo-700 dark:hover:bg-indigo-950/20', - isAnswerShown && 'cursor-default hover:bg-white dark:hover:bg-gray-800', + optionDisabled && 'cursor-default hover:bg-white dark:hover:bg-gray-800', + currentKindDone && !isAnswerShown && 'bg-gray-50 opacity-55 dark:bg-gray-800/70', shouldHighlightCorrect && 'border-emerald-400 bg-emerald-50 shadow-[inset_0_0_0_2px_rgba(52,211,153,0.65)] dark:border-emerald-500 dark:bg-emerald-950/30 dark:shadow-[inset_0_0_0_2px_rgba(16,185,129,0.45)]', isWrongSelected && 'border-rose-300 bg-rose-50 shadow-[inset_0_0_0_2px_rgba(251,113,133,0.65)] dark:border-rose-600 dark:bg-rose-950/30 dark:shadow-[inset_0_0_0_2px_rgba(244,63,94,0.45)]' )} > -
- +
+
+ +
+
+
+ {domain.name} +
+
+ {domain.nameEn} +
+
-
-
- {domain.name} -
-
- {domain.nameEn} -
+ +
+ {[ + { label: '目标', data: expectedGoalProgress }, + { label: '要点', data: keyPointProgress }, + ].map((item) => { + const isFull = item.data.total > 0 && item.data.completed >= item.data.total + return ( +
+
+ {item.label} + {item.data.completed}/{item.data.total} +
+
+
+
+
+ ) + })}
{isCorrectSelected && (