diff --git a/frontend/src/views/exam/practice.vue b/frontend/src/views/exam/practice.vue index 8f6b468..1bd5d6b 100644 --- a/frontend/src/views/exam/practice.vue +++ b/frontend/src/views/exam/practice.vue @@ -772,32 +772,48 @@ const submitAnswer = () => { const checkObjectiveAnswer = (): boolean => { const q = currentQuestion.value - if (q.type === 'single' || q.type === 'multiple') { - const correctIndexes = q.options - .map((opt: any, idx: number) => opt.isCorrect ? idx : -1) - .filter((idx: number) => idx !== -1) - - // 调试日志:显示正确答案索引和用户选择 - console.log(`🔍 客观题判断 - 题目: "${q.title.substring(0, 30)}..."`) - console.log(` 选项详情:`, q.options.map((opt: any, idx: number) => ({ - index: idx, - letter: String.fromCharCode(65 + idx), - isCorrect: opt.isCorrect, - content: opt.content?.substring(0, 20) + '...' - }))) - console.log(` 正确答案索引: [${correctIndexes.join(', ')}]`) - console.log(` 用户选择索引: [${userAnswer.selected.join(', ')}]`) - - const isCorrect = JSON.stringify(userAnswer.selected.sort()) === JSON.stringify(correctIndexes.sort()) - console.log(` 判断结果: ${isCorrect ? '✅正确' : '❌错误'}`) - - return isCorrect - } else if (q.type === 'judge') { - console.log(`🔍 判断题判断 - 正确答案: ${q.correctAnswer}, 用户答案: ${userAnswer.judge}`) - return userAnswer.judge === q.correctAnswer + if (!q) { + console.error('checkObjectiveAnswer: currentQuestion 为空') + return false } - return false + try { + if (q.type === 'single' || q.type === 'multiple') { + // 增加空值保护 + if (!q.options || !Array.isArray(q.options)) { + console.error('checkObjectiveAnswer: options 无效', q.options) + return false + } + + const correctIndexes = q.options + .map((opt: any, idx: number) => opt?.isCorrect ? idx : -1) + .filter((idx: number) => idx !== -1) + + // 调试日志:显示正确答案索引和用户选择 + console.log(`🔍 客观题判断 - 题目: "${q.title?.substring(0, 30) || '无标题'}..."`) + console.log(` 选项详情:`, q.options.map((opt: any, idx: number) => ({ + index: idx, + letter: String.fromCharCode(65 + idx), + isCorrect: opt?.isCorrect, + content: opt?.content?.substring(0, 20) + '...' + }))) + console.log(` 正确答案索引: [${correctIndexes.join(', ')}]`) + console.log(` 用户选择索引: [${userAnswer.selected.join(', ')}]`) + + const isCorrect = JSON.stringify([...userAnswer.selected].sort()) === JSON.stringify([...correctIndexes].sort()) + console.log(` 判断结果: ${isCorrect ? '✅正确' : '❌错误'}`) + + return isCorrect + } else if (q.type === 'judge') { + console.log(`🔍 判断题判断 - 正确答案: ${q.correctAnswer}, 用户答案: ${userAnswer.judge}`) + return userAnswer.judge === q.correctAnswer + } + + return false + } catch (error) { + console.error('checkObjectiveAnswer 出错:', error) + return false + } } /** @@ -863,18 +879,29 @@ const checkSubjectiveAnswer = async (question: any): Promise => { * 记录错题到数据库 */ const recordWrongAnswer = async () => { - const q = currentQuestion.value + // 使用 dialogQuestion(已保存的题目快照)而不是 currentQuestion + const q = dialogQuestion.value || currentQuestion.value + + if (!q) { + console.error('recordWrongAnswer: 题目数据为空') + return + } // 获取用户答案 let userAnswerText = '' - if (q.type === 'single' || q.type === 'multiple') { - userAnswerText = userAnswer.selected.map(idx => String.fromCharCode(65 + idx)).join(',') - } else if (q.type === 'judge') { - userAnswerText = userAnswer.judge ? '正确' : '错误' - } else if (q.type === 'blank') { - userAnswerText = userAnswer.blank - } else if (q.type === 'essay') { - userAnswerText = userAnswer.essay + try { + if (q.type === 'single' || q.type === 'multiple') { + userAnswerText = userAnswer.selected.map(idx => String.fromCharCode(65 + idx)).join(',') + } else if (q.type === 'judge') { + userAnswerText = userAnswer.judge ? '正确' : '错误' + } else if (q.type === 'blank') { + userAnswerText = userAnswer.blank || '' + } else if (q.type === 'essay') { + userAnswerText = userAnswer.essay || '' + } + } catch (e) { + console.error('获取用户答案失败:', e) + userAnswerText = '' } try { @@ -883,10 +910,10 @@ const recordWrongAnswer = async () => { round: currentRound.value, // 记录当前轮次 question_id: null, // AI生成的题目没有question_id knowledge_point_id: q.knowledge_point_id || null, - question_content: q.title, + question_content: q.title || '', correct_answer: formatCorrectAnswer(q), user_answer: userAnswerText, - question_type: q.type // 新增:记录题型 + question_type: q.type || '' // 新增:记录题型 }) } catch (error: any) { console.error('记录错题失败:', error) @@ -1181,35 +1208,45 @@ const renderMarkdown = (content: string): string => { * 格式化正确答案 */ const formatCorrectAnswer = (question: any) => { - if (question.type === 'single' || question.type === 'multiple') { - // 如果有correctAnswer字段(来自Dify的原始correct) - if (question.correctAnswer) { - // 多选题格式优化:将 "A:xxx、B:xxx" 或 "A:xxx,B:xxx" 改为换行显示 - // 使用更精确的匹配:提取完整的选项格式 X:内容 - const optionPattern = /([A-Za-z][::])([^A-Za-z]*?)(?=(?:[,、]?[A-Za-z][::])|$)/g - const matches = [...question.correctAnswer.matchAll(optionPattern)] - if (matches.length > 1) { - // 多个选项,换行显示 - return matches.map(m => m[1] + m[2].trim()).join('\n') + if (!question) return '' + + try { + if (question.type === 'single' || question.type === 'multiple') { + // 如果有correctAnswer字段(来自Dify的原始correct) + if (question.correctAnswer) { + // 多选题格式优化:将 "A:xxx、B:xxx" 或 "A:xxx,B:xxx" 改为换行显示 + // 使用更精确的匹配:提取完整的选项格式 X:内容 + const optionPattern = /([A-Za-z][::])([^A-Za-z]*?)(?=(?:[,、]?[A-Za-z][::])|$)/g + const matches = [...String(question.correctAnswer).matchAll(optionPattern)] + if (matches.length > 1) { + // 多个选项,换行显示 + return matches.map(m => m[1] + m[2].trim()).join('\n') + } + return question.correctAnswer } - return question.correctAnswer + // 否则从options中提取(增加空值保护) + if (!question.options || !Array.isArray(question.options)) { + return '' + } + return question.options + .map((opt: any, idx: number) => opt?.isCorrect ? String.fromCharCode(65 + idx) : null) + .filter((v: any) => v) + .join('、') + } else if (question.type === 'judge') { + // 优先使用correctAnswerText(Dify原始值:"正确"或"错误") + if (question.correctAnswerText) { + return question.correctAnswerText + } + // 备用:从boolean转换 + return question.correctAnswer ? '正确' : '错误' + } else if (question.type === 'blank' || question.type === 'essay') { + return question.correctAnswer || '' } - // 否则从options中提取 - return question.options - .map((opt: any, idx: number) => opt.isCorrect ? String.fromCharCode(65 + idx) : null) - .filter((v: any) => v) - .join('、') - } else if (question.type === 'judge') { - // 优先使用correctAnswerText(Dify原始值:"正确"或"错误") - if (question.correctAnswerText) { - return question.correctAnswerText - } - // 备用:从boolean转换 - return question.correctAnswer ? '正确' : '错误' - } else if (question.type === 'blank' || question.type === 'essay') { + return '' + } catch (error) { + console.error('formatCorrectAnswer 出错:', error, question) return question.correctAnswer || '' } - return '' } /**