yindongqi b20c4dc376 feat(安全): 添加加密解密功能并更新考试组件
- 新增crypto-js依赖用于数据加密解密
- 添加decrypt.js工具文件实现AES解密功能
- 修改Exam.vue组件使用加密接口获取考试数据
- 清理main.js中多余空行并格式化代码
2025-08-15 12:47:21 +08:00

1089 lines
35 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>
<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>