From 96a1c3808f1795c3543c373918eb6c313feadfb7 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Tue, 13 Oct 2026 22:24:59 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E8=87=AA=E5=AD=A6):=20=E6=89=8B=E6=9C=BA?= =?UTF-8?q?=E4=B8=8A=E3=80=8C=E4=BB=A3=E7=A0=81=E6=8E=92=E5=BA=8F=E3=80=8D?= =?UTF-8?q?=E3=80=8C=E5=88=86=E7=BB=84=E3=80=8D=E4=B8=A4=E7=A7=8D=E7=BB=83?= =?UTF-8?q?=E4=B8=80=E7=BB=83=E6=8B=96=E4=B8=8D=E5=8A=A8=E3=80=81=E5=81=9A?= =?UTF-8?q?=E4=B8=8D=E4=BA=86=EF=BC=8C=E6=94=B9=E6=88=90=E7=82=B9=E4=B8=80?= =?UTF-8?q?=E4=B8=8B=E9=80=89=E4=B8=AD=E3=80=81=E5=86=8D=E7=82=B9=E4=B8=80?= =?UTF-8?q?=E4=B8=8B=E6=94=BE=E4=B8=8B=E4=B9=9F=E8=A1=8C=EF=BC=9B=E5=A1=AB?= =?UTF-8?q?=E7=A9=BA=E4=B8=8D=E5=86=8D=E8=A2=AB=E6=89=8B=E6=9C=BA=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E6=B3=95=E6=8A=8A=E9=A6=96=E5=AD=97=E6=AF=8D=E6=94=B9?= =?UTF-8?q?=E6=88=90=E5=A4=A7=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- .../src/oj/learn/components/ExerciseDebug.vue | 2 +- .../src/oj/learn/components/ExerciseFill.vue | 4 ++ .../src/oj/learn/components/ExerciseGroup.vue | 40 ++++++++++- .../oj/learn/components/ExercisePredict.vue | 1 + .../src/oj/learn/components/ExerciseSort.vue | 66 +++++++++++++------ 5 files changed, 92 insertions(+), 21 deletions(-) diff --git a/apps/web/src/oj/learn/components/ExerciseDebug.vue b/apps/web/src/oj/learn/components/ExerciseDebug.vue index c553500..8b5a7a1 100644 --- a/apps/web/src/oj/learn/components/ExerciseDebug.vue +++ b/apps/web/src/oj/learn/components/ExerciseDebug.vue @@ -101,7 +101,7 @@ function reset() { {{ idx + 1 }} - + diff --git a/apps/web/src/oj/learn/components/ExerciseFill.vue b/apps/web/src/oj/learn/components/ExerciseFill.vue index 1b8d305..2e7432a 100644 --- a/apps/web/src/oj/learn/components/ExerciseFill.vue +++ b/apps/web/src/oj/learn/components/ExerciseFill.vue @@ -96,6 +96,10 @@ function inputWidth(idx: number): string { v-else :value="userInputs[seg.index]" :disabled="allCorrect" + autocapitalize="off" + autocorrect="off" + autocomplete="off" + spellcheck="false" :style="{ width: inputWidth(seg.index), fontFamily: 'var(--learn-code-font)', diff --git a/apps/web/src/oj/learn/components/ExerciseGroup.vue b/apps/web/src/oj/learn/components/ExerciseGroup.vue index e9d1afa..ebddaaf 100644 --- a/apps/web/src/oj/learn/components/ExerciseGroup.vue +++ b/apps/web/src/oj/learn/components/ExerciseGroup.vue @@ -13,12 +13,15 @@ const data = computed(() => props.exercise.data as ExerciseGroupData) const order = ref([]) // item 的稳定展示顺序(初始乱序) const placement = ref([]) // placement[itemIdx] = 桶下标,-1 表示在池中 const dragIdx = ref(null) +// 手机上没有 HTML5 拖放(触屏不触发 dragstart),所以再给一条点选的路:先点项目、再点分组 +const pickedIdx = ref(null) const submitted = ref(false) function init() { order.value = shuffle(data.value.items.map((_, i) => i)) placement.value = Array(data.value.items.length).fill(-1) dragIdx.value = null + pickedIdx.value = null submitted.value = false } @@ -32,6 +35,7 @@ const locked = computed(() => submitted.value && allCorrect.value) function onDragStart(i: number) { if (locked.value) return dragIdx.value = i + pickedIdx.value = null } function dropTo(bucket: number) { @@ -41,6 +45,25 @@ function dropTo(bucket: number) { submitted.value = false } +// 手机上分组框不大,点分组时多半点在框里已有的项目上 —— 这时算「放进它所在的分组」, +// 只有点同一区域里的另一项才是换选 +function onItemClick(i: number) { + if (locked.value) return + const picked = pickedIdx.value + if (picked !== null && picked !== i && placement.value[picked] !== placement.value[i]) { + onAreaClick(placement.value[i]) + return + } + pickedIdx.value = picked === i ? null : i +} + +function onAreaClick(bucket: number) { + if (locked.value || pickedIdx.value === null) return + placement.value[pickedIdx.value] = bucket + pickedIdx.value = null + submitted.value = false +} + const poolItems = computed(() => order.value.filter((i) => placement.value[i] === -1)) function itemsIn(bucket: number): number[] { return order.value.filter((i) => placement.value[i] === bucket) @@ -56,6 +79,17 @@ function chipStyle(i: number): Record { const color = status === "correct" ? "#18a058" : status === "wrong" ? "#d03050" : "var(--learn-control-line)" const plain = color === "var(--learn-control-line)" + if (pickedIdx.value === i) { + return { + padding: "5.5px 11.5px", + borderRadius: "6px", + border: "2px solid #2080f0", + background: "rgba(32,128,240,0.08)", + cursor: "pointer", + userSelect: "none", + fontSize: "15px", + } + } return { padding: "6px 12px", borderRadius: "6px", @@ -86,7 +120,7 @@ function reset() { {{ data.question }}

- 把下面的项目拖到对应的分组里,可在分组间拖动调整。 + 把下面的项目拖到对应的分组里,也可以先点项目、再点分组。

(已全部归类) @@ -112,6 +147,7 @@ function reset() { draggable="true" :style="chipStyle(i)" @dragstart="onDragStart(i)" + @click.stop="onItemClick(i)" > {{ data.items[i] }}
@@ -135,6 +171,7 @@ function reset() { }" @dragover.prevent @drop="dropTo(b)" + @click="onAreaClick(b)" >

{{ bucket }} @@ -146,6 +183,7 @@ function reset() { draggable="true" :style="chipStyle(i)" @dragstart="onDragStart(i)" + @click.stop="onItemClick(i)" > {{ data.items[i] }} diff --git a/apps/web/src/oj/learn/components/ExercisePredict.vue b/apps/web/src/oj/learn/components/ExercisePredict.vue index ee62d9b..def0911 100644 --- a/apps/web/src/oj/learn/components/ExercisePredict.vue +++ b/apps/web/src/oj/learn/components/ExercisePredict.vue @@ -81,6 +81,7 @@ function reset() { :rows="3" :disabled="submitted && allCorrect" placeholder="在这里输入程序会打印的内容" + :input-props="{ autocapitalize: 'off', autocorrect: 'off', spellcheck: false }" style="font-family: var(--learn-code-font)" /> diff --git a/apps/web/src/oj/learn/components/ExerciseSort.vue b/apps/web/src/oj/learn/components/ExerciseSort.vue index 871ea63..bd7a9a6 100644 --- a/apps/web/src/oj/learn/components/ExerciseSort.vue +++ b/apps/web/src/oj/learn/components/ExerciseSort.vue @@ -24,6 +24,7 @@ function init() { ;[shuffled[0], shuffled[1]] = [shuffled[1], shuffled[0]] } lines.value = shuffled + pickedIdx.value = null submitted.value = false } @@ -31,19 +32,37 @@ onMounted(init) watch(() => props.exercise.id, init) const dragIdx = ref(null) +// 手机上没有 HTML5 拖放(触屏不触发 dragstart),所以再给一条点选的路:先点一行、再点它该去的位置 +const pickedIdx = ref(null) function onDragStart(idx: number) { dragIdx.value = idx + pickedIdx.value = null +} + +function moveLine(from: number, to: number) { + if (from === to) return + const newLines = [...lines.value] + const [moved] = newLines.splice(from, 1) + newLines.splice(to, 0, moved) + lines.value = newLines + submitted.value = false } function onDrop(targetIdx: number) { - if (dragIdx.value === null || dragIdx.value === targetIdx) return - const newLines = [...lines.value] - const [moved] = newLines.splice(dragIdx.value, 1) - newLines.splice(targetIdx, 0, moved) - lines.value = newLines + if (dragIdx.value === null) return + moveLine(dragIdx.value, targetIdx) dragIdx.value = null - submitted.value = false +} + +function onLineClick(idx: number) { + if (submitted.value && allCorrect.value) return + if (pickedIdx.value === null) { + pickedIdx.value = idx + return + } + moveLine(pickedIdx.value, idx) + pickedIdx.value = null } function lineStatus(idx: number): "correct" | "wrong" | "default" { @@ -86,19 +105,24 @@ const lineHtml = computed(() => highlightLines(data.value.lines, props gap: '10px', padding: '8px 12px', borderRadius: '6px', - border: `1.5px ${submitted ? 'solid' : 'dashed'} ${ - lineStatus(idx) === 'correct' - ? '#18a058' - : lineStatus(idx) === 'wrong' - ? '#d03050' - : 'var(--learn-control-line)' - }`, + border: + pickedIdx === idx + ? '2px solid #2080f0' + : `1.5px ${submitted ? 'solid' : 'dashed'} ${ + lineStatus(idx) === 'correct' + ? '#18a058' + : lineStatus(idx) === 'wrong' + ? '#d03050' + : 'var(--learn-control-line)' + }`, background: - lineStatus(idx) === 'correct' - ? 'rgba(24,160,88,0.08)' - : lineStatus(idx) === 'wrong' - ? 'rgba(208,48,80,0.07)' - : 'transparent', + pickedIdx === idx + ? 'rgba(32,128,240,0.08)' + : lineStatus(idx) === 'correct' + ? 'rgba(24,160,88,0.08)' + : lineStatus(idx) === 'wrong' + ? 'rgba(208,48,80,0.07)' + : 'transparent', cursor: 'grab', fontFamily: 'var(--learn-code-font)', userSelect: 'none', @@ -106,9 +130,13 @@ const lineHtml = computed(() => highlightLines(data.value.lines, props @dragstart="onDragStart(idx)" @dragover.prevent @drop="onDrop(idx)" + @click="onLineClick(idx)" > ⠿ - +