From f120701ebea76e61ddf2c60b41b25cd13178e1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=B2=85?= <907037276@qq.com> Date: Mon, 28 Sep 2026 15:05:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=BB=BA=E8=80=83=E8=AF=95=E9=80=89?= =?UTF-8?q?=E9=A2=98=E6=94=B9=E4=B8=BA=E6=8C=89=E6=A0=A1=E9=A2=98=E5=BA=93?= =?UTF-8?q?(scope=3Dschool)=EF=BC=9B=E6=AD=A5=E9=AA=A4=E6=9D=A1=E4=B8=8E?= =?UTF-8?q?=E8=80=83=E8=AF=95=E5=88=97=E8=A1=A8=E8=B5=B7=E6=AD=A2=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=A0=B7=E5=BC=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/teacherEnd/exam/editor.vue | 48 +++++++++++++++++----------- src/views/teacherEnd/exam/index.vue | 31 ++++++++++++++++-- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/views/teacherEnd/exam/editor.vue b/src/views/teacherEnd/exam/editor.vue index e5daecd..fc05062 100644 --- a/src/views/teacherEnd/exam/editor.vue +++ b/src/views/teacherEnd/exam/editor.vue @@ -51,9 +51,9 @@
- >>> + - >>> +
@@ -233,7 +233,7 @@ const totalScore = computed(() => form.questions.reduce((sum, item) => sum + Num const selectedTypes = computed(() => typeOptions.filter((item) => selectedByType(item.value))); onMounted(load); -async function load() { loading.value = true; try { const [classRes, questionRes] = await Promise.all([examApi.getExamClasses(), examApi.getQuestions({})]); classes.value = classRes.data || []; bank.value = questionRes.data || []; if (!isNew.value) { const { data } = await examApi.getTeacherExam(id.value); status.value = data.status; const bankIds = new Set(bank.value.map((item) => item.id)); bank.value = [...bank.value, ...data.questions.filter((item) => !bankIds.has(item.id))]; Object.assign(form, { name: data.name, startTime: formatValue(data.startTime), endTime: formatValue(data.endTime), classIds: data.classes.map((item) => item.id), questionOrderMode: data.questionOrderMode || "FIXED", optionOrderMode: data.optionOrderMode || "FIXED", allowCopyQuestion: toBoolean(data.allowCopyQuestion, false), allowPasteAnswer: toBoolean(data.allowPasteAnswer, false), allowRollback: toBoolean(data.allowRollback, true), multipleScoreMode: data.multipleScoreMode || "ALL_OR_NOTHING", questions: data.questions.map((item) => ({ questionId: item.id, score: Number(item.score) })) }); for (const type of typeOptions.map((item) => item.value)) { const first = data.questions.find((item) => item.type === type); if (first) typeScores[type] = Number(first.score) || 1; } duration.value = data.durationMinutes; } else { const start = new Date(Date.now() + 3600000); form.startTime = formatValue(start); form.endTime = formatValue(new Date(start.getTime() + 3600000)); } } finally { loading.value = false; } } +async function load() { loading.value = true; try { const [classRes, questionRes] = await Promise.all([examApi.getExamClasses(), examApi.getQuestions({ scope: "school" })]); classes.value = classRes.data || []; bank.value = questionRes.data || []; if (!isNew.value) { const { data } = await examApi.getTeacherExam(id.value); status.value = data.status; const bankIds = new Set(bank.value.map((item) => item.id)); bank.value = [...bank.value, ...data.questions.filter((item) => !bankIds.has(item.id))]; Object.assign(form, { name: data.name, startTime: formatValue(data.startTime), endTime: formatValue(data.endTime), classIds: data.classes.map((item) => item.id), questionOrderMode: data.questionOrderMode || "FIXED", optionOrderMode: data.optionOrderMode || "FIXED", allowCopyQuestion: toBoolean(data.allowCopyQuestion, false), allowPasteAnswer: toBoolean(data.allowPasteAnswer, false), allowRollback: toBoolean(data.allowRollback, true), multipleScoreMode: data.multipleScoreMode || "ALL_OR_NOTHING", questions: data.questions.map((item) => ({ questionId: item.id, score: Number(item.score) })) }); for (const type of typeOptions.map((item) => item.value)) { const first = data.questions.find((item) => item.type === type); if (first) typeScores[type] = Number(first.score) || 1; } duration.value = data.durationMinutes; } else { const start = new Date(Date.now() + 3600000); form.startTime = formatValue(start); form.endTime = formatValue(new Date(start.getTime() + 3600000)); } } finally { loading.value = false; } } function syncEndTime() { if (!form.startTime) return; form.endTime = formatValue(new Date(new Date(form.startTime.replace(" ", "T")).getTime() + duration.value * 60000)); } function syncDurationFromEnd() { if (!form.startTime || !form.endTime) return; const start = new Date(form.startTime.replace(" ", "T")); const end = new Date(form.endTime.replace(" ", "T")); if (end > start) duration.value = Math.round((end - start) / 60000); } function isSelected(questionId) { return form.questions.some((item) => item.questionId === questionId); } @@ -403,38 +403,48 @@ function toBoolean(value, fallback) { if (value === undefined || value === null display: flex; align-items: center; justify-content: center; - gap: var(--sp-4); + gap: var(--sp-3); margin-top: var(--sp-5); } .fixed-step-button { - min-width: 164px; - height: 40px; - padding: 0 var(--sp-5); - border: 0; + min-width: 148px; + height: 38px; + padding: 0 var(--sp-4); + border: 1px solid var(--border-color); border-radius: var(--r-control); - background: var(--edu-primary); - color: #ffffff; + background: #ffffff; + color: var(--text-body); + font: inherit; font-size: var(--fs-body); - font-weight: 600; + font-weight: 500; cursor: pointer; - transition: background 0.16s ease, transform 0.16s ease, box-shadow 0.16s ease; + transition: border-color 0.16s ease, background 0.16s ease, color 0.16s ease, box-shadow 0.16s ease; + + &:hover { + border-color: var(--edu-primary); + color: var(--edu-primary); + } - &:hover, &.is-active { - background: var(--edu-primary-deep); + border-color: var(--edu-primary); + background: var(--edu-primary); + color: #ffffff; box-shadow: 0 4px 10px rgba(25, 137, 204, 0.18); - transform: translateY(-1px); + + &:hover { color: #ffffff; } } &:focus-visible { outline: 2px solid var(--edu-primary); outline-offset: 2px; } } .fixed-step-arrow { - color: var(--text-strong); - font-size: 20px; - font-weight: 700; - letter-spacing: -3px; + display: inline-flex; + align-items: center; + color: var(--text-muted); + font-size: 16px; + + .el-icon { font-size: 16px; } } .form-row { diff --git a/src/views/teacherEnd/exam/index.vue b/src/views/teacherEnd/exam/index.vue index ac7123a..4518a7a 100644 --- a/src/views/teacherEnd/exam/index.vue +++ b/src/views/teacherEnd/exam/index.vue @@ -10,7 +10,7 @@
-

{{ row.name }}

起止时间:{{ formatTime(row.startTime) }} - {{ formatTime(row.endTime) }}

考试时长:{{ row.durationMinutes || durationBetween(row) }}分钟

+

{{ row.name }}

起止时间{{ formatTime(row.startTime) }} ~ {{ formatTime(row.endTime) }}

考试时长:{{ row.durationMinutes || durationBetween(row) }}分钟

{{ statusMeta[row.status]?.label || row.status }}
撤回 @@ -115,7 +115,7 @@ import { computed, onActivated, onMounted, reactive, ref } from "vue"; import { ElMessage, ElMessageBox } from "element-plus"; import { useRouter } from "vue-router"; -import { ArrowDown, Check, Close, DataAnalysis, Delete, Download, Edit, EditPen, FolderOpened, MagicStick, Paperclip, PictureFilled, Plus, RefreshLeft, Search, Upload } from "@element-plus/icons-vue"; +import { ArrowDown, Check, Clock, Close, DataAnalysis, Delete, Download, Edit, EditPen, FolderOpened, MagicStick, Paperclip, PictureFilled, Plus, RefreshLeft, Search, Upload } from "@element-plus/icons-vue"; import { saveAs } from "file-saver"; import * as examApi from "@/api/exam"; @@ -470,6 +470,33 @@ function durationBetween(row) { if (!row.startTime || !row.endTime) return 0; re color: var(--text-body); font-size: var(--fs-body); } + + .time-line { + display: inline-flex; + align-items: center; + gap: 6px; + margin: 4px 0; + padding: 4px 10px; + border-radius: 6px; + background: var(--edu-primary-soft); + + .el-icon { + font-size: 15px; + color: var(--edu-primary); + } + + .time-label { + color: var(--edu-primary-deep); + font-size: var(--fs-body); + } + + .time-value { + color: var(--text-strong); + font-size: var(--fs-body); + font-weight: 600; + font-variant-numeric: tabular-nums; + } + } } .assessment-status {