فهرست منبع

阿里云SLS日志记录

Michael Wang 5 سال پیش
والد
کامیت
c0c076e516

+ 80 - 3
src/components/FaceRecognition/FaceRecognition.vue

@@ -108,11 +108,19 @@ export default {
       if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
         try {
           console.log("启动摄像头");
+          this.logger({ action: "启动摄像头" });
           console.log({
             getSupportedConstraints:
               navigator.mediaDevices.getSupportedConstraints &&
               navigator.mediaDevices.getSupportedConstraints(),
           });
+          this.logger({
+            action: "摄像头打开",
+            detail: "摄像头getSupportedConstraints",
+            getSupportedConstraints:
+              navigator.mediaDevices.getSupportedConstraints &&
+              navigator.mediaDevices.getSupportedConstraints(),
+          });
           const stream = await navigator.mediaDevices.getUserMedia({
             video: {
               facingMode: "user",
@@ -149,6 +157,9 @@ export default {
                 if (error.name == "AbortError") {
                   console.log("AbortError and retry");
                   await video.play();
+                  this.logger({
+                    action: "摄像头没有正常启用: AbortError 重试成功",
+                  });
                   window._hmt.push([
                     "_trackEvent",
                     "摄像头框",
@@ -173,8 +184,21 @@ export default {
                 "摄像头打开耗时",
                 Math.floor((_openEndTime - _openStartTime) / 1000) + "秒"
               );
+              this.logger({
+                action:
+                  "摄像头打开耗时" +
+                  Math.floor((_openEndTime - _openStartTime) / 1000) +
+                  "秒",
+              });
             } catch (error) {
               console.log("摄像头没有正常启用", error);
+              this.logger({
+                action: "摄像头没有正常启用",
+                detail: error,
+                errorName: error.name,
+                errorMessage: error.message,
+                errorStringify: JSON.stringify(error),
+              });
               this.$Message.error({
                 content: "摄像头没有正常启用: " + error,
                 duration: 15,
@@ -188,6 +212,10 @@ export default {
               ]);
             }
           } else {
+            this.logger({
+              action: "摄像头打开失败",
+              detail: "没有可用的视频流",
+            });
             this.$Message.error({
               content: "没有可用的视频流",
               duration: 15,
@@ -202,6 +230,14 @@ export default {
           }
         } catch (error) {
           console.log("无法启用摄像头", error);
+          this.logger({
+            action: "摄像头打开失败",
+            detail: "无法启用摄像头",
+            error: error.message,
+            // getSupportedConstraints:
+            //   navigator.mediaDevices.getSupportedConstraints &&
+            //   navigator.mediaDevices.getSupportedConstraints(),
+          });
           let errMsg;
           if (error.name || error.message) {
             errMsg = `${error.name} ${error.message}`;
@@ -234,16 +270,29 @@ export default {
               closable: true,
             });
           }
+
+          const errorMsgLog =
+            errMsg + (typeof errMsg === "object" ? JSON.stringify(errMsg) : "");
+          this.logger({
+            action: "摄像头打开失败",
+            detail: "无法启用摄像头",
+            error: errorMsgLog,
+            // getSupportedConstraints:
+            //   navigator.mediaDevices.getSupportedConstraints &&
+            //   navigator.mediaDevices.getSupportedConstraints(),
+          });
           window._hmt.push([
             "_trackEvent",
             "摄像头框",
             "摄像头状态",
-            "无法启用摄像头" +
-              errMsg +
-              (typeof errMsg === "object" ? JSON.stringify(errMsg) : ""),
+            "无法启用摄像头" + errorMsgLog,
           ]);
         }
       } else {
+        this.logger({
+          action: "摄像头打开失败",
+          detail: "没有找到可用的摄像头",
+        });
         this.$Message.error({
           content: "没有找到可用的摄像头",
           duration: 15,
@@ -259,8 +308,10 @@ export default {
     },
     async snapTimer() {
       try {
+        this.logger({ action: "定时抓拍开始" });
         const examRecordDataId = this.$route.params.examRecordDataId;
         const captureBlob = await this.getSnapShot({ compareSync: false });
+        this.logger({ action: "抓拍照片的大小:" + captureBlob.size });
         this.videoStartPlay();
         console.log("抓拍照片的大小:" + captureBlob.size);
         if (captureBlob.size < 48 * 48 || captureBlob.size >= 2 * 1024 * 1024) {
@@ -272,20 +323,37 @@ export default {
             "定时抓拍照片大小异常" + chromeUA.major,
             captureBlob.size,
           ]);
+          this.logger({
+            action: "摄像头异常",
+            detail: "定时抓拍照片大小异常",
+            error: captureBlob.size,
+          });
           throw "定时抓拍照片大小异常";
         }
         // this.serverLog("debug/S-004001", "抓拍照片的大小:" + captureBlob.size);
+        const startTime = Date.now();
         const [captureFilePath, signIdentifier] = await this.uploadToServer(
           captureBlob
         );
+        const endTime = Date.now();
+        this.logger({
+          action: "定时抓拍上传耗时:" + (endTime - startTime),
+        });
         await this.faceCompare(
           captureFilePath,
           signIdentifier,
           examRecordDataId
         );
+        this.logger({
+          action: "定时抓拍比对耗时:" + (Date.now() - endTime),
+        });
         console.log("定时抓拍流程成功", signIdentifier);
       } catch (error) {
         console.log("定时抓拍流程失败", error);
+        this.logger({
+          action: "定时抓拍流程失败",
+          detail: error,
+        });
         window._hmt.push([
           "_trackEvent",
           "摄像头框",
@@ -596,6 +664,15 @@ export default {
         if (cameraInfos) {
           body.cameraInfos = cameraInfos;
           body.hasVirtualCamera = hasVirtualCamera;
+
+          this.logger({
+            action: "抓拍照片详细日志",
+            fileUrl: captureFilePath,
+            signIdentifier,
+            examRecordDataId,
+            cameraInfos,
+            hasVirtualCamera,
+          });
         }
         const res = await this.$http.post(
           "/api/ecs_oe_student_face/examCaptureQueue/uploadExamCapture",

+ 23 - 2
src/features/Login/Login.vue

@@ -310,7 +310,11 @@ export default {
     }
   },
   async created() {
-    createLog({ loginPage: "登录页面-created" });
+    createLog({
+      currentPage: "登录页面",
+      action: "page created",
+      UA: navigator.userAgent,
+    });
     if (navigator.connection) {
       console.log("UA: ", navigator.userAgent);
       console.log(
@@ -455,6 +459,7 @@ export default {
     },
     async loginForuser() {
       // 供user点击的 login 方法。主要是保护 login 方法,不因为user重复点击,多个请求不按预期时间进行。
+      createLog({ currentPage: "登录页面", action: "点击登录按钮" });
       if (this.loginBtnLoading) {
         return;
       }
@@ -555,6 +560,7 @@ export default {
           ]);
           const alreadyInExam = await this.checkExamInProgress();
           if (alreadyInExam) {
+            this.logger({ action: "断点续考", detail: "登录页面" });
             window._hmt.push([
               "_trackEvent",
               "登录页面",
@@ -563,8 +569,9 @@ export default {
             ]);
             return;
           }
-          this.$router.push("/online-exam");
           window._hmt.push(["_trackEvent", "登录页面", "登录成功"]);
+          this.logger({ action: "登录成功" });
+          this.$router.push("/online-exam");
           let userIds = JSON.parse(localStorage.getItem("userIds"));
           userIds = [...new Set(userIds).add(user.id)];
           localStorage.setItem("userIds", JSON.stringify(userIds));
@@ -580,6 +587,7 @@ export default {
             "登录失败",
             "getStudentInfoBySession失败",
           ]);
+          this.logger({ action: "登录失败" });
           this.$Message.error({
             content: "获取学生信息失败,请重试!",
             duration: 15,
@@ -592,6 +600,7 @@ export default {
         }
       } else {
         window._hmt.push(["_trackEvent", "登录页面", "登录失败", data.desc]);
+        createLog({ currentPage: "登录页面", action: "登录失败" });
         this.errorInfo = data.desc;
       }
     },
@@ -709,6 +718,12 @@ export default {
           }
         } catch (error) {
           console.log(error);
+          createLog({
+            currentPage: "登录页面",
+            errorType: "e-01",
+            error: error.message,
+            detail: applicationNames,
+          });
           window._hmt.push([
             "_trackEvent",
             "登录页面",
@@ -813,6 +828,12 @@ export default {
           }
         } catch (error) {
           console.log(error);
+          createLog({
+            currentPage: "登录页面",
+            errorType: "e-02",
+            error: error.message,
+            detail: applicationNames,
+          });
           window._hmt.push([
             "_trackEvent",
             "登录页面",

+ 39 - 1
src/features/OnlineExam/Examing/ExamingHome.vue

@@ -233,10 +233,19 @@ export default {
   },
   async created() {
     this.timeoutTimeout = setTimeout(() => (this.timeouted = true), 30 * 1000);
+    this.logger({
+      action: "答题页面",
+      detail: "进入答题页面-created",
+      examRecordDataId: this.$route.params.examRecordDataId,
+    });
 
     try {
       await this.initData();
     } catch (error) {
+      this.logger({
+        action: "答题页面",
+        detail: "获取考试和试卷信息失败,退出登录",
+      });
       this.$Message.error({
         content: "获取考试和试卷信息失败,退出登录",
         duration: 15,
@@ -434,11 +443,20 @@ export default {
             !video || video.readyState !== 4 || !video.srcObject.active;
           if (videoStartFailed && initSnapshotTrialTimes < 5) {
             initSnapshotTrialTimes++;
+            this.logger({
+              action: "答题页面",
+              detail:
+                "进入考试后60秒内抓拍-" + `(第${initSnapshotTrialTimes}次尝试)`,
+            });
           } else {
             // 超过6次后,强行抓拍,如果抓拍不成功,则会因抓拍不成功而退出。
             clearInterval(this.initSnapInterval);
 
             if (videoStartFailed) {
+              this.logger({
+                action: "答题页面",
+                detail: "摄像头没有正常启用-进入考试抓拍",
+              });
               this.$Message.error({
                 content: "摄像头没有正常启用",
                 duration: 5,
@@ -458,6 +476,12 @@ export default {
                 "进入考试后60秒内抓拍-" +
                   `(第${initSnapshotTrialTimes + 1}次尝试)`
               );
+              this.logger({
+                action: "答题页面",
+                detail:
+                  "进入考试后60秒内抓拍-" +
+                  `(第${initSnapshotTrialTimes + 1}次尝试成功)`,
+              });
               this.toggleSnapNow(); // 开启抓拍才在进入考试时抓拍一张
             }
           }
@@ -483,6 +507,10 @@ export default {
             // );
             this.toggleSnapNow();
           }, SNAPSHOT_INTERVAL * 60 * 1000);
+          this.logger({
+            action: "答题页面",
+            detail: "设置抓拍间隔-" + SNAPSHOT_INTERVAL,
+          });
         }
       }
 
@@ -632,6 +660,7 @@ export default {
             }, 10 * 1000)
           );
           console.log("活检定时");
+          this.logger({ action: "活检定时", detail: faceVerifyMinute });
           const enoughTimeForFaceId = this.remainTime // 如果remainTime取到了的话
             ? this.remainTime / (60 * 1000) - 1 > faceVerifyMinute
             : true;
@@ -717,6 +746,7 @@ export default {
           return true;
         } catch (error) {
           console.log(error);
+          this.logger({ action: "提交答案失败", detail: error });
           this.$Message.error({
             content: "提交答案失败",
             duration: 15,
@@ -785,7 +815,9 @@ export default {
           return <div style="font-size: 44px">正在交卷,请耐心等待...</div>;
         },
       });
+      this.logger({ action: "正在交卷,请耐心等待..." });
       if (this.faceEnable) {
+        this.logger({ action: "交卷前抓拍" });
         this.serverLog("debug/S-002001", "交卷前抓拍");
         this.toggleSnapNow();
       }
@@ -844,6 +876,7 @@ export default {
               (this.__submitPaperEndTime - this.__submitPaperStartTime) / 1000
             ).toPrecision(1) + "秒",
           ]);
+          this.logger({ action: "交卷成功" });
           return;
         } else {
           this.$Message.error({
@@ -851,6 +884,10 @@ export default {
             duration: 15,
             closable: true,
           });
+          this.logger({
+            action: "交卷失败",
+            detail: "endExam response status is not 200",
+          });
         }
         this.submitLock = false;
       } catch (e) {
@@ -860,10 +897,10 @@ export default {
           closable: true,
         });
         console.log(e);
+        this.logger({ action: "交卷失败", detail: e });
       }
       this.submitLock = false;
       this.$Spin.hide();
-      console.log("交卷成功");
     },
     examQuestion() {
       return (
@@ -880,6 +917,7 @@ export default {
         "页面加载失败",
         "reload",
       ]);
+      this.logger({ page: "正在考试页面", action: "页面加载失败" });
       window.location.reload();
     },
   },

+ 92 - 0
src/features/OnlineExam/Examing/FaceId.vue

@@ -91,6 +91,10 @@ export default {
     this.examRecordId = this.$route.params.examRecordDataId;
     console.debug("startFaceVerify");
     window._hmt.push(["_trackEvent", "活体检测弹出框", "弹出框"]);
+    this.logger({
+      page: "活体检测弹出框",
+      action: "弹出框",
+    });
     // open websocket
     this.openWebsocketToStartFaceIDTest();
 
@@ -103,6 +107,10 @@ export default {
     }
   },
   beforeDestroy() {
+    this.logger({
+      page: "活体检测弹出框",
+      action: "关闭框",
+    });
     try {
       if (this.ws && this.ws.readyState === 1) this.ws.close();
     } catch (e) {
@@ -121,6 +129,10 @@ export default {
         this.redoBtnMsg = redoMsg;
       } else {
         this.redoBtnMsg = "系统繁忙,请手动点击重试";
+        this.logger({
+          page: "活体检测弹出框",
+          action: "系统繁忙,请手动点击重试",
+        });
       }
     },
     updateFaceVerifyMsg(errorMsg) {
@@ -146,6 +158,10 @@ export default {
               "活体检测弹出框",
               "60秒超时非websocket处理结果",
             ]);
+            this.logger({
+              page: "活体检测弹出框",
+              action: "60秒超时非websocket处理结果",
+            });
             var receivedMsg = response.data;
             shouldTimeout = false;
             this.faceTestEnd(receivedMsg);
@@ -161,6 +177,10 @@ export default {
               "活体检测弹出框",
               "60秒超时非websocket处理结果--api失败",
             ]);
+            this.logger({
+              page: "活体检测弹出框",
+              action: "60秒超时非websocket处理结果--api失败",
+            });
           });
       }
       if (!shouldTimeout) return;
@@ -187,6 +207,10 @@ export default {
               duration: 30,
               closable: true,
             });
+            this.logger({
+              page: "活体检测弹出框",
+              action: "指定动作检测超时,系统退出,请重新登录",
+            });
           }
           this.logout(
             "?LogoutReason=" +
@@ -208,6 +232,10 @@ export default {
           "websocket的打开成功",
         ]);
         console.log("websocket已连接");
+        this.logger({
+          page: "活体检测弹出框",
+          action: "websocket已连接",
+        });
       };
       this.ws.onmessage = response => {
         console.log("faceid websocket response: ", response);
@@ -227,6 +255,10 @@ export default {
             "活体检测弹出框",
             "websocket得到消息",
           ]);
+          this.logger({
+            page: "活体检测弹出框",
+            action: "websocket得到消息",
+          });
         }
       };
 
@@ -238,6 +270,10 @@ export default {
           "活体检测弹出框",
           "websocket连接关闭",
         ]);
+        this.logger({
+          page: "活体检测弹出框",
+          action: "websocket连接关闭",
+        });
       };
       this.ws.onerror = () => {
         window._hmt.push([
@@ -245,6 +281,10 @@ export default {
           "活体检测弹出框",
           "websocket连接失败",
         ]);
+        this.logger({
+          page: "活体检测弹出框",
+          action: "websocket连接失败",
+        });
         this.wsReconnectCount = this.wsReconnectCount || 0;
         this.wsReconnectCount++;
         if (!this.haveReceivedMsg && this.wsReconnectCount < 10) {
@@ -254,6 +294,11 @@ export default {
             "活体检测弹出框",
             "websocket重新连接" + this.wsReconnectCount,
           ]);
+          this.logger({
+            page: "活体检测弹出框",
+            action: "websocket重新连接",
+            detail: this.wsReconnectCount,
+          });
         }
         // this.showRedo("websocket连接异常,请手动点击重试");
       };
@@ -268,12 +313,22 @@ export default {
           "活体检测弹出框",
           "关闭websocket异常",
         ]);
+        this.logger({
+          page: "活体检测弹出框",
+          action: "关闭websocket异常",
+        });
       }
     },
     /**
      * 指定动作检测结束
      */
     faceTestEnd(receivedMsg) {
+      this.logger({
+        page: "活体检测弹出框",
+        action: "指定动作检测结束",
+        verifyCount: receivedMsg.verifyCount,
+        verifyResult: receivedMsg.verifyResult,
+      });
       if (receivedMsg.verifyCount == 1) {
         if (receivedMsg.verifyResult == "TIME_OUT") {
           this.$Message.error({
@@ -348,8 +403,16 @@ export default {
           if (result != "SUCCESS") {
             this.logout("?LogoutReason=活体检测失败");
             window._hmt.push(["_trackEvent", "活体检测弹出框", "活体检测失败"]);
+            this.logger({
+              page: "活体检测弹出框",
+              action: "活体检测失败",
+            });
           } else {
             window._hmt.push(["_trackEvent", "活体检测弹出框", "活体检测成功"]);
+            this.logger({
+              page: "活体检测弹出框",
+              action: "活体检测成功",
+            });
           }
         })
         .catch(() => {
@@ -363,6 +426,11 @@ export default {
             "活体检测弹出框",
             "上传指定动作检测结果出错!",
           ]);
+          this.logger({
+            page: "活体检测弹出框",
+            action: "上传指定动作检测结果出错!",
+          });
+          console.log("上传指定动作检测结果出错!");
           this.logout("?LogoutReason=上传指定动作检测结果出错!");
         });
     },
@@ -372,6 +440,10 @@ export default {
         "活体检测弹出框",
         "FaceID页面iframe加载成功",
       ]);
+      this.logger({
+        page: "活体检测弹出框",
+        action: "FaceID页面iframe加载成功",
+      });
 
       clearInterval(this.timeCountInterval);
       this.timeCount = 60; //指定动作检测倒计时60秒
@@ -408,6 +480,10 @@ export default {
             "活体检测弹出框",
             "网络异常-getFaceVerifyToken",
           ]);
+          this.logger({
+            page: "活体检测弹出框",
+            action: "网络异常-getFaceVerifyToken",
+          });
           return;
         }
       } else {
@@ -424,6 +500,10 @@ export default {
             duration: 15,
             closable: true,
           });
+          this.logger({
+            page: "活体检测弹出框",
+            action: "获取底照token失败,请重新登录!",
+          });
           this.logout("?LogoutReason=获取底照token失败,请重新登录!");
           return;
         }
@@ -436,6 +516,10 @@ export default {
           duration: 15,
           closable: true,
         });
+        this.logger({
+          page: "活体检测弹出框",
+          action: "您上传的底照不适合做活体检测,请联系老师!",
+        });
         this.logout("?LogoutReason=您上传的底照不适合做活体检测,请联系老师!");
         return;
       }
@@ -467,6 +551,10 @@ export default {
               "活体检测弹出框",
               "网络异常-加载失败",
             ]);
+            this.logger({
+              page: "活体检测弹出框",
+              action: "网络异常-加载失败",
+            });
           }
         });
 
@@ -476,6 +564,10 @@ export default {
             clearTimeout(this.iframeDomReadyTimeout);
             this.showRedo("网络异常,请手动点击重试");
             window._hmt.push(["_trackEvent", "活体检测弹出框", "网络异常"]);
+            this.logger({
+              page: "活体检测弹出框",
+              action: "网络异常",
+            });
           }
         }, 30 * 1000);
 

+ 17 - 0
src/features/OnlineExam/Examing/RemainTime.vue

@@ -73,6 +73,7 @@ export default {
         const res = await this.$http.get(
           "/api/ecs_oe_student/examControl/examHeartbeat"
         );
+        this.logger({ action: "发出心跳", response: res.data });
         if (/\d+/.test(res.data)) {
           if (res.data <= 0) {
             this.setShouldSubmitPaper();
@@ -103,12 +104,22 @@ export default {
             "心跳",
             "失败-会话过期",
           ]);
+          this.logger({
+            action: "发出心跳",
+            error: "心跳失败",
+            detail: "失败-会话过期",
+          });
           this.serverLog(
             "debug/S-008002",
             `心跳失败-会话过期 => 考试剩余时间:${this.remainTime / 1000}`
           );
         } else {
           window._hmt.push(["_trackEvent", "正在考试页面", "心跳", "失败"]);
+          this.logger({
+            action: "发出心跳",
+            error: "心跳失败",
+            detail: `考试剩余时间:${this.remainTime / 1000} => ${error}`,
+          });
           this.serverLog(
             "debug/S-008003",
             `心跳失败 => 考试剩余时间:${this.remainTime / 1000} => ${error}`
@@ -126,6 +137,12 @@ export default {
             "失败10次-退出",
           ]);
           const redirectUrl = sessionStorage.getItem("redirectUrl");
+          this.logger({
+            action: "发出心跳",
+            error: "心跳失败",
+            detail: `失败10次-退出`,
+          });
+          console.log(`失败10次-退出`);
           this.$Modal.error({
             title: "网络连接异常",
             content: "退出考试",

+ 16 - 1
src/features/OnlineExam/Examing/ws.js

@@ -1,6 +1,7 @@
 import store from "@/store";
 import { Message } from "iview";
 import { VUE_APP_WK_SERVER_SOCKET_FOR_AUDIO } from "@/constants/constants";
+import { createUserLog } from "@/utils/logger";
 
 let ws;
 let shouldReconnect = true;
@@ -12,6 +13,7 @@ let reconnectNumber = 0;
 export function openWS({ examRecordDataId }) {
   window._hmt.push(["_trackEvent", "websocket", "准备连接"]);
   console.log("in openWS", examRecordDataId);
+  createUserLog({ type: "websocket", action: "准备连接", examRecordDataId });
   ws = new WebSocket(
     VUE_APP_WK_SERVER_SOCKET_FOR_AUDIO +
       `?key=${store.state.user.key}&token=${store.state.user.token}`
@@ -25,6 +27,7 @@ export function openWS({ examRecordDataId }) {
 
     ws.onclose = () => {
       console.log("ws close by server");
+      createUserLog({ type: "websocket", action: "ws close by server" });
       for (const heartbeatId of heartbeatIds) {
         clearInterval(heartbeatId);
       }
@@ -52,6 +55,11 @@ export function openWS({ examRecordDataId }) {
             "websocket",
             "连接被关闭后-准备连接",
           ]);
+          createUserLog({
+            type: "websocket",
+            action: "连接被关闭后-准备连接",
+            detail: "onclose",
+          });
           openWS({ examRecordDataId });
         }, RECONNECT_INTERVAL);
       } else {
@@ -80,6 +88,11 @@ export function openWS({ examRecordDataId }) {
       }
       if (location.href.includes("/order/")) {
         window._hmt.push(["_trackEvent", "websocket", "连接错误后-重新连接"]);
+        createUserLog({
+          type: "websocket",
+          action: "连接被关闭后-准备连接",
+          detail: "onerror",
+        });
         openWS({ examRecordDataId });
       } else {
         window._hmt.push([
@@ -105,11 +118,13 @@ function heartbeat() {
 }
 
 export function closeWsWithoutReconnect() {
+  createUserLog({ type: "websocket", action: "客户端准备关闭ws。" });
   shouldReconnect = false;
   try {
     if (ws && ws.readyState === 1) ws.close();
   } catch (e) {
     console.log("关闭ws异常。");
+    createUserLog({ type: "websocket", action: "关闭ws异常。", detail: e });
   }
 }
 
@@ -130,7 +145,7 @@ export function closeWsWithoutReconnect() {
 // }
 
 function processWSMessage(event) {
-  console.log("get ws msg: ", event);
+  // console.log("get ws msg: ", event);
   let res;
   try {
     res = JSON.parse(event.data).content;

+ 5 - 2
src/features/OnlineExam/OnlineExamFaceCheckModal.vue

@@ -121,10 +121,12 @@ export default {
             title: "郑重承诺",
             content:
               "我承诺由本人参加考试,并且同意接受考试监控系统信息审核,一经发现作弊,立即取消本门课程考试成绩。",
-            onOk: () =>
+            onOk: () => {
+              this.logger({ action: "进入考试", detail: "承诺同意" });
               this.$router.push(
                 `/online-exam/exam/${this.course.examId}/overview?examStudentId=${this.course.examStudentId}`
-              ),
+              );
+            },
           });
         }
         return;
@@ -147,6 +149,7 @@ export default {
         "人脸检测成功",
       ]);
       this.toggleFaceCheckModal(false);
+      this.logger({ action: "进入考试", detail: "人脸检测成功" });
       this.$router.push(
         `/online-exam/exam/${this.course.examId}/overview?examStudentId=${this.course.examStudentId}`
       );

+ 2 - 0
src/features/OnlineExam/OnlineExamList.vue

@@ -265,6 +265,7 @@ export default {
         const alreadyInExam = await this.checkExamInProgress();
         if (alreadyInExam) {
           this.spinShow = false;
+          this.logger({ action: "断点续考", detail: "在线考试列表页面" });
           window._hmt.push([
             "_trackEvent",
             "在线考试列表页面",
@@ -427,6 +428,7 @@ export default {
         this.toggleFaceCheckModal(true);
       } else {
         this.spinShow = false;
+        this.logger({ action: "进入考试", detail: "无人脸检测" });
         window._hmt.push([
           "_trackEvent",
           "在线考试列表页面",

+ 1 - 0
src/features/OnlinePractice/OnlinePracticeList.vue

@@ -93,6 +93,7 @@ export default {
       const alreadyInExam = await this.checkExamInProgress();
       if (alreadyInExam) {
         window._hmt.push(["_trackEvent", "在线练习页面", "断点续考", "进入"]);
+        this.logger({ action: "断点续考", detail: "在线练习页面" });
         return;
       }