feat(exam): 优化答案解析弹窗和判断题/填空题样式
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
- 答案解析弹窗限制最大高度45vh,超出可滚动 - 判断题改为卡片式按钮,带图标和状态反馈 - 填空题增大输入框,添加图标和提示
This commit is contained in:
@@ -67,20 +67,57 @@
|
|||||||
|
|
||||||
<!-- 判断题 -->
|
<!-- 判断题 -->
|
||||||
<div v-else-if="currentQuestion.type === 'judge'" class="judge-options">
|
<div v-else-if="currentQuestion.type === 'judge'" class="judge-options">
|
||||||
<el-radio-group v-model="userAnswer.judge" :disabled="showAnswer" @change="handleJudgeChange">
|
<div class="judge-cards">
|
||||||
<el-radio :label="true">正确</el-radio>
|
<div
|
||||||
<el-radio :label="false">错误</el-radio>
|
class="judge-card"
|
||||||
</el-radio-group>
|
:class="{
|
||||||
|
active: userAnswer.judge === true,
|
||||||
|
disabled: showAnswer,
|
||||||
|
correct: showAnswer && currentQuestion.correctAnswer === true,
|
||||||
|
wrong: showAnswer && userAnswer.judge === true && currentQuestion.correctAnswer !== true
|
||||||
|
}"
|
||||||
|
@click="!showAnswer && selectJudge(true)"
|
||||||
|
>
|
||||||
|
<div class="judge-icon correct-icon">
|
||||||
|
<el-icon :size="32"><CircleCheck /></el-icon>
|
||||||
|
</div>
|
||||||
|
<span class="judge-text">正确</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="judge-card"
|
||||||
|
:class="{
|
||||||
|
active: userAnswer.judge === false,
|
||||||
|
disabled: showAnswer,
|
||||||
|
correct: showAnswer && currentQuestion.correctAnswer === false,
|
||||||
|
wrong: showAnswer && userAnswer.judge === false && currentQuestion.correctAnswer !== false
|
||||||
|
}"
|
||||||
|
@click="!showAnswer && selectJudge(false)"
|
||||||
|
>
|
||||||
|
<div class="judge-icon wrong-icon">
|
||||||
|
<el-icon :size="32"><CircleClose /></el-icon>
|
||||||
|
</div>
|
||||||
|
<span class="judge-text">错误</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 填空题 -->
|
<!-- 填空题 -->
|
||||||
<div v-else-if="currentQuestion.type === 'blank'" class="blank-answer">
|
<div v-else-if="currentQuestion.type === 'blank'" class="blank-answer">
|
||||||
<el-input
|
<div class="blank-input-wrapper">
|
||||||
v-model="userAnswer.blank"
|
<el-input
|
||||||
placeholder="请输入答案"
|
v-model="userAnswer.blank"
|
||||||
:disabled="showAnswer"
|
placeholder="请在此输入你的答案..."
|
||||||
@keyup.enter="handleBlankSubmit"
|
:disabled="showAnswer"
|
||||||
/>
|
@keyup.enter="handleBlankSubmit"
|
||||||
|
size="large"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<el-icon><Edit /></el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<p class="blank-hint">按 Enter 键提交答案</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 问答题 -->
|
<!-- 问答题 -->
|
||||||
@@ -150,28 +187,31 @@
|
|||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
:close-on-press-escape="false"
|
:close-on-press-escape="false"
|
||||||
:show-close="false"
|
:show-close="false"
|
||||||
|
class="answer-dialog"
|
||||||
>
|
>
|
||||||
<div v-if="dialogQuestion" class="answer-dialog-content">
|
<div v-if="dialogQuestion" class="answer-dialog-content">
|
||||||
<div class="result-section">
|
<div class="result-section">
|
||||||
<div class="result-icon-large wrong">
|
<div class="result-icon-large wrong">
|
||||||
<el-icon :size="48"><CircleClose /></el-icon>
|
<el-icon :size="40"><CircleClose /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="result-text">回答错误</h3>
|
<h3 class="result-text">回答错误</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="question-review">
|
<div class="dialog-scroll-area">
|
||||||
<h4>题目:</h4>
|
<div class="question-review">
|
||||||
<p>{{ dialogQuestion.title }}</p>
|
<h4>题目:</h4>
|
||||||
</div>
|
<p>{{ dialogQuestion.title }}</p>
|
||||||
|
</div>
|
||||||
<div class="answer-review">
|
|
||||||
<h4>正确答案:</h4>
|
<div class="answer-review">
|
||||||
<div class="correct-answer-text markdown-content" v-html="renderMarkdown(formatCorrectAnswer(dialogQuestion))"></div>
|
<h4>正确答案:</h4>
|
||||||
</div>
|
<div class="correct-answer-text markdown-content" v-html="renderMarkdown(formatCorrectAnswer(dialogQuestion))"></div>
|
||||||
|
</div>
|
||||||
<div class="explanation-review">
|
|
||||||
<h4>解析:</h4>
|
<div class="explanation-review">
|
||||||
<div class="explanation-text markdown-content" v-html="renderMarkdown(dialogQuestion.explanation)"></div>
|
<h4>解析:</h4>
|
||||||
|
<div class="explanation-text markdown-content" v-html="renderMarkdown(dialogQuestion.explanation)"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -190,7 +230,7 @@
|
|||||||
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
|
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { ElMessage, ElMessageBox, ElDialog, ElLoading } from 'element-plus'
|
import { ElMessage, ElMessageBox, ElDialog, ElLoading } from 'element-plus'
|
||||||
import { Loading, CircleCheck, CircleClose } from '@element-plus/icons-vue'
|
import { Loading, CircleCheck, CircleClose, Edit } from '@element-plus/icons-vue'
|
||||||
import { courseApi } from '@/api/course'
|
import { courseApi } from '@/api/course'
|
||||||
import { generateExam, judgeAnswer, recordMistake, getMistakes, updateRoundScore, type MistakeRecordItem } from '@/api/exam'
|
import { generateExam, judgeAnswer, recordMistake, getMistakes, updateRoundScore, type MistakeRecordItem } from '@/api/exam'
|
||||||
import { marked } from 'marked'
|
import { marked } from 'marked'
|
||||||
@@ -903,6 +943,14 @@ const handleJudgeChange = () => {
|
|||||||
checkAndHandleAnswer()
|
checkAndHandleAnswer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断题卡片点击
|
||||||
|
*/
|
||||||
|
const selectJudge = (value: boolean) => {
|
||||||
|
userAnswer.judge = value
|
||||||
|
checkAndHandleAnswer()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 填空题回车提交处理
|
* 填空题回车提交处理
|
||||||
*/
|
*/
|
||||||
@@ -1355,21 +1403,118 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.judge-options {
|
.judge-options {
|
||||||
.el-radio-group {
|
.judge-cards {
|
||||||
.el-radio {
|
display: flex;
|
||||||
margin-right: 32px;
|
gap: 20px;
|
||||||
|
justify-content: center;
|
||||||
:deep(.el-radio__label) {
|
|
||||||
|
.judge-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 140px;
|
||||||
|
height: 120px;
|
||||||
|
border: 2px solid #e4e7ed;
|
||||||
|
border-radius: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
&:hover:not(.disabled) {
|
||||||
|
border-color: #409eff;
|
||||||
|
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border-color: #409eff;
|
||||||
|
background: linear-gradient(135deg, #ecf5ff 0%, #f5f9ff 100%);
|
||||||
|
|
||||||
|
.judge-icon {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.correct {
|
||||||
|
border-color: #67c23a;
|
||||||
|
background: linear-gradient(135deg, #f0f9eb 0%, #f5faf2 100%);
|
||||||
|
|
||||||
|
.judge-text {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wrong {
|
||||||
|
border-color: #f56c6c;
|
||||||
|
background: linear-gradient(135deg, #fef0f0 0%, #fdf5f5 100%);
|
||||||
|
|
||||||
|
.judge-text {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge-icon {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
|
||||||
|
&.correct-icon {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wrong-icon {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge-text {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #606266;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.blank-answer {
|
.blank-answer {
|
||||||
.el-input {
|
.blank-input-wrapper {
|
||||||
width: 100%;
|
max-width: 500px;
|
||||||
max-width: 400px;
|
|
||||||
|
.el-input {
|
||||||
|
:deep(.el-input__wrapper) {
|
||||||
|
padding: 8px 15px;
|
||||||
|
box-shadow: 0 0 0 1px #dcdfe6 inset;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 0 0 1px #c0c4cc inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-focus {
|
||||||
|
box-shadow: 0 0 0 1px #409eff inset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__inner) {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__prefix) {
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.blank-hint {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1470,15 +1615,22 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 答案解析弹窗样式
|
// 答案解析弹窗样式
|
||||||
|
:deep(.answer-dialog) {
|
||||||
|
.el-dialog__body {
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.answer-dialog-content {
|
.answer-dialog-content {
|
||||||
.result-section {
|
.result-section {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 16px;
|
||||||
|
|
||||||
.result-icon-large {
|
.result-icon-large {
|
||||||
width: 80px;
|
width: 64px;
|
||||||
height: 80px;
|
height: 64px;
|
||||||
margin: 0 auto 16px;
|
margin: 0 auto 10px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1491,39 +1643,58 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.result-text {
|
.result-text {
|
||||||
font-size: 20px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #f56c6c;
|
color: #f56c6c;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dialog-scroll-area {
|
||||||
|
max-height: 45vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-right: 8px;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #dcdfe6;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.question-review,
|
.question-review,
|
||||||
.answer-review,
|
.answer-review,
|
||||||
.explanation-review {
|
.explanation-review {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 16px;
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #333;
|
color: #333;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.8;
|
line-height: 1.6;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
.correct-answer-text {
|
.correct-answer-text {
|
||||||
font-size: 15px;
|
font-size: 14px;
|
||||||
line-height: 1.8;
|
line-height: 1.6;
|
||||||
color: #333;
|
color: #333;
|
||||||
background: #f0f9ff;
|
background: #f0f9ff;
|
||||||
border-left: 4px solid #67c23a;
|
border-left: 4px solid #67c23a;
|
||||||
padding: 12px 16px;
|
padding: 10px 14px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
|
||||||
strong {
|
strong {
|
||||||
@@ -1533,11 +1704,11 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.explanation-text {
|
.explanation-text {
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
line-height: 1.8;
|
line-height: 1.6;
|
||||||
color: #666;
|
color: #666;
|
||||||
background: #f5f7fa;
|
background: #f5f7fa;
|
||||||
padding: 16px;
|
padding: 12px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|
||||||
strong {
|
strong {
|
||||||
|
|||||||
Reference in New Issue
Block a user