浏览代码

完善处理网络异常处理。big update。

Michael Wang 6 年之前
父节点
当前提交
74275e205d

+ 51 - 28
src/components/FaceRecognition/FaceRecognition.vue

@@ -76,15 +76,21 @@ export default {
       }
       }
     },
     },
     async snapTimer() {
     async snapTimer() {
-      const examRecordDataId = this.$route.params.examRecordDataId;
-      const captureBlob = await this.getSnapShot();
-      const [fileName, captureFilePath] = await this.uploadToServer(
-        captureBlob
-      );
-      await this.faceCompare(fileName, captureFilePath, examRecordDataId);
-      this.decreaseSnapCount();
-      const video = this.$refs.video;
-      video && video.play();
+      try {
+        const examRecordDataId = this.$route.params.examRecordDataId;
+        const captureBlob = await this.getSnapShot();
+        const [fileName, captureFilePath] = await this.uploadToServer(
+          captureBlob
+        );
+        await this.faceCompare(fileName, captureFilePath, examRecordDataId);
+      } catch (error) {
+        // FIXME: more processing
+        console.log("定时抓拍流程失败");
+      } finally {
+        const video = this.$refs.video;
+        video && video.play();
+        this.decreaseSnapCount();
+      }
     },
     },
     async snap() {
     async snap() {
       // TODO: chrome 70. FaceDetector检测人脸
       // TODO: chrome 70. FaceDetector检测人脸
@@ -98,17 +104,24 @@ export default {
       // const v = await f.detect(canvas);
       // const v = await f.detect(canvas);
       // console.log(v);
       // console.log(v);
       // return;
       // return;
-      this.disableSnap = true;
-      this.msg = "拍照中...";
-      const captureBlob = await this.getSnapShot();
-      this.msg = "上传照片中...";
-      const [, captureFilePath] = await this.uploadToServer(captureBlob);
-      this.msg = "人脸比对中...";
-      await this.faceCompareSync(captureFilePath);
-      const video = this.$refs.video;
-      video && video.play();
-      this.msg = "开始识别";
-      this.disableSnap = false;
+
+      try {
+        this.disableSnap = true;
+        this.msg = "拍照中...";
+        const captureBlob = await this.getSnapShot();
+        this.msg = "上传照片中...";
+        const [, captureFilePath] = await this.uploadToServer(captureBlob);
+        this.msg = "人脸比对中...";
+        await this.faceCompareSync(captureFilePath);
+      } catch (error) {
+        // FIXME: more processing
+        console.log("同步照片比对流程失败");
+      } finally {
+        const video = this.$refs.video;
+        video && video.play();
+        this.msg = "开始识别";
+        this.disableSnap = false;
+      }
     },
     },
     async getSnapShot() {
     async getSnapShot() {
       return new Promise(resolve => {
       return new Promise(resolve => {
@@ -136,13 +149,18 @@ export default {
         });
         });
       } catch (e) {
       } catch (e) {
         console.log(e);
         console.log(e);
-        this.$Message.error(e.message);
-        return;
+        this.$Message.error("保存抓拍照片到又拍云失败!");
+        throw "保存抓拍照片到又拍云失败!";
       }
       }
 
 
-      const UPYUN_URL = (await this.$http.get("/api/ecs_oe_student_face/upyun"))
-        .data.downloadPrefix;
-
+      let UPYUN_URL;
+      try {
+        UPYUN_URL = (await this.$http.get("/api/ecs_oe_student_face/upyun"))
+          .data.downloadPrefix;
+      } catch (error) {
+        this.$Message.error("获取又拍云下载前缀失败!");
+        throw "获取又拍云下载前缀失败!";
+      }
       return [
       return [
         fileName,
         fileName,
         UPYUN_URL + "/capture_photo/" + this.user.userId + "/" + fileName
         UPYUN_URL + "/capture_photo/" + this.user.userId + "/" + fileName
@@ -164,7 +182,7 @@ export default {
       } catch (e) {
       } catch (e) {
         console.log(e);
         console.log(e);
         // this.$Message.error(e.message);
         // this.$Message.error(e.message);
-        return;
+        throw "同步照片比较失败!";
       }
       }
     },
     },
     async faceCompare(fileName, captureFilePath, examRecordDataId) {
     async faceCompare(fileName, captureFilePath, examRecordDataId) {
@@ -177,11 +195,15 @@ export default {
             "&examRecordDataId=" +
             "&examRecordDataId=" +
             examRecordDataId
             examRecordDataId
         );
         );
-        await this.showSnapResult(fileName, examRecordDataId);
+        try {
+          await this.showSnapResult(fileName, examRecordDataId);
+        } catch (error) {
+          this.$Message.error("设置获取抓拍结果失败!");
+        }
       } catch (e) {
       } catch (e) {
         console.log(e);
         console.log(e);
         this.$Message.error(e.message);
         this.$Message.error(e.message);
-        return;
+        throw "异步比较抓拍照片失败";
       }
       }
     },
     },
     async showSnapResult(fileName, examRecordDataId) {
     async showSnapResult(fileName, examRecordDataId) {
@@ -213,6 +235,7 @@ export default {
       } catch (e) {
       } catch (e) {
         console.log(e);
         console.log(e);
         this.$Message.error(e.message);
         this.$Message.error(e.message);
+        throw e.message;
       }
       }
     }
     }
   },
   },

+ 40 - 37
src/features/Login/Login.vue

@@ -120,9 +120,18 @@ export default {
       var fs = window.nodeRequire("fs");
       var fs = window.nodeRequire("fs");
       var config = fs.readFileSync("config.js", "utf-8");
       var config = fs.readFileSync("config.js", "utf-8");
       var nameJson = JSON.parse(config);
       var nameJson = JSON.parse(config);
-      const electronConfig = (await this.$http.get(
-        "https://ecs.qmth.com.cn:8878/electron-config/" + nameJson.name + ".js"
-      )).data;
+
+      let electronConfig = null;
+      try {
+        electronConfig = (await this.$http.get(
+          "https://ecs.qmth.com.cn:8878/electron-config/" +
+            nameJson.name +
+            ".js"
+        )).data;
+      } catch (error) {
+        this.$Message.error("获取机构的客户端设置失败,请退出后重试!");
+        return;
+      }
 
 
       //如果配置中配置了  checkRemoteControl:true
       //如果配置中配置了  checkRemoteControl:true
       if (electronConfig.otherConfig.checkRemoteControl) {
       if (electronConfig.otherConfig.checkRemoteControl) {
@@ -165,51 +174,45 @@ export default {
       } else {
       } else {
         return;
         return;
       }
       }
+
       let repPara = this.loginForm;
       let repPara = this.loginForm;
-      try {
-        const response = await this.$http.post("/api/ecs_core/auth/login", {
-          ...repPara,
-          accountType: this.loginType,
-          domain: this.$route.params.domain
+      // 以下网络请求失败,直接报网络异常错误
+      const response = await this.$http.post("/api/ecs_core/auth/login", {
+        ...repPara,
+        accountType: this.loginType,
+        domain: this.$route.params.domain
+      });
+      let data = response.data;
+      if (Math.abs(moment(response.headers.date).diff(moment())) > 30 * 1000) {
+        this.$Message.error({
+          content: "与服务器时间差异超过30秒,请校准本机时间之后再重试!",
+          duration: 30
         });
         });
-        let data = response.data;
-        if (
-          Math.abs(moment(response.headers.date).diff(moment())) >
-          30 * 1000
-        ) {
-          this.$Message.error({
-            content: "与服务器时间差异超过30秒,请校准本机时间之后再重试!",
-            duration: 30
-          });
-          throw "与服务器时间差异超过30秒,请校准本机时间之后再重试!";
-        }
-        if (data.token) {
-          this.errorInfo = "";
-          //缓存用户信息
-          window.sessionStorage.setItem("token", data.token);
-          window.localStorage.setItem("key", data.key);
-          window.localStorage.setItem("domain", this.$route.params.domain);
+        throw "与服务器时间差异超过30秒,请校准本机时间之后再重试!";
+      }
+      if (data.token) {
+        this.errorInfo = "";
+        //缓存用户信息
+        window.sessionStorage.setItem("token", data.token);
+        window.localStorage.setItem("key", data.key);
+        window.localStorage.setItem("domain", this.$route.params.domain);
 
 
+        try {
           const student = (await this.$http.get(
           const student = (await this.$http.get(
             "/api/ecs_core/student/getStudentInfoBySession"
             "/api/ecs_core/student/getStudentInfoBySession"
           )).data;
           )).data;
-          if (student === undefined) {
-            this.$Message.error({
-              content: "获取学生信息失败,请重试!",
-              duration: 30
-            });
-            throw "获取学生信息失败,请重试!";
-          }
           const user = { ...data, ...student };
           const user = { ...data, ...student };
           this.updateUser(user);
           this.updateUser(user);
           window.localStorage.setItem("user-for-reload", JSON.stringify(user));
           window.localStorage.setItem("user-for-reload", JSON.stringify(user));
           this.$router.push("/online-exam");
           this.$router.push("/online-exam");
-        } else {
-          this.errorInfo = data.desc;
+        } catch (error) {
+          this.$Message.error({
+            content: "获取学生信息失败,请重试!",
+            duration: 30
+          });
         }
         }
-      } catch (e) {
-        console.log(e);
-        // this.$Message.error(e);
+      } else {
+        this.errorInfo = data.desc;
       }
       }
     },
     },
     closeApp() {
     closeApp() {

+ 5 - 1
src/features/OfflineExam/OfflineExamHome.vue

@@ -22,7 +22,11 @@ export default {
     };
     };
   },
   },
   async mounted() {
   async mounted() {
-    await this.fetchData();
+    try {
+      await this.fetchData();
+    } catch (error) {
+      this.$Message.error("获取离线考试列表失败");
+    }
   },
   },
   methods: {
   methods: {
     async fetchData() {
     async fetchData() {

+ 1 - 0
src/features/OfflineExam/OfflineExamList.vue

@@ -76,6 +76,7 @@ export default {
   },
   },
   methods: {
   methods: {
     async enterExam(course) {
     async enterExam(course) {
+      // 若出错,直接报网络异常
       await this.$http.get("/api/ecs_oe_student/offlineExam/startOfflineExam", {
       await this.$http.get("/api/ecs_oe_student/offlineExam/startOfflineExam", {
         params: { examStudentId: course.examStudentId }
         params: { examStudentId: course.examStudentId }
       });
       });

+ 18 - 17
src/features/OnlineExam/Examing/ExamingEnd.vue

@@ -4,6 +4,8 @@
     <div class="instructions">
     <div class="instructions">
       <h1 class="">考试已结束</h1>
       <h1 class="">考试已结束</h1>
       <div><img class="user-avatar" :src="user.photoPath" alt="无底照" /></div>
       <div><img class="user-avatar" :src="user.photoPath" alt="无底照" /></div>
+      <div class="qm-big-text score-text" v-if="!examResult">答案获取中...</div>
+      <div class="qm-big-text score-text" v-if="!examResult && getResultTimes > 30">后台繁忙,请稍后在待考列表中查看客观题得分。</div>
       <div class="qm-big-text score-text" v-if="showObjectScore && !examResult.isWarn">客观题得分: <span style="color: red">{{examResult.objectiveScore}}</span></div>
       <div class="qm-big-text score-text" v-if="showObjectScore && !examResult.isWarn">客观题得分: <span style="color: red">{{examResult.objectiveScore}}</span></div>
       <div class="qm-big-text score-text" v-if="exam.examType !== 'ONLINE' && showObjectScore && !examResult.isWarn">客观题正确率: <span style="color: red">{{examResult.objectiveAccuracy}}%</span></div>
       <div class="qm-big-text score-text" v-if="exam.examType !== 'ONLINE' && showObjectScore && !examResult.isWarn">客观题正确率: <span style="color: red">{{examResult.objectiveAccuracy}}%</span></div>
       <div class="qm-big-text score-text" v-if="examResult.isWarn">客观题得分: 成绩待审核</div>
       <div class="qm-big-text score-text" v-if="examResult.isWarn">客观题得分: 成绩待审核</div>
@@ -21,13 +23,6 @@
 
 
     </div>
     </div>
 
 
-    <!-- <div class="exam-detail">
-      <h3 class="">科目:{{exam.name}}</h3>
-      <br>
-      <h4 class="">试卷总分:{{paperTotalScore}}</h4>
-      <br>
-    </div> -->
-
   </div>
   </div>
 
 
   <div v-else>
   <div v-else>
@@ -47,22 +42,28 @@ export default {
       showObjectScore: null,
       showObjectScore: null,
       paperTotalScore: null,
       paperTotalScore: null,
       cheatingRemark: null,
       cheatingRemark: null,
-      examResult: null
+      examResult: null,
+      getResultTimes: 0
     };
     };
   },
   },
   async mounted() {
   async mounted() {
     const examRecordDataId = this.$route.params.examRecordDataId;
     const examRecordDataId = this.$route.params.examRecordDataId;
     const f = async () => {
     const f = async () => {
-      const examResult = (await this.$http.get(
-        "/api/ecs_oe_student/examControl/getEndExamInfo?examRecordDataId=" +
-          examRecordDataId
-      )).data;
-
-      if (examResult === undefined || examResult === null) {
-        setTimeout(f, 3000);
-        return;
+      try {
+        this.getResultTimes = this.getResultTimes + 1;
+        const examResult = (await this.$http.get(
+          "/api/ecs_oe_student/examControl/getEndExamInfo?examRecordDataId=" +
+            examRecordDataId
+        )).data;
+
+        if (examResult === undefined || examResult === null) {
+          setTimeout(() => f(), 3000);
+          return;
+        }
+        this.examResult = examResult;
+      } catch (error) {
+        setTimeout(() => f(), 3000);
       }
       }
-      this.examResult = examResult;
     };
     };
     await f();
     await f();
 
 

+ 44 - 24
src/features/OnlineExam/Examing/ExamingHome.vue

@@ -50,7 +50,13 @@ export default {
   },
   },
   async created() {
   async created() {
     this.timeoutTimeout = setTimeout(() => (this.timeouted = true), 30 * 1000);
     this.timeoutTimeout = setTimeout(() => (this.timeouted = true), 30 * 1000);
-    await this.initData();
+    try {
+      await this.initData();
+    } catch (error) {
+      this.$Message.error("获取试卷信息失败,退出登录");
+      this.logout();
+      return;
+    }
 
 
     // 仅在线上使用活体检测
     // 仅在线上使用活体检测
     if (
     if (
@@ -73,16 +79,19 @@ export default {
     //   // }, this.$route.query.faceVerifyMinute * 60 * 1000); // 定时做活体检测
     //   // }, this.$route.query.faceVerifyMinute * 60 * 1000); // 定时做活体检测
     // }, 5 * 1000); // 定时做活体检测
     // }, 5 * 1000); // 定时做活体检测
 
 
-    const faceEnable = await this.$http.get(
-      "/api/ecs_exam_work/exam/examOrgProperty/" +
-        this.$route.params.examId +
-        `/IS_FACE_ENABLE`
-    );
-    if (faceEnable.data === undefined) {
+    let faceEnable;
+    try {
+      faceEnable = await this.$http.get(
+        "/api/ecs_exam_work/exam/examOrgProperty/" +
+          this.$route.params.examId +
+          `/IS_FACE_ENABLE`
+      );
+    } catch (error) {
       this.$Message.error("获取人脸检测设置失败");
       this.$Message.error("获取人脸检测设置失败");
       this.logout();
       this.logout();
       return;
       return;
     }
     }
+
     if (faceEnable.data) {
     if (faceEnable.data) {
       this.faceEnable = true;
       this.faceEnable = true;
 
 
@@ -90,22 +99,23 @@ export default {
         this.toggleSnapNow(); // 开启抓拍才在进入考试时抓拍一张
         this.toggleSnapNow(); // 开启抓拍才在进入考试时抓拍一张
       }, 5 * 1000); // 5秒钟后抓拍
       }, 5 * 1000); // 5秒钟后抓拍
 
 
-      const snapshotInterval = await this.$http.get(
-        "/api/ecs_exam_work/exam/examOrgProperty/" +
-          this.$route.params.examId +
-          `/SNAPSHOT_INTERVAL`
-      );
-      if (snapshotInterval.data === undefined) {
+      try {
+        const snapshotInterval = await this.$http.get(
+          "/api/ecs_exam_work/exam/examOrgProperty/" +
+            this.$route.params.examId +
+            `/SNAPSHOT_INTERVAL`
+        );
+        if (snapshotInterval.data) {
+          // 考务设置抓拍间隔
+          this.snapInterval = setInterval(() => {
+            this.toggleSnapNow();
+          }, snapshotInterval.data * 60 * 1000);
+        }
+      } catch (error) {
         this.$Message.error("获取人脸抓拍间隔设置失败");
         this.$Message.error("获取人脸抓拍间隔设置失败");
         this.logout();
         this.logout();
         return;
         return;
       }
       }
-      if (snapshotInterval.data) {
-        // 考务设置抓拍间隔
-        this.snapInterval = setInterval(() => {
-          this.toggleSnapNow();
-        }, snapshotInterval.data * 60 * 1000);
-      }
     }
     }
 
 
     this.submitInterval = setInterval(
     this.submitInterval = setInterval(
@@ -257,15 +267,24 @@ export default {
           );
           );
         });
         });
       if (answers.length > 0) {
       if (answers.length > 0) {
-        await this.$http.post(
-          "/api/ecs_oe_student/examQuestion/submitQuestionAnswer",
-          answers
-        );
+        try {
+          await this.$http.post(
+            "/api/ecs_oe_student/examQuestion/submitQuestionAnswer",
+            answers
+          );
+        } catch (error) {
+          console.log(error);
+          this.$Message.error("提交答案失败");
+        }
         this.resetExamQuestionDirty();
         this.resetExamQuestionDirty();
       }
       }
     },
     },
     async submitPaper() {
     async submitPaper() {
-      await this.answerAllQuestions();
+      try {
+        await this.answerAllQuestions();
+      } catch (error) {
+        return;
+      }
 
 
       const answered = this.examQuestionList.filter(
       const answered = this.examQuestionList.filter(
         q => q.studentAnswer !== null
         q => q.studentAnswer !== null
@@ -331,6 +350,7 @@ export default {
         }
         }
         this.submitLock = false;
         this.submitLock = false;
       } catch (e) {
       } catch (e) {
+        this.$Message.error("交卷失败");
         console.log(e);
         console.log(e);
       }
       }
       this.submitLock = false;
       this.submitLock = false;

+ 15 - 7
src/features/OnlineExam/Examing/FaceId.vue

@@ -44,6 +44,9 @@ export default {
     this.startFaceVerify();
     this.startFaceVerify();
   },
   },
   methods: {
   methods: {
+    logout() {
+      this.$router.push("/login/" + localStorage.getItem("domain"));
+    },
     showRedo(redoMsg) {
     showRedo(redoMsg) {
       this.showIframe = false;
       this.showIframe = false;
       this.redoBtnDisabled = false;
       this.redoBtnDisabled = false;
@@ -103,9 +106,6 @@ export default {
         }
         }
       }, 1000);
       }, 1000);
 
 
-      this.logout = () => {
-        this.$router.push("/login/" + localStorage.getItem("domain"));
-      };
       //定时事件,如果1分钟内未完成人脸检测,执行内部程序
       //定时事件,如果1分钟内未完成人脸检测,执行内部程序
       var faceIdTime = setTimeout(() => {
       var faceIdTime = setTimeout(() => {
         ws.close();
         ws.close();
@@ -215,10 +215,18 @@ export default {
       this.redoBtnDisabled = true;
       this.redoBtnDisabled = true;
       this.redoBtnMsg = "正在进入人脸检测...";
       this.redoBtnMsg = "正在进入人脸检测...";
       const examRecordId = this.$route.params.examRecordDataId;
       const examRecordId = this.$route.params.examRecordDataId;
-      const response = await this.$http.get(
-        "/api/ecs_oe_student/examFaceLivenessVerify/getFaceLivenessVerifyToken/" +
-          examRecordId
-      );
+
+      let response = null;
+      try {
+        response = await this.$http.get(
+          "/api/ecs_oe_student/examFaceLivenessVerify/getFaceLivenessVerifyToken/" +
+            examRecordId
+        );
+      } catch (error) {
+        this.$Message.error("获取底照token失败,请重新登录!");
+        this.logout();
+        return;
+      }
 
 
       if (!response.data.success) {
       if (!response.data.success) {
         console.log(response.data.errorMsg);
         console.log(response.data.errorMsg);

+ 2 - 2
src/features/OnlineExam/Examing/QuestionBody.vue

@@ -41,7 +41,7 @@ export default {
     async parseQuestion() {
     async parseQuestion() {
       let question = {};
       let question = {};
       if (this.questionBody.includes("question-audio")) {
       if (this.questionBody.includes("question-audio")) {
-        let audioArray = this.questionBody.match(/<a.*?question-audio.*?\/a>/g);
+        // let audioArray = this.questionBody.match(/<a.*?question-audio.*?\/a>/g);
         if (!this.examQuestion.audioPlayTimes) {
         if (!this.examQuestion.audioPlayTimes) {
           // 初始化音频播放次数
           // 初始化音频播放次数
           this.audioPlayTimes = [];
           this.audioPlayTimes = [];
@@ -79,7 +79,7 @@ export default {
         // /question-audio.*?url="[^"]*"/.exec(this.questionBody)
         // /question-audio.*?url="[^"]*"/.exec(this.questionBody)
 
 
         question.audio = [];
         question.audio = [];
-        let re = /name="([^"]*)".*question-audio.*?url="([^"]*)"/g;
+        let re = /name="([^"]*)".*?question-audio.*?url="([^"]*)"/g;
         let array1;
         let array1;
         while ((array1 = re.exec(this.questionBody)) !== null) {
         while ((array1 = re.exec(this.questionBody)) !== null) {
           // console.log(`Found ${array1[0]}. Next starts at ${re.lastIndex}.`);
           // console.log(`Found ${array1[0]}. Next starts at ${re.lastIndex}.`);

+ 11 - 9
src/features/OnlineExam/Examing/QuestionView.vue

@@ -65,24 +65,26 @@ export default {
     async updateQuestion() {
     async updateQuestion() {
       const currentExamQuestion = this.examQuestion; // 避免以后执行时,this.examQuestion换掉了
       const currentExamQuestion = this.examQuestion; // 避免以后执行时,this.examQuestion换掉了
       const examRecordDataId = this.$route.params.examRecordDataId;
       const examRecordDataId = this.$route.params.examRecordDataId;
-      const res = await this.$http.get(
-        "/api/ecs_oe_student/examQuestion/getQuestionContent?questionId=" +
-          currentExamQuestion.questionId +
-          "&exam_record_id=" +
-          examRecordDataId
-      );
-
-      if (res.data === undefined) {
+
+      let qContentRes = null;
+      try {
+        qContentRes = await this.$http.get(
+          "/api/ecs_oe_student/examQuestion/getQuestionContent?questionId=" +
+            currentExamQuestion.questionId +
+            "&exam_record_id=" +
+            examRecordDataId
+        );
+      } catch (e) {
         this.parentQuestionBody = null;
         this.parentQuestionBody = null;
         this.question = null;
         this.question = null;
         return;
         return;
       }
       }
+      const question = qContentRes.data;
 
 
       this.updateExamQuestion({
       this.updateExamQuestion({
         order: currentExamQuestion.order,
         order: currentExamQuestion.order,
         getQuestionContent: true
         getQuestionContent: true
       });
       });
-      const question = res.data;
 
 
       const transferWellNumberAndTrustInBody = function(repQuestion) {
       const transferWellNumberAndTrustInBody = function(repQuestion) {
         //将题干中的三个#替换为下划线
         //将题干中的三个#替换为下划线

+ 16 - 12
src/features/OnlineExam/Examing/RemainTime.vue

@@ -32,19 +32,23 @@ export default {
   methods: {
   methods: {
     ...mapMutations(["setShouldSubmitPaper"]),
     ...mapMutations(["setShouldSubmitPaper"]),
     async getRemainTimeFromServer() {
     async getRemainTimeFromServer() {
-      const res = await this.$http.get(
-        "/api/ecs_oe_student/examControl/examHeartbeat"
-      );
-      if (/\d+/.test(res.data)) {
-        if (res.data <= 0) {
-          this.setShouldSubmitPaper();
+      try {
+        const res = await this.$http.get(
+          "/api/ecs_oe_student/examControl/examHeartbeat"
+        );
+        if (/\d+/.test(res.data)) {
+          if (res.data <= 0) {
+            this.setShouldSubmitPaper();
+          }
+          if (this.remainTime === null) {
+            // 仅当剩余考试时间没有被初始化才使用服务器时间。否则使用本机时间。
+            this.remainTime = res.data;
+          }
+          this.heartbeatErrorNum = 0;
+        } else {
+          this.$Message.error("服务器返回的心跳结果不是数字");
         }
         }
-        if (this.remainTime === null) {
-          // 仅当剩余考试时间没有被初始化才使用服务器时间。否则使用本机时间。
-          this.remainTime = res.data;
-        }
-        this.heartbeatErrorNum = 0;
-      } else {
+      } catch (error) {
         this.heartbeatErrorNum++;
         this.heartbeatErrorNum++;
         if (this.heartbeatErrorNum >= 10) {
         if (this.heartbeatErrorNum >= 10) {
           // 心跳异常10次则退出考试
           // 心跳异常10次则退出考试

+ 13 - 8
src/features/OnlineExam/OnlineExamFaceCheckModal.vue

@@ -47,14 +47,19 @@ export default {
     open: Boolean,
     open: Boolean,
     course: Object
     course: Object
   },
   },
-  async created() {
-    const res = await this.$http.get(
-      "/api/ecs_core/student/getStudentInfoBySession"
-    );
-    this.userPhoto = res.data.photoPath;
-    if (!this.userPhoto) {
-      this.$Message.error("没有底照");
-      return;
+  async mounted() {
+    try {
+      const res = await this.$http.get(
+        "/api/ecs_core/student/getStudentInfoBySession"
+      );
+      this.userPhoto = res.data.photoPath;
+      if (!this.userPhoto) {
+        this.$Message.error("没有底照");
+        return;
+      }
+    } catch (error) {
+      this.$Message.error("获取学生底照信息失败");
+      this.closeModal();
     }
     }
   },
   },
   computed: {
   computed: {

+ 20 - 14
src/features/OnlineExam/OnlineExamHome.vue

@@ -25,20 +25,26 @@ export default {
     };
     };
   },
   },
   async mounted() {
   async mounted() {
-    // 断点续考
-    const examingRes = (await this.$http.get(
-      "/api/ecs_oe_student/examControl/checkExamInProgress"
-    )).data;
-
-    if (examingRes) {
-      this.$router.push(
-        `/online-exam/exam/${examingRes.examId}/examRecordData/${
-          examingRes.examRecordDataId
-        }/order/1` +
-          (examingRes.faceVerifyMinute
-            ? `?faceVerifyMinute=${examingRes.faceVerifyMinute}`
-            : "")
-      );
+    try {
+      // 断点续考
+      const examingRes = (await this.$http.get(
+        "/api/ecs_oe_student/examControl/checkExamInProgress"
+      )).data;
+
+      if (examingRes) {
+        this.$router.push(
+          `/online-exam/exam/${examingRes.examId}/examRecordData/${
+            examingRes.examRecordDataId
+          }/order/1` +
+            (examingRes.faceVerifyMinute
+              ? `?faceVerifyMinute=${examingRes.faceVerifyMinute}`
+              : "")
+        );
+        return;
+      }
+    } catch (error) {
+      this.$Message.error("获取断点续考信息异常,退出登录");
+      // FIXME: 整个系统的mixin,logout
       return;
       return;
     }
     }
 
 

+ 37 - 27
src/features/OnlineExam/OnlineExamList.vue

@@ -77,17 +77,19 @@ export default {
     async enterExam(course) {
     async enterExam(course) {
       this.spinShow = true;
       this.spinShow = true;
       this.processingMessage = "正在检测IP合法性...";
       this.processingMessage = "正在检测IP合法性...";
-      const ipLimit = (await this.$http.get(
-        "/api/ecs_exam_work/exam/ipLimit/" + course.examId
-      )).data;
-      // await new Promise(resolve => setTimeout(() => resolve(), 3000));
-      if (ipLimit === undefined) {
-        this.spinShow = false;
-        return;
-      }
-      if (ipLimit.limited) {
+      try {
+        const ipLimit = (await this.$http.get(
+          "/api/ecs_exam_work/exam/ipLimit/" + course.examId
+        )).data;
+        // sleep function: await new Promise(resolve => setTimeout(() => resolve(), 3000));
+        if (ipLimit.limited) {
+          this.spinShow = false;
+          this.$Message.error("IP受限,请到中心指定地点进行考试!");
+          return;
+        }
+      } catch (error) {
+        this.$Message.error("查询IP限制出错!");
         this.spinShow = false;
         this.spinShow = false;
-        this.$Message.error("IP受限,请到中心指定地点进行考试!");
         return;
         return;
       }
       }
 
 
@@ -103,28 +105,36 @@ export default {
         }
         }
 
 
         this.processingMessage = "正在获取考试设置...";
         this.processingMessage = "正在获取考试设置...";
-        const faceLiveness = await this.$http.get(
-          "/api/ecs_exam_work/exam/examOrgProperty/" +
-            course.examId +
-            `/IS_FACE_VERIFY`
-        );
-        if (faceLiveness.data === undefined) {
+
+        let faceLiveness = null;
+        try {
+          faceLiveness = await this.$http.get(
+            "/api/ecs_exam_work/exam/examOrgProperty/" +
+              course.examId +
+              `/IS_FACE_VERIFY`
+          );
+        } catch (error) {
           this.spinShow = false;
           this.spinShow = false;
+          this.$Message.info("查询考试的人脸检测设置属性出错!");
           return;
           return;
         }
         }
         if (faceLiveness.data) {
         if (faceLiveness.data) {
           this.processingMessage = "正在检测底照是否满足活体检测标准...";
           this.processingMessage = "正在检测底照是否满足活体检测标准...";
-          const checkBasePhoto = (await this.$http.get(
-            "/api/ecs_oe_student/examFaceLivenessVerify/checkFaceLiveness"
-          )).data;
-          this.spinShow = false;
-          if (checkBasePhoto === undefined) {
-            return;
-          }
-          if (!checkBasePhoto.success) {
-            this.$Message.error(
-              "您上传的底照不符合活体检测的要求,请联系老师!"
-            );
+          let checkBasePhoto;
+          try {
+            checkBasePhoto = (await this.$http.get(
+              "/api/ecs_oe_student/examFaceLivenessVerify/checkFaceLiveness"
+            )).data;
+            this.spinShow = false;
+            if (!checkBasePhoto.success) {
+              this.$Message.error(
+                "您上传的底照不符合活体检测的要求,请联系老师!"
+              );
+              return;
+            }
+          } catch (error) {
+            this.spinShow = false;
+            this.$Message.error("查询检测底照是否满足活体检测标准的接口出错!");
             return;
             return;
           }
           }
         }
         }

+ 27 - 24
src/features/OnlineExam/OnlineExamOverview.vue

@@ -61,24 +61,36 @@ export default {
       }
       }
     }, 1000);
     }, 1000);
 
 
-    const exam = await this.$http.get(
-      "/api/ecs_exam_work/exam/examOrgProperty/" +
-        this.$route.params.examId +
-        `/BEFORE_EXAM_REMARK`
-    );
-    this.beforeExamRemark = exam.data || "";
-    // await this.$http.get("/api/ecs_oe_student/examControl/endExam");
-    const res = await this.$http.get(
-      "/api/ecs_oe_student/examControl/startExam?examStudentId=" +
-        this.$route.query.examStudentId
-    );
-    if (res.status !== 200) {
-      // this.$Message.error(error.message);
+    try {
+      const exam = await this.$http.get(
+        "/api/ecs_exam_work/exam/examOrgProperty/" +
+          this.$route.params.examId +
+          `/BEFORE_EXAM_REMARK`
+      );
+      this.beforeExamRemark = exam.data || "";
+      // await this.$http.get("/api/ecs_oe_student/examControl/endExam");
+      const res = await this.$http.get(
+        "/api/ecs_oe_student/examControl/startExam?examStudentId=" +
+          this.$route.query.examStudentId
+      );
+
+      this.startInfo = res.data;
+      this.examRecordDataId = res.data.examRecordDataId;
+
+      const paperStruct = await this.$http.get(
+        "/api/ecs_oe_student/examRecordPaperStruct/getExamRecordPaperStruct?examRecordDataId=" +
+          this.examRecordDataId
+      );
+      this.paperStruct = paperStruct.data;
+
+      this.paperTotalScore = this.paperStruct.defaultPaper.questionGroupList
+        .map(q => q.groupScore)
+        .reduce((p, c) => p + c);
+    } catch (e) {
+      // FIXME: global logout
       this.$router.back();
       this.$router.back();
       return;
       return;
     }
     }
-    this.startInfo = res.data;
-    this.examRecordDataId = res.data.examRecordDataId;
     // this.startInfo = {
     // this.startInfo = {
     //   id: 101436,
     //   id: 101436,
     //   courseName: "计算机应用基础",
     //   courseName: "计算机应用基础",
@@ -92,15 +104,6 @@ export default {
     //   faceVerifyMinute: null
     //   faceVerifyMinute: null
     // };
     // };
     // this.examRcordId = this.startInfo.id;
     // this.examRcordId = this.startInfo.id;
-    const paperStruct = await this.$http.get(
-      "/api/ecs_oe_student/examRecordPaperStruct/getExamRecordPaperStruct?examRecordDataId=" +
-        this.examRecordDataId
-    );
-    this.paperStruct = paperStruct.data;
-
-    this.paperTotalScore = this.paperStruct.defaultPaper.questionGroupList
-      .map(q => q.groupScore)
-      .reduce((p, c) => p + c);
   },
   },
   beforeDestroy() {
   beforeDestroy() {
     clearInterval(this.intervalId);
     clearInterval(this.intervalId);

+ 12 - 8
src/features/OnlineExam/OnlineExamResultList.vue

@@ -40,14 +40,18 @@ export default {
     };
     };
   },
   },
   async mounted() {
   async mounted() {
-    const results = (await this.$http.get(
-      "/api/ecs_oe_student/examScore/queryObjectiveScoreList?examStudentId=" +
-        this.examStudentId
-    )).data;
-    this.results = (results || [])
-      .sort((a, b) => b.examOrder - a.examOrder)
-      .slice(0, 10);
-    this.loading = false;
+    try {
+      const results = (await this.$http.get(
+        "/api/ecs_oe_student/examScore/queryObjectiveScoreList?examStudentId=" +
+          this.examStudentId
+      )).data;
+      this.results = (results || [])
+        .sort((a, b) => b.examOrder - a.examOrder)
+        .slice(0, 10);
+      this.loading = false;
+    } catch (error) {
+      this.$Message.error("查询客观分列表出错!");
+    }
   }
   }
 };
 };
 </script>
 </script>

+ 23 - 11
src/features/OnlineExam/PhoneVerifyForDD.vue

@@ -41,7 +41,12 @@ export default {
   },
   },
   methods: {
   methods: {
     async getCode() {
     async getCode() {
-      await this.$http.post("/api/ecs_oe_student/sms/sendSmsCodeToStudent");
+      try {
+        await this.$http.post("/api/ecs_oe_student/sms/sendSmsCodeToStudent");
+      } catch (error) {
+        this.$Message.error("发送验证码失败,请重试!");
+        return;
+      }
 
 
       this.remainTime = 90;
       this.remainTime = 90;
       let interval = setInterval(() => {
       let interval = setInterval(() => {
@@ -52,16 +57,23 @@ export default {
       }, 1000);
       }, 1000);
     },
     },
     async verify() {
     async verify() {
-      const res = await this.$http.post(
-        `/api/ecs_oe_student/sms/checkSmsCode?phoneNumber=${
-          this.user.phoneNumber
-        }&code=${this.code}`
-      );
-      if (res.data.success) {
-        this.phoneModal = false;
-        localStorage.setItem("phoneVerified:" + this.user.phoneNumber, "true");
-      } else {
-        this.$Message.error(res.data.returnMsg);
+      try {
+        const res = await this.$http.post(
+          `/api/ecs_oe_student/sms/checkSmsCode?phoneNumber=${
+            this.user.phoneNumber
+          }&code=${this.code}`
+        );
+        if (res.data.success) {
+          this.phoneModal = false;
+          localStorage.setItem(
+            "phoneVerified:" + this.user.phoneNumber,
+            "true"
+          );
+        } else {
+          this.$Message.error(res.data.returnMsg);
+        }
+      } catch (error) {
+        this.$Message.error("验证手机号接口失败,请重试!");
       }
       }
     }
     }
   },
   },

+ 33 - 15
src/features/OnlinePractice/OnlinePracticeHome.vue

@@ -36,29 +36,47 @@ export default {
   async mounted() {
   async mounted() {
     if (this.$route.query.examId) {
     if (this.$route.query.examId) {
       this.examId = this.$route.query.examId - 0;
       this.examId = this.$route.query.examId - 0;
-      await this.fetchList(this.examId);
+      try {
+        await this.fetchList(this.examId);
+      } catch (error) {
+        return;
+      }
     }
     }
 
 
-    const res = await this.$http.get(
-      "/api/ecs_exam_work/exam/queryByNameLike?name=&examType=PRACTICE&studentId=" +
-        this.user.id
-    );
-    this.examList = (res.data || []).filter(e => e.enable);
-    if (this.$route.query.examId === undefined && this.examList[0]) {
-      const examId = this.examList[0].id;
-      // this.$router.replace({ query: { examId } });
-      this.examId = examId;
-      await this.fetchList(this.examId);
+    try {
+      const res = await this.$http.get(
+        "/api/ecs_exam_work/exam/queryByNameLike?name=&examTypes=PRACTICE&studentId=" +
+          this.user.id
+      );
+      this.examList = (res.data || []).filter(e => e.enable);
+      if (this.$route.query.examId === undefined && this.examList[0]) {
+        const examId = this.examList[0].id;
+        // this.$router.replace({ query: { examId } });
+        this.examId = examId;
+        try {
+          await this.fetchList(this.examId);
+        } catch (error) {
+          return;
+        }
+      }
+    } catch (error) {
+      this.$Message.error("查询练习列表失败!");
     }
     }
   },
   },
   methods: {
   methods: {
     async fetchList(examId) {
     async fetchList(examId) {
       this.$router.replace({ query: { examId } });
       this.$router.replace({ query: { examId } });
-      const res = await this.$http.get(
-        "/api/ecs_oe_student/practice/queryPracticeCourseList?examId=" + examId
-      );
 
 
-      this.courses = res.data;
+      try {
+        const res = await this.$http.get(
+          "/api/ecs_oe_student/practice/queryPracticeCourseList?examId=" +
+            examId
+        );
+
+        this.courses = res.data;
+      } catch (error) {
+        this.$Message.error("获取课程列表失败");
+      }
     }
     }
   },
   },
   computed: {
   computed: {

+ 9 - 5
src/features/OnlinePractice/OnlinePracticeRecordDetail.vue

@@ -59,11 +59,15 @@ export default {
     return { examRecordResult: [] };
     return { examRecordResult: [] };
   },
   },
   async created() {
   async created() {
-    const res = await this.$http.get(
-      "/api/ecs_oe_student/practice/getPracticeDetailInfo?examRecordDataId=" +
-        this.$route.query.examRecordDataId
-    );
-    this.examRecordResult = res.data || [];
+    try {
+      const res = await this.$http.get(
+        "/api/ecs_oe_student/practice/getPracticeDetailInfo?examRecordDataId=" +
+          this.$route.query.examRecordDataId
+      );
+      this.examRecordResult = res.data || [];
+    } catch (error) {
+      this.$Message.error("查询练习试卷详情出错!");
+    }
   },
   },
   methods: {
   methods: {
     async enterPracticeRecord(course) {
     async enterPracticeRecord(course) {

+ 9 - 5
src/features/OnlinePractice/OnlinePracticeRecordList.vue

@@ -67,11 +67,15 @@ export default {
     return { recordList: [] };
     return { recordList: [] };
   },
   },
   async created() {
   async created() {
-    const res = await this.$http.get(
-      "/api/ecs_oe_student/practice/queryPracticeRecordList?examStudentId=" +
-        this.$route.query.examStudentId
-    );
-    this.recordList = (res.data || []).reverse();
+    try {
+      const res = await this.$http.get(
+        "/api/ecs_oe_student/practice/queryPracticeRecordList?examStudentId=" +
+          this.$route.query.examStudentId
+      );
+      this.recordList = (res.data || []).reverse();
+    } catch (error) {
+      this.$Message.error("查询练习记录列表出错!");
+    }
   },
   },
   methods: {
   methods: {
     async enterPracticeRecordDetail(course) {
     async enterPracticeRecordDetail(course) {

+ 1 - 1
src/utils/axiosProgress.js

@@ -34,7 +34,7 @@ export function loadProgressBar(instance = axios) {
         iView.LoadingBar.error();
         iView.LoadingBar.error();
       }
       }
       console.log(error);
       console.log(error);
-      return error;
+      throw error;
     };
     };
 
 
     instance.interceptors.response.use(responseFunc, errorFunc);
     instance.interceptors.response.use(responseFunc, errorFunc);