<template>
|
|
<el-dialog title="考核信息" :visible="dialogVisible" @close="handleClose" width="60%" append-to-body>
|
|
<div v-loading="loading">
|
|
<el-tabs v-model="activeTab">
|
|
<!-- <el-tab-pane label="基本信息" name="basic">
|
|
<el-descriptions :column="2" border>
|
|
<el-descriptions-item label="姓名">{{ examInfo.name }}</el-descriptions-item>
|
|
<el-descriptions-item label="手机号">{{ examInfo.phone }}</el-descriptions-item>
|
|
<el-descriptions-item label="身份证">{{ examInfo.idCard }}</el-descriptions-item>
|
|
<el-descriptions-item label="提交时间">{{ examInfo.createTime }}</el-descriptions-item>
|
|
</el-descriptions>
|
|
</el-tab-pane> -->
|
|
|
|
<el-tab-pane label="基本考核" name="base">
|
|
<div v-for="(question, index) in examInfo.answerList.filter(n => n.type != '培训')" :key="index" class="question-item">
|
|
<div class="question-title">
|
|
<span class="question-index">{{ index + 1 }}.</span>
|
|
<span class="question-type">[{{ question.type === '培训' ? '填空题' : '选择题' }}]</span>
|
|
<span v-if="!isQuestionAnswered(question)" class="unanswered-tag">未答题</span>
|
|
<span class="question-content">{{ question.title }}</span>
|
|
</div>
|
|
|
|
<!-- 填空题答案 -->
|
|
<template v-if="question.type === '培训'">
|
|
<div class="answer-content">
|
|
<div class="answer-label">答案:</div>
|
|
<div class="answer-text" :class="{ 'no-answer': !isQuestionAnswered(question) }">
|
|
{{ question.userAppletAnswerTrain && question.userAppletAnswerTrain.answer || '暂无答案' }}
|
|
</div>
|
|
<div class="answer-requirement">最少字数要求:{{ question.numberWords }}</div>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- 选择题答案 -->
|
|
<template v-else>
|
|
<div v-if="!isQuestionAnswered(question)" class="no-answer-tip">
|
|
<i class="el-icon-warning"></i>
|
|
该题目尚未作答
|
|
</div>
|
|
<div v-else class="options-list">
|
|
<div v-for="option in question.answerList" :key="option.orderNo"
|
|
:class="['option-item', {
|
|
'correct': option.isTrue,
|
|
'selected': isOptionSelected(question, option.id),
|
|
'wrong-selected': isOptionSelected(question, option.id) && !option.isTrue
|
|
}]">
|
|
<span class="option-label">{{ String.fromCharCode(64 + option.orderNo) }}.</span>
|
|
<span class="option-content">{{ option.title }}</span>
|
|
<span v-if="option.isTrue" class="correct-tag">正确答案</span>
|
|
<span v-if="isOptionSelected(question, option.id)"
|
|
:class="['selected-tag', { 'wrong-tag': !option.isTrue }]">
|
|
{{ option.isTrue ? '已选择' : '错误选择' }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="answer-result" :class="{ 'correct': isAnswerCorrect(question), 'wrong': !isAnswerCorrect(question) }">
|
|
<i :class="['el-icon-' + (isAnswerCorrect(question) ? 'success' : 'error')]"></i>
|
|
{{ isAnswerCorrect(question) ? '回答正确' : '回答错误' }}
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</el-tab-pane>
|
|
<el-tab-pane label="培训考核" name="answers">
|
|
<div v-for="(question, index) in examInfo.answerList.filter(n => n.type == '培训')" :key="index" class="question-item">
|
|
<div class="question-title">
|
|
<span class="question-index">{{ index + 1 }}.</span>
|
|
<span class="question-type">[{{ question.type === '培训' ? '填空题' : '选择题' }}]</span>
|
|
<span v-if="!isQuestionAnswered(question)" class="unanswered-tag">未答题</span>
|
|
<span class="question-content">{{ question.title }}</span>
|
|
</div>
|
|
|
|
<!-- 填空题答案 -->
|
|
<template v-if="question.type === '培训'">
|
|
<div class="answer-content">
|
|
<div class="answer-label">答案:</div>
|
|
<div class="answer-text" :class="{ 'no-answer': !isQuestionAnswered(question) }">
|
|
{{ question.userAppletAnswerTrain && question.userAppletAnswerTrain.answer || '暂无答案' }}
|
|
</div>
|
|
<div class="answer-requirement">最少字数要求:{{ question.numberWords }}</div>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- 选择题答案 -->
|
|
<template v-else>
|
|
<div v-if="!isQuestionAnswered(question)" class="no-answer-tip">
|
|
<i class="el-icon-warning"></i>
|
|
该题目尚未作答
|
|
</div>
|
|
<div v-else class="options-list">
|
|
<div v-for="option in question.answerList" :key="option.orderNo"
|
|
:class="['option-item', {
|
|
'correct': option.isTrue,
|
|
'selected': isOptionSelected(question, option.id),
|
|
'wrong-selected': isOptionSelected(question, option.id) && !option.isTrue
|
|
}]">
|
|
<span class="option-label">{{ String.fromCharCode(64 + option.orderNo) }}.</span>
|
|
<span class="option-content">{{ option.title }}</span>
|
|
<span v-if="option.isTrue" class="correct-tag">正确答案</span>
|
|
<span v-if="isOptionSelected(question, option.id)"
|
|
:class="['selected-tag', { 'wrong-tag': !option.isTrue }]">
|
|
{{ option.isTrue ? '已选择' : '错误选择' }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="answer-result" :class="{ 'correct': isAnswerCorrect(question), 'wrong': !isAnswerCorrect(question) }">
|
|
<i :class="['el-icon-' + (isAnswerCorrect(question) ? 'success' : 'error')]"></i>
|
|
{{ isAnswerCorrect(question) ? '回答正确' : '回答错误' }}
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
</div>
|
|
<div slot="footer" class="dialog-footer">
|
|
<el-button @click="handleClose">关 闭</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script>
|
|
import { getAppletUsersTeacher } from "@/api/model/AppletUsersTeacher";
|
|
|
|
export default {
|
|
name: "ExamInfo",
|
|
props: {
|
|
visible: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
userId: {
|
|
type: [String, Number],
|
|
default: null
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
loading: false,
|
|
activeTab: 'base',
|
|
// examInfo: {
|
|
// name: '姓名',
|
|
// phone: '手机号',
|
|
// idCard: '身份证',
|
|
// createTime: '提交时间',
|
|
// answerList: [
|
|
// {
|
|
// title: '题目',
|
|
// type: '类型',
|
|
// userAnswer: '用户选择或者填写的答案',
|
|
// numberWords: '最少字数',
|
|
// answerList: [
|
|
// {
|
|
// title: '选项',
|
|
// isTrue: '是否正确',
|
|
// orderNo: '排序'
|
|
// }
|
|
// ]
|
|
// }
|
|
// ]
|
|
// },
|
|
examInfo: {
|
|
name: '',
|
|
phone: '',
|
|
idCard: '',
|
|
createTime: '',
|
|
answerList: []
|
|
},
|
|
};
|
|
},
|
|
watch: {
|
|
visible(val) {
|
|
if (val && this.userId) {
|
|
this.getExamInfo();
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
getExamInfo() {
|
|
this.loading = true;
|
|
getAppletUsersTeacher(this.userId).then(response => {
|
|
this.examInfo = response.data;
|
|
this.loading = false;
|
|
}).catch(() => {
|
|
this.loading = false;
|
|
});
|
|
},
|
|
handleClose() {
|
|
this.$emit('update:visible', false);
|
|
},
|
|
// 判断选项是否被选中
|
|
isOptionSelected(question, optionId) {
|
|
if (!question.userAnswerBaseList || !question.userAnswerBaseList.length) return false;
|
|
return question.userAnswerBaseList.some(answer => answer.answerId === optionId);
|
|
},
|
|
// 判断答案是否正确
|
|
isAnswerCorrect(question) {
|
|
if (!question.userAnswerBaseList || !question.userAnswerBaseList.length) return false;
|
|
|
|
// 获取所有正确答案的ID
|
|
const correctOptionIds = question.answerList
|
|
.filter(option => option.isTrue)
|
|
.map(option => option.id);
|
|
|
|
// 获取用户选择的答案ID
|
|
const userAnswerIds = [...new Set(question.userAnswerBaseList.map(answer => answer.answerId))];
|
|
|
|
// 判断用户选择的答案数量是否与正确答案数量相同
|
|
if (userAnswerIds.length !== correctOptionIds.length) {
|
|
return false;
|
|
}
|
|
|
|
// 判断用户选择的答案是否都是正确的
|
|
return userAnswerIds.every(answerId => correctOptionIds.includes(answerId));
|
|
},
|
|
isQuestionAnswered(question) {
|
|
if (question.type === '培训') {
|
|
// 填空题:检查是否有答案且答案不为空
|
|
return question.userAppletAnswerTrain &&
|
|
question.userAppletAnswerTrain.answer &&
|
|
question.userAppletAnswerTrain.answer.trim() !== '';
|
|
} else {
|
|
// 选择题:检查是否有选择的答案
|
|
return question.userAnswerBaseList && question.userAnswerBaseList.length > 0;
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
dialogVisible() {
|
|
return this.visible;
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.question-item {
|
|
margin-bottom: 20px;
|
|
padding: 15px;
|
|
background: #f8f9fa;
|
|
border-radius: 4px;
|
|
|
|
.question-title {
|
|
margin-bottom: 15px;
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
|
|
.question-index {
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.question-type {
|
|
color: #409EFF;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.unanswered-tag {
|
|
background: #f56c6c;
|
|
color: #fff;
|
|
font-size: 12px;
|
|
padding: 2px 6px;
|
|
border-radius: 2px;
|
|
margin-right: 8px;
|
|
}
|
|
}
|
|
|
|
.answer-content {
|
|
padding: 10px;
|
|
background: #fff;
|
|
border-radius: 4px;
|
|
|
|
.answer-label {
|
|
font-weight: bold;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.answer-text {
|
|
margin-bottom: 8px;
|
|
line-height: 1.5;
|
|
|
|
&.no-answer {
|
|
color: #909399;
|
|
}
|
|
}
|
|
|
|
.answer-requirement {
|
|
color: #909399;
|
|
font-size: 13px;
|
|
}
|
|
}
|
|
|
|
.options-list {
|
|
.option-item {
|
|
padding: 10px;
|
|
margin-bottom: 8px;
|
|
background: #fff;
|
|
border-radius: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
&.correct {
|
|
background: #f0f9eb;
|
|
}
|
|
|
|
&.selected {
|
|
background: #ecf5ff;
|
|
}
|
|
|
|
&.wrong-selected {
|
|
background: #fef0f0;
|
|
}
|
|
|
|
.option-label {
|
|
font-weight: bold;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.option-content {
|
|
flex: 1;
|
|
}
|
|
|
|
.correct-tag {
|
|
color: #67c23a;
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.selected-tag {
|
|
color: #409EFF;
|
|
margin-left: 10px;
|
|
|
|
&.wrong-tag {
|
|
color: #f56c6c;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.answer-result {
|
|
margin-top: 10px;
|
|
padding: 8px 12px;
|
|
border-radius: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
font-weight: bold;
|
|
|
|
&.correct {
|
|
background: #f0f9eb;
|
|
color: #67c23a;
|
|
}
|
|
|
|
&.wrong {
|
|
background: #fef0f0;
|
|
color: #f56c6c;
|
|
}
|
|
|
|
i {
|
|
margin-right: 8px;
|
|
font-size: 16px;
|
|
}
|
|
}
|
|
|
|
.no-answer-tip {
|
|
margin-bottom: 10px;
|
|
padding: 8px 12px;
|
|
background: #fff;
|
|
border-radius: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 14px;
|
|
color: #909399;
|
|
|
|
i {
|
|
margin-right: 8px;
|
|
font-size: 16px;
|
|
}
|
|
}
|
|
}
|
|
</style>
|