Michael Wang 6 жил өмнө
parent
commit
1ea45be181

+ 78 - 20
src/components/FaceRecognition/FaceRecognition.vue

@@ -9,7 +9,9 @@
 </template>
 
 <script>
-import { mapState } from "vuex";
+import { mapState as globalMapState } from "vuex";
+import { createNamespacedHelpers } from "vuex";
+const { mapState, mapMutations } = createNamespacedHelpers("examingHomeModule");
 import {
   UPYUN_URL,
   FACEPP_API,
@@ -32,6 +34,12 @@ export default {
     this.openCamera();
   },
   watch: {
+    snapNow(val) {
+      if (val) {
+        this.snapTimer();
+        this.toggleSnapNow();
+      }
+    },
     closeCamera: function(newValue) {
       if (newValue) {
         console.log("关闭摄像头");
@@ -49,6 +57,7 @@ export default {
     });
   },
   methods: {
+    ...mapMutations(["toggleSnapNow"]),
     async openCamera() {
       const video = this.$refs.video;
 
@@ -69,19 +78,33 @@ export default {
         this.$Message.error("没有找到可用的摄像头");
       }
     },
-    // TODO: 定时抓拍
-    snap() {
+    async snapTimer() {
+      const captureBlob = await this.getSnapShot();
+      const captureFilePath = await this.uploadToServer(captureBlob);
+      await this.faceCompare(captureFilePath);
       const video = this.$refs.video;
-      video.pause();
-      var canvas = document.createElement("canvas");
-      canvas.width = 220;
-      canvas.height = 165;
+      video && video.play();
+    },
+    async snap() {
+      const captureBlob = await this.getSnapShot();
+      const captureFilePath = await this.uploadToServer(captureBlob);
+      await this.faceCompareSync(UPYUN_URL + captureFilePath);
+      const video = this.$refs.video;
+      video && video.play();
+    },
+    async getSnapShot() {
+      return new Promise((resolve, reject) => {
+        const video = this.$refs.video;
+        video.pause();
+        var canvas = document.createElement("canvas");
+        canvas.width = 220;
+        canvas.height = 165;
 
-      var context = canvas.getContext("2d");
-      context.drawImage(video, 0, 0, 220, 165);
+        var context = canvas.getContext("2d");
+        context.drawImage(video, 0, 0, 220, 165);
 
-      canvas.toBlob(this.uploadToServer);
-      video.play();
+        canvas.toBlob(resolve);
+      });
     },
     async uploadToServer(captureBlob) {
       //保存抓拍照片到又拍云
@@ -99,18 +122,13 @@ export default {
         return;
       }
 
-      const captureFilePath =
-        UPYUN_URL + "/capture_photo/" + this.user.userId + "/" + fileName;
-      await this.faceCompare(captureFilePath);
+      return "/capture_photo/" + this.user.userId + "/" + fileName;
     },
-    async faceCompare(captureFilePath) {
+    async faceCompareSync(captureFilePath) {
       try {
         const res = await this.$http.post(
           "/api/ecs_oe_student_face/examCaptureQueue/compareFaceSync?fileUrl=" +
-            captureFilePath,
-          {
-            fileUrl: captureFilePath
-          }
+            captureFilePath
         );
 
         // TODO: 识别成功、失败的通知或跳转
@@ -124,10 +142,50 @@ export default {
         this.$Message.error(e.message);
         return;
       }
+    },
+    async faceCompare(captureFilePath) {
+      try {
+        const res = await this.$http.post(
+          "/api/ecs_oe_student_face/examCaptureQueue/uploadExamCapture?fileUrl=" +
+            UPYUN_URL +
+            captureFilePath +
+            "&fileName=" +
+            captureFilePath +
+            "&examRecordDataId=" +
+            this.$route.params.examRecordDataId
+        );
+        this.showSnapResult(captureFilePath);
+      } catch (e) {
+        console.log(e);
+        this.$Message.error(e.message);
+        return;
+      }
+    },
+    async showSnapResult(captureFilePath) {
+      try {
+        // 获取抓拍结果
+        const snapRes = (await this.$http.get(
+          "/api/ecs_oe_student_face/examCaptureQueue/getExamCaptureResult?fileName=" +
+            captureFilePath +
+            "&examRecordDataId=" +
+            this.$route.params.examRecordDataId
+        )).data;
+        if (snapRes) {
+          if (snapRes.stranger) {
+            this.$Message.error("请独立考试");
+          }
+        } else {
+          setTimeout(this.showSnapResult.bind(this, captureFilePath), 3000);
+        }
+      } catch (e) {
+        console.log(e);
+        this.$Message.error(e.message);
+      }
     }
   },
   computed: {
-    ...mapState(["user"])
+    ...globalMapState(["user"]),
+    ...mapState(["snapNow"])
   }
 };
 </script>

+ 8 - 4
src/features/OnlineExam/Examing/ExamingHome.vue

@@ -15,7 +15,7 @@
         <QuestionNavView :paperStruct="paperStruct" />
       </div>
       <div class="camera">
-        <!-- <FaceRecognition width="100%" height="100%" :showRecognizeButton="false" /> -->
+        <FaceRecognition width="100%" height="100%" :showRecognizeButton="false" />
       </div>
     </div>
   </div>
@@ -41,12 +41,16 @@ export default {
       this.$router.push(this.$route.fullPath + "/order/1");
       return;
     }
+
+    setInterval(() => {
+      this.toggleSnapNow();
+    }, 30000);
   },
   // beforeRouteUpdate(to, from, next) {
   //   this.updateQuestion(next);
   // },
   methods: {
-    ...mapMutations(["updateExamState"]),
+    ...mapMutations(["updateExamState", "toggleSnapNow"]),
     async initData() {
       const exam = await this.$http.get(
         "/api/ecs_exam_work/exam/" + this.$route.params.examId
@@ -82,7 +86,7 @@ export default {
     },
     async submitPaper() {
       //FIXME: submit precondition
-      await this.$http.get("/api/exam_control/submit");
+      await this.$http.get("/api/ecs_oe_student/examControl/endExam");
       this.$router.push("/");
     },
     examQuestion() {
@@ -95,7 +99,7 @@ export default {
     }
   },
   computed: {
-    ...mapState(["exam", "paperStruct", "examQuestionList"]),
+    ...mapState(["exam", "paperStruct", "examQuestionList", "snapNow"]),
     previousQuestionOrder: vm => {
       if (vm.examQuestion().order > 1) {
         return vm.examQuestion().order - 1;

+ 13 - 1
src/features/OnlineExam/Examing/SingleQuestionView.vue

@@ -19,7 +19,7 @@
 <script>
 import QuestionBody from "./QuestionBody";
 import { createNamespacedHelpers } from "vuex";
-const { mapMutations } = createNamespacedHelpers("examingHomeModule");
+const { mapState, mapMutations } = createNamespacedHelpers("examingHomeModule");
 
 const optionName = ["A", "B", "C", "D", "E", "F"];
 export default {
@@ -84,6 +84,18 @@ export default {
       this.questionBody = this.question.body;
     }
   },
+  computed: {
+    ...mapState(["paperStruct"]),
+    newQuestionOptions() {
+      // TODO: 更换选项,取得paperstruct对应的值
+      const per = this.paperStruct.defaultPaper.questionGruopList[
+        this.examQuestion.order
+      ].questionUnitWrapperList[0].optionPermutation;
+      return this.question.questionOptionList.map((value, index) => {
+        return { value, oldIndex: index, newIndex: per[index] };
+      });
+    }
+  },
   components: {
     QuestionBody
   }

+ 5 - 1
src/store.js

@@ -25,9 +25,13 @@ const examingHomeModule = {
     exam: null,
     paperStruct: null,
     examQuestionList: null,
-    questionFilterType: "ALL"
+    questionFilterType: "ALL",
+    snapNow: false
   },
   mutations: {
+    toggleSnapNow(state) {
+      state.snapNow = !state.snapNow;
+    },
     updateExamState(state, payload) {
       state = Object.assign(state, payload);
     },