猫妈狗爸伴宠师小程序后端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

376 lines
14 KiB

<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>