Merge remote-tracking branch 'origin/fix/exam-question-access-material-excel-delete-draft' into dev-QQq

master
qinzhenpen 5 days ago
commit 623771ec6b

@ -12,7 +12,7 @@
<div class="rich-row"><label>题干</label><Editor v-model="form.stem" :min-height="154" /></div> <div class="rich-row"><label>题干</label><Editor v-model="form.stem" :min-height="154" /></div>
<template v-if="isChoice"><div class="option-block"><label>选项</label><div class="option-list"><div v-for="(option, index) in form.options" :key="index" class="option-row"><div class="option-letter"><el-radio v-if="form.type === 'SINGLE'" v-model="singleAnswer" :label="optionLabel(index)" class="answer-control" /><el-checkbox v-else v-model="answers" :label="optionLabel(index)" class="answer-control" /><span class="letter-tag">{{ optionLabel(index) }}</span></div><Editor v-model="option.content" :min-height="92" /><el-button v-if="form.options.length > 2" link type="danger" :icon="Delete" @click="removeOption(index)" class="remove-btn" /></div><el-button type="primary" plain :icon="Plus" @click="addOption" class="add-option-btn">新增选项</el-button></div></div><div class="rich-row analysis-row"><label>答案解析(选填)</label><Editor v-model="form.analysis" :min-height="112" /></div></template> <template v-if="isChoice"><div class="option-block"><label>选项</label><div class="option-list"><div v-for="(option, index) in form.options" :key="index" class="option-row"><div class="option-letter"><el-radio v-if="form.type === 'SINGLE'" v-model="singleAnswer" :label="optionLabel(index)" class="answer-control" /><el-checkbox v-else v-model="answers" :label="optionLabel(index)" class="answer-control" /><span class="letter-tag">{{ optionLabel(index) }}</span></div><Editor v-model="option.content" :min-height="92" /><el-button v-if="form.options.length > 2" link type="danger" :icon="Delete" @click="removeOption(index)" class="remove-btn" /></div><el-button type="primary" plain :icon="Plus" @click="addOption" class="add-option-btn">新增选项</el-button></div></div><div class="rich-row analysis-row"><label>答案解析(选填)</label><Editor v-model="form.analysis" :min-height="112" /></div></template>
<template v-else-if="form.type === 'TRUE_FALSE'"><div class="tf-block"><label>选项</label><div class="tf-options"><el-radio-group v-model="form.answer" class="tf-radio-group"><el-radio-button :label="true" class="tf-radio">对</el-radio-button><el-radio-button :label="false" class="tf-radio">错</el-radio-button></el-radio-group></div></div><div class="rich-row analysis-row"><label>答案解析(选填)</label><Editor v-model="form.analysis" :min-height="112" /></div></template> <template v-else-if="form.type === 'TRUE_FALSE'"><div class="tf-block"><label>选项</label><div class="tf-options"><el-radio-group v-model="form.answer" class="tf-radio-group"><el-radio-button :label="true" class="tf-radio">对</el-radio-button><el-radio-button :label="false" class="tf-radio">错</el-radio-button></el-radio-group></div></div><div class="rich-row analysis-row"><label>答案解析(选填)</label><Editor v-model="form.analysis" :min-height="112" /></div></template>
<template v-else><div class="material-row"><el-upload :show-file-list="false" :http-request="uploadMaterial" accept=".pdf,.doc,.docx,.png,.jpg,.jpeg,.xls,.xlsx"><el-button type="primary" plain :loading="uploading">上传简答题资料</el-button></el-upload><span v-if="form.attachmentName" class="material-name">{{ form.attachmentName }}</span></div><div class="rich-row"><label>参考答案</label><Editor v-model="form.answer" :min-height="180" /></div><div class="rich-row analysis-row"><label>答案解析(选填)</label><Editor v-model="form.analysis" :min-height="112" /></div></template> <template v-else><div class="material-row"><el-upload :show-file-list="false" :http-request="uploadMaterial" accept=".pdf,.doc,.docx,.xls,.xlsx,.png,.jpg,.jpeg"><el-button type="primary" plain :loading="uploading">上传简答题资料</el-button></el-upload><span v-if="form.attachmentName" class="material-name">{{ form.attachmentName }}</span></div><div class="rich-row"><label>参考答案</label><Editor v-model="form.answer" :min-height="180" /></div><div class="rich-row analysis-row"><label>答案解析(选填)</label><Editor v-model="form.analysis" :min-height="112" /></div></template>
</div><template #footer><el-button @click="editorVisible=false">取消</el-button><el-button type="primary" :loading="saving" @click="save">确定</el-button></template> </div><template #footer><el-button @click="editorVisible=false">取消</el-button><el-button type="primary" :loading="saving" @click="save">确定</el-button></template>
</el-dialog> </el-dialog>

@ -15,6 +15,7 @@
<div class="assessment-actions"> <div class="assessment-actions">
<el-button v-if="row.status === 'NOT_STARTED'" text type="primary" :icon="RefreshLeft" @click="withdraw(row)">撤回</el-button> <el-button v-if="row.status === 'NOT_STARTED'" text type="primary" :icon="RefreshLeft" @click="withdraw(row)">撤回</el-button>
<el-button v-if="['DRAFT','IN_PROGRESS'].includes(row.status)" text type="primary" :icon="Edit" @click="$router.push(`/exam/manage/${row.id}`)">编辑</el-button> <el-button v-if="['DRAFT','IN_PROGRESS'].includes(row.status)" text type="primary" :icon="Edit" @click="$router.push(`/exam/manage/${row.id}`)">编辑</el-button>
<el-button v-if="row.status === 'DRAFT'" text type="danger" :icon="Delete" @click="removeExam(row)">删除</el-button>
<el-button v-if="row.status === 'IN_PROGRESS'" text type="primary" :icon="RefreshLeft" @click="$router.push(`/exam/review/${row.id}`)">指定人回退</el-button> <el-button v-if="row.status === 'IN_PROGRESS'" text type="primary" :icon="RefreshLeft" @click="$router.push(`/exam/review/${row.id}`)">指定人回退</el-button>
<template v-if="row.status === 'ENDED'"><el-button text type="primary" :icon="EditPen" @click="$router.push(`/exam/review/${row.id}`)">评阅</el-button><el-button text type="primary" :icon="DataAnalysis" @click="$router.push(`/exam/analysis/${row.id}`)">分析</el-button><el-dropdown @command="(command) => handleExport(command, row)"><el-button text type="primary" :icon="Download">导出<el-icon class="el-icon--right"><ArrowDown /></el-icon></el-button><template #dropdown><el-dropdown-menu><el-dropdown-item command="paper">空白试卷</el-dropdown-item><el-dropdown-item command="scores">班级成绩</el-dropdown-item><el-dropdown-item command="submissions">全部答卷</el-dropdown-item></el-dropdown-menu></template></el-dropdown><el-button text type="danger" :icon="Delete" @click="removeExam(row)">删除</el-button></template> <template v-if="row.status === 'ENDED'"><el-button text type="primary" :icon="EditPen" @click="$router.push(`/exam/review/${row.id}`)">评阅</el-button><el-button text type="primary" :icon="DataAnalysis" @click="$router.push(`/exam/analysis/${row.id}`)">分析</el-button><el-dropdown @command="(command) => handleExport(command, row)"><el-button text type="primary" :icon="Download">导出<el-icon class="el-icon--right"><ArrowDown /></el-icon></el-button><template #dropdown><el-dropdown-menu><el-dropdown-item command="paper">空白试卷</el-dropdown-item><el-dropdown-item command="scores">班级成绩</el-dropdown-item><el-dropdown-item command="submissions">全部答卷</el-dropdown-item></el-dropdown-menu></template></el-dropdown><el-button text type="danger" :icon="Delete" @click="removeExam(row)">删除</el-button></template>
</div> </div>
@ -116,7 +117,7 @@
<el-form-item v-else-if="questionForm.type === 'TRUE_FALSE'" label="正确答案"><el-radio-group v-model="questionForm.answer"><el-radio :label="true">正确</el-radio><el-radio :label="false">错误</el-radio></el-radio-group></el-form-item> <el-form-item v-else-if="questionForm.type === 'TRUE_FALSE'" label="正确答案"><el-radio-group v-model="questionForm.answer"><el-radio :label="true">正确</el-radio><el-radio :label="false">错误</el-radio></el-radio-group></el-form-item>
<el-form-item v-else label="参考答案" prop="answer"><el-input v-model="questionForm.answer" type="textarea" :rows="4" /></el-form-item> <el-form-item v-else label="参考答案" prop="answer"><el-input v-model="questionForm.answer" type="textarea" :rows="4" /></el-form-item>
<el-form-item v-if="questionForm.type === 'SHORT_ANSWER'" label="题目资料"> <el-form-item v-if="questionForm.type === 'SHORT_ANSWER'" label="题目资料">
<el-upload :show-file-list="false" :http-request="uploadMaterial" accept=".pdf,.doc,.docx,.png,.jpg,.jpeg,.xls,.xlsx"><el-button :icon="Paperclip">上传资料</el-button></el-upload> <el-upload :show-file-list="false" :http-request="uploadMaterial" accept=".pdf,.doc,.docx,.xls,.xlsx,.png,.jpg,.jpeg"><el-button :icon="Paperclip">上传资料</el-button></el-upload>
<span v-if="questionForm.attachmentName" class="file-name">{{ questionForm.attachmentName }}</span> <span v-if="questionForm.attachmentName" class="file-name">{{ questionForm.attachmentName }}</span>
</el-form-item> </el-form-item>
<el-form-item label="答案解析"><el-input v-model="questionForm.analysis" type="textarea" :rows="3" /></el-form-item> <el-form-item label="答案解析"><el-input v-model="questionForm.analysis" type="textarea" :rows="3" /></el-form-item>
@ -186,7 +187,7 @@ async function doImport({ file }) { importing.value = true; try { const form = n
async function downloadTemplate(format) { const extension = format === "excel" ? "xlsx" : "docx"; saveAs(await examApi.downloadQuestionTemplate(format), `考试题库${format === "excel" ? "Excel" : "Word"}导入模板.${extension}`); } async function downloadTemplate(format) { const extension = format === "excel" ? "xlsx" : "docx"; saveAs(await examApi.downloadQuestionTemplate(format), `考试题库${format === "excel" ? "Excel" : "Word"}导入模板.${extension}`); }
async function publish(row) { await ElMessageBox.confirm(`确认发布“${row.name}”?发布后将在设定时间自动开始。`, "发布考试", { type: "warning" }); await examApi.publishExam(row.id); ElMessage.success("已发布"); loadExams(); } async function publish(row) { await ElMessageBox.confirm(`确认发布“${row.name}”?发布后将在设定时间自动开始。`, "发布考试", { type: "warning" }); await examApi.publishExam(row.id); ElMessage.success("已发布"); loadExams(); }
async function withdraw(row) { await examApi.withdrawExam(row.id); ElMessage.success("已撤回"); loadExams(); } async function withdraw(row) { await examApi.withdrawExam(row.id); ElMessage.success("已撤回"); loadExams(); }
async function removeExam(row) { await ElMessageBox.confirm(`确认永久删除“${row.name}”?仅在已导出全部答卷后允许删除。`, "删除考试", { type: "warning", confirmButtonText: "确认删除" }); await examApi.deleteExam(row.id); ElMessage.success("已删除"); loadExams(); } async function removeExam(row) { const message = row.status === "DRAFT" ? `确认删除未发布的考试“${row.name}”?删除后无法恢复。` : `确认永久删除“${row.name}”?仅在已导出全部答卷后允许删除。`; await ElMessageBox.confirm(message, "删除考试", { type: "warning", confirmButtonText: "确认删除" }); await examApi.deleteExam(row.id); ElMessage.success("已删除"); loadExams(); }
async function handleExport(command, row) { const actions = { paper: [examApi.exportExamPaper, `${row.name}试卷.docx`], scores: [examApi.exportExamScores, `${row.name}班级成绩.xlsx`], submissions: [examApi.exportExamSubmissions, `${row.name}全部试卷.zip`] }; const [action, filename] = actions[command]; saveAs(await action(row.id), filename); if (command === "submissions") loadExams(); } async function handleExport(command, row) { const actions = { paper: [examApi.exportExamPaper, `${row.name}试卷.docx`], scores: [examApi.exportExamScores, `${row.name}班级成绩.xlsx`], submissions: [examApi.exportExamSubmissions, `${row.name}全部试卷.zip`] }; const [action, filename] = actions[command]; saveAs(await action(row.id), filename); if (command === "submissions") loadExams(); }
function displayAnswer(value) { if (Array.isArray(value)) return value.join("、"); if (value === true) return "正确"; if (value === false) return "错误"; return value || "-"; } function displayAnswer(value) { if (Array.isArray(value)) return value.join("、"); if (value === true) return "正确"; if (value === false) return "错误"; return value || "-"; }
function formatTime(value) { return value ? new Date(value).toLocaleString("zh-CN", { hour12: false }).replaceAll("/", "-") : "-"; } function formatTime(value) { return value ? new Date(value).toLocaleString("zh-CN", { hour12: false }).replaceAll("/", "-") : "-"; }

Loading…
Cancel
Save