|
@@ -3,9 +3,29 @@
|
|
<div class="header">
|
|
<div class="header">
|
|
</div>
|
|
</div>
|
|
<div class="main">
|
|
<div class="main">
|
|
- <!-- <QuestionView :exam-question="examQuestion()"></QuestionView> -->
|
|
|
|
<div v-for="(qG, index) in questionGroupList" :key="index">
|
|
<div v-for="(qG, index) in questionGroupList" :key="index">
|
|
- <div>{{index+1}}、{{qG.groupName}} ({{qG.length}})</div>
|
|
|
|
|
|
+ <div>{{toChineseNumber(index+1)}}、{{qG.groupName}} ({{qG.groupScore}}分)</div>
|
|
|
|
+ <div v-for="(questionWrapper) in qG.questionWrapperList" :key="questionWrapper.questionId" class="question-wrapper">
|
|
|
|
+ <div v-html="restoreAudio(questionWrapper.body)"></div>
|
|
|
|
+ <div v-for="(questionUnit, index) in questionWrapper.questionUnitList" :key="index">
|
|
|
|
+ <div class="flex">
|
|
|
|
+ <div>{{questionWrapper.eqs[index].order}}、
|
|
|
|
+ </div>
|
|
|
|
+ <div v-html="restoreAudio(questionUnit.body)"></div>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-for="(optionOrder, index) in questionWrapper.eqs[index].optionPermutation" :key="index">
|
|
|
|
+ <div class="flex">
|
|
|
|
+ <div>{{indexToABCD(index)}}、</div>
|
|
|
|
+ <div v-html="restoreAudio(questionUnit.questionOptionList[optionOrder-0].body)"></div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="flex">正确答案:<div v-html="rightAnswerToABCD(questionUnit.questionType, questionUnit.rightAnswer, questionWrapper.eqs[index].optionPermutation)"></div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex">学生答案:<div v-html="questionWrapper.eqs[index].studentAnswer"></div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@@ -24,16 +44,16 @@ import QuestionNavView from "./QuestionNavView.vue";
|
|
import FaceTracking from "./FaceTracking.vue";
|
|
import FaceTracking from "./FaceTracking.vue";
|
|
import FaceId from "./FaceId.vue";
|
|
import FaceId from "./FaceId.vue";
|
|
import FaceRecognition from "../../../components/FaceRecognition/FaceRecognition";
|
|
import FaceRecognition from "../../../components/FaceRecognition/FaceRecognition";
|
|
-import { createNamespacedHelpers } from "vuex";
|
|
|
|
-const { mapState, mapMutations } = createNamespacedHelpers("examingHomeModule");
|
|
|
|
|
|
+
|
|
|
|
+const optionName = "ABCDEF".split("");
|
|
|
|
|
|
export default {
|
|
export default {
|
|
name: "ExamPaper",
|
|
name: "ExamPaper",
|
|
data() {
|
|
data() {
|
|
return {
|
|
return {
|
|
exam: null,
|
|
exam: null,
|
|
- paperStruct: null,
|
|
|
|
- questionGroupList: null
|
|
|
|
|
|
+ questionGroupList: null,
|
|
|
|
+ examQuestionList: null
|
|
};
|
|
};
|
|
},
|
|
},
|
|
props: {
|
|
props: {
|
|
@@ -48,7 +68,9 @@ export default {
|
|
const [
|
|
const [
|
|
examData,
|
|
examData,
|
|
paperStructData,
|
|
paperStructData,
|
|
- examQuestionListData
|
|
|
|
|
|
+ examQuestionListData,
|
|
|
|
+ examRecordDataData,
|
|
|
|
+ courseInfoData
|
|
] = await Promise.all([
|
|
] = await Promise.all([
|
|
this.$http.get("/api/ecs_exam_work/exam/" + this.examId),
|
|
this.$http.get("/api/ecs_exam_work/exam/" + this.examId),
|
|
this.$http.get(
|
|
this.$http.get(
|
|
@@ -58,9 +80,22 @@ export default {
|
|
this.$http.get(
|
|
this.$http.get(
|
|
"/api/ecs_oe_admin/examRecordQuestions/getExamRecordQuestions?examRecordDataId=" +
|
|
"/api/ecs_oe_admin/examRecordQuestions/getExamRecordQuestions?examRecordDataId=" +
|
|
this.examRecordDataId
|
|
this.examRecordDataId
|
|
|
|
+ ),
|
|
|
|
+ this.$http.get(
|
|
|
|
+ "/api/ecs_oe_admin/exam/record/data/findExamRecordDataEntity?examRecordDataId=" +
|
|
|
|
+ this.examRecordDataId
|
|
|
|
+ ),
|
|
|
|
+ this.$http.get(
|
|
|
|
+ "/api/ecs_oe_student/practice/getPracticeDetailInfo?examRecordDataId=" +
|
|
|
|
+ this.examRecordDataId
|
|
)
|
|
)
|
|
]);
|
|
]);
|
|
- const [exam, paperStruct] = [examData.data, paperStructData.data];
|
|
|
|
|
|
+ const [exam, paperStruct, examRecordData, courseInfo] = [
|
|
|
|
+ examData.data,
|
|
|
|
+ paperStructData.data,
|
|
|
|
+ examRecordDataData.data,
|
|
|
|
+ courseInfoData.data
|
|
|
|
+ ];
|
|
|
|
|
|
let examQuestionList = examQuestionListData.data.examQuestionEntities;
|
|
let examQuestionList = examQuestionListData.data.examQuestionEntities;
|
|
|
|
|
|
@@ -126,12 +161,94 @@ export default {
|
|
});
|
|
});
|
|
|
|
|
|
this.exam = examData.data;
|
|
this.exam = examData.data;
|
|
- this.paperStructData = paperStructData.data;
|
|
|
|
- // this.examQuestionList = examQuestionListData.data;
|
|
|
|
|
|
+ this.examQuestionList = examQuestionList;
|
|
|
|
+
|
|
|
|
+ // 子题乱序只在纯选择题中出现。选项乱序出现在任何选择题中。
|
|
|
|
+ const questionGroupList =
|
|
|
|
+ paperStructData.data.defaultPaper.questionGroupList;
|
|
|
|
+ for (const qG of questionGroupList) {
|
|
|
|
+ for (const question of qG.questionWrapperList) {
|
|
|
|
+ const qs = this.examQuestionList.filter(
|
|
|
|
+ eq => eq.questionId === question.questionId
|
|
|
|
+ );
|
|
|
|
+ // if (qs.length === 1) {
|
|
|
|
+ // const q = qs[0];
|
|
|
|
+ // Object.assign(question, {
|
|
|
|
+ // correctAnswer: q.correctAnswer,
|
|
|
|
+ // groupOrder: q.groupOrder,
|
|
|
|
+ // groupTotal: q.groupTotal,
|
|
|
|
+ // isAnswer: q.isAnswer,
|
|
|
|
+ // isSign: q.isSign,
|
|
|
|
+ // mainNumber: q.mainNumber,
|
|
|
|
+ // optionPermutation: q.optionPermutation,
|
|
|
|
+ // order: q.order,
|
|
|
|
+ // questionScore: q.questionScore,
|
|
|
|
+ // questionType: q.questionType,
|
|
|
|
+ // studentAnswer: q.studentAnswer,
|
|
|
|
+ // subNumber: q.subNumber
|
|
|
|
+ // });
|
|
|
|
+ // } else {
|
|
|
|
+ Object.assign(question, {
|
|
|
|
+ eqs: qs
|
|
|
|
+ });
|
|
|
|
+ // }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (const qG of questionGroupList) {
|
|
|
|
+ for (const question of qG.questionWrapperList) {
|
|
|
|
+ const q = await this.getQuestionContent(
|
|
|
|
+ question.questionId,
|
|
|
|
+ this.exam,
|
|
|
|
+ courseInfo,
|
|
|
|
+ examRecordData
|
|
|
|
+ );
|
|
|
|
+ question.body = q.body;
|
|
|
|
+ question.hasAudios = q.hasAudios;
|
|
|
|
+ question.questionUnitList = q.questionUnitList;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.questionGroupList = questionGroupList;
|
|
|
|
+ },
|
|
|
|
+ async getQuestionContent(questionId, exam, courseInfo, examRecordData) {
|
|
|
|
+ const qContentRes = await this.$http.post(
|
|
|
|
+ "/api/ecs_ques/default_question/question",
|
|
|
|
+ {
|
|
|
|
+ questionId: questionId,
|
|
|
|
+ examId: this.exam.id,
|
|
|
|
+ courseCode: courseInfo.courseCode,
|
|
|
|
+ groupCode: examRecordData.examRecord.paperType
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ return qContentRes.data.masterVersion;
|
|
|
|
+ },
|
|
|
|
+ restoreAudio(str) {
|
|
|
|
+ return (str || "")
|
|
|
|
+ .replace(/<a/g, "<audio controls ")
|
|
|
|
+ .replace(/url=/g, "src=")
|
|
|
|
+ .replace(/a>/g, "audio>");
|
|
|
|
+ },
|
|
|
|
+ toChineseNumber(num) {
|
|
|
|
+ return num.toLocaleString("zh-u-nu-hanidec");
|
|
|
|
+ },
|
|
|
|
+ indexToABCD(index) {
|
|
|
|
+ return optionName[index];
|
|
|
|
+ },
|
|
|
|
+ rightAnswerToABCD(questionType, studentAnswer, optionPermutation) {
|
|
|
|
+ if (["SINGLE_CHOICE", "MULTIPLE_CHOICE"].includes(questionType)) {
|
|
|
|
+ //
|
|
|
|
+ const t = studentAnswer
|
|
|
|
+ .map(v => optionPermutation.indexOf(v - 0))
|
|
|
|
+ .sort();
|
|
|
|
+ return t.map(v => this.indexToABCD(v + "")).join("");
|
|
|
|
+ } else if (["TRUE_OR_FALSE"].includes(questionType)) {
|
|
|
|
+ return { true: "正确", false: "错误" }[studentAnswer.join("")];
|
|
|
|
+ }
|
|
|
|
+ return studentAnswer.join("");
|
|
}
|
|
}
|
|
},
|
|
},
|
|
computed: {},
|
|
computed: {},
|
|
- watch: {},
|
|
|
|
components: {
|
|
components: {
|
|
RemainTime,
|
|
RemainTime,
|
|
OverallProgress,
|
|
OverallProgress,
|
|
@@ -147,69 +264,18 @@ export default {
|
|
</script>
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
<style scoped>
|
|
-.container {
|
|
|
|
- display: grid;
|
|
|
|
- grid-template-areas:
|
|
|
|
- "header header"
|
|
|
|
- "main side";
|
|
|
|
- grid-template-rows: 80px 1fr;
|
|
|
|
- grid-template-columns: 1fr 400px;
|
|
|
|
-
|
|
|
|
- height: 100vh;
|
|
|
|
- width: 100vw;
|
|
|
|
- overflow: auto;
|
|
|
|
|
|
+.flex {
|
|
|
|
+ display: flex;
|
|
}
|
|
}
|
|
|
|
|
|
-.header {
|
|
|
|
- display: grid;
|
|
|
|
- align-items: center;
|
|
|
|
- justify-items: center;
|
|
|
|
- grid-template-columns: 200px 1fr 300px 100px;
|
|
|
|
- grid-area: header;
|
|
|
|
- height: 80px;
|
|
|
|
- background-color: #f5f5f5;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-.main {
|
|
|
|
- display: grid;
|
|
|
|
- grid-area: main;
|
|
|
|
- grid-template-rows: 1fr 50px;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-.side {
|
|
|
|
- display: grid;
|
|
|
|
- grid-area: side;
|
|
|
|
- grid-template-rows: 1fr 250px;
|
|
|
|
- background-color: #f5f5f5;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-.side-row-size {
|
|
|
|
- grid-template-rows: 1fr;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-.question-nav {
|
|
|
|
- overflow-y: scroll;
|
|
|
|
- max-height: calc(100vh - 300px);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-.question-nav-long {
|
|
|
|
- max-height: calc(100vh - 100px);
|
|
|
|
|
|
+.container {
|
|
|
|
+ text-align: left;
|
|
|
|
+ padding: 20px;
|
|
}
|
|
}
|
|
|
|
|
|
-.camera {
|
|
|
|
- align-self: flex-end;
|
|
|
|
- justify-self: flex-end;
|
|
|
|
|
|
+.header {
|
|
}
|
|
}
|
|
-
|
|
|
|
-@media screen and (max-height: 768px) {
|
|
|
|
- .container {
|
|
|
|
- grid-template-rows: 50px minmax(0, 1fr);
|
|
|
|
- }
|
|
|
|
- .header {
|
|
|
|
- height: 50px;
|
|
|
|
- }
|
|
|
|
- .side {
|
|
|
|
- grid-template-rows: minmax(0, 1fr) 200px;
|
|
|
|
- }
|
|
|
|
|
|
+.question-wrapper {
|
|
|
|
+ padding-bottom: 20px;
|
|
}
|
|
}
|
|
</style>
|
|
</style>
|