|
@@ -29,7 +29,7 @@
|
|
<div class="exam-question-div">
|
|
<div class="exam-question-div">
|
|
<div class="exam-question-card">
|
|
<div class="exam-question-card">
|
|
<!-- 标题、分数、题页 -->
|
|
<!-- 标题、分数、题页 -->
|
|
- <div class="exam-question-head">
|
|
|
|
|
|
+ <div v-if="examQuestionList.length" class="exam-question-head">
|
|
<div class="exam-question-head-left">
|
|
<div class="exam-question-head-left">
|
|
<div class="exam-question-head-left-icon"></div>
|
|
<div class="exam-question-head-left-icon"></div>
|
|
<div class="exam-question-head-left-txt">
|
|
<div class="exam-question-head-left-txt">
|
|
@@ -48,7 +48,7 @@
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- 描述 -->
|
|
<!-- 描述 -->
|
|
- <div class="exam-question-describe">
|
|
|
|
|
|
+ <div v-if="examQuestionList.length" class="exam-question-describe">
|
|
{{
|
|
{{
|
|
examQuestionList[answerIndex].questionContent ||
|
|
examQuestionList[answerIndex].questionContent ||
|
|
examQuestionList[answerIndex].content
|
|
examQuestionList[answerIndex].content
|
|
@@ -58,8 +58,11 @@
|
|
<!-- 单选题、多选题的选项区域 -->
|
|
<!-- 单选题、多选题的选项区域 -->
|
|
<div
|
|
<div
|
|
v-if="
|
|
v-if="
|
|
- examQuestionList[answerIndex].type === questionType.singleChoice ||
|
|
|
|
- examQuestionList[answerIndex].type === questionType.multipleChoice
|
|
|
|
|
|
+ examQuestionList.length &&
|
|
|
|
+ (examQuestionList[answerIndex].type ===
|
|
|
|
+ questionType.singleChoice ||
|
|
|
|
+ examQuestionList[answerIndex].type ===
|
|
|
|
+ questionType.multipleChoice)
|
|
"
|
|
"
|
|
class="exam-question-options"
|
|
class="exam-question-options"
|
|
>
|
|
>
|
|
@@ -77,15 +80,21 @@
|
|
</div>
|
|
</div>
|
|
<!-- 填空题的答题区域 -->
|
|
<!-- 填空题的答题区域 -->
|
|
<div
|
|
<div
|
|
- v-if="examQuestionList[answerIndex].type === questionType.gapFilling"
|
|
|
|
|
|
+ v-if="
|
|
|
|
+ examQuestionList.length &&
|
|
|
|
+ examQuestionList[answerIndex].type === questionType.gapFilling
|
|
|
|
+ "
|
|
class="exam-question-gapFilling"
|
|
class="exam-question-gapFilling"
|
|
>
|
|
>
|
|
<textarea
|
|
<textarea
|
|
- ref="questionInputRef"
|
|
|
|
- v-model="inputValue"
|
|
|
|
|
|
+ v-for="(item, index) in examQuestionList[answerIndex]
|
|
|
|
+ .questionInputNum"
|
|
|
|
+ :key="index"
|
|
|
|
+ :ref="'questionInputRef' + index"
|
|
|
|
+ v-model="inputValue[index]"
|
|
maxlength="200"
|
|
maxlength="200"
|
|
rows="1"
|
|
rows="1"
|
|
- @change="handleExamQuestionOptionsItemFun(inputValue)"
|
|
|
|
|
|
+ @change="handleExamQuestionOptionsItemFun(inputValue, index)"
|
|
/>
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="exam-question-button-box">
|
|
<div class="exam-question-button-box">
|
|
@@ -93,7 +102,6 @@
|
|
class="exam-question-button"
|
|
class="exam-question-button"
|
|
type="primary"
|
|
type="primary"
|
|
color="#FE6347"
|
|
color="#FE6347"
|
|
- :disabled="this.timeDiff === '00:00:00'"
|
|
|
|
@click="handleSureFun"
|
|
@click="handleSureFun"
|
|
>确定</van-button
|
|
>确定</van-button
|
|
>
|
|
>
|
|
@@ -109,6 +117,16 @@
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
+ <!-- 拍照用 -->
|
|
|
|
+ <input
|
|
|
|
+ ref="uploadUserInput"
|
|
|
|
+ type="file"
|
|
|
|
+ name="file"
|
|
|
|
+ accept="image/*"
|
|
|
|
+ capture="user"
|
|
|
|
+ @change="startTakePhotoFUn"
|
|
|
|
+ style="display: none;"
|
|
|
|
+ />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
@@ -120,15 +138,6 @@ export default {
|
|
components: {},
|
|
components: {},
|
|
data() {
|
|
data() {
|
|
return {
|
|
return {
|
|
- userInfo: {
|
|
|
|
- id: "testuser-ztdxxDGdNj",
|
|
|
|
- username: "testuser-ztdxxDGdNj",
|
|
|
|
- firstName: "string",
|
|
|
|
- lastName: "string",
|
|
|
|
- email: "string",
|
|
|
|
- encodedPassword: "string",
|
|
|
|
- userStatus: "suspended"
|
|
|
|
- },
|
|
|
|
questionType: {
|
|
questionType: {
|
|
singleChoice: "DanXuan", // 单选题
|
|
singleChoice: "DanXuan", // 单选题
|
|
multipleChoice: "DuoXuan", // 多选题
|
|
multipleChoice: "DuoXuan", // 多选题
|
|
@@ -140,7 +149,7 @@ export default {
|
|
examQuestionList: [], // 试题列表
|
|
examQuestionList: [], // 试题列表
|
|
answerIndex: null, // 当前试题的下标索引
|
|
answerIndex: null, // 当前试题的下标索引
|
|
answerValue: [], // 当前试题的所答
|
|
answerValue: [], // 当前试题的所答
|
|
- inputValue: "", // 填空题时输入框的值
|
|
|
|
|
|
+ inputValue: [], // 填空题时输入框的值
|
|
isInited: false, // 是否已初始化完毕
|
|
isInited: false, // 是否已初始化完毕
|
|
answerTime: {
|
|
answerTime: {
|
|
startTime: 0,
|
|
startTime: 0,
|
|
@@ -159,14 +168,20 @@ export default {
|
|
watch: {},
|
|
watch: {},
|
|
computed: {
|
|
computed: {
|
|
...mapState({
|
|
...mapState({
|
|
- examItem: state => state.exam.examItem
|
|
|
|
|
|
+ examItem: state => state.exam.examItem,
|
|
|
|
+ userInfo: state => state.user.userInfo
|
|
})
|
|
})
|
|
},
|
|
},
|
|
methods: {
|
|
methods: {
|
|
// 初始化数据信息
|
|
// 初始化数据信息
|
|
initDataFun() {
|
|
initDataFun() {
|
|
if (!this.examItem) {
|
|
if (!this.examItem) {
|
|
- Dialog({ message: "试题信息有误,请重新进入当前页面" });
|
|
|
|
|
|
+ Dialog.alert({
|
|
|
|
+ message: "试题信息有误,请重新进入当前页面",
|
|
|
|
+ theme: "round-button"
|
|
|
|
+ }).then(() => {
|
|
|
|
+ this.$router.back();
|
|
|
|
+ });
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
this.examStartFun(); // 方法:开始考试
|
|
this.examStartFun(); // 方法:开始考试
|
|
@@ -229,6 +244,7 @@ export default {
|
|
);
|
|
);
|
|
httpResultDataItme.typeTxt = results.typeTxt;
|
|
httpResultDataItme.typeTxt = results.typeTxt;
|
|
httpResultDataItme.questionContent = results.questionContent;
|
|
httpResultDataItme.questionContent = results.questionContent;
|
|
|
|
+ httpResultDataItme.questionInputNum = results.questionInputNum;
|
|
httpResultDataItme.userAnswer = [];
|
|
httpResultDataItme.userAnswer = [];
|
|
return httpResultDataItme;
|
|
return httpResultDataItme;
|
|
},
|
|
},
|
|
@@ -291,7 +307,7 @@ export default {
|
|
if (diffTime <= 0) {
|
|
if (diffTime <= 0) {
|
|
clearInterval(_self.interval);
|
|
clearInterval(_self.interval);
|
|
_self.timeDiff = "00:00:00";
|
|
_self.timeDiff = "00:00:00";
|
|
- this.handleSubmitFun(); // 自动交卷
|
|
|
|
|
|
+ this.examsEndFun(true); // 自动交卷
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
let hours = Math.floor(diffTime / (1000 * 60 * 60));
|
|
let hours = Math.floor(diffTime / (1000 * 60 * 60));
|
|
@@ -309,10 +325,11 @@ export default {
|
|
}
|
|
}
|
|
}, 1000);
|
|
}, 1000);
|
|
},
|
|
},
|
|
- // 方法:过滤试题的类型、填空题的题目
|
|
|
|
|
|
+ // 方法:过滤试题的类型、填空题的题目、填空题的回答框个数
|
|
formatQuestionType(type, content) {
|
|
formatQuestionType(type, content) {
|
|
let typeTxt = "";
|
|
let typeTxt = "";
|
|
let questionContent = "";
|
|
let questionContent = "";
|
|
|
|
+ let questionInputNum = 0;
|
|
switch (type) {
|
|
switch (type) {
|
|
case this.questionType.singleChoice:
|
|
case this.questionType.singleChoice:
|
|
typeTxt = "单选题";
|
|
typeTxt = "单选题";
|
|
@@ -322,16 +339,30 @@ export default {
|
|
break;
|
|
break;
|
|
case this.questionType.gapFilling:
|
|
case this.questionType.gapFilling:
|
|
typeTxt = "填空题";
|
|
typeTxt = "填空题";
|
|
- this.questionContent = content.replace("$PH$", "()");
|
|
|
|
|
|
+ console.log(content);
|
|
|
|
+ questionInputNum = this.getPlaceholderCount(content);
|
|
|
|
+ questionContent = content.replace("$PH$", "()");
|
|
|
|
+ console.log(questionContent, questionInputNum);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
return {
|
|
return {
|
|
typeTxt: typeTxt,
|
|
typeTxt: typeTxt,
|
|
- questionContent: questionContent
|
|
|
|
|
|
+ questionContent: questionContent,
|
|
|
|
+ questionInputNum: questionInputNum
|
|
};
|
|
};
|
|
},
|
|
},
|
|
|
|
+ // 方法:统计字符串中包含的特定字符个数
|
|
|
|
+ getPlaceholderCount(strSource) {
|
|
|
|
+ // 统计字符串中包含{}或{xxXX}的个数
|
|
|
|
+ let thisCount = 0;
|
|
|
|
+ strSource.replace("$PH$", function(m, i) {
|
|
|
|
+ // m为找到的{xx}元素、i为索引
|
|
|
|
+ thisCount++;
|
|
|
|
+ });
|
|
|
|
+ return thisCount;
|
|
|
|
+ },
|
|
// 操作:点击了某个题序
|
|
// 操作:点击了某个题序
|
|
handleExamQuestionItemFun(item, index) {
|
|
handleExamQuestionItemFun(item, index) {
|
|
if (this.answerIndex === index || !this.examQuestionList.length) {
|
|
if (this.answerIndex === index || !this.examQuestionList.length) {
|
|
@@ -345,14 +376,14 @@ export default {
|
|
break;
|
|
break;
|
|
case this.questionType.gapFilling:
|
|
case this.questionType.gapFilling:
|
|
this.answerValue = [...new Set(item.userAnswer)];
|
|
this.answerValue = [...new Set(item.userAnswer)];
|
|
- this.inputValue = this.answerValue[0] || "";
|
|
|
|
|
|
+ this.inputValue = this.answerValue || [];
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
},
|
|
// 操作:作答了某个选项
|
|
// 操作:作答了某个选项
|
|
- handleExamQuestionOptionsItemFun(value) {
|
|
|
|
|
|
+ handleExamQuestionOptionsItemFun(value, index) {
|
|
let answerQuestionType = this.examQuestionList[this.answerIndex].type;
|
|
let answerQuestionType = this.examQuestionList[this.answerIndex].type;
|
|
switch (answerQuestionType) {
|
|
switch (answerQuestionType) {
|
|
// 单选题
|
|
// 单选题
|
|
@@ -379,8 +410,8 @@ export default {
|
|
break;
|
|
break;
|
|
// 填空题
|
|
// 填空题
|
|
case this.questionType.gapFilling:
|
|
case this.questionType.gapFilling:
|
|
- this.$refs.questionInputRef.blur(); // 清除input的焦点
|
|
|
|
- this.answerValue = [value];
|
|
|
|
|
|
+ this.$refs["questionInputRef" + index][0].blur(); // 清除input的焦点
|
|
|
|
+ this.answerValue = value;
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
@@ -396,17 +427,49 @@ export default {
|
|
this.examQuestionList[nextIndex],
|
|
this.examQuestionList[nextIndex],
|
|
nextIndex
|
|
nextIndex
|
|
);
|
|
);
|
|
|
|
+ if (nextIndex + 1 > 3) {
|
|
|
|
+ let isPrimeVal = this.isPrime(nextIndex + 1);
|
|
|
|
+ if (isPrimeVal) {
|
|
|
|
+ this.$refs.uploadUserInput.click(); // 调用拍照工具
|
|
|
|
+ }
|
|
|
|
+ }
|
|
},
|
|
},
|
|
// 操作:确定
|
|
// 操作:确定
|
|
handleSureFun() {
|
|
handleSureFun() {
|
|
|
|
+ if (!this.examQuestionList.length) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
this.examQuestionList[this.answerIndex].userAnswer = this.answerValue;
|
|
this.examQuestionList[this.answerIndex].userAnswer = this.answerValue;
|
|
this.handleNextFun();
|
|
this.handleNextFun();
|
|
},
|
|
},
|
|
|
|
+ // 方法:判断一个数是否为质数
|
|
|
|
+ isPrime(num) {
|
|
|
|
+ // 不是数字或者数字小于2
|
|
|
|
+ if (typeof num !== "number" || !Number.isInteger(num)) {
|
|
|
|
+ // Number.isInterget 判断是否为整数
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // 2是质数
|
|
|
|
+ if (num === 2) {
|
|
|
|
+ return true;
|
|
|
|
+ } else if (num % 2 === 0) {
|
|
|
|
+ // 排除偶数
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // 依次判断是否能被奇数整除,最大循环为数值的开方
|
|
|
|
+ var squareRoot = Math.sqrt(num);
|
|
|
|
+ // 因为2已经验证过,所以从3开始;且已经排除偶数,所以每次加2
|
|
|
|
+ for (var i = 3; i <= squareRoot; i += 2) {
|
|
|
|
+ if (num % i === 0) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ },
|
|
// 操作:交卷 isAuto:true(时间到了的自动交卷) false(手动交卷)
|
|
// 操作:交卷 isAuto:true(时间到了的自动交卷) false(手动交卷)
|
|
handleSubmitFun() {
|
|
handleSubmitFun() {
|
|
let isAuto = this.timeDiff === "00:00:00";
|
|
let isAuto = this.timeDiff === "00:00:00";
|
|
if (isAuto) {
|
|
if (isAuto) {
|
|
- Dialog({ message: "考试时间已到,该考试已结束" });
|
|
|
|
this.examsEndFun(isAuto);
|
|
this.examsEndFun(isAuto);
|
|
} else {
|
|
} else {
|
|
Dialog.confirm({
|
|
Dialog.confirm({
|
|
@@ -424,11 +487,11 @@ export default {
|
|
// 方法:结束考试
|
|
// 方法:结束考试
|
|
examsEndFun(isAuto) {
|
|
examsEndFun(isAuto) {
|
|
if (isAuto) {
|
|
if (isAuto) {
|
|
- Toast("考试时间已到");
|
|
|
|
|
|
+ Dialog({ message: "考试时间已到,该考试已结束,并自动交卷" });
|
|
}
|
|
}
|
|
this.$store.commit("toggleLoading", true);
|
|
this.$store.commit("toggleLoading", true);
|
|
let grades = this.getUserExamAllPointsFun(); // 方法:计算成绩
|
|
let grades = this.getUserExamAllPointsFun(); // 方法:计算成绩
|
|
- let answers = this.getUserExamAllAnswersFun(); // 方法:获取题目的答案
|
|
|
|
|
|
+ let answers = this.getUserExamAllAnswersFun(); // 方法:获取当前用户所有题目作答的答案
|
|
let params = {
|
|
let params = {
|
|
user: this.userInfo,
|
|
user: this.userInfo,
|
|
exam: {
|
|
exam: {
|
|
@@ -461,6 +524,9 @@ export default {
|
|
})
|
|
})
|
|
.catch(() => {
|
|
.catch(() => {
|
|
this.$store.commit("toggleLoading", false);
|
|
this.$store.commit("toggleLoading", false);
|
|
|
|
+ Dialog.close();
|
|
|
|
+ Dialog({ message: "结束考试异常,请联系系统管理员" });
|
|
|
|
+ this.$router.back();
|
|
});
|
|
});
|
|
},
|
|
},
|
|
// 方法:计算成绩
|
|
// 方法:计算成绩
|
|
@@ -485,9 +551,23 @@ export default {
|
|
getUserExamAllAnswersFun() {
|
|
getUserExamAllAnswersFun() {
|
|
let answers = [];
|
|
let answers = [];
|
|
this.examQuestionList.forEach((item, index) => {
|
|
this.examQuestionList.forEach((item, index) => {
|
|
- answers[index] = item.userAnswer.join(",");
|
|
|
|
|
|
+ // answers[index] = item.userAnswer;
|
|
|
|
+ answers[index] = item.userAnswer.join("||");
|
|
});
|
|
});
|
|
return answers;
|
|
return answers;
|
|
|
|
+ },
|
|
|
|
+ // 方法:开始考试
|
|
|
|
+ startTakePhotoFUn(event) {
|
|
|
|
+ let file = event.target.files[0]; // 获取文件对象
|
|
|
|
+ if (file) {
|
|
|
|
+ // let fd = new FormData(); // 构造formdata对象
|
|
|
|
+ // fd.append("file", file); // 向formdata里面存放键值对存放图片文件
|
|
|
|
+ // fd.append("userId", this.userInfo.id); // 向formdata里面存放用户的ID
|
|
|
|
+ // console.log(fd);
|
|
|
|
+ this.$router.replace({ name: "Exam" });
|
|
|
|
+ } else {
|
|
|
|
+ Toast("请完成拍照后,再进行考试");
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
};
|