|
@@ -41,10 +41,10 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- <div class="question-analysis">
|
|
|
|
|
|
|
+ <div class="question-analysis" v-if="props.examType === 'exam'">
|
|
|
<h4>题目分析:</h4>
|
|
<h4>题目分析:</h4>
|
|
|
<div v-html="getQuestionAnalysis(item)"></div>
|
|
<div v-html="getQuestionAnalysis(item)"></div>
|
|
|
- </div> -->
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
<a-divider />
|
|
<a-divider />
|
|
|
</div>
|
|
</div>
|
|
@@ -59,6 +59,9 @@
|
|
|
import { ref, watch } from 'vue'
|
|
import { ref, watch } from 'vue'
|
|
|
import examManagerApi from '@/api/exam/paper/examManager.js'
|
|
import examManagerApi from '@/api/exam/paper/examManager.js'
|
|
|
import * as echarts from 'echarts'
|
|
import * as echarts from 'echarts'
|
|
|
|
|
+ import { useExamStore } from '@/store/exam'
|
|
|
|
|
+ const examStore = useExamStore()
|
|
|
|
|
+ const questionTypeEnum = computed(() => examStore.questionTypeEnum)
|
|
|
const props = defineProps({
|
|
const props = defineProps({
|
|
|
paperId: {
|
|
paperId: {
|
|
|
type: String,
|
|
type: String,
|
|
@@ -67,7 +70,8 @@
|
|
|
paperName: {
|
|
paperName: {
|
|
|
type: String,
|
|
type: String,
|
|
|
default: ''
|
|
default: ''
|
|
|
- }
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+ examType: String // exam-考试,questionnaire-调查问卷
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
const loading = ref(false)
|
|
const loading = ref(false)
|
|
@@ -181,6 +185,15 @@
|
|
|
|
|
|
|
|
// 获取题目类型
|
|
// 获取题目类型
|
|
|
const getQuestionType = (item) => {
|
|
const getQuestionType = (item) => {
|
|
|
|
|
+ // 如果有 questionType 字段,优先使用 questionTypeEnum 获取题型名称
|
|
|
|
|
+ if (item.questionType !== undefined) {
|
|
|
|
|
+ const questionType = questionTypeEnum.value.find((type) => type.key === item.questionType)
|
|
|
|
|
+ if (questionType) {
|
|
|
|
|
+ return questionType.value
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果没有 questionType 字段或找不到对应的题型,使用原来的逻辑作为备选
|
|
|
try {
|
|
try {
|
|
|
const content = JSON.parse(item.content)
|
|
const content = JSON.parse(item.content)
|
|
|
if (!content.questionItemObjects || content.questionItemObjects.length === 0) {
|
|
if (!content.questionItemObjects || content.questionItemObjects.length === 0) {
|
|
@@ -197,6 +210,13 @@
|
|
|
|
|
|
|
|
// 判断是否为选择题
|
|
// 判断是否为选择题
|
|
|
const isChoiceQuestion = (item) => {
|
|
const isChoiceQuestion = (item) => {
|
|
|
|
|
+ // 使用 questionType 字段判断
|
|
|
|
|
+ if (item.questionType !== undefined) {
|
|
|
|
|
+ // 1是单选题,2是多选题,3是判断题,这三种都是选择题
|
|
|
|
|
+ return [1, 2, 3].includes(item.questionType)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果没有 questionType 字段,使用原来的逻辑
|
|
|
try {
|
|
try {
|
|
|
const content = JSON.parse(item.content)
|
|
const content = JSON.parse(item.content)
|
|
|
return content.questionItemObjects && content.questionItemObjects.length > 0
|
|
return content.questionItemObjects && content.questionItemObjects.length > 0
|
|
@@ -218,9 +238,14 @@
|
|
|
// 获取选项选择人数
|
|
// 获取选项选择人数
|
|
|
const getOptionCount = (item, prefix) => {
|
|
const getOptionCount = (item, prefix) => {
|
|
|
try {
|
|
try {
|
|
|
|
|
+ // 确保 answerList 是字符串,并且是选择题类型
|
|
|
|
|
+ if (typeof item.answerList !== 'string' || !isChoiceQuestion(item)) {
|
|
|
|
|
+ return 0
|
|
|
|
|
+ }
|
|
|
const answerList = item.answerList.split(',')
|
|
const answerList = item.answerList.split(',')
|
|
|
return answerList.filter((answer) => answer === prefix).length
|
|
return answerList.filter((answer) => answer === prefix).length
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
|
|
+ console.error('获取选项选择人数失败', e)
|
|
|
return 0
|
|
return 0
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -242,10 +267,96 @@
|
|
|
const getSubjectiveAnswers = (item) => {
|
|
const getSubjectiveAnswers = (item) => {
|
|
|
try {
|
|
try {
|
|
|
if (!isChoiceQuestion(item)) {
|
|
if (!isChoiceQuestion(item)) {
|
|
|
- return JSON.parse(item.answerList)
|
|
|
|
|
|
|
+ // 处理填空题的特殊格式
|
|
|
|
|
+ if (item.questionType === 4) {
|
|
|
|
|
+ // 填空题
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 填空题的答案格式可能是 "["i","i","o","o"],[]" 这样的格式
|
|
|
|
|
+ // 这不是标准的 JSON 格式,需要特殊处理
|
|
|
|
|
+ const raw = item.answerList
|
|
|
|
|
+ let s = typeof raw === 'string' ? raw.trim() : JSON.stringify(raw)
|
|
|
|
|
+
|
|
|
|
|
+ if (s === '' || s === 'null' || s === 'undefined') {
|
|
|
|
|
+ return []
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const tryParse = (text) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ return JSON.parse(text)
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ return undefined
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let answerData = tryParse(s)
|
|
|
|
|
+
|
|
|
|
|
+ if (answerData === undefined) {
|
|
|
|
|
+ let fixed = s
|
|
|
|
|
+ // 去掉 ] 前多余逗号,以及结尾多余逗号
|
|
|
|
|
+ fixed = fixed.replace(/,\s*]/g, ']').replace(/,\s*$/, '')
|
|
|
|
|
+ // 单引号转双引号(常见于后端返回)
|
|
|
|
|
+ if (fixed.includes("'") && !fixed.includes('"')) {
|
|
|
|
|
+ fixed = fixed.replace(/'/g, '"')
|
|
|
|
|
+ }
|
|
|
|
|
+ // 缺少最外层 [] 的情况,例如 ["i","i"],[]
|
|
|
|
|
+ if (
|
|
|
|
|
+ (fixed.startsWith('[') && fixed.includes('],') && !(fixed.startsWith('[[') && fixed.endsWith(']]'))) ||
|
|
|
|
|
+ (!fixed.startsWith('[') && fixed.includes('],'))
|
|
|
|
|
+ ) {
|
|
|
|
|
+ fixed = `[${fixed}]`
|
|
|
|
|
+ }
|
|
|
|
|
+ answerData = tryParse(fixed)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 将解析结果格式化为字符串数组用于展示
|
|
|
|
|
+ const result = []
|
|
|
|
|
+ if (Array.isArray(answerData)) {
|
|
|
|
|
+ // 二维数组:每个空对应一个数组
|
|
|
|
|
+ if (answerData.length > 0 && Array.isArray(answerData[0])) {
|
|
|
|
|
+ answerData.forEach((ans) => {
|
|
|
|
|
+ if (Array.isArray(ans)) {
|
|
|
|
|
+ const line = ans
|
|
|
|
|
+ .filter((x) => x !== null && x !== undefined && x !== '')
|
|
|
|
|
+ .map((x) => String(x))
|
|
|
|
|
+ .join(', ')
|
|
|
|
|
+ if (line !== '') result.push(line)
|
|
|
|
|
+ } else if (ans !== null && ans !== undefined && ans !== '') {
|
|
|
|
|
+ result.push(String(ans))
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 一维数组:合并为一条
|
|
|
|
|
+ const line = answerData
|
|
|
|
|
+ .filter((x) => x !== null && x !== undefined && x !== '')
|
|
|
|
|
+ .map((x) => String(x))
|
|
|
|
|
+ .join(', ')
|
|
|
|
|
+ if (line !== '') result.push(line)
|
|
|
|
|
+ }
|
|
|
|
|
+ return result
|
|
|
|
|
+ } else if (typeof answerData === 'string') {
|
|
|
|
|
+ return [answerData]
|
|
|
|
|
+ } else if (answerData != null) {
|
|
|
|
|
+ return [JSON.stringify(answerData)]
|
|
|
|
|
+ }
|
|
|
|
|
+ return []
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('解析填空题答案失败', error)
|
|
|
|
|
+ // 如果特殊处理失败,尝试直接显示原始答案
|
|
|
|
|
+ return [item.answerList]
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 其他主观题类型
|
|
|
|
|
+ try {
|
|
|
|
|
+ return JSON.parse(item.answerList)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ // 如果解析失败,可能是普通字符串
|
|
|
|
|
+ return [item.answerList]
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
return []
|
|
return []
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
|
|
+ console.error('解析答案列表失败', e)
|
|
|
return []
|
|
return []
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|