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