| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673 |
- <template>
- <PageShell>
- <div class="evaluation-view-page" v-loading="loading">
- <div class="left-card">
- <div class="card-title">考生信息</div>
- <div class="info-list">
- <div class="info-item"><span>姓名:</span><span>{{ studentName }}</span></div>
- <div class="info-item"><span>报名岗位:</span><span>{{ positionName }}</span></div>
- <div class="info-item"><span>开始时间:</span><span>{{ startTime || '-' }}</span></div>
- <div class="info-item"><span>结束时间:</span><span>{{ commitTime || '-' }}</span></div>
- <div class="info-item"><span>答题时长:</span><span>{{ ansTime || '-' }}</span></div>
- </div>
- <div class="card-title second">答题信息</div>
- <div class="answer-list">
- <div v-for="ab in scores" :key="ab.abilityName" class="answer-item">
- <span>{{ ab.abilityName }}:{{ ab.score }}/{{ ab.totalScore }}</span>
- <el-tag :type="ab.pass ? 'success' : 'danger'">{{ ab.pass ? '通过' : '未通过' }}</el-tag>
- </div>
- <div v-if="!scores.length" class="answer-item" style="color:#999">暂无答题记录</div>
- </div>
- <div class="card-title second">维度分析</div>
- <div v-if="scores.length >= 3" ref="radarChartRef" class="radar-chart"></div>
- <div v-else class="chart-placeholder">维度数据不足,至少需要3项能力</div>
- <div class="footer-btn">
- <el-button @click="handleBack">返回</el-button>
- <el-button type="primary" :loading="exportLoading" @click="handleExport">导出测评</el-button>
- </div>
- </div>
- <div class="right-card">
- <template v-if="questionList.length > 0">
- <div v-for="(item, index) in questionList" :key="item.id" class="question-block">
- <div class="question-head">
- <span>第{{ index + 1 }}题 <el-tag size="small" type="info">{{ item.typeName }}</el-tag></span>
- <div class="question-result">
- <el-tag :type="item.correct ? 'success' : 'danger'">{{ item.correct ? '正确' : '错误' }}</el-tag>
- <span>得分</span>
- <el-input :model-value="String(item.score)" class="score-input" readonly />
- </div>
- </div>
- <div class="question-title" v-html="item.questionTitle"></div>
- <!-- 选择题:显示选项,标记用户选择和正确答案 -->
- <div v-if="item.options && item.options.length > 0" class="question-options">
- <div v-for="option in item.options" :key="option.label" class="question-option" :class="{ 'is-user-answer': item.answer && item.answer.includes(option.label) }">
- <!-- 单选题 -->
- <el-radio v-if="item.typeName === '单选题'" :model-value="item.answer" :label="option.label" disabled>{{ option.label }}.<span v-html="option.text"></span></el-radio>
- <!-- 多选题 -->
- <el-checkbox v-else :model-value="item.answer ? item.answer.includes(option.label) : false" :label="option.label" disabled>{{ option.label }}.<span v-html="option.text"></span></el-checkbox>
- <el-tag v-if="option.correct" size="small" type="success">正确答案</el-tag>
- <el-tag v-if="item.answer && item.answer.includes(option.label) && !option.correct" size="small" type="danger">考生选择</el-tag>
- </div>
- </div>
- <!-- 问答题:显示考生作答 -->
- <div v-if="item.answer && (!item.options || item.options.length === 0)" class="question-user-answer">
- <span>考生作答:</span><span v-html="item.answer"></span>
- </div>
- <!-- 正确答案(问答题) -->
- <div v-if="item.typeName === '问答题' && item.testAnsRight" class="question-right-answer">
- <span>参考答案:</span><span v-html="item.testAnsRight"></span>
- </div>
- <div v-if="item.analysis" class="question-analysis">
- <div>答案解析:</div>
- <div v-html="item.analysis"></div>
- </div>
- </div>
- </template>
- <el-empty v-else description="暂无答题详情数据" />
- </div>
- </div>
- </PageShell>
- </template>
- <script setup name="EvaluationView" lang="ts">
- import { getCurrentInstance, type ComponentInternalInstance, ref, onMounted, nextTick, watch } from 'vue';
- import { useRoute, useRouter } from 'vue-router';
- import * as echarts from 'echarts';
- import html2canvas from 'html2canvas';
- import jsPDF from 'jspdf';
- import PageShell from '@/components/PageShell/index.vue';
- import { getEvaluation, getExamScoreList, getExamPaperQuestions, getExamAnswerList } from '@/api/main/evaluation/index';
- const { proxy } = getCurrentInstance() as ComponentInternalInstance;
- const router = useRouter();
- const route = useRoute();
- const loading = ref(false);
- const evaluationId = route.query.evaluationId as string;
- const studentId = route.query.studentId as string;
- const studentName = ref((route.query.name as string) || '');
- const positionName = ref('');
- const startTime = ref('');
- const commitTime = ref('');
- const ansTime = ref('');
- const scores = ref<any[]>([]);
- const questionList = ref<any[]>([]);
- const radarChartRef = ref<HTMLElement | null>(null);
- const exportLoading = ref(false);
- let radarChart: echarts.ECharts | null = null;
- /** 解析接口返回的 msg 字段(JSON 字符串),提取 bizContent */
- const parseBizContent = (res: any) => {
- const msgStr = res?.msg;
- if (typeof msgStr !== 'string') return {};
- try {
- const parsed = JSON.parse(msgStr);
- return parsed?.bizContent || parsed || {};
- } catch (e) {
- return {};
- }
- };
- /** 从 score-list 的 bizContent.rows 中查找指定学生的最新记录 */
- const findStudentInScoreList = (bizContent: any, sid: string) => {
- const rows: any[] = bizContent?.rows || [];
- if (!Array.isArray(rows) || !sid) return null;
- // 同一考生可能有多条记录,取最后一条(最新的)
- let result: any = null;
- for (const item of rows) {
- if (String(item.userId) === String(sid)) {
- result = item;
- }
- }
- return result;
- };
- /** 将 com_ans 中的 key1~key4 转为 A/B/C/D 标签 */
- const convertComAnsToLabel = (comAns: string): string => {
- if (!comAns) return '';
- const keyMap: Record<string, string> = { key1: 'A', key2: 'B', key3: 'C', key4: 'D' };
- // com_ans 格式可能是 "key2," 或 "key1,key3," 等
- const keys = comAns.split(',').map((k: string) => k.trim()).filter(Boolean);
- return keys.map((k: string) => keyMap[k] || k).join('');
- };
- const TYPE_NAME_MAP: Record<number, string> = {
- 1: '单选题',
- 2: '多选题',
- 3: '判断题',
- 5: '问答题'
- };
- /** 从 paper-questions 的 bizContent.rows 中提取题目列表
- * 注意:paper-questions 的 testId 是 "--",真实的 test_id 在 answer-list 中
- * 所以这里需要用 answer-list 中的信息来确定题目 ID
- */
- const extractQuestions = (bizContent: any, ansMap: Map<string, any>) => {
- const rows: any[] = bizContent?.rows || [];
- if (!Array.isArray(rows)) return [];
- // 建立 question 文本 -> answer-map 中 test_id 的映射
- const questionToTestId = new Map<string, string>();
- ansMap.forEach((detail: any, testId: string) => {
- const q = detail.question || '';
- if (q) {
- questionToTestId.set(q, testId);
- }
- });
- const questions: any[] = [];
- let seq = 0;
- rows.forEach((row: any) => {
- const tc = row.testContent || {};
- const qType = Number(tc.type);
- const questionTitle = tc.question || '';
- const analysis = tc.analysis || '';
- // 优先用 answer-list 中的 test_id 匹配
- let questionId = questionToTestId.get(questionTitle);
- if (!questionId) {
- questionId = tc.test_id || row.testId || `q_${seq}`;
- }
- // 构建选项:问答题无选项,单选/多选题从 answer1~answer4 + key1~key4 构建
- const options: { label: string; text: string; correct: boolean }[] = [];
- if (qType === 1 || qType === 2) {
- const answerFields = ['answer1', 'answer2', 'answer3', 'answer4'];
- const keyFields = ['key1', 'key2', 'key3', 'key4'];
- const labels = ['A', 'B', 'C', 'D'];
- for (let i = 0; i < 4; i++) {
- const text = tc[answerFields[i]];
- if (text) {
- options.push({
- label: labels[i],
- text,
- correct: tc[keyFields[i]] === '1'
- });
- }
- }
- }
- questions.push({
- id: questionId,
- questionTitle,
- analysis,
- options,
- type: qType,
- typeName: TYPE_NAME_MAP[qType] || '其他',
- testName: row.testName || ''
- });
- seq++;
- });
- return questions;
- };
- /** 从 answer-list 的 bizContent.rows 中查找指定学生,并提取其作答信息 */
- const extractAnswers = (bizContent: any, sid: string) => {
- const rows: any[] = bizContent?.rows || [];
- if (!Array.isArray(rows) || !sid) return new Map<string, any>();
- const studentRow = rows.find((item: any) => String(item.userId) === String(sid));
- if (!studentRow?.ansAndScore) return new Map<string, any>();
- const ansMap = new Map<string, any>();
- const ansAndScore: any[] = studentRow.ansAndScore;
- for (const group of ansAndScore) {
- if (!Array.isArray(group)) continue;
- for (let i = 1; i < group.length; i++) {
- const entry = group[i];
- if (Array.isArray(entry) && entry.length >= 2) {
- const testId = String(entry[0]);
- const detail = entry[1] || {};
- ansMap.set(testId, detail);
- }
- }
- }
- return ansMap;
- };
- /** 将题目和作答合并为展示数据 */
- const combineQA = (questions: any[], ansMap: Map<string, any>) => {
- return questions.map((q, index) => {
- const ans = ansMap.get(String(q.id));
- let correct = false;
- if (ans) {
- if (ans.is_ok === 'right') correct = true;
- }
- // 用户答案
- let answer = '';
- if (ans) {
- const comAns = ans.com_ans || '';
- if (comAns && (q.type === 1 || q.type === 2)) {
- // 选择题:将 key1~key4 转为 A~D
- answer = convertComAnsToLabel(comAns);
- } else if (comAns) {
- // 问答题:直接使用 HTML 内容
- answer = comAns;
- }
- }
- // 正确答案文本(问答题用)
- const testAnsRight = ans?.test_ans_right || '';
- const options = q.options.map((o: any) => ({ ...o }));
- return {
- id: q.id || `q_${index}`,
- questionTitle: q.questionTitle || '未命名题目',
- correct,
- score: ans?.score ?? 0,
- answer,
- options: options.length > 0 ? options : q.type === 5 ? [] : [{ label: 'A', text: '选项A' }, { label: 'B', text: '选项B' }],
- analysis: q.analysis || '',
- typeName: q.typeName,
- testName: q.testName,
- testAnsRight
- };
- });
- };
- /** 渲染雷达图 */
- const renderRadarChart = () => {
- if (!radarChartRef.value || scores.value.length < 3) return;
- if (!radarChart) {
- radarChart = echarts.init(radarChartRef.value);
- }
- const indicator = scores.value.map((s: any) => ({
- name: s.abilityName,
- max: Number(s.totalScore) || 100
- }));
- const dataValues = scores.value.map((s: any) => Number(s.score) || 0);
- radarChart.setOption({
- tooltip: {
- trigger: 'item'
- },
- radar: {
- indicator,
- radius: '65%',
- name: {
- textStyle: {
- fontSize: 11
- }
- },
- splitArea: {
- areaStyle: {
- color: ['rgba(64,158,255,0.05)', 'rgba(64,158,255,0.1)', 'rgba(64,158,255,0.15)', 'rgba(64,158,255,0.2)']
- }
- }
- },
- series: [{
- type: 'radar',
- data: [{
- value: dataValues,
- name: '得分',
- areaStyle: {
- color: 'rgba(64,158,255,0.2)'
- },
- lineStyle: {
- color: '#409EFF'
- },
- itemStyle: {
- color: '#409EFF'
- }
- }]
- }]
- });
- };
- const loadData = async () => {
- if (!evaluationId) return;
- loading.value = true;
- try {
- const res = await getEvaluation(evaluationId);
- const evalData = res.data;
- positionName.value = evalData.positionName || evalData.position || '未知岗位';
- const abilityConfigs = evalData.abilityConfigs || [];
- let allQuestions: any[] = [];
- let scoreItems: any[] = [];
- for (const ability of abilityConfigs) {
- const examId = ability.thirdExamInfoId;
- if (!examId) continue;
- // 获取成绩列表
- const scoreRes = await getExamScoreList({ examInfoId: examId, page: 1 }).catch(() => ({ msg: '{}' }));
- const scoreBiz = parseBizContent(scoreRes);
- const myScoreObj = findStudentInScoreList(scoreBiz, studentId);
- const score = myScoreObj?.score || 0;
- const passMark = ability.thirdExamPassMark || ability.passingScore || 0;
- const pass = myScoreObj ? String(myScoreObj.isPass) === '1' : Number(score) >= Number(passMark);
- // 取考生时间信息(只需取第一次有数据的记录)
- if (myScoreObj && !startTime.value) {
- startTime.value = myScoreObj.startTime || '';
- commitTime.value = myScoreObj.commitTime || '';
- ansTime.value = myScoreObj.ansTime || '';
- }
- scoreItems.push({
- abilityName: ability.abilityName || ability.thirdExamName || '考核',
- score: score,
- totalScore: ability.thirdExamTotalScore || ability.score || 100,
- pass
- });
- // 获取答题详情(先获取,因为需要用 test_id 来匹配 paper-questions)
- const answerRes = await getExamAnswerList({ examInfoId: examId }).catch(() => ({ msg: '{}' }));
- const answerBiz = parseBizContent(answerRes);
- const ansMap = extractAnswers(answerBiz, studentId);
- // 获取试卷题目
- const paperRes = await getExamPaperQuestions({ examInfoId: examId }).catch(() => ({ msg: '{}' }));
- const paperBiz = parseBizContent(paperRes);
- const questions = extractQuestions(paperBiz, ansMap);
- allQuestions.push(...combineQA(questions, ansMap));
- }
- scores.value = scoreItems;
- questionList.value = allQuestions;
- // 渲染雷达图
- await nextTick();
- renderRadarChart();
- } catch (e) {
- console.error(e);
- proxy?.$modal?.msgError('获取测评数据失败');
- } finally {
- loading.value = false;
- }
- };
- const handleExport = async () => {
- if (exportLoading.value) return;
- exportLoading.value = true;
- try {
- const container = document.createElement('div');
- container.style.cssText = 'position:fixed;left:-9999px;top:0;width:794px;background:#fff;padding:40px;font-family:"Microsoft YaHei",sans-serif;font-size:14px;color:#333;line-height:1.6;';
- const title = document.createElement('h2');
- title.style.cssText = 'text-align:center;margin-bottom:24px;font-size:20px;';
- title.textContent = `测评报告 - ${positionName.value || '未知岗位'}`;
- container.appendChild(title);
- const infoSection = document.createElement('div');
- infoSection.style.cssText = 'margin-bottom:20px;padding:16px;border:1px solid #e4e7ed;border-radius:6px;';
- infoSection.innerHTML = `
- <div style="font-size:16px;font-weight:600;margin-bottom:10px;">考生信息</div>
- <div style="display:grid;grid-template-columns:1fr 1fr;gap:6px;font-size:13px;">
- <div><strong>姓名:</strong>${studentName.value || '-'}</div>
- <div><strong>报名岗位:</strong>${positionName.value || '未知岗位'}</div>
- <div><strong>开始时间:</strong>${startTime.value || '-'}</div>
- <div><strong>结束时间:</strong>${commitTime.value || '-'}</div>
- <div><strong>答题时长:</strong>${ansTime.value || '-'}</div>
- </div>
- `;
- container.appendChild(infoSection);
- if (scores.value.length > 0) {
- const scoreSection = document.createElement('div');
- scoreSection.style.cssText = 'margin-bottom:20px;padding:16px;border:1px solid #e4e7ed;border-radius:6px;';
- let scoreHtml = '<div style="font-size:16px;font-weight:600;margin-bottom:10px;">答题信息</div>';
- scoreHtml += '<table style="width:100%;border-collapse:collapse;font-size:13px;">';
- scoreHtml += '<tr style="background:#f5f7fa;"><th style="border:1px solid #e4e7ed;padding:8px;text-align:left;">能力项</th><th style="border:1px solid #e4e7ed;padding:8px;text-align:center;">得分</th><th style="border:1px solid #e4e7ed;padding:8px;text-align:center;">满分</th><th style="border:1px solid #e4e7ed;padding:8px;text-align:center;">结果</th></tr>';
- scores.value.forEach((s: any) => {
- const passColor = s.pass ? '#67c23a' : '#f56c6c';
- const passText = s.pass ? '通过' : '未通过';
- scoreHtml += `<tr><td style="border:1px solid #e4e7ed;padding:8px;">${s.abilityName}</td><td style="border:1px solid #e4e7ed;padding:8px;text-align:center;">${s.score}</td><td style="border:1px solid #e4e7ed;padding:8px;text-align:center;">${s.totalScore}</td><td style="border:1px solid #e4e7ed;padding:8px;text-align:center;color:${passColor};font-weight:600;">${passText}</td></tr>`;
- });
- scoreHtml += '</table>';
- scoreSection.innerHTML = scoreHtml;
- container.appendChild(scoreSection);
- }
- if (questionList.value.length > 0) {
- const qSection = document.createElement('div');
- qSection.style.cssText = 'padding:16px;border:1px solid #e4e7ed;border-radius:6px;';
- let qHtml = '<div style="font-size:16px;font-weight:600;margin-bottom:10px;">答题详情</div>';
- questionList.value.forEach((item: any, index: number) => {
- const resultColor = item.correct ? '#67c23a' : '#f56c6c';
- const resultText = item.correct ? '正确' : '错误';
- qHtml += `<div style="margin-bottom:16px;padding-bottom:12px;border-bottom:1px dashed #ebeef5;">`;
- qHtml += `<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">`;
- qHtml += `<span>第${index + 1}题 <span style="background:#f0f2f5;color:#909399;padding:2px 6px;border-radius:3px;font-size:12px;">${item.typeName}</span></span>`;
- qHtml += `<span><span style="color:${resultColor};font-weight:600;">${resultText}</span> | 得分:${item.score}</span>`;
- qHtml += `</div>`;
- const plainTitle = item.questionTitle?.replace(/<[^>]*>/g, '') || '未命名题目';
- qHtml += `<div style="margin-bottom:8px;">${plainTitle}</div>`;
- if (item.options && item.options.length > 0) {
- item.options.forEach((opt: any) => {
- const isCorrect = opt.correct;
- const isUserAnswer = item.answer && item.answer.includes(opt.label);
- let optStyle = 'padding:2px 0;';
- if (isCorrect) optStyle += 'color:#67c23a;font-weight:600;';
- if (isUserAnswer && !isCorrect) optStyle += 'color:#f56c6c;';
- const tags = [];
- if (isCorrect) tags.push('【正确答案】');
- if (isUserAnswer && !isCorrect) tags.push('【考生选择】');
- const plainText = opt.text?.replace(/<[^>]*>/g, '') || '';
- qHtml += `<div style="${optStyle}">${opt.label}. ${plainText} ${tags.join('')}</div>`;
- });
- }
- if (item.answer && (!item.options || item.options.length === 0)) {
- const plainAnswer = item.answer?.replace(/<[^>]*>/g, '') || '';
- qHtml += `<div style="margin-top:6px;padding:6px 10px;background:#f5f7fa;border-radius:4px;font-size:13px;">考生作答:${plainAnswer}</div>`;
- }
- if (item.testAnsRight) {
- const plainRight = item.testAnsRight?.replace(/<[^>]*>/g, '') || '';
- qHtml += `<div style="margin-top:6px;padding:6px 10px;background:#f0f9eb;border-radius:4px;font-size:13px;color:#67c23a;">参考答案:${plainRight}</div>`;
- }
- if (item.analysis) {
- const plainAnalysis = item.analysis?.replace(/<[^>]*>/g, '') || '';
- qHtml += `<div style="margin-top:6px;font-size:13px;color:#606266;">答案解析:${plainAnalysis}</div>`;
- }
- qHtml += `</div>`;
- });
- qSection.innerHTML = qHtml;
- container.appendChild(qSection);
- }
- document.body.appendChild(container);
- await nextTick();
- await new Promise(resolve => setTimeout(resolve, 300));
- const canvas = await html2canvas(container, { scale: 2, useCORS: true, backgroundColor: '#ffffff' });
- document.body.removeChild(container);
- const imgData = canvas.toDataURL('image/jpeg', 0.95);
- const imgWidth = 210;
- const pageHeight = 297;
- const imgHeight = (canvas.height * imgWidth) / canvas.width;
- const pdf = new jsPDF('p', 'mm', 'a4');
- let heightLeft = imgHeight;
- let position = 0;
- pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight);
- heightLeft -= pageHeight;
- while (heightLeft > 0) {
- position = heightLeft - imgHeight;
- pdf.addPage();
- pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight);
- heightLeft -= pageHeight;
- }
- const fileName = `测评报告_${studentName.value || '考生'}_${positionName.value || '未知岗位'}.pdf`;
- pdf.save(fileName);
- } catch (e) {
- console.error('导出测评失败:', e);
- proxy?.$modal?.msgError('导出测评失败');
- } finally {
- exportLoading.value = false;
- }
- };
- const handleBack = () => {
- proxy?.$tab.closePage();
- router.back();
- };
- onMounted(() => {
- loadData();
- });
- </script>
- <style scoped>
- .evaluation-view-page {
- display: grid;
- grid-template-columns: 280px 1fr;
- gap: 16px;
- }
- .left-card {
- background: #fff;
- border-radius: 6px;
- padding: 16px;
- height: calc(100vh - 180px);
- overflow-y: auto;
- }
- .right-card {
- background: #fff;
- border-radius: 6px;
- padding: 16px;
- height: calc(100vh - 180px);
- overflow-y: auto;
- }
- .card-title {
- font-size: 16px;
- font-weight: 600;
- margin-bottom: 12px;
- }
- .card-title.second {
- margin-top: 20px;
- }
- .info-list,
- .answer-list {
- display: flex;
- flex-direction: column;
- gap: 8px;
- font-size: 12px;
- color: #606266;
- }
- .info-item,
- .answer-item {
- display: flex;
- justify-content: space-between;
- gap: 8px;
- }
- .chart-placeholder {
- height: 180px;
- border: 1px dashed #dcdfe6;
- border-radius: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
- color: #909399;
- font-size: 12px;
- }
- .radar-chart {
- height: 220px;
- margin-top: 8px;
- }
- .footer-btn {
- margin-top: 16px;
- display: flex;
- justify-content: flex-end;
- gap: 12px;
- }
- .question-block {
- padding-bottom: 18px;
- margin-bottom: 18px;
- border-bottom: 1px dashed #ebeef5;
- }
- .question-head {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 16px;
- }
- .question-result {
- display: flex;
- align-items: center;
- gap: 8px;
- }
- .score-input {
- width: 56px;
- }
- .question-title {
- margin-bottom: 12px;
- }
- .question-options {
- display: flex;
- flex-direction: column;
- gap: 10px;
- }
- .question-option {
- display: flex;
- align-items: center;
- gap: 8px;
- padding: 4px 8px;
- border-radius: 4px;
- }
- .question-option.is-user-answer {
- background: #ecf5ff;
- }
- .correct-text {
- color: #67c23a;
- font-size: 12px;
- }
- .question-analysis {
- margin-top: 16px;
- color: #606266;
- font-size: 13px;
- }
- .question-user-answer {
- margin-top: 8px;
- padding: 8px 12px;
- background: #f5f7fa;
- border-radius: 4px;
- color: #606266;
- font-size: 13px;
- }
- .question-right-answer {
- margin-top: 8px;
- padding: 8px 12px;
- background: #f0f9eb;
- border-radius: 4px;
- color: #67c23a;
- font-size: 13px;
- }
- </style>
|