- 新增crypto-js依赖用于数据加密解密 - 添加decrypt.js工具文件实现AES解密功能 - 修改Exam.vue组件使用加密接口获取考试数据 - 清理main.js中多余空行并格式化代码
1089 lines
35 KiB
Vue
1089 lines
35 KiB
Vue
<template>
|
||
<div class="liuyan">
|
||
<!-- <back title="考试中心" buttonText="模拟考试" buttonUrl="/examTest"></back>-->
|
||
<mt-header fixed :title="title">
|
||
<mt-button icon="back" @click="back" slot="left"></mt-button>
|
||
<!-- <div v-show="this.is_start == 0"> -->
|
||
|
||
<!-- </div> -->
|
||
</mt-header>
|
||
<div class="exam-info" v-if="is_start == 0 && config.exam_type != 3">
|
||
<div>
|
||
<p>
|
||
1、考试时间为{{
|
||
config.exam_time / 60
|
||
}}分钟。一旦开始考试,不可中断,如中途退出,继续计时,且所答的题目不做记录。
|
||
</p>
|
||
<p>2、考试题共{{ config.exam_num }}题。不答视为0分。</p>
|
||
<p>
|
||
3、{{
|
||
config.exam_score
|
||
}}分及以上视为考试通过。如未通过,请联系企业负责人申请补考。
|
||
</p>
|
||
<p>4、右下角点击序号会显示序号列表,点击跳至对应题目,已答题目显示为绿色。</p>
|
||
<p>5、需要上传证件照的学员,请先在"个人中心"上传证件照,否则无法进行考试。</p>
|
||
<p>6、请在课程结束日期前完成所有课程,所有课程完成后进入考试系统 。</p>
|
||
<p v-if="config.exam_type == 2" class="active">
|
||
7、本次考试为补考,补考开始时间请联系工作人员确认。您已参与补考{{
|
||
config.bu_num
|
||
}}次。
|
||
</p>
|
||
</div>
|
||
<mt-button class="tijiao" type="primary" size="large" @click="btn_course(2)"
|
||
v-if="config.exam_type == 1">正式考试</mt-button>
|
||
<mt-button class="tijiao" type="primary" size="large" @click="btn_course(2)"
|
||
v-if="config.exam_type == 2">开始补考</mt-button>
|
||
<mt-button class="sub-button" type="primary" size="large" @click="btn_course(1)"
|
||
v-show="monishow">模拟考试</mt-button>
|
||
</div>
|
||
<div v-if="is_start == 0 && config.exam_type == 3" class="pass-exam">
|
||
恭喜您!<br />您已通过考核!
|
||
<mt-button class="tijiao" type="primary" size="large" @click="goCert">查看证书</mt-button>
|
||
</div>
|
||
<div v-if="is_start == 1" class="lx">
|
||
<div class="times">剩余时间:{{ time_str }}</div>
|
||
<div v-if="current_question_data.type == 13">
|
||
<div class="lianxiTiMu">
|
||
<span class="lianxiTiMu1">判断题</span>
|
||
<span>{{ current_question_data.name }}</span>
|
||
</div>
|
||
<div class="lianxiTiMu" v-for="(item, index) in current_question_data.content" :key="index"
|
||
@click="responseQ(item)">
|
||
<span class="lianxiXueZe" v-bind:class="{ active: current_question_data.response == item }">{{ xuhao[index]
|
||
}}</span>
|
||
<span class="lianxiXueZe1">{{ item }}</span>
|
||
</div>
|
||
</div>
|
||
<div v-if="current_question_data.type == 3">
|
||
<div class="lianxiTiMu">
|
||
<span class="lianxiTiMu1">单选题</span>
|
||
<span>{{ current_question_data.name }}</span>
|
||
</div>
|
||
<div class="lianxiTiMu" v-for="(item, index) in current_question_data.content" :key="index"
|
||
@click="responseQ(item)">
|
||
<span class="lianxiXueZe" v-bind:class="{ active: current_question_data.response == item }">{{ xuhao[index]
|
||
}}</span>
|
||
<span class="lianxiXueZe1">{{ item }}</span>
|
||
</div>
|
||
</div>
|
||
<div v-if="current_question_data.type == 4">
|
||
<div class="lianxiTiMu">
|
||
<span class="lianxiTiMu1">多选题</span>
|
||
<span>{{ current_question_data.name }}</span>
|
||
</div>
|
||
<div class="lianxiTiMu" v-for="(item, index) in current_question_data.content" :key="index"
|
||
@click="responseS(index)">
|
||
<span class="lianxiXueZe" v-bind:class="{
|
||
active: current_question_data.response.indexOf(index) != -1,
|
||
}">{{ xuhao[index] }}</span>
|
||
<span class="lianxiXueZe1">{{ item }}</span>
|
||
</div>
|
||
</div>
|
||
<div v-if="current_question_data.type == 12">
|
||
<div class="lianxiTiMu">
|
||
<span class="lianxiTiMu1">填空题</span>
|
||
<span>{{ current_question_data.name }}</span>
|
||
<div class="tiankong" v-for="(i, key) in tiankongdata" :key="key">
|
||
<div v-for="(item, index) in i.label.length" :key="index">
|
||
<input type="text" class="tiank" maxlength="1" v-model="i.num[index]" :id="'tk' + index"
|
||
@blur="responseC(i.num[index])" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="lianxiBottom">
|
||
<div class="lianxiBottomL">
|
||
<div @click="prevQ">上一题</div>
|
||
<div @click="nextQ">下一题</div>
|
||
<div @click="subQ">交卷</div>
|
||
</div>
|
||
|
||
<div class="lianxiBottomR" @click="popupVisible = true">
|
||
<img src="../../../static/img/gengduo.png" alt="" /><span>{{
|
||
current_question + 1
|
||
}}</span>/{{ questions.length }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<mt-popup v-model="popupVisible" position="bottom">
|
||
<div class="order_number">
|
||
<div v-for="(item, index) in questions" :key="index" @click="goQ(index)" v-bind:class="{
|
||
done: item.response != '' && current_question != index,
|
||
error: !item.response && current_question != index,
|
||
active: current_question == index,
|
||
}">
|
||
{{ index + 1 }}
|
||
</div>
|
||
</div>
|
||
</mt-popup>
|
||
<mt-popup v-model="popupVisible2" popup-transition="popup-fade"
|
||
style="background-color: #5e5e5e; border-radius: 20px;">
|
||
<div style=" top: 5px; font-size: 20px; font-weight: bold; margin: 20px 0; color: white;">请选择要考试的课程</div>
|
||
<div style=" margin: 30px; width: 250px;" v-for="(item, index) in courseData" :key="index">
|
||
<mt-button @click="btn_courseID(item.id)" type="default" class=""
|
||
style="width: 100%; height: 100%; padding: 10px 0;">{{ item.name }}</mt-button>
|
||
</div>
|
||
</mt-popup>
|
||
<div v-show="showPhotoMask" class="photo-mask" @click="showPhotoMask = false">
|
||
<div class="mask-content" @click.stop>
|
||
<p>未上传证件照,无法开启正式考试</p>
|
||
<mt-button type="primary" @click="$router.push('/user/uploadphoto')">去上传</mt-button>
|
||
</div>
|
||
</div>
|
||
<input type="hidden" ref="isphoto" :value="loginInfo.isphoto" />
|
||
<input type="hidden" ref="needuploadphoto" :value="loginInfo.need_upload_photo" />
|
||
<input type="hidden" ref="exam_end_time" :value="loginInfo.id_end" />
|
||
<WXTake ref="wxchild" @result="printResult"></WXTake>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { mapState } from "vuex";
|
||
import Back from "../common/Back";
|
||
import { getStore } from "@/utils/storage";
|
||
import { Toast } from "mint-ui";
|
||
import { MessageBox } from "mint-ui";
|
||
import WXTake from "../study/weixinTake.vue";
|
||
import { decrypt } from "@/utils/decrypt";
|
||
export default {
|
||
name: "LiuYan",
|
||
components: { Back, WXTake },
|
||
data() {
|
||
return {
|
||
id: "",
|
||
config: {},
|
||
is_start: 0,
|
||
exam_data: {},
|
||
xuhao: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N"],
|
||
questions: [],
|
||
current_question: 0,
|
||
current_question_data: {},
|
||
popupVisible: false,
|
||
popupVisible2: false,
|
||
timer: "",
|
||
time_str: "",
|
||
tiankongdata: [],
|
||
num: 0, // 模拟考试1 正式考试2
|
||
courseID: 0, //选择的课程ID
|
||
courseData: [], //所有考试课程集合
|
||
true_quesstion: 0,
|
||
title: "考试中心",
|
||
monishow: true,
|
||
showPhotoMask: false,
|
||
submitCount: 0, //开启相机的次数
|
||
allSubmitCount: 3, //允许拍照次数
|
||
canTakePhoto: true, //节流
|
||
isFaceDetected: false, //检测人脸是否成功
|
||
currenttime: 1, //当前考试时间
|
||
};
|
||
},
|
||
methods: {
|
||
//课程弹框
|
||
btn_course(num) {
|
||
this.num = num;
|
||
|
||
// 点击“开始考试”按钮,弹出“课程选择框”,让学员选择需要考试的课程
|
||
this.getData("/Question/getCourse", {
|
||
token: getStore("token"),
|
||
}).then((data) => {
|
||
this.courseData = data.data;
|
||
if (this.courseData.length === 1) {
|
||
this.btn_courseID(this.courseData[0].id);
|
||
} else if (this.courseData.length > 1) {
|
||
this.popupVisible2 = true;
|
||
} else {
|
||
Toast("暂无考试");
|
||
}
|
||
});
|
||
},
|
||
//选择课程
|
||
btn_courseID(val) {
|
||
this.courseID = val;
|
||
this.popupVisible2 = false;
|
||
console.log(this.courseID);
|
||
console.log(this.num);
|
||
if (this.num == 1) {
|
||
MessageBox.confirm("确定开始模拟考试吗").then(
|
||
(action) => {
|
||
this.GoExamTest();
|
||
},
|
||
() => { }
|
||
);
|
||
} else {
|
||
//开启人脸识别
|
||
if (this.loginInfo.need_check_face == 1) {
|
||
this.partakePhoto(0);
|
||
} else {
|
||
MessageBox.confirm("确定开始正式考试吗").then(
|
||
(action) => {
|
||
this.start();
|
||
},
|
||
() => { }
|
||
);
|
||
}
|
||
}
|
||
},
|
||
back() {
|
||
if (this.title == "正式考试") {
|
||
MessageBox.confirm("退出后不会保存当前所答题目,确定退出吗?").then(
|
||
(action) => {
|
||
this.$router.go(-1);
|
||
},
|
||
() => { }
|
||
);
|
||
} else {
|
||
this.$router.go(-1);
|
||
}
|
||
},
|
||
//模拟考试
|
||
GoExamTest() {
|
||
this.getData("/Question/examNum", {
|
||
token: getStore("token"),
|
||
course_id: this.courseID,
|
||
}).then((data) => {
|
||
if (data.code == 2) {
|
||
// console.log("不能考试了");
|
||
// Toast(data.msg);
|
||
Toast("您的模拟考试次数已经用完!");
|
||
}
|
||
if (data.code == 1) {
|
||
// console.log("调用接口,开始模拟考试");
|
||
this.$router.push({
|
||
path: "/examTest",
|
||
query: {
|
||
course_id: this.courseID,
|
||
},
|
||
});
|
||
}
|
||
});
|
||
},
|
||
goCert() {
|
||
this.$router.push({ path: "/certificate" });
|
||
},
|
||
//正式考试
|
||
start() {
|
||
if (
|
||
(this.$refs.isphoto.value == 1 && this.$refs.needuploadphoto.value == 1) ||
|
||
this.$refs.needuploadphoto.value != 1
|
||
) {
|
||
var current_time_stamp = new Date().getTime();
|
||
|
||
//调用接口,获得正式考试的相关数据
|
||
// this.getData("/Question/getExamQuestions", {
|
||
this.getData("/Question/getExamQuestionsSecurity", {
|
||
token: getStore("token"),
|
||
course_id: this.courseID,
|
||
}).then(
|
||
(data) => {
|
||
if (data.code == 1) {
|
||
const questions = decrypt(data.data);
|
||
let _this = this;
|
||
this.is_start = 1;
|
||
this.id = questions.id;
|
||
this.questions = questions.question_data;
|
||
this.current_question_data = questions.question_data[0];
|
||
this.exam_data = questions.exam_data;
|
||
this.title = "正式考试";
|
||
this.monishow = false;
|
||
var count = 1;
|
||
this.timer = setInterval(function () {
|
||
var nowonceTime = new Date().getTime();
|
||
if (_this.exam_data.remain_time > 0) {
|
||
var jiange = (nowonceTime - current_time_stamp) / 1000 - count;
|
||
count = (nowonceTime - current_time_stamp) / 1000;
|
||
_this.exam_data.remain_time = _this.exam_data.remain_time - jiange;
|
||
} else {
|
||
_this.time_str = "时间结束";
|
||
clearInterval(_this.timer);
|
||
}
|
||
let times = _this.exam_data.remain_time;
|
||
if (times > 60) {
|
||
_this.time_str =
|
||
parseInt(times / 60.0) +
|
||
"分" +
|
||
parseInt((parseFloat(times / 60.0) - parseInt(times / 60.0)) * 60) +
|
||
"秒";
|
||
} else {
|
||
_this.time_str = parseInt(times) + "秒";
|
||
}
|
||
|
||
var timePassed = _this.config.exam_time - _this.exam_data.remain_time;
|
||
timePassed = Math.trunc(timePassed);
|
||
// console.log(timePassed);
|
||
_this.currenttime = timePassed;
|
||
// 先提示用户准备人脸检测
|
||
if (
|
||
(timePassed == 895 ||
|
||
timePassed == 2695 ||
|
||
timePassed == 4495 ||
|
||
timePassed == 6295) &&
|
||
_this.loginInfo.need_check_face == 1
|
||
) {
|
||
Toast("稍后开启相机,进行人脸检测,请做好准备");
|
||
}
|
||
// 拍照
|
||
if (
|
||
(timePassed == 900 ||
|
||
timePassed == 2700 ||
|
||
timePassed == 4500 ||
|
||
timePassed == 6300) &&
|
||
_this.loginInfo.need_check_face == 1
|
||
) {
|
||
if (_this.canTakePhoto) {
|
||
_this.canTakePhoto = false;
|
||
_this.partakePhoto();
|
||
setTimeout(() => {
|
||
_this.canTakePhoto = true;
|
||
}, 10000);
|
||
}
|
||
}
|
||
}, 1000);
|
||
} else {
|
||
// console.log("---------------")
|
||
// console.log(data)
|
||
// console.log(data.code)
|
||
// 不满足正式考试条件,给出相应的提示(考试时间未到/课程视频未观看完)
|
||
Toast(data.msg);
|
||
}
|
||
},
|
||
(err) => { }
|
||
);
|
||
} else {
|
||
this.showPhotoMask = true;
|
||
}
|
||
},
|
||
start_bu() {
|
||
this.getData("/Question/getExamBuQuestions", {
|
||
token: getStore("token"),
|
||
}).then(
|
||
(data) => {
|
||
if (data.code == 1) {
|
||
let _this = this;
|
||
this.is_start = 1;
|
||
this.questions = data.data.question_data;
|
||
this.current_question_data = data.data.question_data[0];
|
||
this.exam_data = data.data.exam_data;
|
||
if (this.current_question_data.type == 12) {
|
||
this.tk(this.current_question_data.answer.split("*"));
|
||
}
|
||
this.timer = setInterval(function () {
|
||
if (_this.exam_data.remain_time > 0) {
|
||
_this.exam_data.remain_time--;
|
||
} else {
|
||
_this.time_str = "时间结束";
|
||
_this.subQ();
|
||
clearInterval(_this.timer);
|
||
}
|
||
let times = _this.exam_data.remain_time;
|
||
if (times > 60) {
|
||
_this.time_str =
|
||
parseInt(times / 60.0) +
|
||
"分" +
|
||
parseInt((parseFloat(times / 60.0) - parseInt(times / 60.0)) * 60) +
|
||
"秒";
|
||
} else {
|
||
_this.time_str = parseInt(times) + "秒";
|
||
}
|
||
}, 1000);
|
||
} else {
|
||
Toast(data.msg);
|
||
}
|
||
},
|
||
(err) => { }
|
||
);
|
||
},
|
||
getConfig() {
|
||
this.getData("/Question/getExamConfig", {
|
||
token: getStore("token"),
|
||
}).then(
|
||
(data) => {
|
||
if (data.code == 1) {
|
||
this.config = data.data;
|
||
} else {
|
||
Toast(data.msg);
|
||
}
|
||
},
|
||
(err) => { }
|
||
);
|
||
},
|
||
tk(daan) {
|
||
let _this = this;
|
||
_this.tiankongdata = [];
|
||
let bb = this.questions[this.current_question].response;
|
||
|
||
if (bb.length > 0) {
|
||
let cc = bb.split("*");
|
||
|
||
for (var i = 0; i < daan.length - 1; i++) {
|
||
var json = {
|
||
label: daan[i],
|
||
num: cc[i].split("|"),
|
||
};
|
||
_this.tiankongdata.push(json);
|
||
}
|
||
} else {
|
||
for (var i = 0; i < daan.length - 1; i++) {
|
||
var json = {
|
||
label: daan[i],
|
||
num: [],
|
||
};
|
||
_this.tiankongdata.push(json);
|
||
}
|
||
}
|
||
// daan.forEach(function(data,i){
|
||
// var str=[',','。','、',',','.'] //定义一个能够被使用的标点符号集合,这块补充全面,足以注意徐弘雯应中文英文都需要考虑的
|
||
// //如果是文字。就跳出,如果是标点,就放到具体的位置上面
|
||
// if(str.indexOf(data)>=0){
|
||
// //faxian标点,就把标点昂到卡暖绑定的数组相应的位置显示
|
||
// _this.current_question_data.response[i] = data
|
||
// setTimeout(function(){
|
||
// document.getElementById('tk'+i).disabled = true
|
||
// },100)
|
||
// }else{
|
||
// setTimeout(function(){
|
||
// document.getElementById('tk'+i).disabled = false
|
||
// },100)
|
||
// }
|
||
// })
|
||
},
|
||
prevQ() {
|
||
if (this.current_question <= 0) {
|
||
Toast("已是第一题");
|
||
} else {
|
||
this.current_question--;
|
||
this.current_question_data = this.questions[this.current_question];
|
||
if (this.current_question_data.type == 12) {
|
||
this.tk(this.current_question_data.answer.split("*"));
|
||
}
|
||
}
|
||
},
|
||
nextQ() {
|
||
if (this.current_question >= this.questions.length - 1) {
|
||
Toast("已是最后一题");
|
||
} else {
|
||
this.current_question++;
|
||
this.current_question_data = this.questions[this.current_question];
|
||
if (this.current_question_data.type == 12) {
|
||
this.tk(this.current_question_data.answer.split("*"));
|
||
}
|
||
}
|
||
},
|
||
responseQ(item) {
|
||
this.questions[this.current_question].response = item;
|
||
this.current_question_data = {};
|
||
this.current_question_data = this.questions[this.current_question];
|
||
},
|
||
responseS(item) {
|
||
let arr = this.questions[this.current_question].response;
|
||
if (!arr) {
|
||
this.questions[this.current_question].response = [item];
|
||
return;
|
||
}
|
||
let index;
|
||
index = arr.indexOf(item);
|
||
if (index == -1) {
|
||
this.questions[this.current_question].response.push(item);
|
||
} else {
|
||
this.questions[this.current_question].response.splice(index, 1);
|
||
}
|
||
this.current_question_data = {};
|
||
this.current_question_data = this.questions[this.current_question];
|
||
},
|
||
responseC(item) {
|
||
var str = "";
|
||
for (let i = 0; i < this.tiankongdata.length; i++) {
|
||
var aa = this.tiankongdata[i].num;
|
||
for (var j = 0; j < aa.length; j++) {
|
||
str += aa[j];
|
||
str += "|";
|
||
}
|
||
str += "*";
|
||
// console.log(this.tiankongdata[i].num)
|
||
}
|
||
this.questions[this.current_question].response = str;
|
||
// var dom = document.getElementsByClassName("tiank");
|
||
// var currInput = dom[index];
|
||
// var nextInput = dom[index + 1];
|
||
// var lastInput = dom[index - 1];
|
||
// if (el.keyCode != 8) {
|
||
// if (index < (this.current_question_data.answer.length - 1)) {
|
||
// nextInput.focus();
|
||
// } else {
|
||
// currInput.blur();
|
||
// }
|
||
// }else{
|
||
// if (index !=0) {
|
||
// lastInput.focus();
|
||
// }
|
||
// }
|
||
// console.log()
|
||
},
|
||
goQ(index) {
|
||
this.current_question = index;
|
||
this.current_question_data = this.questions[this.current_question];
|
||
},
|
||
subQ() {
|
||
if (this.currenttime >= 1200) {
|
||
let subQuestions = this.questions;
|
||
for (let i = 0; i < subQuestions.length; i++) {
|
||
if (subQuestions[i].type == 4) {
|
||
let arr = subQuestions[i].response;
|
||
let newArr = arr;
|
||
let res = "";
|
||
for (let j = 0; j < newArr.length; j++) {
|
||
res += subQuestions[i].content[newArr[j]];
|
||
if (j < newArr.length - 1) {
|
||
res += "|";
|
||
}
|
||
}
|
||
subQuestions[i].response = res;
|
||
}
|
||
|
||
if (subQuestions[i].type == 12) {
|
||
let arrT = subQuestions[i].response;
|
||
if (typeof arrT == "string") {
|
||
subQuestions[i].response = arrT.replace(/\|/g, "");
|
||
}
|
||
}
|
||
|
||
//判断做对了几道题
|
||
if (subQuestions[i].response == subQuestions[i].answer) {
|
||
this.true_quesstion++;
|
||
}
|
||
}
|
||
// 先提示是否要提交考卷
|
||
MessageBox({
|
||
title: "提示",
|
||
message: "是否提交考卷,结束考试",
|
||
showConfirmButton: true,
|
||
showCancelButton: true,
|
||
confirmButtonText: "确认交卷",
|
||
cancelButtonText: "继续答题",
|
||
}).then((action) => {
|
||
if (action == "confirm") {
|
||
// 当用户点击“确认交卷时”,如果该用户的成绩小于80,会再次进行提示
|
||
if (this.true_quesstion < 80) {
|
||
MessageBox({
|
||
title: "提示",
|
||
message: "考试剩余时间为" + this.time_str + ",是否继续答题?",
|
||
showConfirmButton: true,
|
||
showCancelButton: true,
|
||
confirmButtonText: "确认交卷",
|
||
cancelButtonText: "继续答题",
|
||
}).then(
|
||
(action) => {
|
||
// console.log(this.true_quesstion);
|
||
if (action == "confirm") {
|
||
if (this.config.exam_type == 1) {
|
||
this.getData("/Question/sendExam", {
|
||
token: getStore("token"),
|
||
content: JSON.stringify(subQuestions),
|
||
course_id: this.courseID,
|
||
}).then(
|
||
(data) => {
|
||
if (data.code == 1) {
|
||
if (data.data.is_standard == 1) {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,通过了本次考试",
|
||
"恭喜"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
} else {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,未通过本次考试",
|
||
"抱歉"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
}
|
||
} else {
|
||
Toast(data.msg);
|
||
}
|
||
},
|
||
(err) => { }
|
||
);
|
||
} else if (this.config.exam_type == 2) {
|
||
this.getData("/Question/sendExamBu", {
|
||
token: getStore("token"),
|
||
content: JSON.stringify(this.questions),
|
||
id: this.exam_data.id,
|
||
num: "3",
|
||
}).then(
|
||
(data) => {
|
||
if (data.code == 1) {
|
||
if (data.data.is_standard == 1) {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,通过了本次补考",
|
||
"恭喜"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
} else {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,未通过本次补考",
|
||
"抱歉"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
}
|
||
} else {
|
||
Toast(data.msg);
|
||
}
|
||
},
|
||
(err) => { }
|
||
);
|
||
} else {
|
||
Toast("非法操作");
|
||
}
|
||
}
|
||
},
|
||
() => { }
|
||
);
|
||
} else {
|
||
if (this.config.exam_type == 1) {
|
||
this.getData("/Question/sendExam", {
|
||
token: getStore("token"),
|
||
content: JSON.stringify(subQuestions),
|
||
course_id: this.courseID,
|
||
}).then(
|
||
(data) => {
|
||
if (data.code == 1) {
|
||
if (data.data.is_standard == 1) {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,通过了本次考试",
|
||
"恭喜"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
} else {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,未通过本次考试",
|
||
"抱歉"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
}
|
||
} else {
|
||
Toast(data.msg);
|
||
}
|
||
},
|
||
(err) => { }
|
||
);
|
||
} else if (this.config.exam_type == 2) {
|
||
this.getData("/Question/sendExamBu", {
|
||
token: getStore("token"),
|
||
content: JSON.stringify(this.questions),
|
||
id: this.exam_data.id,
|
||
num: "3",
|
||
}).then(
|
||
(data) => {
|
||
if (data.code == 1) {
|
||
if (data.data.is_standard == 1) {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,通过了本次补考",
|
||
"恭喜"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
} else {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,未通过本次补考",
|
||
"抱歉"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
}
|
||
} else {
|
||
Toast(data.msg);
|
||
}
|
||
},
|
||
(err) => { }
|
||
);
|
||
} else {
|
||
Toast("非法操作");
|
||
}
|
||
}
|
||
}
|
||
});
|
||
} else {
|
||
Toast("考试20分钟以后才可交卷,请耐心等待");
|
||
}
|
||
},
|
||
|
||
//直接提交了
|
||
directSubQ() {
|
||
let subQuestions = this.questions;
|
||
for (let i = 0; i < subQuestions.length; i++) {
|
||
if (subQuestions[i].type == 4) {
|
||
let arr = subQuestions[i].response;
|
||
let newArr = arr;
|
||
let res = "";
|
||
for (let j = 0; j < newArr.length; j++) {
|
||
res += subQuestions[i].content[newArr[j]];
|
||
if (j < newArr.length - 1) {
|
||
res += "|";
|
||
}
|
||
}
|
||
subQuestions[i].response = res;
|
||
}
|
||
|
||
if (subQuestions[i].type == 12) {
|
||
let arrT = subQuestions[i].response;
|
||
if (typeof arrT == "string") {
|
||
subQuestions[i].response = arrT.replace(/\|/g, "");
|
||
}
|
||
}
|
||
|
||
//判断做对了几道题
|
||
if (subQuestions[i].response == subQuestions[i].answer) {
|
||
this.true_quesstion++;
|
||
}
|
||
|
||
if (this.config.exam_type == 1) {
|
||
this.getData("/Question/sendExam", {
|
||
token: getStore("token"),
|
||
content: JSON.stringify(subQuestions),
|
||
course_id: this.courseID,
|
||
}).then(
|
||
(data) => {
|
||
if (data.code == 1) {
|
||
if (data.data.is_standard == 1) {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,通过了本次考试",
|
||
"恭喜"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
} else {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,未通过本次考试",
|
||
"抱歉"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
}
|
||
} else {
|
||
Toast(data.msg);
|
||
}
|
||
},
|
||
(err) => { }
|
||
);
|
||
} else if (this.config.exam_type == 2) {
|
||
this.getData("/Question/sendExamBu", {
|
||
token: getStore("token"),
|
||
content: JSON.stringify(this.questions),
|
||
id: this.exam_data.id,
|
||
num: "3",
|
||
}).then(
|
||
(data) => {
|
||
if (data.code == 1) {
|
||
if (data.data.is_standard == 1) {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,通过了本次补考",
|
||
"恭喜"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
} else {
|
||
MessageBox.alert(
|
||
"您的考试成绩为" + data.data.score + "分,未通过本次补考",
|
||
"抱歉"
|
||
).then((action) => {
|
||
this.$router.push({ path: "/" });
|
||
});
|
||
}
|
||
} else {
|
||
Toast(data.msg);
|
||
}
|
||
},
|
||
(err) => { }
|
||
);
|
||
} else {
|
||
Toast("非法操作");
|
||
}
|
||
}
|
||
},
|
||
|
||
// 拍照
|
||
partakePhoto(num = 1) {
|
||
this.$refs.wxchild.takePhoto(num);
|
||
},
|
||
|
||
// 打印结果
|
||
printResult(e1, e2) {
|
||
if (e2 == 0) {
|
||
console.log("识别结果:", e1);
|
||
if (e1 == "success") {
|
||
MessageBox.confirm("确定开始正式考试吗").then(
|
||
(action) => {
|
||
this.start();
|
||
},
|
||
() => { }
|
||
);
|
||
} else {
|
||
Toast("人脸检测失败");
|
||
}
|
||
} else {
|
||
this.allSubmitCount--;
|
||
console.log("识别结果:", e1);
|
||
if (e1 == "success") {
|
||
Toast("识别成功,请继续答题");
|
||
this.submitCount = 0;
|
||
this.isFaceDetected = true;
|
||
} else {
|
||
this.submitCount = this.submitCount + 1;
|
||
if (this.submitCount > 2) {
|
||
this.submitCount = 0;
|
||
setTimeout(() => {
|
||
Toast("人脸检测失败,系统已自动提交考卷");
|
||
}, 5000);
|
||
setTimeout(() => {
|
||
this.directSubQ();
|
||
}, 10000);
|
||
} else {
|
||
setTimeout(() => {
|
||
// Toast("第" + (this.submitCount + 1) + "次开启人脸检测拍照,请拍照提交");
|
||
Toast("将再次打开相机,请重新拍照提交");
|
||
}, 5000);
|
||
setTimeout(() => {
|
||
this.partakePhoto();
|
||
}, 10000);
|
||
}
|
||
}
|
||
}
|
||
},
|
||
},
|
||
mounted() {
|
||
this.getConfig();
|
||
},
|
||
computed: {
|
||
...mapState(["loginInfo"]),
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.photo-mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 1000;
|
||
}
|
||
|
||
.mask-content {
|
||
background: white;
|
||
padding: 30px;
|
||
border-radius: 10px;
|
||
text-align: center;
|
||
width: 80%;
|
||
max-width: 400px;
|
||
}
|
||
|
||
.mask-content p {
|
||
margin-bottom: 20px;
|
||
font-size: 16px;
|
||
}
|
||
</style>
|
||
|
||
<style lang="scss" scoped>
|
||
.mint-header.is-fixed {
|
||
color: #000;
|
||
height: 5rem;
|
||
font-size: 1.88rem;
|
||
font-family: MicrosoftYaHei;
|
||
font-weight: 400;
|
||
background: #fff;
|
||
}
|
||
|
||
.sub-button {
|
||
font-family: MicrosoftYaHei;
|
||
font-weight: 400;
|
||
top: 3rem;
|
||
}
|
||
|
||
.liuyan {
|
||
padding-top: 5rem;
|
||
|
||
.exam-info {
|
||
width: 80%;
|
||
margin: 0 auto;
|
||
text-align: left;
|
||
font-size: 1.35rem;
|
||
line-height: 2rem;
|
||
|
||
>div {
|
||
margin-bottom: 2rem;
|
||
|
||
p {
|
||
font-size: 1.5rem;
|
||
|
||
&.active {
|
||
color: #e60012;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.pass-exam {
|
||
width: 80%;
|
||
margin: 10rem auto;
|
||
text-align: center;
|
||
font-size: 3rem;
|
||
line-height: 6rem;
|
||
color: #e60012;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
|
||
.lx {
|
||
padding-bottom: 5rem;
|
||
|
||
.lianxiTiMu {
|
||
width: 90%;
|
||
margin: 2rem auto;
|
||
font-size: 1.56rem;
|
||
font-family: MicrosoftYaHei;
|
||
font-weight: 400;
|
||
text-align: left;
|
||
line-height: 2.5rem;
|
||
color: #333333;
|
||
|
||
.lianxiTiMu1 {
|
||
width: 4.9rem;
|
||
line-height: 1.7rem;
|
||
color: #0375e4;
|
||
border: 0.05rem solid #0375e4;
|
||
border-radius: 1rem 0rem 1rem 0rem;
|
||
display: inline-block;
|
||
text-align: center;
|
||
font-size: 1.04rem;
|
||
font-family: MicrosoftYaHei;
|
||
font-weight: 400;
|
||
}
|
||
|
||
.lianxiXueZe {
|
||
color: #5e5e5e;
|
||
width: 2.5rem;
|
||
line-height: 2.5rem;
|
||
border: 0.05rem solid #5e5e5e;
|
||
border-radius: 50%;
|
||
display: inline-block;
|
||
font-size: 1.56rem;
|
||
font-family: ArialMT;
|
||
font-weight: 400;
|
||
text-align: center;
|
||
margin-right: 1rem;
|
||
|
||
&.active {
|
||
background: #0083ff;
|
||
color: #fff;
|
||
border-color: #0083ff;
|
||
}
|
||
}
|
||
|
||
.lianxiXueZe1 {
|
||
color: #5e5e5e;
|
||
}
|
||
|
||
&.cuoti {
|
||
color: red;
|
||
}
|
||
|
||
.tiankong {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
|
||
.tiank {
|
||
width: 3rem;
|
||
height: 3rem;
|
||
border: 0.05rem solid #9c9c9c;
|
||
margin: 0.5rem;
|
||
text-align: center;
|
||
}
|
||
}
|
||
}
|
||
|
||
.lianxiBottom {
|
||
width: 100%;
|
||
height: 5rem;
|
||
border-top: 0.05rem solid #9c9c9c;
|
||
position: fixed;
|
||
bottom: 0;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 0 2rem;
|
||
font-size: 1.56rem;
|
||
font-family: MicrosoftYaHei;
|
||
font-weight: 400;
|
||
background: white;
|
||
|
||
img {
|
||
width: 1.5rem;
|
||
height: 1.5rem;
|
||
margin-right: 0.5rem;
|
||
}
|
||
|
||
.lianxiBottomL {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 69%;
|
||
|
||
div {
|
||
padding: 0 0.4rem;
|
||
background: #0083ff;
|
||
color: white;
|
||
line-height: 2rem;
|
||
|
||
&.disable {
|
||
background: grey;
|
||
}
|
||
}
|
||
}
|
||
|
||
.lianxiBottomR {
|
||
color: #a5a5a5;
|
||
|
||
span {
|
||
color: #333333;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.order_number {
|
||
width: 100vw;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
|
||
>div {
|
||
width: 10vw;
|
||
font-size: 1.5rem;
|
||
height: 10vw;
|
||
line-height: 10vw;
|
||
border: 1px solid black;
|
||
box-sizing: border-box;
|
||
|
||
&.active {
|
||
background: #31a6ff;
|
||
}
|
||
|
||
&.error {
|
||
background: red;
|
||
}
|
||
|
||
&.done {
|
||
background: greenyellow;
|
||
}
|
||
}
|
||
}
|
||
</style>
|