184 lines
5.2 KiB
Vue
184 lines
5.2 KiB
Vue
<template>
|
||
|
||
|
||
<Dialog v-model="visible" :title="'查看试卷'" width="860" @open="handleOpen" center>
|
||
|
||
|
||
<!-- <div style="margin-bottom: 16px">
|
||
<strong>试卷ID:</strong>
|
||
{{ paperId ? paperId : '未提供试卷ID' }}
|
||
</div> -->
|
||
|
||
|
||
<!-- 滚动区域 -->
|
||
<div style="max-height: 400px; overflow-y: auto;">
|
||
<!-- 分组展示题目 -->
|
||
<div
|
||
v-for="(items, subject) in sortedGroupedQuestions"
|
||
:key="subject"
|
||
>
|
||
<h4 class="mb-2 text-base text-gray-700 font-medium">
|
||
{{ subject }}
|
||
<span v-if="schemeMap[subject]" class="text-sm text-gray-500 font-normal">
|
||
(每小题 {{ parseFloat(schemeMap[subject].quScores).toFixed(1) }} 分,共 {{ parseFloat(schemeMap[subject].subtotalScore).toFixed(1) }} 分)
|
||
</span>
|
||
</h4>
|
||
|
||
|
||
|
||
<el-card
|
||
v-for="(item, index) in items"
|
||
:key="item.quId"
|
||
class="mb-3"
|
||
shadow="never"
|
||
>
|
||
<div class="text-gray-500 mb-2">题目 {{ index + 1 }}</div>
|
||
<div v-html="item.content" class="mb-2"></div>
|
||
|
||
<!-- 🎯 判断是否为编程题 -->
|
||
<div v-if="item.subjectName === '编程题'">
|
||
<!-- 编程题解析 -->
|
||
<div class="mt-2">
|
||
<div class="font-bold text-blue-600">答案</div>
|
||
<pre
|
||
style="background-color: #f5f5f5; padding: 10px; border-radius: 4px; overflow-x: auto;"
|
||
>{{ item.analysis }}</pre>
|
||
</div>
|
||
<!-- <div
|
||
v-for="(answer, aIndex) in item.answerList"
|
||
:key="answer.answerId"
|
||
class="mb-1"
|
||
>
|
||
测试用例 {{ aIndex + 1 }}:输入: {{ answer.contentIn }} | 输出: {{ answer.content }} | 占比: {{ answer.scoreRate }}
|
||
</div> -->
|
||
</div>
|
||
|
||
<!-- 📝 普通题目的选项显示 -->
|
||
<div v-else-if="item.subjectName === '选择题'">
|
||
<div
|
||
v-for="(answer, aIndex) in item.answerList.slice().sort((a, b) => a.sort - b.sort)"
|
||
:key="answer.answerId"
|
||
:style="{
|
||
color: answer.isRight === '0' ? 'green' : 'inherit',
|
||
fontWeight: answer.isRight === '0' ? 'bold' : 'normal'
|
||
}"
|
||
class="mb-1"
|
||
>
|
||
{{ String.fromCharCode(65 + aIndex) }}. {{ answer.content }}
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</div>
|
||
</div>
|
||
|
||
<template #footer>
|
||
<el-button @click="handleCancel">取消</el-button>
|
||
|
||
</template>
|
||
</Dialog>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, nextTick, computed } from 'vue';
|
||
import { useFormData } from '@/utils/use-form-data';
|
||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||
const message = useMessage(); // 消息弹窗
|
||
|
||
const props = defineProps({
|
||
paperId: String // 接收父组件传来的 paperId
|
||
});
|
||
|
||
const emit = defineEmits(['done']);
|
||
const visible = defineModel({ type: Boolean });
|
||
const loading = ref(false);
|
||
const formRef = ref(null);
|
||
const questionList = ref([]); // 用于存放试题列表
|
||
const schemeMap = ref({});
|
||
|
||
const [form, resetFields, assignFields] = useFormData({
|
||
paperId: void 0,
|
||
taskId: '',
|
||
counts: '',
|
||
rollUp: '',
|
||
isAb: '',
|
||
status: ''
|
||
});
|
||
|
||
const rules = reactive({});
|
||
|
||
const handleCancel = () => {
|
||
visible.value = false;
|
||
};
|
||
|
||
const groupedQuestions = ref({});
|
||
|
||
const subjectPriority = {
|
||
'选择题': 1,
|
||
'多选题': 2,
|
||
'判断题': 3,
|
||
'编程题': 4,
|
||
'其他': 5
|
||
};
|
||
|
||
// 根据试题的类型进行分组
|
||
const groupBySubjectName = (list) => {
|
||
const group = {};
|
||
list.forEach((item) => {
|
||
const subject = item.subjectName || '其他'; // 默认为'其他'
|
||
if (!group[subject]) {
|
||
group[subject] = [];
|
||
}
|
||
group[subject].push(item);
|
||
});
|
||
groupedQuestions.value = group;
|
||
};
|
||
|
||
// 按题型排序
|
||
const sortedGroupedQuestions = computed(() => {
|
||
return Object.keys(groupedQuestions.value)
|
||
.sort((a, b) => (subjectPriority[a] || subjectPriority['其他']) - (subjectPriority[b] || subjectPriority['其他']))
|
||
.reduce((acc, subject) => {
|
||
acc[subject] = groupedQuestions.value[subject];
|
||
return acc;
|
||
}, {});
|
||
});
|
||
|
||
// 打开弹窗时的处理逻辑
|
||
const handleOpen = (type, paperId) => {
|
||
resetFields();
|
||
questionList.value = [];
|
||
console.log(paperId+"paperIdpaperId")
|
||
if (props.paperId) {
|
||
loading.value = true;
|
||
getPaperDetailByTaskId(props.paperId)
|
||
.then((res) => {
|
||
const { educationPaperSchemeList, examQuestionList } = res || {};
|
||
if (Array.isArray(examQuestionList)) {
|
||
questionList.value = examQuestionList;
|
||
groupBySubjectName(examQuestionList); // 分类
|
||
}
|
||
|
||
if (Array.isArray(educationPaperSchemeList)) {
|
||
// 构建以题型名为 key 的映射表(spName 与 scheme 对应)
|
||
schemeMap.value = educationPaperSchemeList.reduce((acc, item) => {
|
||
acc[item.spName] = item;
|
||
return acc;
|
||
}, {});
|
||
}
|
||
assignFields(res);
|
||
})
|
||
.catch((e) => {
|
||
message.error(`获取试卷详情失败: ${e.message}`);
|
||
})
|
||
.finally(() => {
|
||
loading.value = false;
|
||
nextTick(() => {
|
||
formRef.value?.clearValidate?.();
|
||
});
|
||
});
|
||
}
|
||
};
|
||
|
||
</script>
|
||
|