From 9afb57a9edc2234254f2d6733ac7c9bc70c88d82 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Fri, 24 Apr 2026 02:01:35 -0600 Subject: [PATCH] feat: rewrite ExerciseMcq for multi-select with partial feedback --- src/oj/learn/components/ExerciseMcq.vue | 49 +++++++++++++++++-------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/oj/learn/components/ExerciseMcq.vue b/src/oj/learn/components/ExerciseMcq.vue index 07220a4..9f5a3c7 100644 --- a/src/oj/learn/components/ExerciseMcq.vue +++ b/src/oj/learn/components/ExerciseMcq.vue @@ -4,36 +4,53 @@ import { Exercise, ExerciseMcqData } from "utils/types" const props = defineProps<{ exercise: Exercise }>() const data = computed(() => props.exercise.data as ExerciseMcqData) -const selected = ref(null) +const selected = ref>(new Set()) const correct = ref(false) const wrong = ref(false) +const partial = ref(false) function select(idx: number) { if (correct.value) return - selected.value = idx + const s = new Set(selected.value) + if (s.has(idx)) s.delete(idx) + else s.add(idx) + selected.value = s wrong.value = false + partial.value = false } function submit() { - if (selected.value === null || correct.value) return - if (selected.value === data.value.answer) { + if (selected.value.size === 0 || correct.value) return + const answer = new Set(data.value.answer) + const sel = selected.value + const isEqual = + sel.size === answer.size && [...sel].every((v) => answer.has(v)) + if (isEqual) { correct.value = true wrong.value = false + partial.value = false } else { - wrong.value = true - selected.value = null + const hasIntersection = [...sel].some((v) => answer.has(v)) + if (hasIntersection) { + partial.value = true + wrong.value = false + } else { + wrong.value = true + partial.value = false + } } } function reset() { - selected.value = null + selected.value = new Set() correct.value = false wrong.value = false + partial.value = false } function optionType(idx: number): "default" | "primary" | "success" { - if (correct.value && idx === data.value.answer) return "success" - if (idx === selected.value) return "primary" + if (correct.value && data.value.answer.includes(idx)) return "success" + if (selected.value.has(idx)) return "primary" return "default" } @@ -46,7 +63,7 @@ function optionType(idx: number): "default" | "primary" | "success" { @@ -60,7 +77,7 @@ function optionType(idx: number): "default" | "primary" | "success" { :type="optionType(idx)" :secondary="optionType(idx) !== 'default'" :tertiary="optionType(idx) === 'default'" - :strong="idx === selected" + :strong="selected.has(idx)" :style="{ justifyContent: 'flex-start', width: '100%', @@ -78,9 +95,11 @@ function optionType(idx: number): "default" | "primary" | "success" { @@ -88,7 +107,7 @@ function optionType(idx: number): "default" | "primary" | "success" { 提交