YNUtdPlatform/pages/YNEduApp/exam/examinationResultDetails.vue

580 lines
17 KiB
Vue
Raw Normal View History

2024-08-14 18:55:18 +08:00
<template>
<view>
2024-11-27 17:00:00 +08:00
<div class="content" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd">
2024-08-14 18:55:18 +08:00
<div class="top-content">
<div class="top-wrapper">
<div class="all" :class="{ isAllActive: isActive !== 1 }" @click="handleTab(1)">全部</div>
<div :class="{ isTopActive: isActive == 2 }" @click="handleTab(2)">正确{{ rightCount }}</div>
<div :class="{ isTopActive: isActive == 3 }" @click="handleTab(3)">错误{{ wrongCount }}</div>
<div :class="{ isTopActive: isActive == 4 }" @click="handleTab(4)">未答{{ unAnsweredCount }}</div>
<div>
<span style="color: #1989fa">{{ currentIndex + 1 }}</span>
/{{ list.length }}
</div>
</div>
<div class="center-wrapper">
<div class="answer-wrapper">
<div
class="item-wrapper"
v-for="(item, index) in list"
:key="index"
v-show="item.isShow"
@click="handleQuestionNumber(item, index)"
>
<div
class="answer-item"
:class="{ currentBg: currentIndex == index, rightBg: item.isRight, wrongBg: item.isWrong }"
>
{{ index + 1 }}
</div>
</div>
</div>
<div class="unfold" @click="handleUnfold">
{{ isRotating ? '收起' : '展开' }}
<u-icon v-if="!this.isRotating" name="arrow-down-fill" size="10" />
<u-icon v-else name="arrow-up-fill" size="10" />
</div>
</div>
</div>
<!-- 题目 -->
<div class="question-wrapper" v-for="(item, index) in list" :key="index" v-show="index == currentIndex">
<div class="question-type-wrapper">
<div class="line" />
<div class="question-type">
2024-08-23 16:00:43 +08:00
<div v-if="item.examType == 1">单选题{{ item.questionScore }}</div>
<div v-if="item.examType == 2">多选题{{ item.questionScore }}</div>
<div v-if="item.examType == 3">判断题{{ item.questionScore }}</div>
2024-08-14 18:55:18 +08:00
</div>
</div>
2024-08-23 16:00:43 +08:00
<div class="question">{{ currentIndex + 1 }}. {{ item.examTopic }}</div>
2024-11-27 17:00:00 +08:00
<u-image
v-if="item.examTopicUrl"
:showLoading="true"
:src="fileUrl + item.examTopicUrl || ''"
width="60px"
height="60px"
style="margin-bottom: 10px"
@click="clickImg(fileUrl + item.examTopicUrl)"
/>
2024-08-14 18:55:18 +08:00
<div class="options">
2024-11-27 17:00:00 +08:00
<div class="option-wrapper" v-for="(option, optionIndex) in item.listOption" :key="optionIndex">
<div class="option" :class="{ isRight: option.isRight, isError: option.isError }">
<div class="option-item">{{ option.optionIdent }}.</div>
<div class="option-content">
<div>{{ option.optionContent }}</div>
<u-icon v-if="option.isRight" name="/static/images/correct.png" />
<u-icon v-if="option.isError" name="/static/images/error.png" />
</div>
2024-08-14 18:55:18 +08:00
</div>
2024-11-27 17:00:00 +08:00
<u--image
v-if="option.optionUrl"
:showLoading="true"
:src="fileUrl + option.optionUrl || ''"
width="60px"
height="60px"
style="margin-bottom: 10px"
@click="clickImg(fileUrl + option.optionUrl)"
/>
2024-08-14 18:55:18 +08:00
</div>
</div>
</div>
<div v-for="(item, index) in list" v-show="index == currentIndex" style="margin-top: 30px; font-size: 12px">
<div v-if="item.isRight" style="color: #48d66b">回答正确</div>
<div v-else-if="item.isWrong" style="color: #fa4f19">回答错误</div>
<div v-else-if="item.isUnAnswered" style="color: #656565">未选择</div>
<div class="select-wrapper">
<div class="select-item">
<div>正确选择</div>
2024-08-23 16:00:43 +08:00
<div v-if="item.examType == 1 || item.examType == 3" style="color: #48d66b">
{{ item.correctGrade || '' }}
</div>
<div v-else style="color: #48d66b" class="grade">
<div v-for="(grade, gradeIndex) in item.correctGrade.split('')" :key="gradeIndex">
{{ grade }}{{ gradeIndex + 1 == item.correctGrade.split('').length ? '' : ',&nbsp;' }}
</div>
</div>
2024-08-14 18:55:18 +08:00
</div>
<div class="select-item" v-show="!item.isUnAnswered">
<div>你的选择</div>
2024-08-23 16:00:43 +08:00
<div
v-if="item.examType == 1 || item.examType == 3"
:style="{ color: item.isRight ? '#48d66b' : '#fa4f19' }"
>
{{ item.selectAnswer || '' }}
</div>
<div v-else :style="{ color: item.isRight ? '#48d66b' : '#fa4f19' }" class="grade">
<div v-if="item.selectAnswer">
2024-09-03 16:07:30 +08:00
<span v-for="(grade, gradeIndex) in item.selectAnswer.split('')" :key="gradeIndex">
2024-08-23 16:00:43 +08:00
{{ grade }}{{ gradeIndex + 1 == item.selectAnswer.split('').length ? '' : ',&nbsp;' }}
2024-09-03 16:07:30 +08:00
</span>
2024-08-23 16:00:43 +08:00
</div>
2024-08-14 18:55:18 +08:00
</div>
</div>
</div>
2024-08-23 16:00:43 +08:00
<div class="analysis">
2024-08-27 14:03:52 +08:00
<u-icon name="/static/images/analysis.png" style="margin-right: 5px" />
2024-08-23 16:00:43 +08:00
解析
</div>
<div class="analysis-item">{{ item.examAnaly }}</div>
</div>
<!-- 底部按钮 -->
<div class="bottom-btn">
<div class="btn" v-show="currentIndex != 0">
<u-button size="small" shape="circle" text="上一题" @click="currentIndex--" />
</div>
2024-09-03 16:07:30 +08:00
<div class="btn" v-if="currentIndex !== list.length - 1">
2024-08-23 16:00:43 +08:00
<u-button type="primary" size="small" shape="circle" text="下一题" @click="currentIndex++" />
</div>
2024-08-14 18:55:18 +08:00
</div>
</div>
</view>
</template>
<script>
2024-08-23 16:00:43 +08:00
import { getExamRecordAnswer } from '@/api/eduApp'
2024-08-28 09:51:05 +08:00
import config from '@/config'
2024-08-23 16:00:43 +08:00
2024-08-14 18:55:18 +08:00
export default {
data() {
return {
2024-08-23 16:00:43 +08:00
examId: '', // 考试id
recordId: '', // 考试记录id
2024-08-14 18:55:18 +08:00
isActive: 1,
isRotating: false,
currentIndex: 0,
// 正确
rightCount: 0,
// 错误
wrongCount: 0,
// 未答
unAnsweredCount: 0,
// 问题列表
2024-08-23 16:00:43 +08:00
questionList: [],
2024-11-27 17:00:00 +08:00
fileUrl: config.fileUrl,
2024-08-14 18:55:18 +08:00
rightList: [],
// 错误列表
wrongList: [],
// 未答列表
unAnsweredList: [],
2024-11-27 17:00:00 +08:00
list: [],
startX: 0, // 起始触摸点X坐标
endX: 0 // 结束触摸点X坐标
2024-08-14 18:55:18 +08:00
}
},
2024-08-23 16:00:43 +08:00
onLoad(opt) {
opt = JSON.parse(opt.params)
console.log('🚀 ~ onLoad ~ opt-结果详情:', opt)
this.examId = opt.examId
this.recordId = opt.recordId
},
2024-08-14 18:55:18 +08:00
mounted() {
this.getList()
},
methods: {
2024-08-30 19:04:00 +08:00
getList() {
2024-08-23 16:00:43 +08:00
const params = {
examId: this.examId,
recordId: this.recordId
}
2024-08-28 09:51:05 +08:00
// const res = await getExamRecordAnswer(params)
// this.questionList = res.data.examPaperData
2024-09-06 14:53:49 +08:00
this.$verificationToken()
2024-08-28 09:51:05 +08:00
uni.request({
url: config.baseUrl + '/exam-student/studentExam/getExamRecordAnswer',
method: 'post',
data: params,
header: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: uni.getStorageSync('access_token')
},
success: res => {
res = res.data
2024-08-30 19:04:00 +08:00
console.log('🚀 ~ getList ~ res:', res.data.examPaperData)
if (res.code != 200) {
uni.showToast({
title: res.msg,
icon: 'none'
2024-08-14 18:55:18 +08:00
})
2024-08-30 19:04:00 +08:00
return
2024-08-14 18:55:18 +08:00
}
2024-08-30 19:04:00 +08:00
this.questionList = res.data.examPaperData
this.list = this.questionList
this.list.forEach((item, index) => {
if (index < 7) {
item.isShow = true
2024-08-14 18:55:18 +08:00
} else {
2024-08-30 19:04:00 +08:00
item.isShow = false
2024-08-14 18:55:18 +08:00
}
2024-08-30 19:04:00 +08:00
})
console.log('🚀 ~ getList ~ res:', res)
this.questionList.forEach((item, index) => {
if (item.examType === 1 || item.examType === 3) {
if (!item.selectAnswer) {
this.unAnsweredCount++
item.isUnAnswered = true
// 添加正确背景色
item.listOption.forEach(option => {
option.isRight = option.optionIdent === item.correctGrade
})
} else {
2024-09-14 18:12:16 +08:00
if (item.selectAnswer == '对' || item.selectAnswer == '错') {
item.selectAnswer = item.selectAnswer === '对' ? 'A' : 'B'
}
2024-08-30 19:04:00 +08:00
if (item.correctGrade === item.selectAnswer) {
this.rightCount++
// 添加正确背景色
item.isRight = true
item.listOption.forEach(option => {
option.isRight = option.optionIdent === item.correctGrade
})
} else {
this.wrongCount++
// 添加错误背景色
item.isWrong = true
item.listOption.forEach(option => {
option.isError = option.optionIdent === item.selectAnswer
if (option.optionIdent === item.correctGrade) {
option.isRight = true
}
})
}
2024-08-23 16:00:43 +08:00
}
2024-08-30 19:04:00 +08:00
} else {
if (!item.selectAnswer) {
this.unAnsweredCount++
item.isUnAnswered = true
// 添加正确背景色
item.listOption.forEach(option => {
option.isRight = item.correctGrade.includes(option.optionIdent)
})
} else {
if (item.correctGrade.toString() === item.selectAnswer.toString()) {
this.rightCount++
// 添加正确背景色
item.isRight = true
} else {
this.wrongCount++
// 添加错误背景色
item.isWrong = true
}
item.listOption.forEach(option => {
if (item.correctGrade.includes(option.optionIdent)) {
option.isRight = true
}
if (item.selectAnswer.includes(option.optionIdent)) {
option.isError = true
}
if (option.isRight && option.isError) {
option.isError = false
}
})
2024-08-23 16:00:43 +08:00
}
2024-08-30 19:04:00 +08:00
}
})
this.rightList = this.questionList.filter(item => item.isRight)
this.wrongList = this.questionList.filter(item => item.isWrong)
this.unAnsweredList = this.questionList.filter(item => item.isUnAnswered)
},
fail: err => {
console.log(err)
2024-08-14 18:55:18 +08:00
}
})
},
handleTab(index) {
console.log('🚀 ~ handleTab ~ index:', index)
this.isActive = index
2024-08-23 16:00:43 +08:00
this.currentIndex = 0
2024-08-14 18:55:18 +08:00
if (index === 1) {
this.list = this.questionList
} else if (index === 2) {
this.list = this.rightList
} else if (index === 3) {
this.list = this.wrongList
} else if (index === 4) {
this.list = this.unAnsweredList
}
this.list.forEach((item, index) => {
if (index < 7) {
item.isShow = true
} else {
item.isShow = false
}
})
},
handleUnfold() {
this.isRotating = !this.isRotating
this.list.forEach((item, index) => {
if (index >= 7) {
item.isShow = this.isRotating
}
})
},
handleQuestionNumber(item, index) {
this.currentIndex = index
this.list.forEach(element => {
element.isActive = false
})
item.isActive = true
2024-11-27 17:00:00 +08:00
},
clickImg(url) {
this.isHide = true
uni.previewImage({
urls: [url]
})
// this.screenCount--
},
touchStart(event) {
this.startX = 0
this.endX = 0
console.log('🚀 ~ 开始 ~ event:', event)
// 记录触摸开始的位置
this.startX = event.touches[0].clientX
console.log('🚀 ~ touchStart ~ this.startX:', this.startX)
},
touchMove(event) {
console.log('🚀 ~ 移动 ~ event:', event)
// 在触摸过程中可以获取当前触摸点位置
this.endX = event.touches[0].clientX
console.log('🚀 ~ touchMove ~ this.endX:', this.endX)
},
touchEnd() {
// 判断滑动方向
if (this.startX != 0 && this.endX != 0 && this.startX - this.endX > 10) {
// 左滑
console.log('向左滑动')
this.currentIndex++
} else if (this.startX != 0 && this.endX != 0 && this.endX - this.startX > 10) {
// 右滑
console.log('向右滑动')
this.currentIndex--
}
if (this.currentIndex < 0) {
this.currentIndex = 0
} else if (this.currentIndex > this.questionList.length - 1) {
this.currentIndex = this.questionList.length - 1
}
2024-08-14 18:55:18 +08:00
}
}
}
</script>
<style lang="scss" scoped>
.content {
padding: 10px;
.top-content {
background: #fff;
padding: 10px;
border-radius: 5px;
}
.top-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 13px;
color: #333;
.isTopActive {
color: #1989fa;
}
.all {
box-sizing: border-box;
width: 40px;
height: 40px;
background: #1989fa;
border-radius: 50%;
color: #fff;
text-align: center;
line-height: 40px;
&.isAllActive {
background: #fff;
color: #333;
border: 1px solid #1989fa;
}
}
}
.center-wrapper {
display: flex;
justify-content: space-between;
.unfold {
height: 50px;
line-height: 50px;
text-align: center;
display: flex;
justify-content: center;
}
.answer-wrapper {
width: 86%;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
.item-wrapper {
padding: 5px 5px 0 0;
width: 12%;
height: 45px;
display: flex;
justify-content: center;
align-items: center;
.answer-item {
width: 33px;
height: 33px;
line-height: 33px;
text-align: center;
border-radius: 5px;
background: #f4f9fe;
color: #333;
}
// 正确背景色
.rightBg {
background: #eaf8ed;
}
// 错误背景色
.wrongBg {
background: #fcefe9;
}
.currentBg {
background: #1989fa;
}
}
}
}
.question-wrapper {
.question-type-wrapper {
margin: 20px 0;
display: flex;
justify-content: flex-start;
align-items: center;
.line {
width: 2px;
height: 11px;
background: #1989fa;
margin-right: 3px;
}
.question-type {
color: #8a8a8a;
}
}
.question {
font-weight: 800;
font-size: 15px;
color: #333333;
}
}
.options {
margin-top: 10px;
2024-11-27 17:00:00 +08:00
option-wrapper {
max-height: 500px;
overflow: auto;
}
2024-08-14 18:55:18 +08:00
.option {
display: flex;
justify-content: flex-start;
align-items: center;
margin-top: 10px;
2024-11-27 17:00:00 +08:00
margin-bottom: 5px;
2024-08-14 18:55:18 +08:00
background: #f4f9fe;
border-radius: 5px;
&.isRight {
background: #eaf8ed;
}
&.isError {
background: #fcefe9;
}
.option-item {
width: 33px;
height: 33px;
line-height: 33px;
text-align: center;
color: #333;
}
.option-content {
width: calc(100% - 60px);
margin-left: 10px;
color: #333;
display: flex;
justify-content: space-between;
}
}
}
.select-wrapper {
display: flex;
justify-content: space-between;
margin-top: 10px;
.select-item {
width: 48%;
height: 60px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #646464;
background: #edf2f7;
border-radius: 5px;
2024-08-23 16:00:43 +08:00
.grade {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
margin-right: 3px;
}
2024-08-14 18:55:18 +08:00
}
}
.analysis {
margin: 10px 0;
font-size: 14px;
color: #333333;
font-weight: 800;
2024-08-15 17:47:52 +08:00
display: flex;
justify-content: flex-start;
2024-08-14 18:55:18 +08:00
}
.analysis-item {
2024-08-23 16:00:43 +08:00
margin-bottom: 100px;
height: 80px;
2024-08-14 18:55:18 +08:00
background: #edf2f7;
border-radius: 5px;
padding: 10px;
font-size: 12px;
color: #656565;
2024-08-23 16:00:43 +08:00
overflow: auto;
}
.bottom-btn {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
padding: 15px 0;
display: flex;
justify-content: flex-end;
align-items: center;
.btn {
width: 100px;
margin-right: 10px;
}
2024-08-14 18:55:18 +08:00
}
}
</style>