YNUtdPlatform/pages/YNEduApp/exam/examination.vue

568 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<u-navbar leftIcon="" title="考试" :placeholder="true" />
<div class="content">
<div class="top-content">
<div class="top-wrapper">
<div class="time">
<div>距离考试结束</div>
<div>
<u-count-down
class="count-down"
ref="countDown"
:autoStart="false"
:time="time"
@change="changeCountDown"
/>
</div>
</div>
<div>
<span style="color: #1989fa">{{ currentIndex + 1 }}</span>
/{{ questionList.length }}
</div>
</div>
<div class="center-wrapper">
<div class="answer-wrapper">
<div
class="item-wrapper"
v-for="(item, index) in questionList"
:key="index"
v-show="item.isShow"
@click="handleQuestionNumber(item, index)"
>
<div class="answer-item" :class="{ isActive: item.isActive }">{{ 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 questionList" :key="index" v-show="index == currentIndex">
<div class="question-type-wrapper">
<div class="line" />
<div class="question-type">
<div v-if="item.type == 1">单选题({{ item.score }}分)</div>
<div v-if="item.type == 2">多选题({{ item.score }}分)</div>
<div v-if="item.type == 3">判断题({{ item.score }}分)</div>
</div>
</div>
<div class="question">{{ currentIndex + 1 }}. {{ item.question }}</div>
<div class="options">
<div
class="option"
v-for="(option, optionIndex) in item.options"
:key="optionIndex"
:class="{ isActive: option.isActive }"
@click="handleSelectOption(item, index, option, optionIndex)"
>
<div class="option-item">{{ option.value }}.</div>
<div class="option-content">{{ option.label }}</div>
</div>
</div>
</div>
<!-- 底部按钮 -->
<div class="bottom-btn">
<div class="btn" v-show="currentIndex != 0">
<u-button size="small" shape="circle" text="上一题" @click="currentIndex--" />
</div>
<div class="btn" v-if="currentIndex !== questionList.length - 1">
<u-button type="primary" size="small" shape="circle" text="下一题" @click="currentIndex++" />
</div>
<div class="btn" v-else>
<u-button type="primary" size="small" shape="circle" text="交 卷" @click="openConfirmModal" />
</div>
</div>
</div>
<!-- 提交弹框 -->
<u-modal
:show="showConfirmModal"
title="提示"
showCancelButton
@cancel="showConfirmModal = false"
@confirm="handleConfirmSubmit"
>
<view class="slot-content">
<view v-if="unDoCount > 0">
本场考试还有
<span style="color: #1989fa; margin: 0 5px">{{ unDoCount }}</span>
题尚未完成
</view>
<view style="text-align: center">确定交卷?</view>
</view>
</u-modal>
<u-toast ref="uToast"></u-toast>
</view>
</template>
<script>
import face from '@/uni_modules/mcc-face/index.js'
export default {
data() {
return {
// 切屏次数
screenCount: 0,
showConfirmModal: false,
time: 30 * 60 * 1000,
random1: 0,
random2: 0,
// 答题时间
answerTime: 0,
currentIndex: 0,
// 是否展开
isRotating: false,
// 是否结束
isEnd: false,
// 未做题目数
unDoCount: 0,
// 答题卡
answerCard: [],
// 题目列表
questionList: [
{
id: 1,
// 题目类型
type: 1, // 1: 单选题, 2: 多选题, 3: 判断题
// 分数
score: 2,
// 题目
question: '送配电线路架设工的主要工作是?',
// 选项
options: [
{ label: '电力设备的安装、调试、维护和检修', value: 'A' },
{ label: '电力设备的安装、调试、维护和检修', value: 'B' },
{ label: '电力设备的安装、调试、维护和检修', value: 'C' },
{ label: '电力设备的安装、调试、维护和检修', value: 'D' }
]
},
{
id: 2,
type: 2,
score: 2,
question: '送配电线路架设工的主要工作是?',
options: [
{ label: '电力设备的安装、调试、维护和检修', value: 'A' },
{ label: '电力设备的安装、调试、维护和检修', value: 'B' },
{ label: '电力设备的安装、调试、维护和检修', value: 'C' },
{ label: '电力设备的安装、调试、维护和检修', value: 'D' }
]
},
{
id: 3,
type: 3,
score: 2,
question: '送配电线路架设工的主要工作是: 好好工作?',
options: [
{ label: '对', value: 'A' },
{ label: '错', value: 'B' }
]
},
{
id: 11,
// 题目类型
type: 1, // 1: 单选题, 2: 多选题, 3: 判断题
// 分数
score: 2,
// 题目
question: '送配电线路架设工的主要工作是?',
// 选项
options: [
{ label: '电力设备的安装、调试、维护和检修', value: 'A' },
{ label: '电力设备的安装、调试、维护和检修', value: 'B' },
{ label: '电力设备的安装、调试、维护和检修', value: 'C' },
{ label: '电力设备的安装、调试、维护和检修', value: 'D' }
]
},
{
id: 21,
type: 2,
score: 2,
question: '送配电线路架设工的主要工作是?',
options: [
{ label: '电力设备的安装、调试、维护和检修', value: 'A' },
{ label: '电力设备的安装、调试、维护和检修', value: 'B' },
{ label: '电力设备的安装、调试、维护和检修', value: 'C' },
{ label: '电力设备的安装、调试、维护和检修', value: 'D' }
]
},
{
id: 31,
type: 3,
score: 2,
question: '送配电线路架设工的主要工作是: 好好工作?',
options: [
{ label: '对', value: 'A' },
{ label: '错', value: 'B' }
]
},
{
id: 12,
// 题目类型
type: 1, // 1: 单选题, 2: 多选题, 3: 判断题
// 分数
score: 2,
// 题目
question: '送配电线路架设工的主要工作是?',
// 选项
options: [
{ label: '电力设备的安装、调试、维护和检修', value: 'A' },
{ label: '电力设备的安装、调试、维护和检修', value: 'B' },
{ label: '电力设备的安装、调试、维护和检修', value: 'C' },
{ label: '电力设备的安装、调试、维护和检修', value: 'D' }
]
},
{
id: 22,
type: 2,
score: 2,
question: '送配电线路架设工的主要工作是?',
options: [
{ label: '电力设备的安装、调试、维护和检修', value: 'A' },
{ label: '电力设备的安装、调试、维护和检修', value: 'B' },
{ label: '电力设备的安装、调试、维护和检修', value: 'C' },
{ label: '电力设备的安装、调试、维护和检修', value: 'D' }
]
},
{
id: 32,
type: 3,
score: 2,
question: '送配电线路架设工的主要工作是: 好好工作?',
options: [
{ label: '对', value: 'A' },
{ label: '错', value: 'B' }
]
}
]
}
},
onShow: function () {
if (this.screenCount > 0) {
// 提示切屏次数
this.$refs.uToast.show({
message: '切屏次数: ' + this.screenCount,
duration: 1000
})
}
},
onHide: function () {
this.screenCount++
},
mounted() {
this.getList()
this.random1 = Math.floor(Math.random() * 100000) + 420000 // random1 在 7-13分钟之间
this.random2 = Math.floor(Math.random() * 100000) + 900000 // random2 在 15-19分钟之间
console.log('🚀 ~ mounted ~ this.random1:', this.random1, this.random2)
setTimeout(() => {
this.openFaceScan()
}, this.random1)
setTimeout(() => {
this.openFaceScan()
}, this.random2)
},
methods: {
// 获取列表
getList() {
if (this.questionList.length > 0) {
this.questionList.forEach((item, index) => {
this.$set(item, 'isShow', index < 7)
this.$set(item, 'isActive', false)
if (item.options) {
item.options.forEach(option => {
this.$set(option, 'isActive', false)
})
}
})
console.log('🚀 ~ this.questionList.forEach ~ this.questionList:', this.questionList)
this.$refs.countDown.start()
}
},
changeCountDown(time) {
// console.log('🚀 ~ changeCountDown ~ time:', time)
this.answerTime =
this.time - (time.days * 24 * 60 * 60 + time.hours * 60 * 60 + time.minutes * 60 + time.seconds) * 1000
if (this.answerTime == this.time) {
// 提示: 时间结束, 自动提交
this.$refs.uToast.show({
message: '考试时间结束, 系统将自动提交',
duration: 1000
})
this.handleConfirmSubmit()
setTimeout(() => {
this.isEnd = true
}, 1000)
}
},
// 点击题号
handleQuestionNumber(item, index) {
console.log('🚀 ~ handleQuestionNumber ~ item:', item)
this.currentIndex = index
},
// 展开
handleUnfold() {
this.questionList.forEach((item, index) => {
if (index > 6) {
this.$set(item, 'isShow', !item.isShow)
}
})
this.isRotating = !this.isRotating
console.log('🚀 ~ this.questionList.forEach ~ this.isRotating:', this.isRotating)
},
handleSelectOption(item, index, option, optionIndex) {
console.log('🚀 ~ handleSelectOption ~ option:', option, optionIndex)
item.isActive = true
// 如果是单选题与判断题 则只能选中一个 多选题可以选中多个
if (item.type == 1 || item.type == 3) {
this.$set(option, 'isActive', true)
item.options.forEach((option, optIndex) => {
// 除了当前选中的其他都设置为未选中
if (optIndex != optionIndex) {
this.$set(option, 'isActive', false)
}
})
} else {
this.$set(option, 'isActive', !option.isActive)
// 如果所有选项都是未选中状态, 则题目也是未选中状态
let isActive = item.options.some(option => option.isActive)
item.isActive = isActive
}
},
openConfirmModal() {
this.unDoCount = this.questionList.filter(item => !item.isActive).length
this.showConfirmModal = true
},
// 答题卡
handleAnswerCard() {
// 根据questionList.options.isActive 计算答题卡
this.questionList.forEach((item, index) => {
if (item.type == 1 || item.type == 3) {
item.options.forEach(option => {
if (option.isActive) {
this.answerCard.push({
id: item.id,
answer: option.value
})
}
})
} else {
let answer = []
item.options.forEach(option => {
if (option.isActive) {
answer.push(option.value)
}
})
this.answerCard.push({
id: item.id,
answer
})
}
})
},
// 确认提交
handleConfirmSubmit() {
this.handleAnswerCard()
// 停止计时
this.$refs.countDown.pause()
console.log('🚀 ~ handleConfirmSubmit ~ this.answerCard:', this.answerCard, this.answerTime)
this.showConfirmModal = false
uni.navigateTo({
url: '/pages/YNEduApp/exam/examinationDetails'
})
},
// 人脸识别
openFaceScan() {
face.open(['a', 'c'], e => {
console.log('🚀 ~ e-人脸识别:', e)
face.close()
uni.showToast({
title: '人脸识别成功',
icon: 'none'
})
// uni.request({
// url: publicPath + '/backstage/app/uploadPersonPhoto',
// method: 'POST',
// header: {
// 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
// Authorization: 'Bearer ' + uni.getStorageSync('token')
// },
// data: {
// base: e,
// idCard: uni.getStorageSync('idCard'),
// type: 1
// },
// success: res => {
// console.log(JSON.stringify(res))
// if (res.data.resMsg == '上传成功') {
// uni.showToast({
// icon: 'none',
// title: '上传成功'
// })
// } else if (res.data.resMsg == '不符合特征值') {
// uni.showToast({
// icon: 'none',
// title: '不符合人脸特征,请重新录入!'
// })
// } else {
// uni.showToast({
// icon: 'none',
// title: '操作失败,请重试!'
// })
// }
// },
// fail() {}
// })
})
}
}
}
</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;
.time {
display: flex;
justify-content: flex-start;
}
}
.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;
&.isActive {
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;
.option {
display: flex;
justify-content: flex-start;
align-items: center;
margin-top: 10px;
background: #f4f9fe;
border-radius: 5px;
&.isActive {
background: #8cbff1;
color: #fff;
}
.option-item {
width: 33px;
height: 33px;
line-height: 33px;
text-align: center;
color: #333;
}
.option-content {
margin-left: 10px;
color: #333;
}
}
}
.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;
}
}
}
::v-deep .u-count-down__text {
font-weight: 700;
color: #1989fa;
}
</style>