Browse Source

考试记录和考试断点记录mq优化,监控开始和停止逻辑优化

wangliang 4 years ago
parent
commit
eddfe830b4
38 changed files with 790 additions and 653 deletions
  1. 6 2
      themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateCallMobileController.java
  2. 4 2
      themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateController.java
  3. 2 2
      themis-admin/src/main/resources/application.properties
  4. 44 0
      themis-business/src/main/java/com/qmth/themis/business/bean/status/ClientWebsocketStatusBean.java
  5. 43 0
      themis-business/src/main/java/com/qmth/themis/business/bean/status/ExamStatusBean.java
  6. 43 0
      themis-business/src/main/java/com/qmth/themis/business/bean/status/MonitorCallStatusBean.java
  7. 43 0
      themis-business/src/main/java/com/qmth/themis/business/bean/status/MonitorStatusBean.java
  8. 9 12
      themis-business/src/main/java/com/qmth/themis/business/cache/ExamActivityRecordCacheUtil.java
  9. 10 36
      themis-business/src/main/java/com/qmth/themis/business/cache/ExamBreakCacheUtil.java
  10. 167 176
      themis-business/src/main/java/com/qmth/themis/business/cache/ExamRecordCacheUtil.java
  11. 20 0
      themis-business/src/main/java/com/qmth/themis/business/dto/MqDto.java
  12. 3 3
      themis-business/src/main/java/com/qmth/themis/business/enums/MqExecTypeEnum.java
  13. 6 6
      themis-business/src/main/java/com/qmth/themis/business/enums/MqGroupEnum.java
  14. 1 5
      themis-business/src/main/java/com/qmth/themis/business/enums/MqTagEnum.java
  15. 4 9
      themis-business/src/main/java/com/qmth/themis/business/service/TOeExamBreakHistoryService.java
  16. 5 31
      themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java
  17. 4 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/CommonServiceImpl.java
  18. 4 2
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamBreachLogServiceImpl.java
  19. 27 78
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java
  20. 37 26
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamBreakHistoryServiceImpl.java
  21. 142 96
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java
  22. 6 2
      themis-business/src/main/java/com/qmth/themis/business/service/impl/WarningServiceImpl.java
  23. 6 7
      themis-business/src/main/java/com/qmth/themis/business/util/AuthUtil.java
  24. 6 10
      themis-business/src/main/java/com/qmth/themis/business/util/WebsocketUtil.java
  25. 16 16
      themis-common/src/main/java/com/qmth/themis/common/signature/SignatureInfo.java
  26. 9 8
      themis-exam/src/main/java/com/qmth/themis/exam/api/TEExamController.java
  27. 14 4
      themis-exam/src/main/java/com/qmth/themis/exam/api/TIeInvigilateCallMobileController.java
  28. 10 4
      themis-exam/src/main/java/com/qmth/themis/exam/api/TIeInvigilateCallOeController.java
  29. 20 6
      themis-exam/src/main/java/com/qmth/themis/exam/listener/service/impl/MqOeLogicServiceImpl.java
  30. 5 1
      themis-exam/src/main/java/com/qmth/themis/exam/websocket/WebSocketMobileServer.java
  31. 4 2
      themis-exam/src/main/java/com/qmth/themis/exam/websocket/WebSocketOeServer.java
  32. 27 30
      themis-exam/src/main/java/com/qmth/themis/exam/websocketTemplete/WebSocketOeMessageTemplete.java
  33. 2 2
      themis-exam/src/main/resources/application.properties
  34. 4 4
      themis-mq/src/main/java/com/qmth/themis/mq/service/MqLogicService.java
  35. 20 53
      themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java
  36. 9 9
      themis-mq/src/main/java/com/qmth/themis/mq/templete/impl/ExamRecordBreakHistoryPersistedConcurrentlyImpl.java
  37. 6 7
      themis-task/src/main/java/com/qmth/themis/task/start/StartRunning.java
  38. 2 2
      themis-task/src/main/resources/application.properties

+ 6 - 2
themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateCallMobileController.java

@@ -168,7 +168,9 @@ public class TIeInvigilateCallMobileController {
         if (Objects.isNull(ExamRecordCacheUtil.getMonitorStatus(recordId, source))) {
             throw new BusinessException("推流状态为空");
         }
-        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.CALLING);
+        Long timestamp = System.currentTimeMillis();
+        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.CALLING, timestamp);
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId,timestamp);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         MonitorStatusSourceEnum status = ExamRecordCacheUtil.getMonitorStatus(recordId, source);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl,
@@ -206,7 +208,9 @@ public class TIeInvigilateCallMobileController {
         } else if (Objects.isNull(ExamRecordCacheUtil.getMonitorStatus(recordId, source))) {
             throw new BusinessException("推流状态为空");
         }
-        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.STOP);
+        Long timestamp = System.currentTimeMillis();
+        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.STOP, timestamp);
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         MonitorStatusSourceEnum status = ExamRecordCacheUtil.getMonitorStatus(recordId, source);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl,

+ 4 - 2
themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateController.java

@@ -516,7 +516,8 @@ public class TIeInvigilateController {
                     TEExamBreachLog teExamBreachLog = new TEExamBreachLog(examId, examActivityId, l, examStudentId, type.name(), description, status);
                     teExamBreachLog.setCreateId(tbUser.getId());
                     finalTeExamBreachLogList.add(teExamBreachLog);
-                    ExamRecordCacheUtil.setBreachStatus(l, 0, true);
+                    ExamRecordCacheUtil.setBreachStatus(l, 0);
+                    tOeExamRecordService.sendExamRecordDataSaveMq(l, System.currentTimeMillis());
                 }
             } else {//撤销违纪
                 BreachCancelTypeEnum type = BreachCancelTypeEnum.valueOf(String.valueOf(mapParameter.get("type")));
@@ -529,7 +530,8 @@ public class TIeInvigilateController {
                     s.setDescription(description);
                     s.setStatus(status);
                     s.setUpdateId(tbUser.getId());
-                    ExamRecordCacheUtil.setBreachStatus(s.getExamRecordId(), 1, true);
+                    ExamRecordCacheUtil.setBreachStatus(s.getExamRecordId(), 1);
+                    tOeExamRecordService.sendExamRecordDataSaveMq(s.getExamRecordId(), System.currentTimeMillis());
                 });
             }
             for (TEExamBreachLog eb : teExamBreachLogList) {

+ 2 - 2
themis-admin/src/main/resources/application.properties

@@ -13,7 +13,7 @@ spring.application.name=themis-admin
 #\u6570\u636E\u6E90\u914D\u7F6E
 db.host=localhost
 db.port=3306
-db.name=themis
+db.name=themis_test1
 db.username=root
 db.password=123456789
 #redis\u6570\u636E\u6E90\u914D\u7F6E
@@ -180,7 +180,7 @@ mq.config.map.FACE_VERIFY_SAVE_GROUP=themis-group-exam-faceVerifySave
 mq.config.map.LIVENESS_VERIFY_SAVE_GROUP=themis-group-exam-livenessVerifySave
 mq.config.map.EXAM_RECORD_PERSISTED_GROUP=themis-group-exam-examRecordPersisted
 mq.config.map.EXAM_RECORD_UPDATE_GROUP=themis-group-exam-examRecordUpdate
-mq.config.map.EXAM_RECORD_INIT_GROUP=themis-group-exam-examRecordInit
+mq.config.map.EXAM_BREAK_HISTORY_PERSISTED=themis-group-exam-examBreakHistoryPersisted
 mq.config.map.SCORE_CALCULATE_GROUP=themis-group-exam-scoreCalculate
 mq.config.map.EXAM_STUDENT_UPDATE_GROUP=themis-group-exam-examStudentUpdate
 mq.config.map.EXAM_BREAK_GROUP=themis-group-exam-examBreak

+ 44 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/status/ClientWebsocketStatusBean.java

@@ -0,0 +1,44 @@
+package com.qmth.themis.business.bean.status;
+
+import com.qmth.themis.business.enums.MonitorStatusSourceEnum;
+import com.qmth.themis.business.enums.WebsocketStatusEnum;
+
+import java.io.Serializable;
+
+/**
+ * @Description: websocket状态bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/11/25
+ */
+public class ClientWebsocketStatusBean implements Serializable {
+
+    WebsocketStatusEnum websocketStatusEnum;
+    Long timestamp;//时间戳
+
+    public ClientWebsocketStatusBean() {
+
+    }
+
+    public ClientWebsocketStatusBean(WebsocketStatusEnum websocketStatusEnum, Long timestamp) {
+        this.websocketStatusEnum = websocketStatusEnum;
+        this.timestamp = timestamp;
+    }
+
+    public WebsocketStatusEnum getWebsocketStatusEnum() {
+        return websocketStatusEnum;
+    }
+
+    public void setWebsocketStatusEnum(WebsocketStatusEnum websocketStatusEnum) {
+        this.websocketStatusEnum = websocketStatusEnum;
+    }
+
+    public Long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(Long timestamp) {
+        this.timestamp = timestamp;
+    }
+}

+ 43 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/status/ExamStatusBean.java

@@ -0,0 +1,43 @@
+package com.qmth.themis.business.bean.status;
+
+import com.qmth.themis.business.enums.ExamRecordStatusEnum;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 考试状态bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/11/25
+ */
+public class ExamStatusBean implements Serializable {
+
+    ExamRecordStatusEnum examRecordStatusEnum;
+    Long timestamp;//时间戳
+
+    public ExamStatusBean() {
+
+    }
+
+    public ExamStatusBean(ExamRecordStatusEnum examRecordStatusEnum, Long timestamp) {
+        this.examRecordStatusEnum = examRecordStatusEnum;
+        this.timestamp = timestamp;
+    }
+
+    public ExamRecordStatusEnum getExamRecordStatusEnum() {
+        return examRecordStatusEnum;
+    }
+
+    public void setExamRecordStatusEnum(ExamRecordStatusEnum examRecordStatusEnum) {
+        this.examRecordStatusEnum = examRecordStatusEnum;
+    }
+
+    public Long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(Long timestamp) {
+        this.timestamp = timestamp;
+    }
+}

+ 43 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/status/MonitorCallStatusBean.java

@@ -0,0 +1,43 @@
+package com.qmth.themis.business.bean.status;
+
+import com.qmth.themis.business.enums.MonitorCallStatusSourceEnum;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 监控通话状态bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/11/25
+ */
+public class MonitorCallStatusBean implements Serializable {
+
+    MonitorCallStatusSourceEnum monitorCallStatusSourceEnum;
+    Long timestamp;//时间戳
+
+    public MonitorCallStatusBean() {
+
+    }
+
+    public MonitorCallStatusBean(MonitorCallStatusSourceEnum monitorCallStatusSourceEnum, Long timestamp) {
+        this.monitorCallStatusSourceEnum = monitorCallStatusSourceEnum;
+        this.timestamp = timestamp;
+    }
+
+    public MonitorCallStatusSourceEnum getMonitorCallStatusSourceEnum() {
+        return monitorCallStatusSourceEnum;
+    }
+
+    public void setMonitorCallStatusSourceEnum(MonitorCallStatusSourceEnum monitorCallStatusSourceEnum) {
+        this.monitorCallStatusSourceEnum = monitorCallStatusSourceEnum;
+    }
+
+    public Long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(Long timestamp) {
+        this.timestamp = timestamp;
+    }
+}

+ 43 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/status/MonitorStatusBean.java

@@ -0,0 +1,43 @@
+package com.qmth.themis.business.bean.status;
+
+import com.qmth.themis.business.enums.MonitorStatusSourceEnum;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 监控状态bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/11/25
+ */
+public class MonitorStatusBean implements Serializable {
+
+    MonitorStatusSourceEnum monitorStatusSourceEnum;
+    Long timestamp;//时间戳
+
+    public MonitorStatusBean() {
+
+    }
+
+    public MonitorStatusBean(MonitorStatusSourceEnum monitorStatusSourceEnum, Long timestamp) {
+        this.monitorStatusSourceEnum = monitorStatusSourceEnum;
+        this.timestamp = timestamp;
+    }
+
+    public MonitorStatusSourceEnum getMonitorStatusSourceEnum() {
+        return monitorStatusSourceEnum;
+    }
+
+    public void setMonitorStatusSourceEnum(MonitorStatusSourceEnum monitorStatusSourceEnum) {
+        this.monitorStatusSourceEnum = monitorStatusSourceEnum;
+    }
+
+    public Long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(Long timestamp) {
+        this.timestamp = timestamp;
+    }
+}

+ 9 - 12
themis-business/src/main/java/com/qmth/themis/business/cache/ExamActivityRecordCacheUtil.java

@@ -1,8 +1,11 @@
 package com.qmth.themis.business.cache;
 
+import com.qmth.themis.business.bean.status.ExamStatusBean;
 import com.qmth.themis.business.cache.bean.ExamActivityRecordCacheBean;
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.enums.ExceptionResultEnum;
+import com.qmth.themis.common.exception.BusinessException;
 
 import java.util.Objects;
 
@@ -16,17 +19,11 @@ import java.util.Objects;
 public class ExamActivityRecordCacheUtil {
     private static RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);
 
-    public static void removeActivityRecordCache(Long activityId, Long examRecordId) {
-        redisUtil.delete(RedisKeyHelper.examActivityRecordCacheKey(activityId), examRecordId.toString());
-    }
-
-    public static void setExamRecordStatus(Long activityId, Long examRecordId, ExamActivityRecordCacheBean examActivityRecordCacheBean) {
-        redisUtil.set(RedisKeyHelper.examActivityRecordCacheKey(activityId), examRecordId.toString(), examActivityRecordCacheBean);
-    }
-
-    public static ExamActivityRecordCacheBean getExamRecordStatus(Long activityId, Long examRecordId) {
-        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examActivityRecordCacheKey(activityId),
-                examRecordId.toString())) ? (ExamActivityRecordCacheBean) redisUtil.get(RedisKeyHelper.examActivityRecordCacheKey(activityId),
-                examRecordId.toString()) : null;
+    public static void setExamRecordStatus(Long activityId, Long recordId) {
+        ExamStatusBean examStatusBean = ExamRecordCacheUtil.getStatusBean(recordId);
+        if (Objects.isNull(examStatusBean) || Objects.isNull(examStatusBean.getExamRecordStatusEnum())) {
+            throw new BusinessException(ExceptionResultEnum.EXAM_STATUS_NOT_NULL);
+        }
+        redisUtil.set(RedisKeyHelper.examActivityRecordCacheKey(activityId), recordId.toString(), new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId), examStatusBean.getExamRecordStatusEnum()));
     }
 }

+ 10 - 36
themis-business/src/main/java/com/qmth/themis/business/cache/ExamBreakCacheUtil.java

@@ -17,92 +17,66 @@ import java.util.Objects;
  * @Long: 2020-07-29
  */
 public class ExamBreakCacheUtil {
-    private static TOeExamBreakHistoryService tOeExamBreakHistoryService = SpringContextHolder.getBean(TOeExamBreakHistoryService.class);
     private static RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);
 
-    public static void setExamRecordId(Long examBreakId, Long examRecordId, boolean update) {
+    public static void setExamRecordId(Long examBreakId, Long examRecordId) {
         redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.exam_record_id.getCode(), examRecordId);
-        if (update) {
-            tOeExamBreakHistoryService.dataUpdateMq(examBreakId, ExamBreakHistoryFieldEnum.exam_record_id.name(), examRecordId);
-        }
     }
 
     public static Long getExamRecordId(Long examBreakId) {
         return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.exam_record_id.getCode());
     }
 
-    public static void setBreakTime(Long examBreakId, Long breakTime, boolean update) {
+    public static void setBreakTime(Long examBreakId, Long breakTime) {
         redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.break_time.getCode(), breakTime);
-        if (update) {
-            tOeExamBreakHistoryService.dataUpdateMq(examBreakId, ExamBreakHistoryFieldEnum.break_time.name(), breakTime);
-        }
     }
 
     public static Long getBreakTime(Long examBreakId) {
         return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.break_time.getCode());
     }
 
-    public static void setBreakReason(Long examBreakId, ExceptionEnum breakReason, boolean update) {
+    public static void setBreakReason(Long examBreakId, ExceptionEnum breakReason) {
         redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.break_reason.getCode(), breakReason);
-        if (update) {
-            tOeExamBreakHistoryService.dataUpdateMq(examBreakId, ExamBreakHistoryFieldEnum.break_reason.name(), breakReason.name());
-        }
     }
 
     public static ExceptionEnum getBreakReason(Long examBreakId) {
         return Objects.nonNull(redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.break_reason.getCode())) ? ExceptionEnum.valueOf((String) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.break_reason.getCode())) : null;
     }
 
-    public static void setResumeReason(Long examBreakId, String resumeReason, boolean update) {
+    public static void setResumeReason(Long examBreakId, String resumeReason) {
         redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.resume_reason.getCode(), resumeReason);
-        if (update) {
-            tOeExamBreakHistoryService.dataUpdateMq(examBreakId, ExamBreakHistoryFieldEnum.resume_reason.name(), resumeReason);
-        }
     }
 
-    public static Long getResumeReason(Long examBreakId) {
-        return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.resume_reason.getCode());
+    public static String getResumeReason(Long examBreakId) {
+        return (String) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.resume_reason.getCode());
     }
 
-
-    public static void setPrepareTime(Long examBreakId, Long prepareTime, boolean update) {
+    public static void setPrepareTime(Long examBreakId, Long prepareTime) {
         redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.prepare_time.getCode(), prepareTime);
-        if (update) {
-            tOeExamBreakHistoryService.dataUpdateMq(examBreakId, ExamBreakHistoryFieldEnum.prepare_time.name(), prepareTime);
-        }
     }
 
     public static Long getPrepareTime(Long examBreakId) {
         return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.prepare_time.getCode());
     }
 
-    public static void setStartTime(Long examBreakId, Long startTime, boolean update) {
+    public static void setStartTime(Long examBreakId, Long startTime) {
         redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.start_time.getCode(), startTime);
-        if (update) {
-            tOeExamBreakHistoryService.dataUpdateMq(examBreakId, ExamBreakHistoryFieldEnum.start_time.name(), startTime);
-        }
     }
 
     public static Long getStartTime(Long examBreakId) {
         return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.start_time.getCode());
     }
 
-    public static void setEntryAuthenticationResult(Long examBreakId, VerifyExceptionEnum entryAuthenticationResult, boolean update) {
+    public static void setEntryAuthenticationResult(Long examBreakId, VerifyExceptionEnum entryAuthenticationResult) {
         redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.entry_authentication_result.getCode(), entryAuthenticationResult);
-        if (update) {
-            tOeExamBreakHistoryService.dataUpdateMq(examBreakId, ExamBreakHistoryFieldEnum.entry_authentication_result.name(), entryAuthenticationResult.name());
-        }
     }
 
     public static VerifyExceptionEnum getEntryAuthenticationResult(Long examBreakId) {
         return Objects.nonNull(redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.entry_authentication_result.getCode())) ? VerifyExceptionEnum.valueOf((String) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.entry_authentication_result.getCode())) : null;
     }
 
-    public static void setEntryAuthenticationId(Long examBreakId, Long entryAuthenticationId, boolean update) {
+    public static void setEntryAuthenticationId(Long examBreakId, Long entryAuthenticationId) {
         redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.entry_authentication_id.getCode(), entryAuthenticationId);
-        if (update) {
-            tOeExamBreakHistoryService.dataUpdateMq(examBreakId, ExamBreakHistoryFieldEnum.entry_authentication_id.name(), entryAuthenticationId);
-        }
     }
 
     public static Long getEntryAuthenticationId(Long examBreakId) {

+ 167 - 176
themis-business/src/main/java/com/qmth/themis/business/cache/ExamRecordCacheUtil.java

@@ -1,10 +1,16 @@
 package com.qmth.themis.business.cache;
 
+import com.qmth.themis.business.bean.status.ClientWebsocketStatusBean;
+import com.qmth.themis.business.bean.status.ExamStatusBean;
+import com.qmth.themis.business.bean.status.MonitorCallStatusBean;
+import com.qmth.themis.business.bean.status.MonitorStatusBean;
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.enums.*;
 import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.enums.ExceptionResultEnum;
+import com.qmth.themis.common.exception.BusinessException;
 
 import java.util.Objects;
 
@@ -16,8 +22,6 @@ import java.util.Objects;
  * @Date: 2020-07-29
  */
 public class ExamRecordCacheUtil {
-
-    private static TOeExamRecordService examRecordService = SpringContextHolder.getBean(TOeExamRecordService.class);
     private static RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);
 
     public static Long getId(Long recordId) {
@@ -32,24 +36,50 @@ public class ExamRecordCacheUtil {
         return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.paper_id.getCode());
     }
 
-    public static void setFirstStartTime(Long recordId, Long date, boolean update) {
+    public static void setFirstStartTime(Long recordId, Long date) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.first_start_time.getCode(), date);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.first_start_time.name(), date);
-        }
     }
 
-    public static void setStatus(Long recordId, ExamRecordStatusEnum status, boolean update) {
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.status.getCode(), status);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.status.name(), status);
-        }
+    public static void setFirstPrepareTime(Long recordId, Long date) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.first_prepare_time.getCode(), date);
+    }
+
+    public static void setLastPrepareTime(Long recordId, Long date) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.last_prepare_time.getCode(), date);
+    }
+
+    public static void setStatus(Long recordId, ExamRecordStatusEnum status, Long timestamp) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.status.getCode(), new ExamStatusBean(status, timestamp));
     }
 
     public static Long getFirstStartTime(Long recordId) {
         return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.first_start_time.getCode());
     }
 
+    public static Long getFirstPrepareTime(Long recordId) {
+        return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.first_prepare_time.getCode());
+    }
+
+    public static Long getLastPrepareTime(Long recordId) {
+        return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.last_prepare_time.getCode());
+    }
+
+    public static String getClientCurrentIp(Long recordId) {
+        return (String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_current_ip.getCode());
+    }
+
+    public static Double getAnswerProgress(Long recordId) {
+        return (Double) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.answer_progress.getCode());
+    }
+
+    public static ReviewResultEnum getReviewResult(Long recordId) {
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.review_result.getCode())) ? ReviewResultEnum.valueOf((String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.review_result.getCode())) : null;
+    }
+
+    public static ScoreStatusEnum getScoreStatus(Long recordId) {
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.score_status.getCode())) ? ScoreStatusEnum.valueOf((String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.score_status.getCode())) : null;
+    }
+
     public static Integer getDurationSeconds(Long recordId) {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.duration_seconds.getCode());
     }
@@ -62,36 +92,64 @@ public class ExamRecordCacheUtil {
         return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exam_id.getCode());
     }
 
-    public static void setObjectiveScore(Long recordId, Double objectiveScore, boolean update) {
+    public static String getPaperStructPath(Long recordId) {
+        return (String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.paper_struct_path.getCode());
+    }
+
+    public static Integer getPaperStructUpload(Long recordId) {
+        return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.paper_struct_upload.getCode());
+    }
+
+    public static Integer getSerialNumber(Long recordId) {
+        return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.serial_number.getCode());
+    }
+
+    public static VerifyExceptionEnum getEntryAuthenticationResult(Long recordId) {
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.entry_authentication_result.getCode())) ? VerifyExceptionEnum.valueOf((String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.entry_authentication_result.getCode())) : null;
+    }
+
+    public static void setReviewResult(Long recordId, ReviewResultEnum reviewResultEnum) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.review_result.getCode(), reviewResultEnum);
+    }
+
+    public static void setScoreStatus(Long recordId, ScoreStatusEnum scoreStatusEnum) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.score_status.getCode(), scoreStatusEnum);
+    }
+
+    public static void setPaperStructPath(Long recordId, String paperStructPath) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.paper_struct_path.getCode(), paperStructPath);
+    }
+
+    public static void setPaperStructUpload(Long recordId, Integer paperStructUpload) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.paper_struct_upload.getCode(), paperStructUpload);
+    }
+
+    public static void setSerialNumber(Long recordId, Integer serialNumber) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.serial_number.getCode(), serialNumber);
+    }
+
+    public static void setEntryAuthenticationResult(Long recordId, VerifyExceptionEnum entryAuthenticationResult) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.entry_authentication_result.getCode(), entryAuthenticationResult);
+    }
+
+    public static void setObjectiveScore(Long recordId, Double objectiveScore) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.objective_score.getCode(), objectiveScore);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.objective_score.name(), objectiveScore);
-        }
     }
 
-    public static void setFinishTime(Long recordId, Long finishTime, boolean update) {
+    public static void setFinishTime(Long recordId, Long finishTime) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.finish_time.getCode(), finishTime);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.finish_time.name(), finishTime);
-        }
     }
 
     public static Long getFinishTime(Long recordId) {
         return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.finish_time.getCode());
     }
 
-    public static void setDurationSeconds(Long recordId, Integer durationSeconds, boolean update) {
+    public static void setDurationSeconds(Long recordId, Integer durationSeconds) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.duration_seconds.getCode(), durationSeconds);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.duration_seconds.name(), durationSeconds);
-        }
     }
 
-    public static void setFinishType(Long recordId, FinishTypeEnum finishType, boolean update) {
+    public static void setFinishType(Long recordId, FinishTypeEnum finishType) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.finish_type.getCode(), finishType);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.finish_type.name(), finishType);
-        }
     }
 
     public static FinishTypeEnum getFinishType(Long recordId) {
@@ -106,15 +164,20 @@ public class ExamRecordCacheUtil {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.already_break_count.getCode());
     }
 
-    public static void setAlreadyBreakCount(Long recordId, Integer alreadyBreakCount, boolean update) {
+    public static void setAlreadyBreakCount(Long recordId, Integer alreadyBreakCount) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.already_break_count.getCode(), alreadyBreakCount);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.already_break_count.name(), alreadyBreakCount);
-        }
+    }
+
+    public static ExamStatusBean getStatusBean(Long recordId) {
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.status.getCode())) ? (ExamStatusBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.status.getCode()) : null;
     }
 
     public static ExamRecordStatusEnum getStatus(Long recordId) {
-        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.status.getCode())) ? ExamRecordStatusEnum.valueOf((String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.status.getCode())) : null;
+        ExamStatusBean examStatusBean = getStatusBean(recordId);
+        if (Objects.isNull(examStatusBean) || Objects.isNull(examStatusBean.getExamRecordStatusEnum())) {
+            throw new BusinessException(ExceptionResultEnum.EXAM_STATUS_NOT_NULL);
+        }
+        return examStatusBean.getExamRecordStatusEnum();
     }
 
     public static Long getLastBreakId(Long recordId) {
@@ -125,159 +188,134 @@ public class ExamRecordCacheUtil {
         return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.last_break_time.getCode());
     }
 
-    public static void setEntryAuthenticationResult(Long recordId, VerifyExceptionEnum entryAuthenticationResult, boolean update) {
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.entry_authentication_result.getCode(), entryAuthenticationResult);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.entry_authentication_result.name(), entryAuthenticationResult);
-        }
-    }
-
-    public static void setEntryAuthenticationId(Long recordId, Long entryAuthenticationId, boolean update) {
+    public static void setEntryAuthenticationId(Long recordId, Long entryAuthenticationId) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.entry_authentication_id.getCode(), entryAuthenticationId);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.entry_authentication_id.name(), entryAuthenticationId);
-        }
     }
 
     public static Long getExamActivityId(Long recordId) {
         return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exam_activity_id.getCode());
     }
 
-    public static void setWarningCount(Long recordId, Integer warningCount, boolean update) {
+    public static void setWarningCount(Long recordId, Integer warningCount) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode(), warningCount);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.warning_count.name(), warningCount);
-        }
     }
 
     public static Integer getWarningCount(Long recordId) {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode());
     }
 
-    public static void setBreachStatus(Long recordId, Integer breachStatus, boolean update) {
+    public static void setBreachStatus(Long recordId, Integer breachStatus) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.breach_status.getCode(), breachStatus);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.breach_status.name(), breachStatus);
-        }
     }
 
     public static Integer getBreachStatus(Long recordId) {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.breach_status.getCode());
     }
 
-    public static void setInProcessLivenessVerifyCount(Long recordId, Integer inProcessLivenessVerifyCount, boolean update) {
+    public static void setInProcessLivenessVerifyCount(Long recordId, Integer inProcessLivenessVerifyCount) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_count.getCode(), inProcessLivenessVerifyCount);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.in_process_liveness_verify_count.name(), inProcessLivenessVerifyCount);
-        }
     }
 
     public static Integer getInProcessLivenessVerifyCount(Long recordId) {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_count.getCode());
     }
 
-    public static void setMonitorKey(Long recordId, String monitorKey, boolean update) {
+    public static void setMonitorKey(Long recordId, String monitorKey) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.monitor_key.getCode(), monitorKey);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.monitor_key.name(), monitorKey);
-        }
     }
 
     public static String getMonitorKey(Long recordId) {
         if (Objects.isNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.monitor_key.getCode()))) {
-            setMonitorKey(recordId, String.valueOf(redisUtil.getRedisSequence()), true);
+            setMonitorKey(recordId, String.valueOf(redisUtil.getRedisSequence()));
         }
         return (String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.monitor_key.getCode());
     }
 
     public static MonitorStatusSourceEnum getMonitorStatus(Long recordId, MonitorVideoSourceEnum source) {
-        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_STATUS_ + source.name())) ? MonitorStatusSourceEnum.valueOf((String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_STATUS_ + source.name())) : null;
+        MonitorStatusBean monitorStatusBean = getMonitorStatusBean(recordId, source);
+        if (Objects.isNull(monitorStatusBean)) {
+            return null;
+        } else {
+            return monitorStatusBean.getMonitorStatusSourceEnum();
+        }
     }
 
-    public static void setMonitorStatus(Long recordId, MonitorVideoSourceEnum source, MonitorStatusSourceEnum statusSourceEnum, boolean update) {
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_STATUS_ + source.name(), statusSourceEnum);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.monitor_status_source.name(), statusSourceEnum);
-        }
+    public static MonitorStatusBean getMonitorStatusBean(Long recordId, MonitorVideoSourceEnum source) {
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_STATUS_ + source.name())) ? (MonitorStatusBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_STATUS_ + source.name()) : null;
+    }
+
+    public static void setMonitorStatus(Long recordId, MonitorVideoSourceEnum source, MonitorStatusSourceEnum statusSourceEnum, Long timestamp) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_STATUS_ + source.name(), new MonitorStatusBean(statusSourceEnum, timestamp));
     }
 
     public static MonitorCallStatusSourceEnum getMonitorCallStatus(Long recordId, MonitorVideoSourceEnum source) {
-        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_CALL_STATUS_ + source.name())) ? MonitorCallStatusSourceEnum.valueOf((String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_CALL_STATUS_ + source.name())) : null;
+        MonitorCallStatusBean monitorCallStatusBean = getMonitorCallStatusBean(recordId, source);
+        if (Objects.isNull(monitorCallStatusBean)) {
+            return null;
+        } else {
+            return monitorCallStatusBean.getMonitorCallStatusSourceEnum();
+        }
+    }
+
+    public static MonitorCallStatusBean getMonitorCallStatusBean(Long recordId, MonitorVideoSourceEnum source) {
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_CALL_STATUS_ + source.name())) ? (MonitorCallStatusBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_CALL_STATUS_ + source.name()) : null;
+    }
+
+    public static void setMonitorCallStatus(Long recordId, MonitorVideoSourceEnum source, MonitorCallStatusSourceEnum callStatusSourceEnum, Long timestamp) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_CALL_STATUS_ + source.name(), new MonitorCallStatusBean(callStatusSourceEnum, timestamp));
     }
 
-    public static void setMonitorCallStatus(Long recordId, MonitorVideoSourceEnum source, MonitorCallStatusSourceEnum callStatusSourceEnum) {
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_CALL_STATUS_ + source.name(), callStatusSourceEnum);
+    public static ClientWebsocketStatusBean getClientWebsocketStatusBean(Long recordId) {
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_websocket_status.getCode())) ? (ClientWebsocketStatusBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_websocket_status.getCode()) : null;
     }
 
     public static WebsocketStatusEnum getClientWebsocketStatus(Long recordId) {
-        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_websocket_status.getCode())) ? WebsocketStatusEnum.valueOf((String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_websocket_status.getCode())) : null;
+        ClientWebsocketStatusBean clientWebsocketStatusBean = getClientWebsocketStatusBean(recordId);
+        if (Objects.isNull(clientWebsocketStatusBean)) {
+            return null;
+        } else {
+            return clientWebsocketStatusBean.getWebsocketStatusEnum();
+        }
     }
 
     public static String getClientWebsocketId(Long recordId) {
         return (String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_websocket_id.getCode());
     }
 
-    public static void setClientWebsocketStatus(Long recordId, WebsocketStatusEnum websocketStatusEnum, boolean update) {
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_websocket_status.getCode(), websocketStatusEnum);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.client_websocket_status.name(), websocketStatusEnum);
-        }
+    public static void setClientWebsocketStatus(Long recordId, WebsocketStatusEnum websocketStatusEnum, Long timestamp) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_websocket_status.getCode(), new ClientWebsocketStatusBean(websocketStatusEnum, timestamp));
     }
 
-    public static void setClientCurrentIp(Long recordId, String ip, boolean update) {
+    public static void setClientCurrentIp(Long recordId, String ip) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_current_ip.getCode(), ip);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.client_current_ip.name(), ip);
-        }
     }
 
-    public static void setClientWebsocketId(Long recordId, String id, boolean update) {
+    public static void setClientWebsocketId(Long recordId, String id) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_websocket_id.getCode(), id);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.client_websocket_id.name(), id);
-        }
     }
 
-    public static void setClientLastSyncTime(Long recordId, Long date, boolean update) {
+    public static void setClientLastSyncTime(Long recordId, Long date) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.client_last_sync_time.getCode(), date);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.client_last_sync_time.name(), date);
-        }
     }
 
-    public static void setPaperDownload(Long recordId, Integer paperDownload, boolean update) {
+    public static void setPaperDownload(Long recordId, Integer paperDownload) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.paper_download.getCode(), paperDownload);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.paper_download.name(), paperDownload);
-        }
     }
 
-    public static void setAnswerProgress(Long recordId, Double progress, boolean update) {
+    public static void setAnswerProgress(Long recordId, Double progress) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.answer_progress.getCode(), progress);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.answer_progress.name(), progress);
-        }
     }
 
-    public static void setLastBreakId(Long recordId, Long breakId, boolean update) {
+    public static void setLastBreakId(Long recordId, Long breakId) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.last_break_id.getCode(), breakId);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.last_break_id.name(), breakId);
-        }
     }
 
-    public static void setLastBreakTime(Long recordId, Long date, boolean update) {
+    public static void setLastBreakTime(Long recordId, Long date) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.last_break_time.getCode(), date);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.last_break_time.name(), date);
-        }
     }
 
-    public static void setLastStartTime(Long recordId, Long date, boolean update) {
+    public static void setLastStartTime(Long recordId, Long date) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.last_start_time.getCode(), date);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.last_start_time.name(), date);
-        }
     }
 
     public static Long getLastStartTime(Long recordId) {
@@ -312,53 +350,32 @@ public class ExamRecordCacheUtil {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.force_finish.getCode());
     }
 
-    public static void setStartTime(Long recordId, Long startTime, boolean update) {
+    public static void setStartTime(Long recordId, Long startTime) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.start_time.getCode(), startTime);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.start_time.name(), startTime);
-        }
     }
 
-    public static void setEndTime(Long recordId, Long endTime, boolean update) {
+    public static void setEndTime(Long recordId, Long endTime) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.end_time.getCode(), endTime);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.end_time.name(), endTime);
-        }
     }
 
-    public static void setOpeningSeconds(Long recordId, Integer openingSeconds, boolean update) {
+    public static void setOpeningSeconds(Long recordId, Integer openingSeconds) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.opening_seconds.getCode(), openingSeconds);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.opening_seconds.name(), openingSeconds);
-        }
     }
 
-    public static void setMinDurationSeconds(Long recordId, Integer minDurationSeconds, boolean update) {
+    public static void setMinDurationSeconds(Long recordId, Integer minDurationSeconds) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.min_duration_seconds.getCode(), minDurationSeconds);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.min_duration_seconds.name(), minDurationSeconds);
-        }
     }
 
-    public static void setMaxDurationSeconds(Long recordId, Integer maxDurationSeconds, boolean update) {
+    public static void setMaxDurationSeconds(Long recordId, Integer maxDurationSeconds) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.max_duration_seconds.getCode(), maxDurationSeconds);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.max_duration_seconds.name(), maxDurationSeconds);
-        }
     }
 
-    public static void setForceFinish(Long recordId, Integer forceFinish, boolean update) {
+    public static void setForceFinish(Long recordId, Integer forceFinish) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.force_finish.getCode(), forceFinish);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.force_finish.name(), forceFinish);
-        }
     }
 
-    public static void setLastPrepareTime(Long recordId, Long date, boolean update) {
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.last_prepare_time.getCode(), date);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.last_prepare_time.name(), date);
-        }
+    public static void setLastPrepareTime(Long recordId, ScoreStatusEnum scoreStatusEnum) {
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.score_status.getCode(), scoreStatusEnum);
     }
 
     public static void setExamFinalFinishTime(Long recordId, Long date) {
@@ -453,74 +470,44 @@ public class ExamRecordCacheUtil {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.has_answer_file.getCode());
     }
 
-    public static void setCameraPhotoUpload(Long recordId, Integer cameraPhotoUpload, boolean update) {
+    public static void setCameraPhotoUpload(Long recordId, Integer cameraPhotoUpload) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.camera_photo_upload.getCode(), cameraPhotoUpload);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.camera_photo_upload.name(), cameraPhotoUpload);
-        }
     }
 
-    public static void setMobilePhotoUpload(Long recordId, Integer mobilePhotoUpload, boolean update) {
+    public static void setMobilePhotoUpload(Long recordId, Integer mobilePhotoUpload) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.mobile_photo_upload.getCode(), mobilePhotoUpload);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.mobile_photo_upload.name(), mobilePhotoUpload);
-        }
     }
 
-    public static void setEntryAuthenticationPolicy(Long recordId, String entryAuthenticationPolicy, boolean update) {
+    public static void setEntryAuthenticationPolicy(Long recordId, String entryAuthenticationPolicy) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.entry_authentication_policy.getCode(), entryAuthenticationPolicy);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.entry_authentication_policy.name(), entryAuthenticationPolicy);
-        }
     }
 
-    public static void setInProcessFaceStrangerIgnore(Long recordId, Integer inProcessFaceStrangerIgnore, boolean update) {
+    public static void setInProcessFaceStrangerIgnore(Long recordId, Integer inProcessFaceStrangerIgnore) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_face_stranger_ignore.getCode(), inProcessFaceStrangerIgnore);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.in_process_face_stranger_ignore.name(), inProcessFaceStrangerIgnore);
-        }
     }
 
-    public static void setInProcessLivenessFixedRange(Long recordId, String inProcessLivenessFixedRange, boolean update) {
+    public static void setInProcessLivenessFixedRange(Long recordId, String inProcessLivenessFixedRange) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_fixed_range.getCode(), inProcessLivenessFixedRange);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.in_process_liveness_fixed_range.name(), inProcessLivenessFixedRange);
-        }
     }
 
-    public static void setInProcessLivenessJudgePolicy(Long recordId, String inProcessLivenessJudgePolicy, boolean update) {
+    public static void setInProcessLivenessJudgePolicy(Long recordId, String inProcessLivenessJudgePolicy) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_judge_policy.getCode(), inProcessLivenessJudgePolicy);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.in_process_liveness_judge_policy.name(), inProcessLivenessJudgePolicy);
-        }
     }
 
-    public static void setMonitorVideoSource(Long recordId, String monitorVideoSource, boolean update) {
+    public static void setMonitorVideoSource(Long recordId, String monitorVideoSource) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.monitor_video_source.getCode(), monitorVideoSource);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.monitor_video_source.name(), monitorVideoSource);
-        }
     }
 
-    public static void setInProcessRealnessVerifyStatus(Long recordId, Integer inProcessRealnessVerifyStatus, boolean update) {
+    public static void setInProcessRealnessVerifyStatus(Long recordId, Integer inProcessRealnessVerifyStatus) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_realness_verify_status.getCode(), inProcessRealnessVerifyStatus);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.in_process_realness_verify_status.name(), inProcessRealnessVerifyStatus);
-        }
     }
 
-    public static void setInProcessLivenessVerifyStatus(Long recordId, Integer inProcessLivenessVerifyStatus, boolean update) {
+    public static void setInProcessLivenessVerifyStatus(Long recordId, Integer inProcessLivenessVerifyStatus) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_status.getCode(), inProcessLivenessVerifyStatus);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.in_process_liveness_verify_status.name(), inProcessLivenessVerifyStatus);
-        }
     }
 
-    public static void setInProcessFaceVerifyStatus(Long recordId, Integer inProcessFaceVerifyStatus, boolean update) {
+    public static void setInProcessFaceVerifyStatus(Long recordId, Integer inProcessFaceVerifyStatus) {
         redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_face_verify_status.getCode(), inProcessFaceVerifyStatus);
-        if (update) {
-            examRecordService.dataUpdateMq(recordId, ExamRecordFieldEnum.in_process_face_verify_status.name(), inProcessFaceVerifyStatus);
-        }
     }
 
     public static Integer getCameraPhotoUpload(Long recordId) {
@@ -531,6 +518,10 @@ public class ExamRecordCacheUtil {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.mobile_photo_upload.getCode());
     }
 
+    public static Long getEntryAuthenticationId(Long recordId) {
+        return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.entry_authentication_id.getCode());
+    }
+
     public static String getEntryAuthenticationPolicy(Long recordId) {
         return (String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.entry_authentication_policy.getCode());
     }

+ 20 - 0
themis-business/src/main/java/com/qmth/themis/business/dto/MqDto.java

@@ -42,6 +42,26 @@ public class MqDto implements Serializable {
         this.id = String.valueOf(UUID.randomUUID()).replaceAll("-", "");
     }
 
+    public MqDto(String topic, String tag, String objId) {
+        this.topic = topic;
+        this.tag = tag;
+        this.body = tag;
+        this.type = MqTagEnum.valueOf(tag);
+        this.objId = objId;
+        this.timestamp = System.currentTimeMillis();
+        this.id = String.valueOf(UUID.randomUUID()).replaceAll("-", "");
+    }
+
+    public MqDto(String topic, String tag, String objId, Long timestamp) {
+        this.topic = topic;
+        this.tag = tag;
+        this.body = tag;
+        this.type = MqTagEnum.valueOf(tag);
+        this.objId = objId;
+        this.timestamp = timestamp;
+        this.id = String.valueOf(UUID.randomUUID()).replaceAll("-", "");
+    }
+
     public MqDto(String topic, String tag, Object body, MqTagEnum type, String objId, String objName) {
         this.topic = topic;
         this.tag = tag;

+ 3 - 3
themis-business/src/main/java/com/qmth/themis/business/enums/MqExecTypeEnum.java

@@ -25,11 +25,11 @@ public enum MqExecTypeEnum {
 
     EXEC_MQ_EXAM_STUDENT_UPDATE_LOGIC("考生更新逻辑", "execMqExamStudentUpdateLogic"),
 
-    EXEC_MQ_RECORD_UPDATE_LOGIC("考试记录更新逻辑", "execMqRecordUpdateLogic"),
-
     EXEC_MQ_RECORD_PERSISTED_LOGIC("考试记录持久化逻辑", "execMqRecordPersistedLogic"),
 
-    EXEC_MQ_RECORD_INIT_LOGIC("考试记录初始化逻辑", "execMqRecordInitLogic"),
+    EXEC_MQ_RECORD_UPDATE_LOGIC("考试记录数据更新逻辑", "execMqRecordUpdateLogic"),
+
+    EXEC_MQ_RECORD_BREAK_HISTORY_PERSISTED_LOGIC("考试断点记录持久化逻辑", "execMqRecordBreakHistoryPersistedLogic"),
 
     EXEC_MQ_EXAM_BREAK_LOGIC("考试断点逻辑", "execMqExamBreakLogic"),
 

+ 6 - 6
themis-business/src/main/java/com/qmth/themis/business/enums/MqGroupEnum.java

@@ -67,17 +67,17 @@ public enum MqGroupEnum {
      * 考试记录数据持久化
      */
     EXAM_RECORD_PERSISTED_GROUP,
-    
+
     /**
-     * 考试记录数据初始化
+     * 考试记录数据更新
      */
-    EXAM_RECORD_INIT_GROUP,
+    EXAM_RECORD_UPDATE_GROUP,
     
     /**
-     * 考试记录数据更新
+     * 考试断点记录数据初始化
      */
-    EXAM_RECORD_UPDATE_GROUP,
-	
+    EXAM_BREAK_RECORD_PERSISTED_GROUP,
+
 	/**
      * 考试重新算分
      */

+ 1 - 5
themis-business/src/main/java/com/qmth/themis/business/enums/MqTagEnum.java

@@ -35,22 +35,18 @@ public enum MqTagEnum {
     LIVENESS_VERIFY_SAVE("活体验证保存标签", "活体验证", "normal", 23),
     EXAM_RECORD_PERSISTED("考试记录数据持久化标签", "考试", "normal", 24),
     EXAM_RECORD_UPDATE("考试记录数据更新标签", "考试记录数据更新", "normal", 25),
-    EXAM_RECORD_INIT("考试记录数据初始化标签", "考试", "normal", 26),
-    WARNING_LOG("预警标签", "预警", "normal", 27),
     EXCEPTION_LOG("异常标签", "异常", "normal", 28),
     MONITOR_LOG("监考监控标签", "监考监控", "normal", 29),
     EXAM_SCORE_CALCULATE("重新算分标签", "重新算分", "normal", 30),
     EXAM_STUDNET_UPDATE("考生数据更新标签", "考生数据更新", "normal", 31),
     EXAM_BREAK("考试断点标签", "考试断点", "normal", 32),
     EXAM_STOP("考试移动端监控退出标签", "考试移动端退出暂停", "normal", 33),
-    EXAM_RECORD_UPDATE_COLUMNS("考试记录多字段数据更新标签", "考试记录多字段数据更新", "normal", 34),
     EXAM_STUDENT("考生一次性延时任务标签", "考生一次性延时任务", "normal", 35),
     EXAM_STUDENT_EXPORT("考生导出任务标签", "考生导出任务", "normal", 36),
     MARK_RESULT_SIMPLE_EXPORT("成绩查询简版导出任务标签", "成绩查询简版导出任务", "normal", 37),
     MARK_RESULT_STANDARD_EXPORT("成绩查询标准版导出任务标签", "成绩查询标准版导出任务", "normal", 38),
     EXAM_BREAK_DELAY("断点时间标签", "断点时间", "delay", 39),
-    EXAM_BREAK_HISTORY_UPDATE("断点记录数据更新标签", "断点记录数据更新", "normal", 40),
-    EXAM_BREAK_HISTORY_UPDATE_COLUMNS("断点记录多字段数据更新标签", "断点记录多字段数据更新", "normal", 41),
+    EXAM_BREAK_HISTORY_PERSISTED("断点记录数据持久化标签", "断点记录数据持久化", "normal", 40),
     OE_WEBSOCKET_MOBILE_ANSWER_READY("移动端拍照/录音扫描完成标签", "移动端拍照/录音扫描完成","normal", 42),
     OE_WEBSOCKET_MOBILE_ANSWER_UPLOAD("移动端拍照/录音上传成功标签", "移动端拍照/录音上传成功","normal", 43),
     OE_WEBSOCKET_EXAM_STOP("客户端考试结束标签", "客户端考试结束","normal", 44),

+ 4 - 9
themis-business/src/main/java/com/qmth/themis/business/service/TOeExamBreakHistoryService.java

@@ -22,22 +22,17 @@ public interface TOeExamBreakHistoryService extends IService<TOeExamBreakHistory
      */
     void saveAuthenticationResult(Long recordId, Long entryAuthenticationId, VerifyExceptionEnum entryAuthenticationResult);
 
-
     /**
-     * 断点记录字段同步消息发送
+     * 考试断点记录数据持久化
      *
      * @param breakId
-     * @param colName
-     * @param colValue
      */
-    void dataUpdateMq(Long breakId, String colName, Object colValue);
+    void examRecordBreakHistoryDataSave(Long breakId);
 
     /**
-     * 考试记录多字段更新
+     * 发送mq更新考试断点记录
      *
      * @param breakId
-     * @param colNames
-     * @param colValues
      */
-    void dataUpdatesMq(Long breakId, String[] colNames, Object[] colValues);
+    void sendExamRecordBreakHistoryDataMq(Long breakId);
 }

+ 5 - 31
themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java

@@ -52,45 +52,19 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
                             VerifyExceptionEnum entryAuthenticationResult);
 
     /**
-     * 考试记录字段同步消息发送
+     * 保存考试记录数据
      *
      * @param recordId
-     * @param colName
-     * @param colValue
      */
-    void dataUpdateMq(Long recordId, String colName, Object colValue);
+    void examRecordDataSave(Long recordId);
 
     /**
-     * 单字段更新
+     * 发送mq更新考试记录
      *
      * @param recordId
-     * @param colName
-     * @param colValue
+     * @param timestamp
      */
-    void dataUpdate(Long recordId, String colName, Object colValue);
-
-    /**
-     * 考试记录多字段更新
-     *
-     * @param recordId
-     * @param colNames
-     * @param colValues
-     */
-    void dataUpdatesMq(Long recordId, String[] colNames, Object[] colValues);
-
-    /**
-     * 考试记录初始化消息发送
-     *
-     * @param param
-     */
-    void dataInitMq(Map<String, Object> param);
-
-    /**
-     * 考试记录初始化
-     *
-     * @param param
-     */
-    void dataInit(Map<String, Object> param);
+    void sendExamRecordDataSaveMq(Long recordId, Long timestamp);
 
     /**
      * 查询实时监控台列表

+ 4 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/CommonServiceImpl.java

@@ -1,5 +1,6 @@
 package com.qmth.themis.business.service.impl;
 
+import com.qmth.themis.business.bean.status.ExamStatusBean;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.constant.SystemConstant;
@@ -11,6 +12,8 @@ import com.qmth.themis.business.service.MqDtoService;
 import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.MqUtil;
 import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.enums.ExceptionResultEnum;
+import com.qmth.themis.common.exception.BusinessException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
@@ -18,6 +21,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.Collections;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * @Description:

+ 4 - 2
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamBreachLogServiceImpl.java

@@ -67,7 +67,8 @@ public class TEExamBreachLogServiceImpl extends ServiceImpl<TEExamBreachLogMappe
                 TEExamBreachLog teExamBreachLog = new TEExamBreachLog(examId, examActivityId, l, examStudentId, type.name(), String.valueOf(mapParameter.get("description")), status);
                 teExamBreachLog.setCreateId(tbUser.getId());
                 finalTeExamBreachLogList.add(teExamBreachLog);
-                ExamRecordCacheUtil.setBreachStatus(l, 0, true);
+                ExamRecordCacheUtil.setBreachStatus(l, 0);
+                tOeExamRecordService.sendExamRecordDataSaveMq(l, System.currentTimeMillis());
             }
         } else {//撤销违纪
             BreachCancelTypeEnum type = BreachCancelTypeEnum.valueOf(String.valueOf(mapParameter.get("type")));
@@ -80,7 +81,8 @@ public class TEExamBreachLogServiceImpl extends ServiceImpl<TEExamBreachLogMappe
                 s.setDescription(String.valueOf(mapParameter.get("description")));
                 s.setStatus(status);
                 s.setUpdateId(tbUser.getId());
-                ExamRecordCacheUtil.setBreachStatus(s.getExamRecordId(), 1, true);
+                ExamRecordCacheUtil.setBreachStatus(s.getExamRecordId(), 1);
+                tOeExamRecordService.sendExamRecordDataSaveMq(s.getExamRecordId(), System.currentTimeMillis());
             });
         }
     }

+ 27 - 78
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -102,6 +102,9 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
     @Resource
     TGErrorService tgErrorService;
 
+    @Resource
+    TOeExamBreakHistoryService tOeExamBreakHistoryService;
+
     /**
      * 查询考试批次
      *
@@ -296,45 +299,10 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         TEExamActivityDto teExamActivityDto = teExamActivityService.getWaitingExam(activityId, examStudentId, es.getCourseCode());
         prepare.setTeExamActivityDto(teExamActivityDto);
 
-        ExamRecordCacheUtil.setStartTime(recordId, ac.getStartTime(), false);
-        ExamRecordCacheUtil.setEndTime(recordId, ac.getFinishTime(), false);
-        ExamRecordCacheUtil.setOpeningSeconds(recordId, ac.getOpeningSeconds(), false);
-        ExamRecordCacheUtil.setMinDurationSeconds(recordId, examCache.getMinDurationSeconds(), false);
-        ExamRecordCacheUtil.setMaxDurationSeconds(recordId, ac.getMaxDurationSeconds(), false);
-        ExamRecordCacheUtil.setForceFinish(recordId, examCache.getForceFinish(), false);
-        ExamRecordCacheUtil.setCameraPhotoUpload(recordId, examCache.getCameraPhotoUpload(), false);
-        ExamRecordCacheUtil.setMobilePhotoUpload(recordId, examCache.getMobilePhotoUpload(), false);
-        ExamRecordCacheUtil.setEntryAuthenticationPolicy(recordId, examCache.getEntryAuthenticationPolicy().name(), false);
-        ExamRecordCacheUtil.setInProcessFaceVerifyStatus(recordId, examCache.getInProcessFaceVerify(), false);
-        ExamRecordCacheUtil.setInProcessLivenessVerifyStatus(recordId, examCache.getInProcessLivenessVerify(), false);
-        ExamRecordCacheUtil.setInProcessRealnessVerifyStatus(recordId, examCache.getInProcessRealnessVerify(), false);
-        ExamRecordCacheUtil.setInProcessFaceStrangerIgnore(recordId, examCache.getInProcessFaceStrangerIgnore(), false);
-        ExamRecordCacheUtil.setInProcessLivenessFixedRange(recordId, examCache.getInProcessLivenessFixedRange(), false);
-        ExamRecordCacheUtil.setInProcessLivenessJudgePolicy(recordId, examCache.getInProcessLivenessJudgePolicy().name(), false);
-        ExamRecordCacheUtil.setMonitorVideoSource(recordId, examCache.getMonitorVideoSource(), false);
-
-        String[] columns = new String[]{ExamRecordFieldEnum.start_time.name(),
-                ExamRecordFieldEnum.end_time.name(), ExamRecordFieldEnum.opening_seconds.name(),
-                ExamRecordFieldEnum.min_duration_seconds.name(),
-                ExamRecordFieldEnum.max_duration_seconds.name(), ExamRecordFieldEnum.force_finish.name(),
-                ExamRecordFieldEnum.camera_photo_upload.name(), ExamRecordFieldEnum.mobile_photo_upload.name(),
-                ExamRecordFieldEnum.entry_authentication_policy.name(), ExamRecordFieldEnum.in_process_face_verify_status.name(),
-                ExamRecordFieldEnum.in_process_liveness_verify_status.name(), ExamRecordFieldEnum.in_process_realness_verify_status.name(),
-                ExamRecordFieldEnum.in_process_face_stranger_ignore.name(), ExamRecordFieldEnum.in_process_liveness_fixed_range.name(),
-                ExamRecordFieldEnum.in_process_liveness_judge_policy.name(), ExamRecordFieldEnum.monitor_video_source.name()};
-        Object[] values = new Object[]{ac.getStartTime(), ac.getFinishTime(), ac.getOpeningSeconds(),
-                examCache.getMinDurationSeconds(), ac.getMaxDurationSeconds(), examCache.getForceFinish(),
-                examCache.getCameraPhotoUpload(), examCache.getMonitorVideoSource(), examCache.getEntryAuthenticationPolicy().name(),
-                examCache.getInProcessFaceVerify(), examCache.getInProcessLivenessVerify(), examCache.getInProcessRealnessVerify(),
-                examCache.getInProcessFaceStrangerIgnore(), examCache.getInProcessLivenessFixedRange(), examCache.getInProcessLivenessJudgePolicy().name(),
-                examCache.getMonitorVideoSource()};
-        toeExamRecordService.dataUpdatesMq(recordId, columns, values);
         // 更新考生缓存
         redisUtil.set(RedisKeyHelper.examStudentCacheKey(examStudentId), es);
         //更新场次-考试记录缓存
-        ExamActivityRecordCacheUtil.setExamRecordStatus(activityId, recordId,
-                new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
-                        ExamRecordCacheUtil.getStatus(recordId)));
+        ExamActivityRecordCacheUtil.setExamRecordStatus(activityId, recordId);
         ExamingDataCacheUtil.setUnFinishedRecordId(studentId, recordId);
         //mq发送消息start
         //        TEStudentCacheDto teStudentCacheDto = (TEStudentCacheDto) redisUtil.getStudent(studentId);
@@ -484,34 +452,25 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
                 try {
                     // 更新考试记录缓存
                     Long firstStartTime = ExamRecordCacheUtil.getFirstStartTime(recordId), lastStartTime = null;
-                    String[] columns = null;
-                    Object[] values = null;
-                    ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.ANSWERING, false);
+                    Long timestamp = System.currentTimeMillis();
+                    ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.ANSWERING, timestamp);
                     if (Objects.isNull(firstStartTime)) {
-                        firstStartTime = System.currentTimeMillis();
-                        ExamRecordCacheUtil.setFirstStartTime(recordId, firstStartTime, false);
-                        columns = new String[]{ExamRecordFieldEnum.first_start_time.name(),
-                                ExamRecordFieldEnum.status.name()};
-                        values = new Object[]{firstStartTime, ExamRecordStatusEnum.ANSWERING};
+                        ExamRecordCacheUtil.setFirstStartTime(recordId, timestamp);
                     } else {
-                        lastStartTime = System.currentTimeMillis();
-                        ExamRecordCacheUtil.setLastStartTime(recordId, lastStartTime, false);
-                        columns = new String[]{ExamRecordFieldEnum.last_start_time.name(),
-                                ExamRecordFieldEnum.status.name()};
-                        values = new Object[]{lastStartTime, ExamRecordStatusEnum.ANSWERING};
+                        lastStartTime = timestamp;
+                        ExamRecordCacheUtil.setLastStartTime(recordId, timestamp);
                     }
                     Long breakId = ExamRecordCacheUtil.getLastBreakId(recordId);
                     ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
                     if (Objects.nonNull(examRecordStatusEnum)
                             && examRecordStatusEnum == ExamRecordStatusEnum.ANSWERING) {
                         if (Objects.nonNull(breakId) && Objects.nonNull(lastStartTime)) {
-                            ExamBreakCacheUtil.setStartTime(breakId, lastStartTime, true);
+                            ExamBreakCacheUtil.setStartTime(breakId, lastStartTime);
+                            tOeExamBreakHistoryService.sendExamRecordBreakHistoryDataMq(breakId);
                         }
-                        toeExamRecordService.dataUpdatesMq(recordId, columns, values);
+                        toeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
                         //更新场次-考试记录缓存
-                        ExamActivityRecordCacheUtil.setExamRecordStatus(activityId, recordId,
-                                new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
-                                        ExamRecordCacheUtil.getStatus(recordId)));
+                        ExamActivityRecordCacheUtil.setExamRecordStatus(activityId, recordId);
                     } else {
                         throw new BusinessException(ExceptionResultEnum.EXAM_STATUS_ALREADY_UPDATE);
                     }
@@ -666,7 +625,8 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         if (hasAnswerFile.intValue() == 1) {
             // 如果是客观题,重置考试记录客观题得分
             if (answerCache.getObjective()) {
-                ExamRecordCacheUtil.setObjectiveScore(recordId, null, false);
+                ExamRecordCacheUtil.setObjectiveScore(recordId, null);
+                toeExamRecordService.sendExamRecordDataSaveMq(recordId, System.currentTimeMillis());
                 // 发消息计算客观分
                 calculateObjectiveScoreMsg(recordId, mainNumber, subNumber, subIndex);
             }
@@ -868,23 +828,19 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
             if (lock) {
                 try {
                     Long lastPrepareTime = System.currentTimeMillis();
-                    ExamRecordCacheUtil.setLastPrepareTime(recordId, lastPrepareTime, false);
-                    ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.RESUME_PREPARE, false);
-                    String[] columns = new String[]{ExamRecordFieldEnum.last_prepare_time.name(),
-                            ExamRecordFieldEnum.status.name()};
-                    Object[] values = new Object[]{lastPrepareTime, ExamRecordStatusEnum.RESUME_PREPARE};
+                    ExamRecordCacheUtil.setLastPrepareTime(recordId, lastPrepareTime);
+                    ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.RESUME_PREPARE, lastPrepareTime);
                     ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
                     Long breakId = ExamRecordCacheUtil.getLastBreakId(recordId);
                     if (Objects.nonNull(examRecordStatusEnum)
                             && examRecordStatusEnum == ExamRecordStatusEnum.RESUME_PREPARE) {
                         if (Objects.nonNull(breakId)) {
-                            ExamBreakCacheUtil.setPrepareTime(breakId, lastPrepareTime, true);
+                            ExamBreakCacheUtil.setPrepareTime(breakId, lastPrepareTime);
+                            tOeExamBreakHistoryService.sendExamRecordBreakHistoryDataMq(breakId);
                         }
-                        toeExamRecordService.dataUpdatesMq(recordId, columns, values);
+                        toeExamRecordService.sendExamRecordDataSaveMq(recordId, lastPrepareTime);
                         //更新场次-考试记录缓存
-                        ExamActivityRecordCacheUtil.setExamRecordStatus(es.getExamActivityId(), recordId,
-                                new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
-                                        ExamRecordCacheUtil.getStatus(recordId)));
+                        ExamActivityRecordCacheUtil.setExamRecordStatus(es.getExamActivityId(), recordId);
                     } else {
                         throw new BusinessException(ExceptionResultEnum.EXAM_STATUS_ALREADY_UPDATE);
                     }
@@ -1053,23 +1009,16 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
             if (lock) {
                 try {
                     Long finishTime = System.currentTimeMillis();
-                    ExamRecordCacheUtil.setFinishTime(recordId, finishTime, false);
-                    ExamRecordCacheUtil.setDurationSeconds(recordId, durationSeconds, false);
-                    ExamRecordCacheUtil.setFinishType(recordId, FinishTypeEnum.valueOf(type), false);
-                    ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.FINISHED, false);
-                    String[] columns = new String[]{ExamRecordFieldEnum.finish_time.name(),
-                            ExamRecordFieldEnum.duration_seconds.name(), ExamRecordFieldEnum.finish_type.name(),
-                            ExamRecordFieldEnum.status.name()};
-                    Object[] values = new Object[]{finishTime, durationSeconds, FinishTypeEnum.valueOf(type),
-                            ExamRecordStatusEnum.FINISHED};
+                    ExamRecordCacheUtil.setFinishTime(recordId, finishTime);
+                    ExamRecordCacheUtil.setDurationSeconds(recordId, durationSeconds);
+                    ExamRecordCacheUtil.setFinishType(recordId, FinishTypeEnum.valueOf(type));
+                    ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.FINISHED, finishTime);
                     ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
                     if (Objects.nonNull(examRecordStatusEnum)
                             && examRecordStatusEnum == ExamRecordStatusEnum.FINISHED) {
-                        toeExamRecordService.dataUpdatesMq(recordId, columns, values);
+                        toeExamRecordService.sendExamRecordDataSaveMq(recordId, finishTime);
                         //更新场次-考试记录缓存
-                        ExamActivityRecordCacheUtil.setExamRecordStatus(es.getExamActivityId(), recordId,
-                                new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
-                                        ExamRecordCacheUtil.getStatus(recordId)));
+                        ExamActivityRecordCacheUtil.setExamRecordStatus(es.getExamActivityId(), recordId);
                     } else {
                         throw new BusinessException(ExceptionResultEnum.EXAM_STATUS_ALREADY_UPDATE);
                     }

+ 37 - 26
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamBreakHistoryServiceImpl.java

@@ -6,7 +6,7 @@ import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.dao.TOeExamBreakHistoryMapper;
 import com.qmth.themis.business.dto.MqDto;
 import com.qmth.themis.business.entity.TOeExamBreakHistory;
-import com.qmth.themis.business.enums.ExamBreakHistoryFieldEnum;
+import com.qmth.themis.business.enums.ExceptionEnum;
 import com.qmth.themis.business.enums.MqTagEnum;
 import com.qmth.themis.business.enums.VerifyExceptionEnum;
 import com.qmth.themis.business.service.MqDtoService;
@@ -16,8 +16,6 @@ import com.qmth.themis.common.exception.BusinessException;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * @Description: 考试断点记录 服务实现类
@@ -51,35 +49,48 @@ public class TOeExamBreakHistoryServiceImpl extends ServiceImpl<TOeExamBreakHist
         if (ExamBreakCacheUtil.getExamRecordId(examBreakId) == null) {
             throw new BusinessException("未找到断点信息");
         }
-        ExamBreakCacheUtil.setEntryAuthenticationId(examBreakId, entryAuthenticationId, false);
-        ExamBreakCacheUtil.setEntryAuthenticationResult(examBreakId, entryAuthenticationResult, false);
-        String[] columns = new String[]{ExamBreakHistoryFieldEnum.entry_authentication_id.name(),
-                ExamBreakHistoryFieldEnum.entry_authentication_result.name()};
-        Object[] values = new Object[]{entryAuthenticationId, entryAuthenticationResult.name()};
-        this.dataUpdatesMq(examBreakId, columns, values);
+        ExamBreakCacheUtil.setEntryAuthenticationId(examBreakId, entryAuthenticationId);
+        ExamBreakCacheUtil.setEntryAuthenticationResult(examBreakId, entryAuthenticationResult);
+        sendExamRecordBreakHistoryDataMq(examBreakId);
     }
 
+    /**
+     * 考试断点记录数据持久化
+     *
+     * @param breakId
+     */
     @Override
-    public void dataUpdateMq(Long breakId, String colName, Object colValue) {
-        Map<String, Object> transMap = new HashMap<String, Object>();
-        transMap.put("id", breakId);
-        transMap.put("colName", colName);
-        transMap.put("colValue", colValue);
-        //mq发送消息start
-        MqDto mqDto = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXAM_BREAK_HISTORY_UPDATE.name(), transMap,
-                MqTagEnum.EXAM_BREAK_HISTORY_UPDATE, breakId.toString(), colName);
-        mqDtoService.assembleSendOneWayMsg(mqDto);
+    public void examRecordBreakHistoryDataSave(Long breakId) {
+        Long breakTime = ExamBreakCacheUtil.getBreakTime(breakId);
+        ExceptionEnum exceptionEnum = ExamBreakCacheUtil.getBreakReason(breakId);
+        String resumeReason = ExamBreakCacheUtil.getResumeReason(breakId);
+        Long prepareTime = ExamBreakCacheUtil.getPrepareTime(breakId);
+        Long startTime = ExamBreakCacheUtil.getStartTime(breakId);
+        VerifyExceptionEnum verifyExceptionEnum = ExamBreakCacheUtil.getEntryAuthenticationResult(breakId);
+        Long entryAuthenticationId = ExamBreakCacheUtil.getEntryAuthenticationId(breakId);
+        Long recordId = ExamBreakCacheUtil.getExamRecordId(breakId);
+
+        TOeExamBreakHistory tOeExamBreakHistory = new TOeExamBreakHistory();
+        tOeExamBreakHistory.setId(breakId);
+        tOeExamBreakHistory.setExamRecordId(recordId);
+        tOeExamBreakHistory.setBreakTime(breakTime);
+        tOeExamBreakHistory.setBreakReason(exceptionEnum);
+        tOeExamBreakHistory.setResumeReason(resumeReason);
+        tOeExamBreakHistory.setPrepareTime(prepareTime);
+        tOeExamBreakHistory.setStartTime(startTime);
+        tOeExamBreakHistory.setEntryAuthenticationResult(verifyExceptionEnum);
+        tOeExamBreakHistory.setEntryAuthenticationId(entryAuthenticationId);
+        this.saveOrUpdate(tOeExamBreakHistory);
     }
 
+    /**
+     * 发送mq更新考试断点记录
+     *
+     * @param breakId
+     */
     @Override
-    public void dataUpdatesMq(Long breakId, String[] colNames, Object[] colValues) {
-        Map<String, Object> transMap = new HashMap<String, Object>();
-        transMap.put("id", breakId);
-        transMap.put("colNames", colNames);
-        transMap.put("colValues", colValues);
-        //mq发送消息start
-        MqDto mqDto = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXAM_BREAK_HISTORY_UPDATE_COLUMNS.name(),
-                transMap, MqTagEnum.EXAM_BREAK_HISTORY_UPDATE_COLUMNS, breakId.toString(), breakId.toString());
+    public void sendExamRecordBreakHistoryDataMq(Long breakId) {
+        MqDto mqDto = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXAM_BREAK_HISTORY_PERSISTED.name(), breakId.toString());
         mqDtoService.assembleSendOneWayMsg(mqDto);
     }
 }

+ 142 - 96
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.themis.business.bean.admin.*;
+import com.qmth.themis.business.bean.status.ExamStatusBean;
 import com.qmth.themis.business.cache.ExamActivityRecordCacheUtil;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
@@ -164,6 +165,16 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         er.setMinDurationSeconds(exam.getMinDurationSeconds());
         er.setMaxDurationSeconds(ac.getMaxDurationSeconds());
         er.setForceFinish(exam.getForceFinish());
+        er.setCameraPhotoUpload(exam.getCameraPhotoUpload());
+        er.setMobilePhotoUpload(exam.getMobilePhotoUpload());
+        er.setEntryAuthenticationPolicy(exam.getEntryAuthenticationPolicy());
+        er.setInProcessFaceVerifyStatus(exam.getInProcessFaceVerify());
+        er.setInProcessLivenessVerifyStatus(exam.getInProcessLivenessVerify());
+        er.setInProcessRealnessVerifyStatus(exam.getInProcessRealnessVerify());
+        er.setInProcessFaceStrangerIgnore(exam.getInProcessFaceStrangerIgnore());
+        er.setInProcessLivenessFixedRange(exam.getInProcessLivenessFixedRange());
+        er.setInProcessLivenessJudgePolicy(exam.getInProcessLivenessJudgePolicy());
+        er.setMonitorVideoSource(exam.getMonitorVideoSource());
         ExamPaperCacheBean ep = examPaperService.getExamPaperCacheBean(paperId);
         if (StringUtils.isBlank(ep.getAnswerPath())) {
             er.setHasAnswerFile(0);
@@ -171,8 +182,10 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
             er.setHasAnswerFile(1);
         }
         Map<String, Object> map = SimpleBeanUtil.objectToMap(er);
+        ExamStatusBean examStatusBean = new ExamStatusBean(ExamRecordStatusEnum.FIRST_PREPARE, System.currentTimeMillis());
+        map.put("status", examStatusBean);
         redisUtil.setForHash(RedisKeyHelper.examRecordCacheKey(er.getId()), map);
-        dataInitMq(map);
+        sendExamRecordDataSaveMq(er.getId(), System.currentTimeMillis());
         return er.getId();
     }
 
@@ -308,7 +321,8 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                         }
                     }
                     if (total != null) {
-                        ExamRecordCacheUtil.setObjectiveScore(recordId, total, true);
+                        ExamRecordCacheUtil.setObjectiveScore(recordId, total);
+                        this.sendExamRecordDataSaveMq(recordId, System.currentTimeMillis());
                     } else {
                         log.info("calculateTotalObjectiveScore total Score is null recordId:" + recordId + " key:"
                                 + key);
@@ -437,112 +451,151 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
     public void saveFaceVerify(ExamTypeEnum type, Long recordId, Long entryAuthenticationId,
                                VerifyExceptionEnum entryAuthenticationResult) {
         if (ExamTypeEnum.FIRST_START.equals(type)) {
-            ExamRecordCacheUtil.setEntryAuthenticationId(recordId, entryAuthenticationId, false);
-            ExamRecordCacheUtil.setEntryAuthenticationResult(recordId, entryAuthenticationResult, false);
-            String[] columns = new String[]{ExamRecordFieldEnum.entry_authentication_id.name(),
-                    ExamRecordFieldEnum.entry_authentication_result.name()};
-            Object[] values = new Object[]{entryAuthenticationId, entryAuthenticationResult};
-            this.dataUpdatesMq(recordId, columns, values);
-        } else if (ExamTypeEnum.IN_PROCESS.equals(type)) {
-
+            ExamRecordCacheUtil.setEntryAuthenticationId(recordId, entryAuthenticationId);
+            ExamRecordCacheUtil.setEntryAuthenticationResult(recordId, entryAuthenticationResult);
         }
+        this.sendExamRecordDataSaveMq(recordId, System.currentTimeMillis());
     }
 
     @Override
     public void saveLivenessVerify(LivenessTypeEnum type, Long recordId, Long entryAuthenticationId,
                                    VerifyExceptionEnum entryAuthenticationResult) {
         if (LivenessTypeEnum.FIRST_START.equals(type)) {
-            ExamRecordCacheUtil.setEntryAuthenticationId(recordId, entryAuthenticationId, false);
-            ExamRecordCacheUtil.setEntryAuthenticationResult(recordId, entryAuthenticationResult, false);
-            String[] columns = new String[]{ExamRecordFieldEnum.entry_authentication_id.name(),
-                    ExamRecordFieldEnum.entry_authentication_result.name()};
-            Object[] values = new Object[]{entryAuthenticationId, entryAuthenticationResult};
-            this.dataUpdatesMq(recordId, columns, values);
+            ExamRecordCacheUtil.setEntryAuthenticationId(recordId, entryAuthenticationId);
+            ExamRecordCacheUtil.setEntryAuthenticationResult(recordId, entryAuthenticationResult);
         } else if (LivenessTypeEnum.IN_PROCESS.equals(type)) {
             Integer count = ExamRecordCacheUtil.getInProcessLivenessVerifyCount(recordId);
-            ExamRecordCacheUtil.setInProcessLivenessVerifyCount(recordId, (count == null ? 0 : count + 1), true);
+            ExamRecordCacheUtil.setInProcessLivenessVerifyCount(recordId, (count == null ? 0 : count + 1));
         }
-    }
-
-    @Override
-    public void dataUpdateMq(Long recordId, String colName, Object colValue) {
-        Map<String, Object> transMap = new HashMap<String, Object>();
-        transMap.put("recordId", recordId);
-        transMap.put("colName", colName);
-        transMap.put("colValue", colValue);
-        //mq发送消息start
-        MqDto mqDto = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXAM_RECORD_UPDATE.name(), transMap,
-                MqTagEnum.EXAM_RECORD_UPDATE, recordId.toString(), colName);
-        mqDtoService.assembleSendOneWayMsg(mqDto);
+        this.sendExamRecordDataSaveMq(recordId, System.currentTimeMillis());
     }
 
     /**
-     * 单字段更新
+     * 保存考试记录数据
      *
      * @param recordId
-     * @param colName
-     * @param colValue
      */
-    @Transactional
     @Override
-    public void dataUpdate(Long recordId, String colName, Object colValue) {
-        tOeExamRecordMapper.dataUpdate(recordId, colName, colValue);
+    @Transactional
+    public void examRecordDataSave(Long recordId) {
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        Long paperId = ExamRecordCacheUtil.getPaperId(recordId);
+        Long firstStartTime = ExamRecordCacheUtil.getFirstStartTime(recordId);
+        Integer durationSeconds = ExamRecordCacheUtil.getDurationSeconds(recordId);
+        Double objectiveScore = ExamRecordCacheUtil.getObjectiveScore(recordId);
+        Long examId = ExamRecordCacheUtil.getExamId(recordId);
+        Long finishTime = ExamRecordCacheUtil.getFinishTime(recordId);
+        FinishTypeEnum finishTypeEnum = ExamRecordCacheUtil.getFinishType(recordId);
+        Long clientLastSyncTime = ExamRecordCacheUtil.getClientLastSyncTime(recordId);
+        Integer alreadyBreakCount = ExamRecordCacheUtil.getAlreadyBreakCount(recordId);
+        ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
+        Long breakId = ExamRecordCacheUtil.getLastBreakId(recordId);
+        Long lastBreakTime = ExamRecordCacheUtil.getLastBreakTime(recordId);
+        Long examActivityId = ExamRecordCacheUtil.getExamActivityId(recordId);
+        Integer warningCount = ExamRecordCacheUtil.getWarningCount(recordId);
+        Integer breachStatus = ExamRecordCacheUtil.getBreachStatus(recordId);
+        Integer inProcessLivenessVerifyCount = ExamRecordCacheUtil.getInProcessLivenessVerifyCount(recordId);
+        String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
+        WebsocketStatusEnum websocketStatusEnum = ExamRecordCacheUtil.getClientWebsocketStatus(recordId);
+        Long lastStartTime = ExamRecordCacheUtil.getLastStartTime(recordId);
+        Integer paperDownLoad = ExamRecordCacheUtil.getPaperDownload(recordId);
+        Long startTime = ExamRecordCacheUtil.getStartTime(recordId);
+        Long endTime = ExamRecordCacheUtil.getEndTime(recordId);
+        Integer openingSeconds = ExamRecordCacheUtil.getOpeningSeconds(recordId);
+        Integer minDurationSeconds = ExamRecordCacheUtil.getMinDurationSeconds(recordId);
+        Integer maxDurationSeconds = ExamRecordCacheUtil.getMaxDurationSeconds(recordId);
+        Integer forceFinish = ExamRecordCacheUtil.getForceFinish(recordId);
+        Integer hasAnswerFile = ExamRecordCacheUtil.getHasAnswerFile(recordId);
+        Integer cameraPhotoUpload = ExamRecordCacheUtil.getCameraPhotoUpload(recordId);
+        Integer mobilePhotoUpload = ExamRecordCacheUtil.getMobilePhotoUpload(recordId);
+        String entryAuthenticationPolicy = ExamRecordCacheUtil.getEntryAuthenticationPolicy(recordId);
+        Integer inProcessFaceStrangerIgnore = ExamRecordCacheUtil.getInProcessFaceStrangerIgnore(recordId);
+        String inProcessLivenessFixedRange = ExamRecordCacheUtil.getInProcessLivenessFixedRange(recordId);
+        String inProcessLivenessJudgePolicy = ExamRecordCacheUtil.getInProcessLivenessJudgePolicy(recordId);
+        String monitorVideoSource = ExamRecordCacheUtil.getMonitorVideoSource(recordId);
+        Integer inProcessRealnessVerifyStatus = ExamRecordCacheUtil.getInProcessRealnessVerifyStatus(recordId);
+        Integer inProcessLivenessVerifyStatus = ExamRecordCacheUtil.getInProcessLivenessVerifyStatus(recordId);
+        Integer inProcessFaceVerifyStatus = ExamRecordCacheUtil.getInProcessFaceVerifyStatus(recordId);
+        Long firstPrepareTime = ExamRecordCacheUtil.getFirstPrepareTime(recordId);
+        Long lastPrepareTime = ExamRecordCacheUtil.getLastPrepareTime(recordId);
+        String clientCurrentIp = ExamRecordCacheUtil.getClientCurrentIp(recordId);
+        String clientWebsocketId = ExamRecordCacheUtil.getClientWebsocketId(recordId);
+        Double answerProgress = ExamRecordCacheUtil.getAnswerProgress(recordId);
+        ReviewResultEnum reviewResultEnum = ExamRecordCacheUtil.getReviewResult(recordId);
+        String paperStructPath = ExamRecordCacheUtil.getPaperStructPath(recordId);
+        Integer paperStructUpload = ExamRecordCacheUtil.getPaperStructUpload(recordId);
+        Integer serialNumber = ExamRecordCacheUtil.getSerialNumber(recordId);
+        VerifyExceptionEnum verifyExceptionEnum = ExamRecordCacheUtil.getEntryAuthenticationResult(recordId);
+        Long entryAuthenticationId = ExamRecordCacheUtil.getEntryAuthenticationId(recordId);
+        ScoreStatusEnum scoreStatusEnum = ExamRecordCacheUtil.getScoreStatus(recordId);
+
+        TOeExamRecord er = new TOeExamRecord();
+        er.setId(recordId);
+        er.setExamId(examId);
+        er.setExamActivityId(examActivityId);
+        er.setExamStudentId(examStudentId);
+        er.setPaperId(paperId);
+        er.setStatus(examRecordStatusEnum);
+        er.setFirstPrepareTime(firstPrepareTime);
+        er.setFirstStartTime(firstStartTime);
+        er.setLastBreakTime(lastBreakTime);
+        er.setLastPrepareTime(lastPrepareTime);
+        er.setLastStartTime(lastStartTime);
+        er.setAlreadyBreakCount(alreadyBreakCount);
+        er.setClientCurrentIp(clientCurrentIp);
+        er.setClientWebsocketStatus(websocketStatusEnum);
+        er.setClientWebsocketId(clientWebsocketId);
+        er.setClientLastSyncTime(clientLastSyncTime);
+        er.setAnswerProgress(answerProgress);
+        er.setDurationSeconds(durationSeconds);
+        er.setFinishTime(finishTime);
+        er.setFinishType(finishTypeEnum);
+        er.setWarningCount(warningCount);
+        er.setReviewResult(reviewResultEnum);
+        er.setObjectiveScore(objectiveScore);
+        er.setPaperDownload(paperDownLoad);
+        er.setBreachStatus(breachStatus);
+        er.setPaperStructPath(paperStructPath);
+        er.setPaperStructUpload(paperStructUpload);
+        er.setSerialNumber(serialNumber);
+        er.setLastBreakId(breakId);
+        er.setEntryAuthenticationResult(verifyExceptionEnum);
+        er.setEntryAuthenticationId(entryAuthenticationId);
+        er.setInProcessFaceVerifyStatus(inProcessFaceVerifyStatus);
+        er.setInProcessLivenessVerifyStatus(inProcessLivenessVerifyStatus);
+        er.setInProcessLivenessVerifyCount(inProcessLivenessVerifyCount);
+        er.setMonitorKey(monitorKey);
+        er.setScoreStatus(scoreStatusEnum);
+        er.setStartTime(startTime);
+        er.setEndTime(endTime);
+        er.setOpeningSeconds(openingSeconds);
+        er.setMinDurationSeconds(minDurationSeconds);
+        er.setMaxDurationSeconds(maxDurationSeconds);
+        er.setForceFinish(forceFinish);
+        er.setHasAnswerFile(hasAnswerFile);
+        er.setInProcessRealnessVerifyStatus(inProcessRealnessVerifyStatus);
+        er.setCameraPhotoUpload(cameraPhotoUpload);
+        er.setMobilePhotoUpload(mobilePhotoUpload);
+        er.setEntryAuthenticationPolicy(EntryAuthenticationPolicyEnum.valueOf(entryAuthenticationPolicy));
+        er.setInProcessFaceStrangerIgnore(inProcessFaceStrangerIgnore);
+        er.setInProcessLivenessFixedRange(inProcessLivenessFixedRange);
+        er.setInProcessLivenessJudgePolicy(InProcessLivenessJudgePolicyEnum.valueOf(inProcessLivenessJudgePolicy));
+        er.setMonitorVideoSource(monitorVideoSource);
+        this.saveOrUpdate(er);
     }
 
     /**
-     * 多字段更新
+     * 发送mq更新考试记录
      *
      * @param recordId
-     * @param colNames
-     * @param colValues
+     * @param timestamp
      */
     @Override
-    @Transactional
-    public void dataUpdatesMq(Long recordId, String[] colNames, Object[] colValues) {
-        Map<String, Object> transMap = new HashMap<String, Object>();
-        transMap.put("recordId", recordId);
-        transMap.put("colNames", colNames);
-        transMap.put("colValues", colValues);
-        //mq发送消息start
-        MqDto mqDto = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXAM_RECORD_UPDATE_COLUMNS.name(),
-                transMap, MqTagEnum.EXAM_RECORD_UPDATE_COLUMNS, recordId.toString(), recordId.toString());
-        mqDtoService.assembleSendOneWayMsg(mqDto);
-    }
-
-    @Override
-    @Transactional
-    public void dataInitMq(Map<String, Object> param) {
-        Long id = (Long) param.get("id");
-        //mq发送消息start
-        MqDto mqDto = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXAM_RECORD_INIT.name(), param,
-                MqTagEnum.EXAM_RECORD_INIT, id.toString(), id.toString());
+    public void sendExamRecordDataSaveMq(Long recordId, Long timestamp) {
+        MqDto mqDto = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXAM_RECORD_UPDATE.name(), recordId.toString(), timestamp);
         mqDtoService.assembleSendOneWayMsg(mqDto);
     }
 
-    @Transactional
-    @Override
-    public void dataInit(Map<String, Object> param) {
-        TOeExamRecord tr = new TOeExamRecord();
-        tr.setId((Long) param.get("id"));
-        tr.setExamId((Long) param.get("examId"));
-        tr.setExamActivityId((Long) param.get("examActivityId"));
-        tr.setExamStudentId((Long) param.get("examStudentId"));
-        tr.setPaperId((Long) param.get("paperId"));
-        tr.setSerialNumber((Integer) param.get("serialNumber"));
-        tr.setFirstPrepareTime((Long) param.get("firstPrepareTime"));
-        tr.setStatus(ExamRecordStatusEnum.valueOf((String) param.get("status")));
-        tr.setObjectiveScore(0.0);
-        tr.setAlreadyBreakCount(0);
-        tr.setStartTime((Long) param.get("startTime"));
-        tr.setEndTime((Long) param.get("endTime"));
-        tr.setOpeningSeconds((Integer) param.get("openingSeconds"));
-        tr.setMinDurationSeconds((Integer) param.get("minDurationSeconds"));
-        tr.setMaxDurationSeconds((Integer) param.get("maxDurationSeconds"));
-        tr.setForceFinish((Integer) param.get("forceFinish"));
-        tr.setHasAnswerFile((Integer) param.get("hasAnswerFile"));
-        saveOrUpdate(tr);
-    }
-
     /**
      * 查询实时监控台列表
      *
@@ -1020,25 +1073,20 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                     alreadyBreakCount++;
                     Long examActivityId = ExamRecordCacheUtil.getExamActivityId(recordId);
                     Long breakId = uidUtil.getId();
-                    ExamRecordCacheUtil.setLastBreakId(recordId, breakId, false);
-                    ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.BREAK_OFF, false);
                     Long lastBreakTimeNow = System.currentTimeMillis();
-                    ExamRecordCacheUtil.setLastBreakTime(recordId, lastBreakTimeNow, false);
-                    ExamRecordCacheUtil.setAlreadyBreakCount(recordId, alreadyBreakCount, false);
-                    String[] columns = new String[]{ExamRecordFieldEnum.last_break_id.name(),
-                            ExamRecordFieldEnum.status.name(), ExamRecordFieldEnum.last_break_time.name(),
-                            ExamRecordFieldEnum.already_break_count.name()};
-                    Object[] values = new Object[]{breakId, ExamRecordStatusEnum.BREAK_OFF, lastBreakTimeNow,
-                            alreadyBreakCount};
+                    ExamRecordCacheUtil.setLastBreakId(recordId, breakId);
+                    ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.BREAK_OFF, lastBreakTimeNow);
+                    ExamRecordCacheUtil.setLastBreakTime(recordId, lastBreakTimeNow);
+                    ExamRecordCacheUtil.setAlreadyBreakCount(recordId, alreadyBreakCount);
                     ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
                     if (Objects.nonNull(examRecordStatusEnum) && examRecordStatusEnum == ExamRecordStatusEnum.BREAK_OFF) {
-                        this.dataUpdatesMq(recordId, columns, values);
-                        //考试断点异常原因 发送mq start
+                        this.sendExamRecordDataSaveMq(recordId, lastBreakTimeNow);
+//                        //考试断点异常原因 发送mq start
                         MqDto mqDtoBreak = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXAM_BREAK.name(),
                                 ExceptionEnum.NET_TIME_OUT, MqTagEnum.EXAM_BREAK, String.valueOf(recordId),
                                 String.valueOf(recordId));
                         mqDtoService.assembleSendOneWayMsg(mqDtoBreak);
-                        //考试断点异常原因 发送mq end
+//                        //考试断点异常原因 发送mq end
 
                         Long examId = ExamRecordCacheUtil.getExamId(recordId);
                         ExamCacheBean ec = examService.getExamCacheBean(examId);//考试缓存
@@ -1047,9 +1095,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                                 ec.getBreakExpireSeconds();
                         sendExamBreakMqDelayMsg(breakExpireSeconds, recordId);
                         //更新场次-考试记录缓存
-                        ExamActivityRecordCacheUtil.setExamRecordStatus(examActivityId, recordId,
-                                new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
-                                        ExamRecordCacheUtil.getStatus(recordId)));
+                        ExamActivityRecordCacheUtil.setExamRecordStatus(examActivityId, recordId);
                     } else {
                         throw new BusinessException(ExceptionResultEnum.EXAM_STATUS_ALREADY_UPDATE);
                     }

+ 6 - 2
themis-business/src/main/java/com/qmth/themis/business/service/impl/WarningServiceImpl.java

@@ -45,6 +45,9 @@ public class WarningServiceImpl implements WarningService {
     @Resource
     TEExamStudentService teExamStudentService;
 
+    @Resource
+    TOeExamRecordService tOeExamRecordService;
+
     /**
      * 人脸数量异常
      *
@@ -195,10 +198,11 @@ public class WarningServiceImpl implements WarningService {
         Integer warningCount = ExamRecordCacheUtil.getWarningCount(recordId);
         if (Objects.nonNull(warningCount)) {
             warningCount++;
-            ExamRecordCacheUtil.setWarningCount(recordId, warningCount, true);
+            ExamRecordCacheUtil.setWarningCount(recordId, warningCount);
         } else {
-            ExamRecordCacheUtil.setWarningCount(recordId, 1, true);
+            ExamRecordCacheUtil.setWarningCount(recordId, 1);
         }
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, System.currentTimeMillis());
     }
 
     /**

+ 6 - 7
themis-business/src/main/java/com/qmth/themis/business/util/AuthUtil.java

@@ -16,7 +16,6 @@ import com.qmth.themis.common.enums.Platform;
 import com.qmth.themis.common.exception.BusinessException;
 import com.qmth.themis.common.signature.SignatureInfo;
 import com.qmth.themis.common.signature.SignatureType;
-import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -146,14 +145,14 @@ public class AuthUtil {
                                     long time,
                                     String method,
                                     String url) {
-        if (SystemConstant.expire(time)) {
-            log.warn("Authorization faile: time expired, server time=" + System.currentTimeMillis());
-            throw new BusinessException(ExceptionResultEnum.AUTHORIZATION_ERROR);
-        }
+//        if (SystemConstant.expire(time)) {
+//            log.warn("Authorization faile: time expired, server time=" + System.currentTimeMillis());
+//            throw new BusinessException(ExceptionResultEnum.AUTHORIZATION_ERROR);
+//        }
         //测试
-//        final SignatureInfo info = SignatureInfo.parse(authorization);
+        final SignatureInfo info = SignatureInfo.parse(authorization);
         //校验签名信息
-        final SignatureInfo info = SignatureInfo.parse(method.toLowerCase(), url, time, authorization);
+//        final SignatureInfo info = SignatureInfo.parse(method.toLowerCase(), url, time, authorization);
         if (info == null) {
             log.warn("Authorization faile: signature decode error");
             throw new BusinessException(ExceptionResultEnum.AUTHORIZATION_ERROR);

+ 6 - 10
themis-business/src/main/java/com/qmth/themis/business/util/WebsocketUtil.java

@@ -2,11 +2,9 @@ package com.qmth.themis.business.util;
 
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.constant.SpringContextHolder;
-import com.qmth.themis.business.enums.ExamRecordFieldEnum;
 import com.qmth.themis.business.enums.ExamRecordStatusEnum;
 import com.qmth.themis.business.enums.WebsocketStatusEnum;
 import com.qmth.themis.business.service.TOeExamRecordService;
-import com.qmth.themis.common.contanst.Constants;
 import com.qmth.themis.common.enums.ExceptionResultEnum;
 import com.qmth.themis.common.exception.BusinessException;
 import org.slf4j.Logger;
@@ -14,7 +12,6 @@ import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Field;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -81,15 +78,14 @@ public class WebsocketUtil {
      * @param websocketStatusEnum
      */
     public static void updateExamRecordWebsocketStatus(Long recordId, String ip, String websocketSessionId, WebsocketStatusEnum websocketStatusEnum) {
-        ExamRecordCacheUtil.setClientWebsocketStatus(recordId, websocketStatusEnum, false);
-        ExamRecordCacheUtil.setClientCurrentIp(recordId, ip, false);
-        ExamRecordCacheUtil.setClientWebsocketId(recordId, websocketSessionId, false);
+        Long timestamp = System.currentTimeMillis();
+        ExamRecordCacheUtil.setClientWebsocketStatus(recordId, websocketStatusEnum, timestamp);
+        ExamRecordCacheUtil.setClientCurrentIp(recordId, ip);
+        ExamRecordCacheUtil.setClientWebsocketId(recordId, websocketSessionId);
         Long clientLastSyncTime = System.currentTimeMillis();
-        ExamRecordCacheUtil.setClientLastSyncTime(recordId, clientLastSyncTime, false);
-        String[] columns = new String[]{ExamRecordFieldEnum.client_websocket_status.name(), ExamRecordFieldEnum.client_current_ip.name(), ExamRecordFieldEnum.client_websocket_id.name(), ExamRecordFieldEnum.client_last_sync_time.name()};
-        Object[] values = new Object[]{websocketStatusEnum, ip, websocketSessionId, clientLastSyncTime};
+        ExamRecordCacheUtil.setClientLastSyncTime(recordId, clientLastSyncTime);
         TOeExamRecordService tOeExamRecordService = SpringContextHolder.getBean(TOeExamRecordService.class);
-        tOeExamRecordService.dataUpdatesMq(recordId, columns, values);
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
     }
 
     /**

+ 16 - 16
themis-common/src/main/java/com/qmth/themis/common/signature/SignatureInfo.java

@@ -104,32 +104,32 @@ public class SignatureInfo {
         return Base64Util.encode(ShaUtils.sha1(StringUtils.join(values, PARAM_JOINER)));
     }
 
-    /**
-     * 基于解析好的签名对象,使用传入的保密信息进行签名内容验证
-     *
-     * @param secret
-     * @return
-     */
-    public boolean validate(String secret) {
-        if (method != null && uri != null && timestamp >= 0 && secret != null && ciphertext != null) {
-            return encrypt(method, uri, String.valueOf(timestamp), secret).equals(ciphertext);
-        }
-        return false;
-    }
-
 //    /**
-//     * 基于解析好的签名对象,使用传入的保密信息进行签名内容验证(测试用)
+//     * 基于解析好的签名对象,使用传入的保密信息进行签名内容验证
 //     *
 //     * @param secret
 //     * @return
 //     */
 //    public boolean validate(String secret) {
-//        if (secret != null && ciphertext != null) {
-//            return encrypt(secret).equals(ciphertext);
+//        if (method != null && uri != null && timestamp >= 0 && secret != null && ciphertext != null) {
+//            return encrypt(method, uri, String.valueOf(timestamp), secret).equals(ciphertext);
 //        }
 //        return false;
 //    }
 
+    /**
+     * 基于解析好的签名对象,使用传入的保密信息进行签名内容验证(测试用)
+     *
+     * @param secret
+     * @return
+     */
+    public boolean validate(String secret) {
+        if (secret != null && ciphertext != null) {
+            return encrypt(secret).equals(ciphertext);
+        }
+        return false;
+    }
+
     /**
      * 根据标准参数构造最终的签名字符串
      *

+ 9 - 8
themis-exam/src/main/java/com/qmth/themis/exam/api/TEExamController.java

@@ -13,7 +13,10 @@ import com.qmth.themis.business.dto.cache.TEStudentCacheDto;
 import com.qmth.themis.business.dto.response.TEExamDto;
 import com.qmth.themis.business.dto.response.TEExamWaitDto;
 import com.qmth.themis.business.entity.TEExam;
-import com.qmth.themis.business.enums.*;
+import com.qmth.themis.business.enums.ExamRecordStatusEnum;
+import com.qmth.themis.business.enums.ExceptionEnum;
+import com.qmth.themis.business.enums.MqTagEnum;
+import com.qmth.themis.business.enums.SystemOperationEnum;
 import com.qmth.themis.business.service.MqDtoService;
 import com.qmth.themis.business.service.TEExamService;
 import com.qmth.themis.business.service.TOeExamBreakHistoryService;
@@ -165,12 +168,9 @@ public class TEExamController {
                     JSONObject jsonObject = JSONObject.parseObject(param.getReason());
                     ExceptionEnum exceptionEnum = ExceptionEnum.valueOf(ExceptionEnum.convertToName(String.valueOf(jsonObject.get("type"))));
                     String reason = String.valueOf(jsonObject.get("reason"));
-                    ExamBreakCacheUtil.setBreakReason(breakId, exceptionEnum, false);
-                    ExamBreakCacheUtil.setResumeReason(breakId, reason, false);
-                    String[] columns = new String[]{ExamBreakHistoryFieldEnum.break_reason.name(),
-                            ExamBreakHistoryFieldEnum.resume_reason.name()};
-                    Object[] values = new Object[]{exceptionEnum.name(), reason};
-                    tOeExamBreakHistoryService.dataUpdatesMq(breakId, columns, values);
+                    ExamBreakCacheUtil.setBreakReason(breakId, exceptionEnum);
+                    ExamBreakCacheUtil.setResumeReason(breakId, reason);
+                    tOeExamBreakHistoryService.sendExamRecordBreakHistoryDataMq(breakId);
                     //考试断点异常原因 发送mq start
                     MqDto mqDto = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXCEPTION_LOG.name(), JacksonUtil.parseJson(param), MqTagEnum.EXCEPTION_LOG, String.valueOf(param.getRecordId()), param.getReason());
                     mqDtoService.assembleSendOneWayMsg(mqDto);
@@ -343,7 +343,8 @@ public class TEExamController {
         }
         Integer paperDownload = Objects.isNull(ExamRecordCacheUtil.getPaperDownload(param.getRecordId())) ? 1 : ExamRecordCacheUtil.getPaperDownload(param.getRecordId());
         if (paperDownload.intValue() == 1) {
-            ExamRecordCacheUtil.setPaperDownload(param.getRecordId(), 0, true);
+            ExamRecordCacheUtil.setPaperDownload(param.getRecordId(), 0);
+            tOeExamRecordService.sendExamRecordDataSaveMq(param.getRecordId(), System.currentTimeMillis());
         }
         return ResultUtil.ok(Collections.singletonMap("updateTime", System.currentTimeMillis()));
     }

+ 14 - 4
themis-exam/src/main/java/com/qmth/themis/exam/api/TIeInvigilateCallMobileController.java

@@ -8,6 +8,7 @@ import com.qmth.themis.business.dto.MqDto;
 import com.qmth.themis.business.entity.TIeExamInvigilateCallLog;
 import com.qmth.themis.business.enums.*;
 import com.qmth.themis.business.service.MqDtoService;
+import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.MqUtil;
 import com.qmth.themis.common.enums.ExceptionResultEnum;
 import com.qmth.themis.common.exception.BusinessException;
@@ -51,6 +52,9 @@ public class TIeInvigilateCallMobileController {
     @Resource
     DictionaryConfig dictionaryConfig;
 
+    @Resource
+    TOeExamRecordService tOeExamRecordService;
+
 //    @Deprecated
 //    @ApiOperation(value = "监控观看地址更新接口")
 //    @RequestMapping(value = "/live_url", method = RequestMethod.POST)
@@ -129,7 +133,9 @@ public class TIeInvigilateCallMobileController {
             throw new BusinessException("推流状态不正常");
         }
         String liveUrl = dictionaryConfig.monitorDomain().getPrefix() + "_" + recordId + "_" + source.name().toLowerCase();
-        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.START);
+        Long timestamp = System.currentTimeMillis();
+        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.START, timestamp);
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.START);
         tIeExamInvigilateCallLog.setStartTime(System.currentTimeMillis());
@@ -168,8 +174,10 @@ public class TIeInvigilateCallMobileController {
         //获取考试记录缓存
         String liveUrl = dictionaryConfig.monitorDomain().getPrefix() + "_" + recordId + "_" + source.name().toLowerCase();
         MonitorCallStatusSourceEnum callStatus = Objects.nonNull(ExamRecordCacheUtil.getMonitorCallStatus(recordId, source)) ? ExamRecordCacheUtil.getMonitorCallStatus(recordId, source) : null;
-        ExamRecordCacheUtil.setMonitorStatus(recordId, source, status, true);
-        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, callStatus);
+        Long timestamp = System.currentTimeMillis();
+        ExamRecordCacheUtil.setMonitorStatus(recordId, source, status, timestamp);
+        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, callStatus, timestamp);
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, MonitorStatusSourceEnum.START, monitorKey, callStatus);
         if (Objects.nonNull(mapParameter.get("type")) && !Objects.equals(mapParameter.get("type"), "")) {
@@ -223,7 +231,9 @@ public class TIeInvigilateCallMobileController {
             throw new BusinessException("推流状态为空");
         }
         String liveUrl = dictionaryConfig.monitorDomain().getPrefix() + "_" + recordId + "_" + source.name().toLowerCase();
-        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.STOP);
+        Long timestamp = System.currentTimeMillis();
+        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.STOP, timestamp);
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         MonitorStatusSourceEnum status = ExamRecordCacheUtil.getMonitorStatus(recordId, source);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.STOP);

+ 10 - 4
themis-exam/src/main/java/com/qmth/themis/exam/api/TIeInvigilateCallOeController.java

@@ -134,8 +134,10 @@ public class TIeInvigilateCallOeController {
         //获取考试记录缓存
         String liveUrl = dictionaryConfig.monitorDomain().getPrefix() + "_" + recordId + "_" + source.name().toLowerCase();
         MonitorCallStatusSourceEnum callStatus = Objects.nonNull(ExamRecordCacheUtil.getMonitorCallStatus(recordId, source)) ? ExamRecordCacheUtil.getMonitorCallStatus(recordId, source) : null;
-        ExamRecordCacheUtil.setMonitorStatus(recordId, source, status, true);
-        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, callStatus);
+        Long timestamp = System.currentTimeMillis();
+        ExamRecordCacheUtil.setMonitorStatus(recordId, source, status, timestamp);
+        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, callStatus, timestamp);
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, MonitorStatusSourceEnum.START, monitorKey, callStatus);
         if (Objects.nonNull(mapParameter.get("type")) && !Objects.equals(mapParameter.get("type"), "")) {
@@ -173,7 +175,9 @@ public class TIeInvigilateCallOeController {
         if (!Objects.equals(status, MonitorStatusSourceEnum.START)) {
             throw new BusinessException("推流状态不正常");
         }
-        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.START);
+        Long timestamp = System.currentTimeMillis();
+        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.START, timestamp);
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.START);
         tIeExamInvigilateCallLog.setStartTime(System.currentTimeMillis());
@@ -205,7 +209,9 @@ public class TIeInvigilateCallOeController {
             throw new BusinessException("推流状态为空");
         }
         MonitorStatusSourceEnum status = ExamRecordCacheUtil.getMonitorStatus(recordId, source);
-        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.STOP);
+        Long timestamp = System.currentTimeMillis();
+        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.STOP, timestamp);
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.STOP);
         tIeExamInvigilateCallLog.setEndTime(System.currentTimeMillis());

+ 20 - 6
themis-exam/src/main/java/com/qmth/themis/exam/listener/service/impl/MqOeLogicServiceImpl.java

@@ -2,6 +2,7 @@ package com.qmth.themis.exam.listener.service.impl;
 
 import com.alibaba.fastjson.JSONArray;
 import com.google.gson.Gson;
+import com.qmth.themis.business.bean.status.MonitorStatusBean;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
@@ -211,6 +212,7 @@ public class MqOeLogicServiceImpl implements MqOeLogicService {
                 || Objects.equals(MqTagEnum.OE_WEBSOCKET_MOBILE_MONITOR_STATUS.name(), tag)) {//通知客户端移动端当前监控状态
             Long recordId = Long.parseLong(String.valueOf(mqDto.getBody()));
             String clientWebsocketId = ExamRecordCacheUtil.getClientWebsocketId(recordId);
+            Map<String, Object> prop = mqDto.getProperties();
             if (Objects.nonNull(webSocketMap.get(clientWebsocketId))) {
                 WebSocketOeServer webSocketOeServer = webSocketMap.get(clientWebsocketId);
                 ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
@@ -223,22 +225,34 @@ public class MqOeLogicServiceImpl implements MqOeLogicService {
                     WebsocketDto websocketDto = null;
                     switch (tag.toUpperCase()) {
                         case "OE_WEBSOCKET_MOBILE_ANSWER_READY":
-                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_ANSWER_READY.name(), mqDto.getProperties());
+                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_ANSWER_READY.name(), prop);
                             break;
                         case "OE_WEBSOCKET_MOBILE_ANSWER_UPLOAD":
-                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_ANSWER_UPLOAD.name(), mqDto.getProperties());
+                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_ANSWER_UPLOAD.name(), prop);
                             break;
                         case "OE_WEBSOCKET_EXAM_STOP":
-                            websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_STOP.name(), mqDto.getProperties());
+                            websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_STOP.name(), prop);
                             break;
                         case "MONITOR_START":
-                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_MONITOR_START.name(), mqDto.getProperties());
+                            MonitorVideoSourceEnum source = MonitorVideoSourceEnum.valueOf((String) prop.get("source"));
+                            MonitorStatusBean monitorStatusBean = ExamRecordCacheUtil.getMonitorStatusBean(recordId, source);
+                            if (Objects.nonNull(monitorStatusBean)
+                                    && Objects.nonNull(monitorStatusBean.getTimestamp())
+                                    && mqDto.getTimestamp().longValue() >= monitorStatusBean.getTimestamp().longValue()) {
+                                websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_MONITOR_START.name(), prop);
+                            }
                             break;
                         case "MONITOR_STOP":
-                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_MONITOR_STOP.name(), mqDto.getProperties());
+                            source = MonitorVideoSourceEnum.valueOf((String) prop.get("source"));
+                            monitorStatusBean = ExamRecordCacheUtil.getMonitorStatusBean(recordId, source);
+                            if (Objects.nonNull(monitorStatusBean)
+                                    && Objects.nonNull(monitorStatusBean.getTimestamp())
+                                    && mqDto.getTimestamp().longValue() >= monitorStatusBean.getTimestamp().longValue()) {
+                                websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_MONITOR_STOP.name(), prop);
+                            }
                             break;
                         case "OE_WEBSOCKET_MOBILE_MONITOR_STATUS":
-                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_MONITOR_STATUS.name(), mqDto.getProperties());
+                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_MONITOR_STATUS.name(), prop);
                             break;
                         default:
                             break;

+ 5 - 1
themis-exam/src/main/java/com/qmth/themis/exam/websocket/WebSocketMobileServer.java

@@ -13,6 +13,7 @@ import com.qmth.themis.business.enums.MonitorVideoSourceEnum;
 import com.qmth.themis.business.enums.MqTagEnum;
 import com.qmth.themis.business.enums.WebsocketTypeEnum;
 import com.qmth.themis.business.service.MqDtoService;
+import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.*;
 import com.qmth.themis.common.contanst.Constants;
 import com.qmth.themis.common.enums.ExceptionResultEnum;
@@ -120,7 +121,10 @@ public class WebSocketMobileServer implements Concurrently {
             //从set中删除
 //            subOnlineCount();
             //判断是否是正常退出
-            ExamRecordCacheUtil.setMonitorStatus(recordId, this.source, MonitorStatusSourceEnum.STOP, true);
+            Long timestamp = System.currentTimeMillis();
+            ExamRecordCacheUtil.setMonitorStatus(this.recordId, this.source, MonitorStatusSourceEnum.STOP, timestamp);
+            TOeExamRecordService tOeExamRecordService = SpringContextHolder.getBean(TOeExamRecordService.class);
+            tOeExamRecordService.sendExamRecordDataSaveMq(this.recordId, timestamp);
             MqUtil mqUtil = SpringContextHolder.getBean(MqUtil.class);
             MqDtoService mqDtoService = SpringContextHolder.getBean(MqDtoService.class);
             Map mqMap = new HashMap<>();

+ 4 - 2
themis-exam/src/main/java/com/qmth/themis/exam/websocket/WebSocketOeServer.java

@@ -125,7 +125,10 @@ public class WebSocketOeServer implements Concurrently {
             //从set中删除
             subOnlineCount();
             //判断是否是正常退出
-            ExamRecordCacheUtil.setClientWebsocketStatus(this.recordId, WebsocketStatusEnum.OFF_LINE, true);
+            Long timestamp = System.currentTimeMillis();
+            TOeExamRecordService tOeExamRecordService = SpringContextHolder.getBean(TOeExamRecordService.class);
+            ExamRecordCacheUtil.setClientWebsocketStatus(this.recordId, WebsocketStatusEnum.OFF_LINE, timestamp);
+            tOeExamRecordService.sendExamRecordDataSaveMq(this.recordId, timestamp);
             ExamRecordStatusEnum status = ExamRecordCacheUtil.getStatus(this.recordId);
             if (Objects.equals(status, ExamRecordStatusEnum.ANSWERING)) {
                 //大于等于超时时间,说明规定时间内都没有通信,非正常退出,因为期间会有心跳更新updateTime
@@ -141,7 +144,6 @@ public class WebSocketOeServer implements Concurrently {
                 } else {
                     log.info("正常退出");
                     ExamConstant.sendExamStopMsg(this.recordId, true);
-                    TOeExamRecordService tOeExamRecordService = SpringContextHolder.getBean(TOeExamRecordService.class);
                     tOeExamRecordService.examBreakLogic(this.recordId, true);
                 }
             }

+ 27 - 30
themis-exam/src/main/java/com/qmth/themis/exam/websocketTemplete/WebSocketOeMessageTemplete.java

@@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSONObject;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.WebsocketDto;
-import com.qmth.themis.business.enums.ExamRecordFieldEnum;
 import com.qmth.themis.business.enums.WebsocketTypeEnum;
 import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.common.enums.ExceptionResultEnum;
@@ -32,29 +31,29 @@ public class WebSocketOeMessageTemplete {
     @Resource
     TOeExamRecordService tOeExamRecordService;
 
-    /**
-     * 客户端已下载试卷
-     *
-     * @param body
-     * @param time
-     * @return
-     */
-    @Deprecated
-    @Transactional
-    public WebsocketDto clientPaperDownload(String body, Long time) {
-        JSONObject jsonObject = JSONObject.parseObject(body);
-        log.info("clientPaperDownload jsonObject:{}", jsonObject.toJSONString());
-        if (Objects.isNull(jsonObject.get("recordId")) || Objects.equals(jsonObject.get("recordId"), "")) {
-            throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
-        }
-        Long recordId = Long.parseLong(String.valueOf(jsonObject.get("recordId")));
-        Long examId = ExamRecordCacheUtil.getExamId(recordId);
-        if (Objects.isNull(examId)) {
-            throw new BusinessException(ExceptionResultEnum.NOT_FOUND_EXAM_RECORD);
-        }
-        ExamRecordCacheUtil.setPaperDownload(recordId, 0, true);
-        return new WebsocketDto(Collections.singletonMap(SystemConstant.SUCCESS, true));
-    }
+//    /**
+//     * 客户端已下载试卷
+//     *
+//     * @param body
+//     * @param time
+//     * @return
+//     */
+//    @Deprecated
+//    @Transactional
+//    public WebsocketDto clientPaperDownload(String body, Long time) {
+//        JSONObject jsonObject = JSONObject.parseObject(body);
+//        log.info("clientPaperDownload jsonObject:{}", jsonObject.toJSONString());
+//        if (Objects.isNull(jsonObject.get("recordId")) || Objects.equals(jsonObject.get("recordId"), "")) {
+//            throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
+//        }
+//        Long recordId = Long.parseLong(String.valueOf(jsonObject.get("recordId")));
+//        Long examId = ExamRecordCacheUtil.getExamId(recordId);
+//        if (Objects.isNull(examId)) {
+//            throw new BusinessException(ExceptionResultEnum.NOT_FOUND_EXAM_RECORD);
+//        }
+//        ExamRecordCacheUtil.setPaperDownload(recordId, 0);
+//        return new WebsocketDto(Collections.singletonMap(SystemConstant.SUCCESS, true));
+//    }
 
     /**
      * 状态同步
@@ -83,13 +82,11 @@ public class WebSocketOeMessageTemplete {
         if (Objects.isNull(examId)) {
             throw new BusinessException(ExceptionResultEnum.NOT_FOUND_EXAM_RECORD);
         }
-        ExamRecordCacheUtil.setAnswerProgress(recordId, progress, false);
-        ExamRecordCacheUtil.setDurationSeconds(recordId, durationSeconds, false);
+        ExamRecordCacheUtil.setAnswerProgress(recordId, progress);
+        ExamRecordCacheUtil.setDurationSeconds(recordId, durationSeconds);
         Long clientLastSyncTime = System.currentTimeMillis();
-        ExamRecordCacheUtil.setClientLastSyncTime(recordId, clientLastSyncTime, false);
-        String[] columns = new String[]{ExamRecordFieldEnum.answer_progress.name(), ExamRecordFieldEnum.duration_seconds.name(), ExamRecordFieldEnum.client_last_sync_time.name()};
-        Object[] values = new Object[]{progress, durationSeconds, clientLastSyncTime};
-        tOeExamRecordService.dataUpdatesMq(recordId, columns, values);
+        ExamRecordCacheUtil.setClientLastSyncTime(recordId, clientLastSyncTime);
+        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, clientLastSyncTime);
         return this.syncAck(body, time);
     }
 

+ 2 - 2
themis-exam/src/main/resources/application.properties

@@ -13,7 +13,7 @@ spring.application.name=themis-exam
 #\u6570\u636E\u6E90\u914D\u7F6E
 db.host=localhost
 db.port=3306
-db.name=themis
+db.name=themis_test1
 db.username=root
 db.password=123456789
 #redis\u6570\u636E\u6E90\u914D\u7F6E
@@ -132,7 +132,7 @@ mq.config.map.FACE_VERIFY_SAVE_GROUP=themis-group-exam-faceVerifySave
 mq.config.map.LIVENESS_VERIFY_SAVE_GROUP=themis-group-exam-livenessVerifySave
 mq.config.map.EXAM_RECORD_PERSISTED_GROUP=themis-group-exam-examRecordPersisted
 mq.config.map.EXAM_RECORD_UPDATE_GROUP=themis-group-exam-examRecordUpdate
-mq.config.map.EXAM_RECORD_INIT_GROUP=themis-group-exam-examRecordInit
+mq.config.map.EXAM_BREAK_HISTORY_PERSISTED=themis-group-exam-examBreakHistoryPersisted
 mq.config.map.SCORE_CALCULATE_GROUP=themis-group-exam-scoreCalculate
 mq.config.map.EXAM_STUDENT_UPDATE_GROUP=themis-group-exam-examStudentUpdate
 mq.config.map.EXAM_BREAK_GROUP=themis-group-exam-examBreak

+ 4 - 4
themis-mq/src/main/java/com/qmth/themis/mq/service/MqLogicService.java

@@ -90,20 +90,20 @@ public interface MqLogicService {
     public void execMqRecordPersistedLogic(MqDto mqDto, String key);
 
     /**
-     * 考试记录数据更新
+     * 考试断点记录数据持久化
      *
      * @param mqDto
      * @param key
      */
-    void execMqRecordUpdateLogic(MqDto mqDto, String key);
+    public void execMqRecordBreakHistoryPersistedLogic(MqDto mqDto, String key);
 
     /**
-     * 考试记录初始化
+     * 考试记录数据更新
      *
      * @param mqDto
      * @param key
      */
-    void execMqRecordInitLogic(MqDto mqDto, String key);
+    void execMqRecordUpdateLogic(MqDto mqDto, String key);
 
     /**
      * 监控通话申请逻辑

+ 20 - 53
themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java

@@ -273,10 +273,11 @@ public class MqLogicServiceImpl implements MqLogicService {
             //更新客户端摄像头推流状态为stop
             MonitorStatusSourceEnum cameraStatusSourceEnum = ExamRecordCacheUtil
                     .getMonitorStatus(recordId, MonitorVideoSourceEnum.CLIENT_CAMERA);
+            Long timestamp = System.currentTimeMillis();
             if (Objects.nonNull(cameraStatusSourceEnum)) {
                 ExamRecordCacheUtil
                         .setMonitorStatus(recordId, MonitorVideoSourceEnum.CLIENT_CAMERA, MonitorStatusSourceEnum.STOP,
-                                true);
+                                timestamp);
             }
             //更新客户端屏幕推流状态为stop
             MonitorStatusSourceEnum screenStatusSourceEnum = ExamRecordCacheUtil
@@ -284,8 +285,9 @@ public class MqLogicServiceImpl implements MqLogicService {
             if (Objects.nonNull(screenStatusSourceEnum)) {
                 ExamRecordCacheUtil
                         .setMonitorStatus(recordId, MonitorVideoSourceEnum.CLIENT_SCREEN, MonitorStatusSourceEnum.STOP,
-                                true);
+                                timestamp);
             }
+            examRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
             //发送移动端监考退出考试mq消息 start
             MqDto mqDtoExamStop = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXAM_STOP.name(), recordId,
                     MqTagEnum.EXAM_STOP, String.valueOf(recordId), String.valueOf(recordId));
@@ -623,53 +625,18 @@ public class MqLogicServiceImpl implements MqLogicService {
         redisUtil.delete(key, mqDto.getId());
     }
 
+    /**
+     * 考试断点记录数据持久化
+     *
+     * @param mqDto
+     * @param key
+     */
     @Override
     @Transactional
-    public void execMqRecordUpdateLogic(MqDto mqDto, String key) {
+    public void execMqRecordBreakHistoryPersistedLogic(MqDto mqDto, String key) {
         Gson gson = new Gson();
-        String tag = mqDto.getTag();
-        if (Objects.equals(tag, MqTagEnum.EXAM_RECORD_UPDATE.name())) {//考试记录单字段更新
-            Map<String, Object> param = (Map<String, Object>) mqDto.getBody();
-            Long recordId = Long.parseLong(String.valueOf(param.get("recordId")));
-            String colName = (String) param.get("colName");
-            Object colValue = param.get("colValue");
-            examRecordService.dataUpdate(recordId, colName, colValue);
-        } else if (Objects.equals(tag, MqTagEnum.EXAM_RECORD_UPDATE_COLUMNS.name())) {//考试记录多字段更新
-            Map<String, Object> param = (Map<String, Object>) mqDto.getBody();
-            Long recordId = Long.parseLong(String.valueOf(param.get("recordId")));
-            List<String> colNames = (List<String>) (param.get("colNames"));
-            List<Object> colValues = (List<Object>) param.get("colValues");
-            UpdateWrapper<TOeExamRecord> tOeExamRecordUpdateWrapper = new UpdateWrapper<>();
-            for (int i = 0; i < colNames.size(); i++) {
-                String colName = colNames.get(i);
-                Object colValue = colValues.get(i);
-                tOeExamRecordUpdateWrapper.set(colName, colValue);
-            }
-            tOeExamRecordUpdateWrapper.lambda().eq(TOeExamRecord::getId, recordId);
-            examRecordService.update(tOeExamRecordUpdateWrapper);
-        } else if (Objects.equals(tag, MqTagEnum.EXAM_BREAK_HISTORY_UPDATE.name())) {//断点记录多字段更新
-            Map<String, Object> param = (Map<String, Object>) mqDto.getBody();
-            Long breakId = Long.parseLong(String.valueOf(param.get("id")));
-            String colName = (String) param.get("colName");
-            Object colValue = param.get("colValue");
-            UpdateWrapper<TOeExamBreakHistory> tOeExamBreakHistoryUpdateWrapper = new UpdateWrapper<>();
-            tOeExamBreakHistoryUpdateWrapper.set(colName, colValue);
-            tOeExamBreakHistoryUpdateWrapper.lambda().eq(TOeExamBreakHistory::getId, breakId);
-            tOeExamBreakHistoryService.update(tOeExamBreakHistoryUpdateWrapper);
-        } else if (Objects.equals(tag, MqTagEnum.EXAM_BREAK_HISTORY_UPDATE_COLUMNS.name())) {//断点记录多字段更新
-            Map<String, Object> param = (Map<String, Object>) mqDto.getBody();
-            Long breakId = Long.parseLong(String.valueOf(param.get("id")));
-            List<String> colNames = (List<String>) (param.get("colNames"));
-            List<Object> colValues = (List<Object>) param.get("colValues");
-            UpdateWrapper<TOeExamBreakHistory> tOeExamBreakHistoryUpdateWrapper = new UpdateWrapper<>();
-            for (int i = 0; i < colNames.size(); i++) {
-                String colName = colNames.get(i);
-                Object colValue = colValues.get(i);
-                tOeExamBreakHistoryUpdateWrapper.set(colName, colValue);
-            }
-            tOeExamBreakHistoryUpdateWrapper.lambda().eq(TOeExamBreakHistory::getId, breakId);
-            tOeExamBreakHistoryService.update(tOeExamBreakHistoryUpdateWrapper);
-        }
+        Long breakId = Long.parseLong(mqDto.getObjId());
+        tOeExamBreakHistoryService.examRecordBreakHistoryDataSave(breakId);
         mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
         TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
         tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
@@ -679,10 +646,10 @@ public class MqLogicServiceImpl implements MqLogicService {
 
     @Override
     @Transactional
-    public void execMqRecordInitLogic(MqDto mqDto, String key) {
+    public void execMqRecordUpdateLogic(MqDto mqDto, String key) {
         Gson gson = new Gson();
-        Map<String, Object> param = (Map<String, Object>) mqDto.getBody();
-        examRecordService.dataInit(param);
+        Long recordId = Long.parseLong(mqDto.getObjId());
+        examRecordService.examRecordDataSave(recordId);
         mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
         TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
         tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
@@ -787,8 +754,6 @@ public class MqLogicServiceImpl implements MqLogicService {
                         .eq(TEExamStudentLog::getObjId, breakId);
                 teExamStudentLogService.update(teExamStudentLogUpdateWrapper);
             }
-        } else if (Objects.equals(MqTagEnum.WARNING_LOG.name(), tag)) {//考试预警日志
-            //todo 预警先预留
         }
         mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
         TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
@@ -892,10 +857,11 @@ public class MqLogicServiceImpl implements MqLogicService {
         //更新客户端摄像头推流状态为stop
         MonitorStatusSourceEnum cameraStatusSourceEnum = ExamRecordCacheUtil
                 .getMonitorStatus(recordId, MonitorVideoSourceEnum.CLIENT_CAMERA);
+        Long timestamp = System.currentTimeMillis();
         if (Objects.nonNull(cameraStatusSourceEnum)) {
             ExamRecordCacheUtil
                     .setMonitorStatus(recordId, MonitorVideoSourceEnum.CLIENT_CAMERA, MonitorStatusSourceEnum.STOP,
-                            true);
+                            timestamp);
         }
         //更新客户端屏幕推流状态为stop
         MonitorStatusSourceEnum screenStatusSourceEnum = ExamRecordCacheUtil
@@ -903,8 +869,9 @@ public class MqLogicServiceImpl implements MqLogicService {
         if (Objects.nonNull(screenStatusSourceEnum)) {
             ExamRecordCacheUtil
                     .setMonitorStatus(recordId, MonitorVideoSourceEnum.CLIENT_SCREEN, MonitorStatusSourceEnum.STOP,
-                            true);
+                            timestamp);
         }
+        examRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
         //发送移动端监考退出考试mq消息 start
         MqDto mqDtoExamStop = new MqDto(mqUtil.getMqGroupDomain().getTopic(), MqTagEnum.EXAM_STOP.name(), recordId,
                 MqTagEnum.EXAM_STOP, String.valueOf(recordId), String.valueOf(recordId));

+ 9 - 9
themis-mq/src/main/java/com/qmth/themis/mq/templete/impl/ExamRecordInitConcurrentlyImpl.java → themis-mq/src/main/java/com/qmth/themis/mq/templete/impl/ExamRecordBreakHistoryPersistedConcurrentlyImpl.java

@@ -11,19 +11,19 @@ import org.springframework.stereotype.Service;
 
 import java.util.List;
 
-/**
- * 考试记录数据初始化
- *
- * @Description:
- * @Author: xiatian
- * @Date: 2020-08-04
- */
+/** 
+* @Description: 考试断点记录数据持久化 
+* @Param:  
+* @return:  
+* @Author: wangliang
+* @Date: 2020/11/26 
+*/ 
 @Service
-public class ExamRecordInitConcurrentlyImpl implements Concurrently {
+public class ExamRecordBreakHistoryPersistedConcurrentlyImpl implements Concurrently {
 
     @Override
     public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
         MqLogicService mqLogicService = SpringContextHolder.getBean(MqLogicService.class);
-        return mqLogicService.consumeMessage(msgs, consumeConcurrentlyContext, MqExecTypeEnum.EXEC_MQ_RECORD_INIT_LOGIC);
+        return mqLogicService.consumeMessage(msgs, consumeConcurrentlyContext, MqExecTypeEnum.EXEC_MQ_RECORD_BREAK_HISTORY_PERSISTED_LOGIC);
     }
 }

+ 6 - 7
themis-task/src/main/java/com/qmth/themis/task/start/StartRunning.java

@@ -74,7 +74,7 @@ public class StartRunning implements CommandLineRunner {
         /**
          * log
          */
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, dictionaryConfig.mqConfigDomain().getMap().get(MqGroupEnum.LOG_GROUP.name()), dictionaryConfig.mqConfigDomain().getTopic(), MqTagEnum.EXCEPTION_LOG.name() + "||" + MqTagEnum.WARNING_LOG.name() + "||" + MqTagEnum.MONITOR_LOG.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(LogConcurrentlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, dictionaryConfig.mqConfigDomain().getMap().get(MqGroupEnum.LOG_GROUP.name()), dictionaryConfig.mqConfigDomain().getTopic(), MqTagEnum.EXCEPTION_LOG.name() + "||" + MqTagEnum.MONITOR_LOG.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(LogConcurrentlyImpl.class));
         /**
          * task
          */
@@ -97,15 +97,14 @@ public class StartRunning implements CommandLineRunner {
         //活体验证保存
         rocketMessageConsumer.setRocketMQConsumer(nameServer, dictionaryConfig.mqConfigDomain().getMap().get(MqGroupEnum.LIVENESS_VERIFY_SAVE_GROUP.name()), dictionaryConfig.mqConfigDomain().getTopic(), MqTagEnum.LIVENESS_VERIFY_SAVE.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(LivenessVerifyConcurrentlyImpl.class));
 
+        //考试记录数据更新
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, dictionaryConfig.mqConfigDomain().getMap().get(MqGroupEnum.EXAM_RECORD_UPDATE_GROUP.name()), dictionaryConfig.mqConfigDomain().getTopic(), MqTagEnum.EXAM_RECORD_UPDATE.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordUpdateConcurrentlyImpl.class));
         //考试记录数据持久化
         rocketMessageConsumer.setRocketMQConsumer(nameServer, dictionaryConfig.mqConfigDomain().getMap().get(MqGroupEnum.EXAM_RECORD_PERSISTED_GROUP.name()), dictionaryConfig.mqConfigDomain().getTopic(), MqTagEnum.EXAM_RECORD_PERSISTED.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordPersistedConcurrentlyImpl.class));
+        //考试断点记录数据持久化
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, dictionaryConfig.mqConfigDomain().getMap().get(MqGroupEnum.EXAM_BREAK_RECORD_PERSISTED_GROUP.name()), dictionaryConfig.mqConfigDomain().getTopic(), MqTagEnum.EXAM_BREAK_HISTORY_PERSISTED.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordBreakHistoryPersistedConcurrentlyImpl.class));
 
-        //考试记录数据更新
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, dictionaryConfig.mqConfigDomain().getMap().get(MqGroupEnum.EXAM_RECORD_UPDATE_GROUP.name()), dictionaryConfig.mqConfigDomain().getTopic(), MqTagEnum.EXAM_RECORD_UPDATE.name() + "||" + MqTagEnum.EXAM_RECORD_UPDATE_COLUMNS.name() + "||" + MqTagEnum.EXAM_BREAK_HISTORY_UPDATE.name() + "||" + MqTagEnum.EXAM_BREAK_HISTORY_UPDATE_COLUMNS.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordUpdateConcurrentlyImpl.class));
-        //考试记录数据初始化
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, dictionaryConfig.mqConfigDomain().getMap().get(MqGroupEnum.EXAM_RECORD_INIT_GROUP.name()), dictionaryConfig.mqConfigDomain().getTopic(), MqTagEnum.EXAM_RECORD_INIT.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordInitConcurrentlyImpl.class));
-
-        //考生数据更新
+//        考生数据更新
         rocketMessageConsumer.setRocketMQConsumer(nameServer, dictionaryConfig.mqConfigDomain().getMap().get(MqGroupEnum.EXAM_STUDENT_UPDATE_GROUP.name()), dictionaryConfig.mqConfigDomain().getTopic(), MqTagEnum.EXAM_STUDNET_UPDATE.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamStudentUpdateConcurrentlyImpl.class));
 
         //考试断点

+ 2 - 2
themis-task/src/main/resources/application.properties

@@ -13,7 +13,7 @@ spring.application.name=themis-task
 #\u6570\u636E\u6E90\u914D\u7F6E
 db.host=localhost
 db.port=3306
-db.name=themis
+db.name=themis_test1
 db.username=root
 db.password=123456789
 #redis\u6570\u636E\u6E90\u914D\u7F6E
@@ -190,7 +190,7 @@ mq.config.map.FACE_VERIFY_SAVE_GROUP=themis-group-exam-faceVerifySave
 mq.config.map.LIVENESS_VERIFY_SAVE_GROUP=themis-group-exam-livenessVerifySave
 mq.config.map.EXAM_RECORD_PERSISTED_GROUP=themis-group-exam-examRecordPersisted
 mq.config.map.EXAM_RECORD_UPDATE_GROUP=themis-group-exam-examRecordUpdate
-mq.config.map.EXAM_RECORD_INIT_GROUP=themis-group-exam-examRecordInit
+mq.config.map.EXAM_BREAK_HISTORY_PERSISTED=themis-group-exam-examBreakHistoryPersisted
 mq.config.map.SCORE_CALCULATE_GROUP=themis-group-exam-scoreCalculate
 mq.config.map.EXAM_STUDENT_UPDATE_GROUP=themis-group-exam-examStudentUpdate
 mq.config.map.EXAM_BREAK_GROUP=themis-group-exam-examBreak