Ver código fonte

refactor faceid code; add websocket onerror logic

Michael Wang 6 anos atrás
pai
commit
d107624ba6
1 arquivos alterados com 184 adições e 208 exclusões
  1. 184 208
      src/features/OnlineExam/Examing/FaceId.vue

+ 184 - 208
src/features/OnlineExam/Examing/FaceId.vue

@@ -87,6 +87,7 @@ export default {
     };
   },
   mounted() {
+    this.examRecordId = this.$route.params.examRecordDataId;
     console.debug("startFaceVerify");
     window._hmt.push(["_trackEvent", "活体检测弹出框", "弹出框"]);
     this.startFaceVerify();
@@ -103,7 +104,7 @@ export default {
     } catch (e) {
       console.log("关闭ws异常。");
     }
-    clearTimeout(this.faceIdTime);
+    clearTimeout(this.faceIdTimeout);
     clearInterval(this.timeCountInterval);
     clearTimeout(this.iframeDomReadyTimeout);
   },
@@ -118,196 +119,61 @@ export default {
         this.redoBtnMsg = "系统繁忙,请手动点击重试";
       }
     },
-    updateFaceVerify(errorMsg, redoMsg) {
-      this.showRedo(redoMsg);
+    updateFaceVerifyMsg(errorMsg) {
       this.$http.get(
         "/api/ecs_oe_student/examFaceLivenessVerify/updateFaceLivenessVerify/" +
           this.$route.params.examRecordDataId,
         { params: { errorMsg: errorMsg } }
       );
     },
-    // checkIframeOnload() {
-    //   var iframe = document.getElementById("myFrame");
-    //   if (!iframe) {
-    //     return null;
-    //   }
-    //   var app = iframe.contentWindow.document.getElementById("app");
-    //   if (app) {
-    //     return "success";
-    //   } else {
-    //     var preLabel = iframe.contentWindow.document.getElementsByTagName(
-    //       "pre"
-    //     )[0];
-    //     if (
-    //       preLabel &&
-    //       preLabel.innerText &&
-    //       preLabel.innerText.indexOf("error_message") > -1
-    //     ) {
-    //       return preLabel.innerText;
-    //     }
-    //   }
-    //   return null;
-    // },
-    iframeLoadSuccess() {
-      window._hmt.push([
-        "_trackEvent",
-        "活体检测弹出框",
-        "FaceID页面iframe加载成功",
-      ]);
-      // try {
-      //   var iframe = document.getElementById("myFrame");
-      //   var app = iframe.contentWindow.document.getElementById("app");
-      //   app.querySelector(".footer").remove();
-      // } catch (err) {
-      //   console.error(err);
-      // }
-
-      const examRecordId = this.$route.params.examRecordDataId;
-
-      this.timeCount = 60; //人脸检测倒计时60秒
-      this.timeCountInterval = setInterval(() => {
-        --this.timeCount;
-        if (this.timeCount === 0) {
-          clearInterval(this.timeCountInterval);
-        }
-      }, 1000);
-
-      //定时事件,如果1分钟内未完成人脸检测,执行内部程序
-      this.faceIdTime = setTimeout(() => {
-        this.ws.close();
-        this.$http
-          .get(
-            "/api/ecs_oe_student/examFaceLivenessVerify/faceLivenessVerifyTimeOut/" +
-              examRecordId
-          )
-          .then(response => {
-            if (response.status == 200) {
-              var receivedMsg = response.data;
-              this.faceTestEnd(receivedMsg);
-            }
-          })
-          .finally(() => {
-            // Chrome 63开始支持。但是vue-cli引入了p-finally,所以已经加在Promise对象中了
-            clearInterval(this.timeCountInterval);
-            if (!this.faceTestEndCalled) {
-              this.$Message.error({
-                content: "人脸检测超时,系统退出,请重新登录",
-                duration: 30,
-                closable: true,
-              });
-            }
-            this.logout(
-              "?LogoutReason=" +
-                (!this.faceTestEndCalled
-                  ? "活体检测超时-可续考"
-                  : "活体检测超时")
-            );
-          });
-      }, 60000); //60000
-      /**
-       * 人脸检测结果返回后台处理
-       */
-      this.faceTestEndHandle = result => {
-        this.$http
-          .get(
-            "/api/ecs_oe_student/examFaceLivenessVerify/faceLivenessVerifyEnd/" +
-              examRecordId +
-              "?result=" +
-              result
-          )
-          .then(() => {
-            if (result != "SUCCESS") {
-              this.logout("?LogoutReason=活体检测失败");
-              window._hmt.push([
-                "_trackEvent",
-                "活体检测弹出框",
-                "活体检测失败",
-              ]);
-            } else {
-              window._hmt.push([
-                "_trackEvent",
-                "活体检测弹出框",
-                "活体检测成功",
-              ]);
-            }
-          })
-          .catch(() => {
-            this.$Message.error({
-              content: "上传人脸检测结果出错!",
-              duration: 15,
-              closable: true,
-            });
-            this.logout("?LogoutReason=上传人脸检测结果出错!");
-          });
-      };
-      /**
-       * 人脸检测结束
-       */
-      this.faceTestEnd = receivedMsg => {
-        this.faceTestEndCalled = true;
-        if (receivedMsg.verifyCount == 1) {
-          if (receivedMsg.verifyResult == "TIME_OUT") {
-            this.$Message.error({
-              content: "第一次人脸检测超时,检测失败,系统退出,请重新登录",
-              duration: 30,
-              closable: true,
-            });
-            this.logout(
-              "?LogoutReason=第一次活体检测超时,检测失败,系统退出,请重新登录"
-            );
-          } else if (receivedMsg.verifyResult == "VERIFY_FAILED") {
-            this.$Message.error({
-              content: "第一次人脸检测失败,系统退出,请重新登录",
-              duration: 30,
-              closable: true,
-            });
-            this.logout(
-              "?LogoutReason=第一次活体检测失败,系统退出,请重新登录"
-            );
-          } else if (receivedMsg.verifyResult == "NOT_ONESELF") {
-            this.$Message.error({
-              content: "人脸检测不合格,结束考试",
-              duration: 30,
-              closable: true,
-            });
-            this.faceTestEndHandle("FAILED");
-          } else if (receivedMsg.verifyResult == "VERIFY_SUCCESS") {
-            this.$Message.info({
-              content: "人脸检测成功,请继续完成考试",
-              duration: 15,
-              closable: true,
-            });
-            this.faceTestEndHandle("SUCCESS");
+    faceidLoadedButTimeouted() {
+      this.ws.close();
+      let faceTestEndCalled = false;
+      this.$http
+        .get(
+          "/api/ecs_oe_student/examFaceLivenessVerify/faceLivenessVerifyTimeOut/" +
+            this.examRecordId
+        )
+        .then(response => {
+          if (response.status == 200) {
+            var receivedMsg = response.data;
+            this.faceTestEnd(receivedMsg);
+            faceTestEndCalled = true;
           }
-        } else if (receivedMsg.verifyCount >= 2) {
-          if (receivedMsg.verifyResult == "VERIFY_SUCCESS") {
-            this.$Message.info({
-              content: "人脸检测成功,请继续完成考试",
-              duration: 15,
-              closable: true,
-            });
-            this.faceTestEndHandle("SUCCESS");
-          } else {
+        })
+        .finally(() => {
+          // Chrome 63开始支持。但是vue-cli引入了p-finally,所以已经加在Promise对象中了
+          clearInterval(this.timeCountInterval);
+          if (!faceTestEndCalled) {
             this.$Message.error({
-              content: "人脸检测不合格,结束考试",
+              content: "人脸检测超时,系统退出,请重新登录",
               duration: 30,
               closable: true,
             });
-            this.faceTestEndHandle("FAILED");
           }
-        }
-      };
-
-      // open websocket
-      this.ws = new WebSocket(VUE_APP_WK_SERVER_SOCKET + examRecordId);
+          this.logout(
+            "?LogoutReason=" +
+              (faceTestEndCalled ? "活体检测超时" : "活体检测超时-可续考")
+          );
+        });
+    },
+    openWebsocketToStartFaceIDTest() {
+      this.ws = new WebSocket(VUE_APP_WK_SERVER_SOCKET + this.examRecordId);
       this.ws.onopen = function() {
+        window._hmt.push([
+          "_trackEvent",
+          "活体检测弹出框",
+          "websocket的打开成功",
+        ]);
         console.log("websocket已连接");
       };
       this.ws.onmessage = response => {
+        console.log("faceid websocket response: ", response);
         if (response.data.indexOf("verifyResult") > -1) {
           var receivedMsg = JSON.parse(response.data);
+          // 两个结束点。第二个结束点:从websocket得到消息。
           this.faceTestEnd(receivedMsg);
-          clearTimeout(this.faceIdTime);
+          clearTimeout(this.faceIdTimeout);
           clearInterval(this.timeCountInterval);
           this.$emit("closeFaceId");
           this.ws.close();
@@ -318,17 +184,136 @@ export default {
       this.ws.onclose = function() {
         console.log("websocket连接已关闭...");
       };
+      this.ws.onerror = () => {
+        window._hmt.push([
+          "_trackEvent",
+          "活体检测弹出框",
+          "websocket连接失败",
+        ]);
+        this.showRedo("websocket连接异常,请手动点击重试");
+      };
+    },
+    /**
+     * 人脸检测结束
+     */
+    faceTestEnd(receivedMsg) {
+      if (receivedMsg.verifyCount == 1) {
+        if (receivedMsg.verifyResult == "TIME_OUT") {
+          this.$Message.error({
+            content: "第一次人脸检测超时,检测失败,系统退出,请重新登录",
+            duration: 30,
+            closable: true,
+          });
+          this.logout(
+            "?LogoutReason=第一次活体检测超时,检测失败,系统退出,请重新登录"
+          );
+        } else if (receivedMsg.verifyResult == "VERIFY_FAILED") {
+          this.$Message.error({
+            content: "第一次人脸检测失败,系统退出,请重新登录",
+            duration: 30,
+            closable: true,
+          });
+          this.logout("?LogoutReason=第一次活体检测失败,系统退出,请重新登录");
+        } else if (receivedMsg.verifyResult == "NOT_ONESELF") {
+          this.$Message.error({
+            content: "人脸检测不合格,结束考试",
+            duration: 30,
+            closable: true,
+          });
+          this.faceTestUploadResult("FAILED");
+        } else if (receivedMsg.verifyResult == "VERIFY_SUCCESS") {
+          this.$Message.info({
+            content: "人脸检测成功,请继续完成考试",
+            duration: 15,
+            closable: true,
+          });
+          this.faceTestUploadResult("SUCCESS");
+        }
+      } else if (receivedMsg.verifyCount >= 2) {
+        if (receivedMsg.verifyResult == "VERIFY_SUCCESS") {
+          this.$Message.info({
+            content: "人脸检测成功,请继续完成考试",
+            duration: 15,
+            closable: true,
+          });
+          this.faceTestUploadResult("SUCCESS");
+        } else {
+          this.$Message.error({
+            content: "人脸检测不合格,结束考试",
+            duration: 30,
+            closable: true,
+          });
+          this.faceTestUploadResult("FAILED");
+        }
+      }
+    },
+    /**
+     * 人脸检测结果返回后台处理
+     */
+    faceTestUploadResult(result) {
+      this.$http
+        .get(
+          "/api/ecs_oe_student/examFaceLivenessVerify/faceLivenessVerifyEnd/" +
+            this.examRecordId +
+            "?result=" +
+            result
+        )
+        .then(() => {
+          if (result != "SUCCESS") {
+            this.logout("?LogoutReason=活体检测失败");
+            window._hmt.push(["_trackEvent", "活体检测弹出框", "活体检测失败"]);
+          } else {
+            window._hmt.push(["_trackEvent", "活体检测弹出框", "活体检测成功"]);
+          }
+        })
+        .catch(() => {
+          this.$Message.error({
+            content: "上传人脸检测结果出错!",
+            duration: 15,
+            closable: true,
+          });
+          window._hmt.push([
+            "_trackEvent",
+            "活体检测弹出框",
+            "上传人脸检测结果出错!",
+          ]);
+          this.logout("?LogoutReason=上传人脸检测结果出错!");
+        });
+    },
+    iframeLoadSuccess() {
+      window._hmt.push([
+        "_trackEvent",
+        "活体检测弹出框",
+        "FaceID页面iframe加载成功",
+      ]);
+
+      clearInterval(this.timeCountInterval);
+      this.timeCount = 60; //人脸检测倒计时60秒
+      this.timeCountInterval = setInterval(() => {
+        --this.timeCount;
+        if (this.timeCount === 0) {
+          clearInterval(this.timeCountInterval);
+        }
+      }, 1000);
+
+      // 两个结束点。第一个结束点:超时。先传后台,再根据后台信息进行处理。可能ws没有收到处理结果,会通过http接收一遍。
+      //定时事件,如果1分钟内未完成人脸检测,执行内部程序
+      this.faceIdTimeout = setTimeout(() => {
+        this.faceidLoadedButTimeouted();
+      }, 60000); //60000
+
+      // open websocket
+      this.openWebsocketToStartFaceIDTest();
     },
     async startFaceVerify() {
       this.redoBtnDisabled = true;
       this.redoBtnMsg = "正在进入人脸检测...";
-      const examRecordId = this.$route.params.examRecordDataId;
 
       let response = null;
       try {
         response = await this.$http.get(
           "/api/ecs_oe_student/examFaceLivenessVerify/getFaceLivenessVerifyToken/" +
-            examRecordId
+            this.examRecordId
         );
       } catch (error) {
         this.$Message.error({
@@ -358,44 +343,43 @@ export default {
       } catch (err) {
         console.error(err);
       }
-      // var index = 0;
-      // var iframeLoadTime = setInterval(() => {
-      //   var iframeLoadMsg = this.checkIframeOnload();
-      //   if (!iframeLoadMsg) {
-      //     index++;
-      //     if (index == 20) {
-      //       //检测达到20次
-      //       clearInterval(iframeLoadTime);
-      //       this.showRedo("网络异常,请手动点击重试");
-      //       window._hmt.push(["_trackEvent", "活体检测弹出框", "网络异常"]);
-      //     }
-      //   } else if (iframeLoadMsg.indexOf("error_message") > -1) {
-      //     clearInterval(iframeLoadTime);
-      //     this.updateFaceVerify(iframeLoadMsg, null);
-      //   } else if (iframeLoadMsg == "success") {
-      //     clearInterval(iframeLoadTime);
-      //     // this.iframeLoadSuccess();
-      //     setTimeout(() => {
-      //       this.iframeLoadSuccess();
-      //     }, 300); // 延迟确保能删除footer
-      //   }
-      // }, 500);
 
       {
         // iframe 状态管理
+        clearTimeout(this.iframeDomReadyTimeout);
         let iframeDomReady = false;
         iframe.addEventListener("did-start-loading", () => {
           console.log("loading faceid iframe");
+          console.log(iframe);
         });
 
         iframe.addEventListener("did-fail-load", () => {
           console.log("failed loading faceid iframe");
+          clearTimeout(this.iframeDomReadyTimeout);
+          if (iframe.src.includes(".qmth.com.cn") === false) {
+            this.showRedo("网络异常,请手动点击重试");
+            window._hmt.push([
+              "_trackEvent",
+              "活体检测弹出框",
+              "网络异常-加载失败",
+            ]);
+          }
         });
 
+        // 网络异常,最后的管理
+        this.iframeDomReadyTimeout = setTimeout(() => {
+          if (iframeDomReady === false) {
+            clearTimeout(this.iframeDomReadyTimeout);
+            this.showRedo("网络异常,请手动点击重试");
+            window._hmt.push(["_trackEvent", "活体检测弹出框", "网络异常"]);
+          }
+        }, 30 * 1000);
+
         iframe.addEventListener("dom-ready", () => {
           iframeDomReady = true;
           console.log("faceid iframe dom ready");
-          // iframe.openDevTools();
+          iframe.insertCSS(".copyright { display: none !important;}");
+          iframe.openDevTools();
         });
 
         iframe.addEventListener("ipc-message", event => {
@@ -403,22 +387,14 @@ export default {
           clearInterval(this.iframeDomReadyTimeout);
           const iframeLoadMsg = event.channel;
           if (iframeLoadMsg.indexOf("error_message") > -1) {
-            this.updateFaceVerify(iframeLoadMsg, null);
+            this.showRedo();
+            this.updateFaceVerifyMsg(iframeLoadMsg);
           }
           if (iframeLoadMsg === "success") {
             this.iframeLoadSuccess();
-            iframe.send("faceid-footer", ".copyright");
+            // iframe.send("faceid-footer", ".copyright");
           }
         });
-
-        // 网络异常,最后的管理
-        this.iframeDomReadyTimeout = setTimeout(() => {
-          if (iframeDomReady === false) {
-            clearTimeout(this.iframeDomReadyTimeout);
-            this.showRedo("网络异常,请手动点击重试");
-            window._hmt.push(["_trackEvent", "活体检测弹出框", "网络异常"]);
-          }
-        }, 60 * 1000);
       }
     },
   },