- 修复正确答案字母解析的正则表达式 - 支持更多冒号格式(中英文冒号、带空格) - 添加详细的调试日志帮助定位问题 - 当无法解析时尝试内容匹配
This commit is contained in:
@@ -340,30 +340,56 @@ const transformDifyQuestions = (difyQuestions: any[]): any[] => {
|
||||
if (q.type === 'single_choice' || q.type === 'multiple_choice') {
|
||||
const options = q.topic?.options || {}
|
||||
// 解析正确答案:支持 "A"、"A,B"、"A、B"、"A:xxx" 等多种格式
|
||||
const correctAnswerStr = String(q.correct || '')
|
||||
const correctAnswerStr = String(q.correct || '').trim()
|
||||
|
||||
console.log(`📝 开始解析题目[${index + 1}]`)
|
||||
console.log(` 原始correct: "${correctAnswerStr}"`)
|
||||
console.log(` 原始options:`, options)
|
||||
|
||||
// 更精确地提取正确答案字母(避免误提取选项内容中的字母)
|
||||
let correctLetters: string[] = []
|
||||
|
||||
// 情况1:纯选项字母格式(如 "A", "B", "A,B", "A、B", "A,B,C")
|
||||
const pureLetterMatch = correctAnswerStr.trim().match(/^[A-Da-d]([,、\s]+[A-Da-d])*$/)
|
||||
const pureLetterMatch = correctAnswerStr.match(/^[A-Da-d]([,、\s]+[A-Da-d])*$/)
|
||||
if (pureLetterMatch) {
|
||||
correctLetters = correctAnswerStr.match(/[A-Da-d]/g)?.map(l => l.toUpperCase()) || []
|
||||
console.log(` ✓ 匹配情况1(纯字母): correctLetters=[${correctLetters.join(',')}]`)
|
||||
} else {
|
||||
// 情况2:选项字母+内容格式(如 "A:xxx" 或 "A: xxx")
|
||||
// 只提取开头的选项字母(可能有多个,如 "A,C:xxx")
|
||||
const prefixMatch = correctAnswerStr.match(/^([A-Da-d](?:[,、\s]*[A-Da-d])*)[:::\s]/)
|
||||
// 情况2:选项字母+内容格式(如 "A:xxx" 或 "A: xxx" 或 "A:xxx")
|
||||
// 支持多种冒号格式:中文全角冒号、英文冒号
|
||||
const prefixMatch = correctAnswerStr.match(/^([A-Da-d](?:[,、\s]*[A-Da-d])*)\s*[::]\s*/)
|
||||
if (prefixMatch) {
|
||||
correctLetters = prefixMatch[1].match(/[A-Da-d]/g)?.map(l => l.toUpperCase()) || []
|
||||
console.log(` ✓ 匹配情况2(字母+冒号): prefixMatch="${prefixMatch[0]}", correctLetters=[${correctLetters.join(',')}]`)
|
||||
} else {
|
||||
// 情况3:只有开头字母(如 "A" 后面直接跟内容)
|
||||
const firstLetterMatch = correctAnswerStr.match(/^([A-Da-d])/)
|
||||
// 情况3:只有开头字母(如 "A" 后面直接跟非字母内容)
|
||||
const firstLetterMatch = correctAnswerStr.match(/^([A-Da-d])(?![A-Za-z])/)
|
||||
if (firstLetterMatch) {
|
||||
correctLetters = [firstLetterMatch[1].toUpperCase()]
|
||||
console.log(` ✓ 匹配情况3(开头字母): correctLetters=[${correctLetters.join(',')}]`)
|
||||
} else {
|
||||
// 情况4:无法解析,尝试从选项中查找匹配的答案
|
||||
console.log(` ⚠️ 无法从correct字符串解析字母,尝试内容匹配`)
|
||||
// 尝试在选项中查找完全匹配的内容
|
||||
const optionValues = Object.values(options)
|
||||
optionValues.forEach((optVal: any, idx: number) => {
|
||||
const optContent = String(optVal || '')
|
||||
if (optContent === correctAnswerStr || optContent.includes(correctAnswerStr)) {
|
||||
const letter = String.fromCharCode(65 + idx)
|
||||
correctLetters.push(letter)
|
||||
console.log(` → 内容匹配: 选项${letter}="${optContent.substring(0, 30)}..."`)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 确保至少有一个正确答案
|
||||
if (correctLetters.length === 0) {
|
||||
console.warn(` ❌ 警告:未能解析出正确答案字母,默认使用第一个选项`)
|
||||
correctLetters = ['A']
|
||||
}
|
||||
|
||||
console.log(`🔍 解析题目[${index + 1}] - correct: "${q.correct}", correctLetters: [${correctLetters.join(', ')}]`)
|
||||
|
||||
// 获取所有选项的键并排序,确保顺序一致
|
||||
@@ -376,38 +402,46 @@ const transformDifyQuestions = (difyQuestions: any[]): any[] => {
|
||||
return a.localeCompare(b)
|
||||
})
|
||||
|
||||
console.log(` 选项键排序后: [${optionKeys.join(', ')}]`)
|
||||
|
||||
transformed.options = optionKeys.map((key, idx) => {
|
||||
const opt = options[key]
|
||||
const optStr = String(opt)
|
||||
const optStr = String(opt || '')
|
||||
|
||||
// 提取选项内容(去掉 "A:" 或 "A:" 前缀)
|
||||
let content = optStr
|
||||
if (optStr.match(/^[A-Da-d][::]/)) {
|
||||
content = optStr.substring(2).trim()
|
||||
} else if (optStr.includes(':')) {
|
||||
content = optStr.split(':').slice(1).join(':').trim()
|
||||
// 匹配 "A:xxx" 或 "A:xxx" 格式(支持中英文冒号)
|
||||
const contentPrefixMatch = optStr.match(/^[A-Da-d]\s*[::]\s*(.*)$/)
|
||||
if (contentPrefixMatch) {
|
||||
content = contentPrefixMatch[1].trim()
|
||||
}
|
||||
|
||||
// 提取当前选项的字母(优先级:optStr前缀 > key字母 > 索引推断)
|
||||
// 提取当前选项的字母
|
||||
// 优先级:1. 选项内容前缀 > 2. key字母 > 3. 索引推断
|
||||
let optionLetter = ''
|
||||
let letterSource = ''
|
||||
|
||||
// 1. 尝试从选项内容前缀提取(如 "A:xxx" 或 "A:xxx")
|
||||
const prefixMatch = optStr.match(/^([A-Da-d])[::]/)
|
||||
const prefixMatch = optStr.match(/^([A-Da-d])\s*[::]/)
|
||||
if (prefixMatch) {
|
||||
optionLetter = prefixMatch[1].toUpperCase()
|
||||
letterSource = '内容前缀'
|
||||
}
|
||||
// 2. 尝试从 key 提取(如果 key 是单个字母)
|
||||
// 2. 尝试从 key 提取(如果 key 是单个字母 A-D)
|
||||
else if (key.match(/^[A-Da-d]$/)) {
|
||||
optionLetter = key.toUpperCase()
|
||||
letterSource = 'key字母'
|
||||
}
|
||||
// 3. 根据索引推断选项字母(0->A, 1->B, 2->C, 3->D)
|
||||
else {
|
||||
optionLetter = String.fromCharCode(65 + idx) // 65 = 'A'
|
||||
letterSource = '索引推断'
|
||||
}
|
||||
|
||||
// 判断当前选项是否正确:检查选项字母是否在正确答案列表中
|
||||
const isCorrect = correctLetters.includes(optionLetter)
|
||||
|
||||
console.log(` 选项[${key}/${idx}]: letter=${optionLetter}, isCorrect=${isCorrect}, content="${content.substring(0, 20)}..."`)
|
||||
console.log(` 选项[${key}/${idx}]: letter=${optionLetter}(${letterSource}), isCorrect=${isCorrect}, correctLetters=[${correctLetters.join(',')}], content="${content.substring(0, 25)}..."`)
|
||||
|
||||
return { content, isCorrect, optionLetter }
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user