|
@@ -1,5 +1,5 @@
|
|
|
<template>
|
|
|
- <div class="page-exam-question-box">
|
|
|
+ <div v-if="isInited" class="page-exam-question-box">
|
|
|
<van-nav-bar title="考试" />
|
|
|
<!-- 倒计时 -->
|
|
|
<div class="exam-question-countdown">
|
|
@@ -49,7 +49,7 @@
|
|
|
</div>
|
|
|
<!-- 描述 -->
|
|
|
<div class="exam-question-describe">
|
|
|
- {{ examQuestionList[answerIndex].describe }}
|
|
|
+ {{ examQuestionList[answerIndex].content }}
|
|
|
</div>
|
|
|
<!-- 答题列表 -->
|
|
|
<!-- 单选题、多选题的选项区域 -->
|
|
@@ -61,7 +61,7 @@
|
|
|
class="exam-question-options"
|
|
|
>
|
|
|
<div
|
|
|
- v-for="(item, index) in examQuestionList[answerIndex].options"
|
|
|
+ v-for="(item, index) in examQuestionList[answerIndex].answers"
|
|
|
:key="index"
|
|
|
:class="{
|
|
|
'exam-question-options-item': true,
|
|
@@ -98,6 +98,7 @@
|
|
|
class="exam-question-button"
|
|
|
type="primary"
|
|
|
color="#FE6347"
|
|
|
+ :disabled="isOverAnswer"
|
|
|
@click="handleSubmitFun"
|
|
|
>交卷</van-button
|
|
|
>
|
|
@@ -115,18 +116,34 @@ export default {
|
|
|
components: {},
|
|
|
data() {
|
|
|
return {
|
|
|
+ userInfo: {
|
|
|
+ id: 0,
|
|
|
+ username: "string",
|
|
|
+ firstName: "string",
|
|
|
+ lastName: "string",
|
|
|
+ email: "string",
|
|
|
+ encodedPassword: "string",
|
|
|
+ userStatus: "suspended"
|
|
|
+ },
|
|
|
questionType: {
|
|
|
- singleChoice: 1, // 单选题
|
|
|
- multipleChoice: 2, // 多选题
|
|
|
- gapFilling: 3 // 填空题
|
|
|
+ singleChoice: "DanXuan", // 单选题
|
|
|
+ multipleChoice: "DuoXuan", // 多选题
|
|
|
+ gapFilling: "TianKong" // 填空题
|
|
|
}, // 试题类型
|
|
|
- startTimeSeconds: null, // 考试开始时间的信息
|
|
|
+ endTimeSeconds: null, // 考试开始时间的信息
|
|
|
timeDiff: "00:00:00", // 距离考试结束的时间
|
|
|
interval: null, // 计时器
|
|
|
examQuestionList: [], // 试题列表
|
|
|
answerIndex: null, // 当前试题的下标索引
|
|
|
answerValue: [], // 当前试题的所答
|
|
|
- inputValue: "" // 填空题时输入框的值
|
|
|
+ inputValue: "", // 填空题时输入框的值
|
|
|
+ isInited: false, // 是否已初始化完毕
|
|
|
+ answerTime: {
|
|
|
+ startTime: 0,
|
|
|
+ endTime: 0
|
|
|
+ }, // 答题的开始、结束时间
|
|
|
+
|
|
|
+ isOverAnswer: false // 是否已答完所有题目
|
|
|
};
|
|
|
},
|
|
|
created() {
|
|
@@ -146,165 +163,93 @@ export default {
|
|
|
methods: {
|
|
|
// 初始化数据信息
|
|
|
initDataFun() {
|
|
|
- console.log("考试信息:", this.examItem);
|
|
|
- // if (!this.examItem) {
|
|
|
- // return;
|
|
|
- // }
|
|
|
- this.getExamItemQuestionsListFun(); // 查询:当前考试的信息
|
|
|
- this.getExamTimeFun(); // 获取:当前时间及考试限时
|
|
|
- this.setIntervalFun(); // 设置:倒计时定时器
|
|
|
+ if (!this.examItem) {
|
|
|
+ Dialog({ message: "试题信息有误,请重新进入当前页面" });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.examStartFun(); // 方法:开始考试
|
|
|
},
|
|
|
// 查询:当前考试的信息
|
|
|
getExamItemQuestionsListFun() {
|
|
|
- // TODO...
|
|
|
- let httpResultData = [
|
|
|
- {
|
|
|
- id: 1,
|
|
|
- type: 1,
|
|
|
- grade: 1,
|
|
|
- options: ["选项一", "选项二", "选项三"],
|
|
|
- result: ["选项一"],
|
|
|
- describe: "这里是描述(选项一)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 2,
|
|
|
- type: 1,
|
|
|
- grade: 2,
|
|
|
- options: ["选项一", "选项二", "选项三", "选项四"],
|
|
|
- result: ["选项一"],
|
|
|
- describe: "这里是描述,这里是描述,这里是描述(选项一)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 3,
|
|
|
- type: 2,
|
|
|
- grade: 3,
|
|
|
- options: ["选项一", "选项二", "选项三", "选项四"],
|
|
|
- result: ["选项一", "选项二"],
|
|
|
- describe:
|
|
|
- "这里是描述,这里是描述,这里是描述,这里是描述,这里是描述(选项一、选项二)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 4,
|
|
|
- type: 2,
|
|
|
- grade: 3,
|
|
|
- options: ["选项一", "选项二", "选项三", "选项四"],
|
|
|
- result: ["选项一", "选项二", "选项三"],
|
|
|
- describe:
|
|
|
- "这里是描述,这里是描述,这里是描述,这里是描述,这里是描述(选项一、选项二、选项三)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 5,
|
|
|
- type: 3,
|
|
|
- grade: 4,
|
|
|
- options: [],
|
|
|
- result: [1],
|
|
|
- describe:
|
|
|
- "这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述(1)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 6,
|
|
|
- type: 1,
|
|
|
- grade: 1,
|
|
|
- options: ["选项一", "选项二", "选项三"],
|
|
|
- result: ["选项一"],
|
|
|
- describe: "这里是描述(选项一)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 7,
|
|
|
- type: 1,
|
|
|
- grade: 2,
|
|
|
- options: ["选项一", "选项二", "选项三", "选项四"],
|
|
|
- result: ["选项一"],
|
|
|
- describe: "这里是描述,这里是描述,这里是描述(选项一)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 8,
|
|
|
- type: 2,
|
|
|
- grade: 3,
|
|
|
- options: ["选项一", "选项二", "选项三", "选项四"],
|
|
|
- result: ["选项一", "选项二"],
|
|
|
- describe:
|
|
|
- "这里是描述,这里是描述,这里是描述,这里是描述,这里是描述(选项一、选项二)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 9,
|
|
|
- type: 2,
|
|
|
- grade: 3,
|
|
|
- options: ["选项一", "选项二", "选项三", "选项四"],
|
|
|
- result: ["选项一", "选项二", "选项三"],
|
|
|
- describe:
|
|
|
- "这里是描述,这里是描述,这里是描述,这里是描述,这里是描述(选项一、选项二、选项三)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 10,
|
|
|
- type: 3,
|
|
|
- grade: 4,
|
|
|
- options: [],
|
|
|
- result: [1],
|
|
|
- describe:
|
|
|
- "这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述(1)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 11,
|
|
|
- type: 1,
|
|
|
- grade: 1,
|
|
|
- options: ["选项一", "选项二", "选项三"],
|
|
|
- result: ["选项一"],
|
|
|
- describe: "这里是描述(选项一)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 12,
|
|
|
- type: 1,
|
|
|
- grade: 2,
|
|
|
- options: ["选项一", "选项二", "选项三", "选项四"],
|
|
|
- result: ["选项一"],
|
|
|
- describe: "这里是描述,这里是描述,这里是描述(选项一)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 13,
|
|
|
- type: 2,
|
|
|
- grade: 3,
|
|
|
- options: ["选项一", "选项二", "选项三", "选项四"],
|
|
|
- result: ["选项一", "选项二"],
|
|
|
- describe:
|
|
|
- "这里是描述,这里是描述,这里是描述,这里是描述,这里是描述(选项一、选项二)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 14,
|
|
|
- type: 2,
|
|
|
- grade: 3,
|
|
|
- options: ["选项一", "选项二", "选项三", "选项四"],
|
|
|
- result: ["选项一", "选项二", "选项三"],
|
|
|
- describe:
|
|
|
- "这里是描述,这里是描述,这里是描述,这里是描述,这里是描述(选项一、选项二、选项三)"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 15,
|
|
|
- type: 3,
|
|
|
- grade: 4,
|
|
|
- options: [],
|
|
|
- result: [1],
|
|
|
- describe:
|
|
|
- "这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述(1)"
|
|
|
- }
|
|
|
- ];
|
|
|
- this.examQuestionList = this.setPersonDataFun(httpResultData);
|
|
|
- this.handleExamQuestionItemFun(this.examQuestionList[0], 0); // 设置第一题开始
|
|
|
+ // let httpResultData = [
|
|
|
+ // {
|
|
|
+ // answerAnalysis: "", // 答案解析
|
|
|
+ // id: 15,
|
|
|
+ // type: 3,
|
|
|
+ // grade: 4,
|
|
|
+ // status: null, // 答题状态???
|
|
|
+ // answers: [], // 选项
|
|
|
+ // finalAnswer: [1], // 答案
|
|
|
+ // content:
|
|
|
+ // "这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述,这里是描述(1)"
|
|
|
+ // }
|
|
|
+ // ];
|
|
|
+ },
|
|
|
+ // 方法:开始考试
|
|
|
+ examStartFun() {
|
|
|
+ this.$store.commit("toggleLoading", true);
|
|
|
+ this.$_http
|
|
|
+ .post(
|
|
|
+ this.$pathParams(this.$_API.POST_JTXT_GET_EXAMS_START, {
|
|
|
+ examId: this.examItem.id
|
|
|
+ }),
|
|
|
+ this.userInfo
|
|
|
+ )
|
|
|
+ .then(res => {
|
|
|
+ if (res.data) {
|
|
|
+ let httpResultData = [];
|
|
|
+ res.data.forEach((item, index) => {
|
|
|
+ this.getExamQuestionsListFun(
|
|
|
+ item,
|
|
|
+ httpResultData,
|
|
|
+ index === res.data.length - 1
|
|
|
+ );
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ this.$store.commit("toggleLoading", false);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 查询:试题信息
|
|
|
+ async getExamQuestionsListFun(questionId, httpResultData, isLast) {
|
|
|
+ this.$_http
|
|
|
+ .get(
|
|
|
+ this.$pathParams(this.$_API.GET_JTXT_GET_EXAMS_ONE_QUESTIONS_LIST, {
|
|
|
+ questionId: questionId
|
|
|
+ })
|
|
|
+ )
|
|
|
+ .then(res => {
|
|
|
+ let resData = { ...res.data };
|
|
|
+ httpResultData.push(this.setPersonDataFun(resData));
|
|
|
+ if (isLast) {
|
|
|
+ this.examQuestionList = httpResultData;
|
|
|
+ this.handleExamQuestionItemFun(this.examQuestionList[0], 0); // 设置第一题开始
|
|
|
+ this.isInited = true;
|
|
|
+ this.getExamTimeFun(); // 获取:当前时间及考试限时
|
|
|
+ this.setIntervalFun(); // 设置:倒计时定时器
|
|
|
+ this.$store.commit("toggleLoading", false);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ this.$store.commit("toggleLoading", false);
|
|
|
+ });
|
|
|
},
|
|
|
// 方法:过滤试题的类型,添加用户作答的字段
|
|
|
- setPersonDataFun(httpResultData) {
|
|
|
- httpResultData.forEach(item => {
|
|
|
- item.typeTxt = this.formatQuestionType(item.type);
|
|
|
- item.userAnswer = [];
|
|
|
- });
|
|
|
- return httpResultData;
|
|
|
+ setPersonDataFun(httpResultDataItme) {
|
|
|
+ httpResultDataItme.typeTxt = this.formatQuestionType(
|
|
|
+ httpResultDataItme.type
|
|
|
+ );
|
|
|
+ httpResultDataItme.userAnswer = [];
|
|
|
+ return httpResultDataItme;
|
|
|
},
|
|
|
- // 获取:当前时间及考试限时
|
|
|
+ // 获取:考试限定的时间点
|
|
|
getExamTimeFun() {
|
|
|
let tarTime = this.getTimeHoursMinuteSecondsFun(
|
|
|
this.examItem.examTimeMins
|
|
|
);
|
|
|
let curTime = new Date();
|
|
|
+ this.answerTime.startTime = curTime; // 赋值开始时间
|
|
|
// 在当前时间curTime变量上加上小时
|
|
|
let addHour = curTime.setHours(curTime.getHours() + tarTime.hours);
|
|
|
curTime = new Date(addHour);
|
|
@@ -318,7 +263,8 @@ export default {
|
|
|
curTime.setSeconds(curTime.getSeconds() + tarTime.seconds)
|
|
|
);
|
|
|
curTime = new Date(addSeconds);
|
|
|
- this.startTimeSeconds = curTime.getTime();
|
|
|
+ this.answerTime.endTime = curTime; // 赋值结束时间
|
|
|
+ this.endTimeSeconds = curTime.getTime(); // 赋值结束时间的秒数
|
|
|
},
|
|
|
// 方法:分别获取时 分 秒
|
|
|
getTimeHoursMinuteSecondsFun(e) {
|
|
@@ -351,12 +297,12 @@ export default {
|
|
|
// 获取距离目标时间的毫秒时间戳
|
|
|
this.interval = setInterval(() => {
|
|
|
let curTime = Date.now(); // 获取当前时间的毫秒时间戳
|
|
|
- let diffTime = this.startTimeSeconds - curTime; // 计算出当前时间距离目标时间的时间差
|
|
|
+ let diffTime = this.endTimeSeconds - curTime; // 计算出当前时间距离目标时间的时间差
|
|
|
// 判断倒计时是否完成,成立则清除定时器,关闭函数执行
|
|
|
if (diffTime <= 0) {
|
|
|
clearInterval(_self.interval);
|
|
|
_self.timeDiff = "00:00:00";
|
|
|
- this.handleSubmitFun(true); // 自动交卷
|
|
|
+ this.handleSubmitFun(); // 自动交卷
|
|
|
return;
|
|
|
}
|
|
|
let hours = Math.floor(diffTime / (1000 * 60 * 60));
|
|
@@ -459,9 +405,11 @@ export default {
|
|
|
this.examQuestionList[this.answerIndex].userAnswer = this.answerValue;
|
|
|
},
|
|
|
// 操作:交卷 isAuto:true(时间到了的自动交卷) false(手动交卷)
|
|
|
- handleSubmitFun(isAuto) {
|
|
|
+ handleSubmitFun() {
|
|
|
+ let isAuto = this.timeDiff === "00:00:00";
|
|
|
if (isAuto) {
|
|
|
- console.log("自动交卷");
|
|
|
+ Dialog({ message: "考试时间已到,该考试已结束" });
|
|
|
+ this.examsEndFun(isAuto);
|
|
|
} else {
|
|
|
Dialog.confirm({
|
|
|
title: "温馨提示",
|
|
@@ -469,9 +417,67 @@ export default {
|
|
|
})
|
|
|
.then(() => {
|
|
|
// TODO...
|
|
|
+ this.answerTime.endTime = new Date();
|
|
|
+ clearInterval(this.interval); // 销毁前清空计时器
|
|
|
+ this.$store.commit("toggleLoading", true);
|
|
|
+ this.examsEndFun(isAuto);
|
|
|
})
|
|
|
.catch(() => {});
|
|
|
}
|
|
|
+ },
|
|
|
+ // 方法:结束考试
|
|
|
+ examsEndFun(isAuto) {
|
|
|
+ let allPoints = this.getUserExamAllPointsFun(); // 方法:计算成绩
|
|
|
+ let params = {
|
|
|
+ user: this.userInfo,
|
|
|
+ exam: {
|
|
|
+ id: this.examItem.id,
|
|
|
+ name: this.examItem.name,
|
|
|
+ description: this.examItem.description,
|
|
|
+ creator: this.userInfo,
|
|
|
+ duration: this.examItem.duration,
|
|
|
+ deadline: this.examItem.deadline,
|
|
|
+ startTime: this.examItem.startTime
|
|
|
+ },
|
|
|
+ points: allPoints, // 成绩:分数
|
|
|
+ startTime: this.answerTime.startTime,
|
|
|
+ endTime: this.answerTime.endTime
|
|
|
+ };
|
|
|
+ this.$_http
|
|
|
+ .post(
|
|
|
+ this.$pathParams(this.$_API.POST_JTXT_GET_EXAMS_END, {
|
|
|
+ examId: this.examItem.id
|
|
|
+ }),
|
|
|
+ params
|
|
|
+ )
|
|
|
+ .then(res => {
|
|
|
+ console.log("结束考试了", res);
|
|
|
+ this.$store.commit("toggleLoading", false);
|
|
|
+ if (!isAuto) {
|
|
|
+ Dialog("提交试卷成功,总分为:" + allPoints);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ this.$store.commit("toggleLoading", false);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 方法:计算成绩
|
|
|
+ getUserExamAllPointsFun() {
|
|
|
+ let allPoints = 0;
|
|
|
+ this.examQuestionList.forEach((item, index) => {
|
|
|
+ let sureNum = 0;
|
|
|
+ item.finalAnswer.forEach(it => {
|
|
|
+ item.userAnswer.forEach(answerItem => {
|
|
|
+ if (it === answerItem) {
|
|
|
+ sureNum++;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ if (sureNum === item.finalAnswer.length) {
|
|
|
+ allPoints++;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return allPoints;
|
|
|
}
|
|
|
}
|
|
|
};
|