diff --git a/background/preload.js b/background/preload.js index 5a87f96..7084a39 100644 --- a/background/preload.js +++ b/background/preload.js @@ -1,5 +1,4 @@ // Preload script runs in a context that has access to both Node.js and browser APIs -// 在preload.js文件中添加examingProcessPaper API并移除重复的fileGeneratePaperPdf const { contextBridge, ipcRenderer } = require("electron"); // 暴露API给渲染进程 diff --git a/src/components/user/ExamingInfoBar.vue b/src/components/user/ExamingInfoBar.vue new file mode 100644 index 0000000..ec5dceb --- /dev/null +++ b/src/components/user/ExamingInfoBar.vue @@ -0,0 +1,96 @@ + + + + + \ No newline at end of file diff --git a/src/components/user/ExamingPreview.vue b/src/components/user/ExamingPreview.vue new file mode 100644 index 0000000..b635ae1 --- /dev/null +++ b/src/components/user/ExamingPreview.vue @@ -0,0 +1,612 @@ + + + + + \ No newline at end of file diff --git a/src/components/user/ExamingQuestionDetail.vue b/src/components/user/ExamingQuestionDetail.vue new file mode 100644 index 0000000..eb1bd9e --- /dev/null +++ b/src/components/user/ExamingQuestionDetail.vue @@ -0,0 +1,350 @@ + + + + + \ No newline at end of file diff --git a/src/views/user/EndView.vue b/src/views/user/EndView.vue index b226d69..c7df41d 100644 --- a/src/views/user/EndView.vue +++ b/src/views/user/EndView.vue @@ -252,7 +252,7 @@ export default { } }, // 判卷方法 - // 增强checkAnswers方法,确保API存在性检查 + // 判卷方法 async checkAnswers () { try { if (!this.paper || !this.paper.id) { @@ -275,11 +275,24 @@ export default { const result = await window.electronAPI.examingCheckPaperAnswers({ paperId }) if (result && result.success) { - // 更新store中的试卷信息 - // if (result.data) { - // this.$store.commit('setPaper', result.data) - // } - this.$message.success('判卷完成!'); + // this.$message.success('判卷完成!'); + + // 新增:在判卷成功后生成PDF + try { + // 获取最新的试卷数据(包含判卷结果) + const paperDataStr = JSON.stringify(this.paper); + // 生成PDF + const pdfResult = await window.electronAPI.fileGeneratePaperPdf(paperDataStr); + if (pdfResult && pdfResult.filePath) { + this.pdfPath = pdfResult; + console.log('PDF生成成功,保存路径:', pdfResult.filePath); + // this.$message.success('考试报告PDF已生成'); + } else { + console.error('PDF生成失败:', pdfResult); + } + } catch (pdfError) { + console.error('PDF生成过程异常:', pdfError); + } } else { console.error('判卷失败:', result?.message || '未知错误'); this.$message.error('判卷失败,请稍后重试'); diff --git a/src/views/user/ExamingView.vue b/src/views/user/ExamingView.vue index 3af8222..0fcc15f 100644 --- a/src/views/user/ExamingView.vue +++ b/src/views/user/ExamingView.vue @@ -1,20 +1,8 @@ @@ -104,7 +54,10 @@ export default { name: 'ExamingView', components: { ElButton: require('element-ui').Button, - ElTag: require('element-ui').Tag + ElTag: require('element-ui').Tag, + ExamingInfoBar: require('../../components/user/ExamingInfoBar.vue').default, + ExamingQuestionDetail: require('../../components/user/ExamingQuestionDetail.vue').default, + ExamingPreview: require('../../components/user/ExamingPreview.vue').default }, data() { return { @@ -114,12 +67,12 @@ export default { questionDataMap: {}, countdown: '01:59:59', // 初始倒计时120分钟 canSubmit: false, // 控制交卷按钮是否可用 - showImageViewer: false, - currentImage: '', timer: null, processTimer: null, paperId: '', - blankAnswerTip: '数字请保留2位小数,如“100.00”' + blankAnswerTip: '数字请保留2位小数,如"100.00"', + showPreviewModal: false, // 控制交卷预览模态框显示 + previewQuestionData: [] // 存储预览用的所有题目数据 } }, computed: { @@ -134,6 +87,10 @@ export default { // 当前题目数据 currentQuestionData() { return this.questionDataMap[this.currentQuestion] || { question: null, question_detail: null, answer: '' } + }, + // 添加:已作答题目数量计算 + answeredCount() { + return this.questionList.filter(item => item.answered === 1).length; } }, created() { @@ -218,12 +175,6 @@ export default { } }, - // 身份证号格式化方法 - formatIdCard(idCard) { - if (!idCard || idCard.length !== 18) return idCard - return idCard.substring(0, 9) + '*****' + idCard.substring(14) - }, - // 初始化计时器方法 initializeTimer(totalSeconds) { let remainingSeconds = totalSeconds @@ -412,7 +363,6 @@ export default { // 打印questionItem的完整结构 console.log(`题号${serialNo}的完整结构:`, JSON.stringify(questionItem, null, 2)) - // 关键修复:使用正确的ID字段 // 应该使用id字段(来自question_choices或question_fill_blanks表),而不是question_id(来自paper_questions表) let relatedId = questionItem.id // 这是正确的ID字段 @@ -428,7 +378,7 @@ export default { return } - // 修复:使用直接调用方式 + // 使用直接调用方式 const result = await window.electronAPI.examingGetQuestionByRelatedId({ tableName: questionItem.table_name, relatedId: relatedId @@ -545,6 +495,132 @@ export default { await this.loadQuestionDetail(serialNo) }, + // 判断答案是否有效的方法 + isAnswerValid(answer) { + // 如果是undefined或null,视为无效 + if (answer === undefined || answer === null) { + return false + } + + // 处理字符串类型 + if (typeof answer === 'string') { + const trimmed = answer.trim() + // 空字符串、只包含空格的字符串、空数组字符串都视为无效 + return trimmed !== '' && trimmed !== '[]' + } + // 处理数组类型 + else if (Array.isArray(answer)) { + // 空数组视为无效 + if (answer.length === 0) { + return false + } + + // 检查数组中是否有有效值 + const hasValidValue = answer.some(item => { + if (item === null || item === undefined) return false + const itemStr = String(item).trim() + return itemStr !== '' && itemStr !== '[]' && itemStr !== '[[]]' + }) + + return hasValidValue + } + // 其他类型视为无效 + return false; + }, + + // 修改:格式化答案内容 + formatAnswerContent(answer) { + if (!this.isAnswerValid(answer)) { + return ''; // 未作答时显示空 + } + + // 如果是字符串但包含JSON数组,尝试解析 + if (typeof answer === 'string') { + try { + // 检查是否是JSON数组格式 + if (answer.startsWith('[') && answer.endsWith(']')) { + const parsed = JSON.parse(answer); + if (Array.isArray(parsed)) { + // 过滤掉数组中的空值 + const filteredAnswers = parsed.filter(item => + item !== null && item !== undefined && String(item).trim() !== '' + ); + return filteredAnswers.length > 0 ? filteredAnswers.join(', ') : ''; + } + } + return answer; + } catch (e) { + return answer; + } + } + // 如果是数组,过滤掉空值并连接 + else if (Array.isArray(answer)) { + const filteredAnswers = answer.filter(item => + item !== null && item !== undefined && String(item).trim() !== '' + ); + return filteredAnswers.length > 0 ? filteredAnswers.join(', ') : ''; + } + + return String(answer || ''); + }, + + // 修改:交卷预览方法,确保预览数据正确处理 + async showExamPreview() { + try { + // 保存当前答案 + await this.saveCurrentAnswer() + + // 显示加载提示 + this.$message({ message: '正在加载试卷预览,请稍候...', type: 'info', duration: 0, showClose: true }) + + // 加载所有题目的详细数据用于预览 + this.previewQuestionData = [] + + // 遍历所有题目 + for (let i = 0; i < this.questionList.length; i++) { + const questionItem = this.questionList[i] + const serialNo = questionItem.serial_no + + // 检查该题数据是否已经加载 + if (!this.questionDataMap[serialNo] || !this.questionDataMap[serialNo].question) { + // 如果未加载,则加载该题详细数据 + await this.loadQuestionDetail(serialNo) + } + + // 创建预览数据副本,避免修改原数据 + const previewData = { + ...this.questionDataMap[serialNo], + serial_no: serialNo, + answered: questionItem.answered + } + + this.previewQuestionData.push(previewData) + } + + // 关闭加载提示 + this.$message.closeAll() + + // 显示预览模态框 + this.showPreviewModal = true + } catch (error) { + console.error('加载试卷预览失败:', error) + this.$message.error('加载试卷预览失败') + } + }, + + // 关闭交卷预览 + closeExamPreview() { + this.showPreviewModal = false + }, + + // 确认交卷方法 + confirmSubmitExam() { + // 先关闭预览模态框 + this.showPreviewModal = false + // 调用原来的交卷方法 + this.submitExam() + }, + // 交卷方法 - 确保数据完全保存到store后再跳转 async submitExam() { try { @@ -574,26 +650,13 @@ export default { try { // 尝试解析数据 const paperData = JSON.parse(paperDataStr); - // console.log('解析后的试卷数据:', paperData); - // 1. 将试卷数据保存到store this.$store.commit('setPaper', paperData); // 2. 同时保存到localStorage作为备用 localStorage.setItem('lastExamPaper', paperDataStr); - // console.log('保存到store后,store中的paper数据:', this.$store.state.paper); - - // 生成PDF - const pdfResult = await window.electronAPI.fileGeneratePaperPdf(paperDataStr); - if (pdfResult && pdfResult.filePath) { - this.pdfPath = pdfResult; - console.log('PDF生成成功,保存路径:', pdfResult.filePath); - } else { - this.$message.error('PDF生成失败,但不影响考试结果'); // 修改错误消息,不影响交卷流程 - console.error('PDF生成失败:', pdfResult); - // 即使PDF生成失败,也继续交卷流程 - } + // 移除:PDF生成代码已移至EndView.vue this.$message.success('试卷提交成功!'); @@ -691,10 +754,6 @@ export default { // 包装为数组并转换为JSON字符串 const answerToSave = JSON.stringify([answerContent]) await this.saveAnswer(this.currentQuestion, answerToSave) - - // 废弃:原来保存字母的代码 - // const answer = String.fromCharCode(65 + optionIndex) // A, B, C, D... - // await this.saveAnswer(this.currentQuestion, answer) } }, @@ -702,10 +761,10 @@ export default { async saveFillAnswer() { const currentData = this.currentQuestionData if (currentData.question && currentData.question.question_type === 'fill_blank') { - const answer = currentData.question_detail.examinee_answers || '' - // 修复:将填空题答案也包装为JSON数组字符串 - const answerToSave = JSON.stringify([answer]) - await this.saveAnswer(this.currentQuestion, answerToSave) + let answer = currentData.question_detail.examinee_answers || '' + // 修复:处理空字符串、空格字符串和空数组 + const processedAnswer = this.processFillAnswer(answer) + await this.saveAnswer(this.currentQuestion, processedAnswer) } }, @@ -726,10 +785,67 @@ export default { await this.saveAnswer(this.currentQuestion, answerToSave) } } else if (currentData.question.question_type === 'fill_blank' && currentData.question_detail) { - const answer = currentData.question_detail.examinee_answers || '' - // 修复:将填空题答案也包装为JSON数组字符串 - const answerToSave = JSON.stringify([answer]) - await this.saveAnswer(this.currentQuestion, answerToSave) + let answer = currentData.question_detail.examinee_answers || '' + // 修复:处理空字符串、空格字符串和空数组 + const processedAnswer = this.processFillAnswer(answer) + await this.saveAnswer(this.currentQuestion, processedAnswer) + } + }, + + // 添加:处理填空题答案的辅助方法 + processFillAnswer(answer) { + // 1. 检查答案类型 + if (typeof answer === 'string') { + // 去除前后空格 + const trimmed = answer.trim() + // 如果为空字符串或只包含空格,返回空字符串 + if (trimmed === '' || trimmed === '[]') { + return '' + } + // 检查是否已经是JSON数组格式 + if (trimmed.startsWith('[') && trimmed.endsWith(']')) { + try { + const parsed = JSON.parse(trimmed) + // 如果解析结果是空数组或包含空值的数组,返回空字符串 + if (Array.isArray(parsed)) { + // 过滤掉数组中的空值和空格 + const filteredAnswers = parsed.filter(item => { + if (item === null || item === undefined) return false + const itemStr = String(item).trim() + return itemStr !== '' && itemStr !== '[]' && itemStr !== '[[]]' + }) + // 如果过滤后数组为空,返回空字符串 + if (filteredAnswers.length === 0) { + return '' + } + } + // 其他情况保持原样 + return trimmed + } catch (e) { + // 解析失败,可能是普通字符串,检查是否为空或只包含空格 + return trimmed === '' ? '' : JSON.stringify([trimmed]) + } + } + // 普通字符串,包装为数组 + return JSON.stringify([trimmed]) + } else if (Array.isArray(answer)) { + // 如果是数组,检查是否为空或只包含空值 + // 过滤掉数组中的空值和空格 + const filteredAnswers = answer.filter(item => { + if (item === null || item === undefined) return false + const itemStr = String(item).trim() + return itemStr !== '' && itemStr !== '[]' && itemStr !== '[[]]' + }) + // 如果过滤后数组为空,返回空字符串 + if (filteredAnswers.length === 0) { + return '' + } + // 其他情况转换为JSON字符串 + return JSON.stringify(filteredAnswers) + } else { + // 其他类型,转换为字符串并包装为数组 + const answerStr = String(answer || '') + return answerStr.trim() === '' ? '' : JSON.stringify([answerStr]) } }, @@ -740,22 +856,22 @@ export default { const questionItem = this.questionList.find(item => item.serial_no === questionSerialNo) if (!questionItem) return - // 修复:移除重复的JSON.stringify,因为答案在调用前已经是正确格式的JSON字符串 - // const answerToSave = JSON.stringify(answer) - // 修复:传递正确的参数结构,包含tableName const result = await window.electronAPI.examingUpdateAnswer({ tableName: questionItem.table_name, // 添加表名参数 id: questionItem.id, // 使用id而不是questionId + answers: answer // 直接使用已经格式化好的答案 }) if (result && result.success) { console.log('保存答案成功:', questionSerialNo, answer) - // 更新题目回答状态 + // 更新题目回答状态 - 根据答案内容决定是否标记为已作答 const index = this.questionList.findIndex(item => item.serial_no === questionSerialNo) if (index !== -1) { - this.$set(this.questionList[index], 'answered', 1) + // 使用isAnswerValid方法判断答案是否有效 + const isAnswered = this.isAnswerValid(answer) + this.$set(this.questionList[index], 'answered', isAnswered ? 1 : 0) } } else { console.error('保存答案失败:', result) @@ -763,6 +879,15 @@ export default { } catch (error) { console.error('保存答案异常:', error) } + }, + + // 格式化身份证号方法 - 已移动到ExamingInfoBar组件,但保留以便交卷预览使用 + formatIdCard(idCard) { + if (!idCard || typeof idCard !== 'string') { + return idCard + } + // 保留前6位和后4位,中间用*代替 + return idCard.substring(0, 6) + '********' + idCard.substring(14) } } } @@ -788,50 +913,6 @@ export default { margin: 0; } -/* 顶栏:考生信息和考试信息 - 设置固定高度 */ -.exam-top-bar { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0.75rem 1.5rem; - background-color: #fff; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - margin-bottom: var(--gap-between-sections); - gap: 1rem; - height: var(--exam-top-bar-height); - box-sizing: border-box; - flex-shrink: 0; -} - -.left-info, .right-info { - display: flex; - gap: 1.5rem; - align-items: center; - flex-wrap: wrap; -} - -.info-item { - display: flex; - align-items: center; - font-size: 0.875rem; -} - -.label { - color: #606266; - margin-right: 0.25rem; -} - -.value { - color: #303133; - font-weight: 500; -} - -.timer .value { - color: #f56c6c; - font-weight: bold; - font-size: 1rem; -} - /* 主体内容区 - 计算得出的动态高度,填满剩余空间 */ .exam-main { display: flex; @@ -954,210 +1035,6 @@ export default { background: #a1a1a1; } -/* 题目头部 */ -.question-header { - display: flex; - align-items: center; - margin-bottom: 15px; - padding-bottom: 10px; - border-bottom: 2px solid #e4e7ed; -} - -.question-number { - font-size: 18px; - font-weight: bold; - color: #303133; - margin-right: 10px; -} - -.question-score { - font-size: 14px; - font-weight: 500; -} - -/* 题目主体 */ -.question-body { - font-size: 15px; - line-height: 1.6; - color: #303133; -} - -/* 题型标签 */ -.question-type { - display: inline-block; - background-color: #ecf5ff; - color: #409eff; - padding: 2px 8px; - border-radius: 3px; - font-size: 12px; - margin-bottom: 10px; -} - -/* 题目文本 */ -.question-text { - margin-bottom: 15px; - white-space: pre-wrap; - word-wrap: break-word; -} - -/* 题目图片 */ -.question-images { - margin-bottom: 15px; -} - -.question-image { - margin-bottom: 10px; - text-align: center; -} - -.question-image img { - max-width: 100%; - max-height: 400px; - border-radius: 4px; - border: 1px solid #e4e7ed; - cursor: pointer; - transition: transform 0.2s; -} - -.question-image img:hover { - transform: scale(1.02); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); -} - -/* 题目数据集 */ -.question-datasets { - margin-bottom: 15px; -} - -.question-dataset { - margin-bottom: 10px; -} - -.question-dataset h4 { - font-size: 14px; - margin: 0 0 5px 0; - color: #606266; -} - -.question-dataset pre { - background-color: #f8f8f8; - padding: 10px; - border-radius: 4px; - border: 1px solid #e4e7ed; - font-size: 13px; - overflow-x: auto; - white-space: pre-wrap; - word-wrap: break-word; -} - -/* 选择题选项 */ -.question-options { - margin-top: 15px; -} - -.option-item { - display: flex; - align-items: flex-start; - padding: 12px 15px; - margin-bottom: 10px; - background-color: #f8f9fa; - border-radius: 6px; - cursor: pointer; - transition: all 0.2s; - border: 1px solid transparent; -} - -.option-item:hover { - background-color: #f0f2f5; - border-color: #dcdfe6; -} - -.option-item.selected { - background-color: #bcffb3; - border-color: #007c11; - font-weight:bold; -} - -.option-letter { - display: inline-flex; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - background-color: #409eff; - color: white; - border-radius: 50%; - font-size: 12px; - font-weight: bold; - margin-right: 12px; - flex-shrink: 0; -} - -.option-item.selected .option-letter { - background-color: #006e25; -} - -.option-text { - flex: 1; - white-space: pre-wrap; - word-wrap: break-word; -} - -/* 填空题答案 */ -.question-answer { - margin-top: 15px; -} - -.question-answer input { - width: 100%; - padding: 10px 15px; - border: 1px solid #dcdfe6; - border-radius: 4px; - font-size: 14px; - margin-top: 10px; - margin-bottom: 5px; - transition: border-color 0.2s; -} - -.question-answer input:focus { - outline: none; - border-color: #409eff; -} - -/* 表格样式优化 - 针对试题中的表格 */ -.question-text table, -.option-text table { - width: 100%; - border-collapse: collapse; - margin: 10px 0; -} - -.question-text th, -.option-text th, -.question-text td, -.option-text td { - border: 1px solid #dcdfe6; - padding: 8px 12px; - text-align: center; -} - -.question-text th, -.option-text th { - background-color: #f8f9fa; - font-weight: 600; - color: #303133; -} - -.question-text tr:nth-child(even), -.option-text tr:nth-child(even) { - background-color: #fafafa; -} - -.question-text tr:hover, -.option-text tr:hover { - background-color: #f5f7fa; -} - /* 底栏:操作按钮 */ .exam-bottom-bar { display: flex; @@ -1168,96 +1045,6 @@ export default { margin-top: 10px; } -/* 图片查看器样式 */ -.image-viewer-mask { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.8); - display: flex; - align-items: center; - justify-content: center; - z-index: 1000; - cursor: pointer; -} - -.image-viewer-container { - position: relative; - max-width: 90%; - max-height: 90%; - background-color: white; - border-radius: 8px; - padding: 20px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - cursor: default; - display: flex; - flex-direction: column; - align-items: center; -} - -.viewer-image { - max-width: 100%; - max-height: calc(90vh - 80px); /* 减去padding和按钮高度 */ - object-fit: contain; - border-radius: 4px; -} - -.close-btn { - position: absolute; - top: 10px; - right: 10px; - width: 30px; - height: 30px; - background-color: rgba(255, 255, 255, 0.8); - border: none; - border-radius: 50%; - cursor: pointer; - font-size: 16px; - display: flex; - align-items: center; - justify-content: center; - transition: all 0.2s; -} - -.close-btn:hover { - background-color: white; - transform: scale(1.1); -} - -/* 响应式设计 */ -@media (max-width: 768px) { - :root { - --exam-top-bar-height: 120px; - --sidebar-width: 100%; - } - - .exam-top-bar { - flex-direction: column; - gap: 0.5rem; - padding: 0.5rem 1rem; - } - - .left-info, .right-info { - flex-wrap: wrap; - gap: 0.5rem; - justify-content: center; - } - - .exam-main { - flex-direction: column; - } - - .exam-sidebar { - max-height: 150px; - } - - .question-list { - justify-content: center; - } -} - /* 确保整个页面布局正确 */ html, body { height: 100%; @@ -1270,5 +1057,295 @@ html, body { overflow: hidden !important; } -/* 其他原有样式保持不变 */ +/* 修改:交卷预览模态框样式 */ +.preview-modal-mask { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.8); + display: flex; + align-items: center; + justify-content: center; + z-index: 1100; + cursor: pointer; +} + +.preview-modal-container { + position: relative; + width: 90%; + max-width: 1200px; + max-height: 90vh; + background-color: white; + border-radius: 8px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); + cursor: default; + display: flex; + flex-direction: column; + overflow: hidden; +} + +/* 修改:预览弹窗头部样式 */ +.preview-modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 20px; + background-color: #409eff; + color: white; + flex-shrink: 0; +} + +.preview-header-content { + flex: 1; +} + +.preview-title { + font-size: 18px; + font-weight: bold; + margin-bottom: 5px; +} + +.preview-info-row { + display: flex; + flex-wrap: wrap; + gap: 15px; + font-size: 13px; +} + +.preview-info-item { + display: flex; + align-items: center; +} + +.preview-info-label { + margin-right: 4px; + color: rgba(255, 255, 255, 0.9); +} + +.preview-info-value { + color: white; + font-weight: 500; +} + +.answered-count { + color: #9ffa7b; + font-weight: bold; +} + +.preview-modal-body { + flex: 1; + overflow-y: auto; + padding: 20px; +} + +.preview-question-list { + display: flex; + flex-direction: column; + gap: 20px; +} + +.preview-question-item { + border: 1px solid #e4e7ed; + border-radius: 8px; + padding: 15px; + background-color: #fff; +} + +.preview-question-header { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 15px; + padding-bottom: 10px; + border-bottom: 2px solid #e4e7ed; +} + +.preview-question-number { + font-size: 16px; + font-weight: bold; + color: #303133; +} + +.preview-question-type { + background-color: #ecf5ff; + color: #409eff; + padding: 2px 8px; + border-radius: 3px; + font-size: 12px; +} + +.preview-question-status { + margin-left: auto; + padding: 4px 10px; + border-radius: 4px; + font-size: 12px; + font-weight: bold; +} + +.preview-question-status.answered { + background-color: #f0f9ff; + color: #007c11; + border: 1px solid #9ffa7b; +} + +.preview-question-status.unanswered { + background-color: #fff2f0; + color: #f56c6c; + border: 1px solid #ffbbb0; +} + +.preview-question-body { + font-size: 14px; + line-height: 1.6; + color: #303133; +} + +.preview-question-text { + margin-bottom: 15px; + white-space: pre-wrap; + word-wrap: break-word; +} + +.preview-question-images { + margin-bottom: 15px; +} + +.preview-question-image { + margin-bottom: 10px; + text-align: center; +} + +.preview-question-image img { + max-width: 100%; + max-height: 300px; + border-radius: 4px; + border: 1px solid #e4e7ed; +} + +.preview-question-datasets { + margin-bottom: 15px; +} + +.preview-question-dataset { + margin-bottom: 10px; +} + +.preview-question-dataset h4 { + font-size: 13px; + margin: 0 0 5px 0; + color: #606266; +} + +.preview-question-dataset pre { + background-color: #f8f8f8; + padding: 8px; + border-radius: 4px; + border: 1px solid #e4e7ed; + font-size: 12px; + overflow-x: auto; + white-space: pre-wrap; + word-wrap: break-word; +} + +.preview-question-options { + margin-top: 15px; +} + +.preview-option-item { + display: flex; + align-items: flex-start; + padding: 10px 12px; + margin-bottom: 8px; + background-color: #f8f9fa; + border-radius: 4px; + border: 1px solid #e4e7ed; +} + +.preview-option-item.preview-selected { + background-color: #bcffb3; + border-color: #007c11; + font-weight: bold; +} + +.preview-option-letter { + display: inline-flex; + align-items: center; + justify-content: center; + width: 20px; + height: 20px; + background-color: #409eff; + color: white; + border-radius: 50%; + font-size: 11px; + font-weight: bold; + margin-right: 10px; + flex-shrink: 0; +} + +.preview-option-item.preview-selected .preview-option-letter { + background-color: #006e25; +} + +.preview-option-text { + flex: 1; + white-space: pre-wrap; + word-wrap: break-word; + font-size: 13px; +} + +.preview-question-answer { + margin-top: 15px; +} + +.preview-fill-answer { + background-color: #f0f9ff; + padding: 10px 15px; + border-radius: 4px; + border: 1px solid #9ffa7b; + margin-top: 10px; +} + +.answer-label { + font-weight: bold; + color: #007c11; + margin-right: 8px; +} + +.answer-content { + color: #303133; +} + +.preview-modal-footer { + display: flex; + justify-content: flex-end; + gap: 10px; + padding: 15px 20px; + background-color: #f5f7fa; + border-top: 1px solid #e4e7ed; + flex-shrink: 0; +} + +/* 响应式设计补充 */ +@media (max-width: 768px) { + .preview-modal-container { + width: 95%; + max-height: 95vh; + } + + .preview-modal-body { + padding: 15px; + } + + .preview-question-header { + flex-wrap: wrap; + } + + .preview-question-status { + margin-left: 0; + width: 100%; + text-align: center; + } +} \ No newline at end of file