浏览代码

断点时间更新和逻辑修改

wangliang 4 年之前
父节点
当前提交
142f3cd83f

+ 1 - 1
themis-backend/src/main/java/com/qmth/themis/backend/start/StartRunning.java

@@ -68,7 +68,7 @@ public class StartRunning implements CommandLineRunner {
         //考试记录数据持久化
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_RECORD_PERSISTED_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_RECORD_PERSISTED.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordPersistedConcurrentlyImpl.class));
         //考试记录数据更新
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_RECORD_UPDATE_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_RECORD_UPDATE.name() + "||" + MqTagEnum.EXAM_RECORD_UPDATE_COLUMNS.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordUpdateConcurrentlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_RECORD_UPDATE_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), 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, MqGroupEnum.EXAM_RECORD_INIT_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_RECORD_INIT.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordInitConcurrentlyImpl.class));
 

+ 52 - 26
themis-business/src/main/java/com/qmth/themis/business/cache/ExamBreakCacheUtil.java

@@ -1,8 +1,10 @@
 package com.qmth.themis.business.cache;
 
 import com.qmth.themis.business.constant.SpringContextHolder;
+import com.qmth.themis.business.enums.ExamBreakHistoryFieldEnum;
 import com.qmth.themis.business.enums.ExceptionEnum;
 import com.qmth.themis.business.enums.VerifyExceptionEnum;
+import com.qmth.themis.business.service.TOeExamBreakHistoryService;
 import com.qmth.themis.business.util.RedisUtil;
 
 /**
@@ -13,71 +15,95 @@ import com.qmth.themis.business.util.RedisUtil;
  * @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) {
-        redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), "examRecordId", examRecordId);
+    public static void setExamRecordId(Long examBreakId, Long examRecordId, boolean update) {
+        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), "examRecordId");
+        return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.exam_record_id.getCode());
     }
 
-    public static void setBreakTime(Long examBreakId, Long breakTime) {
-        redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), "breakTime", breakTime);
+    public static void setBreakTime(Long examBreakId, Long breakTime, boolean update) {
+        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), "breakTime");
+        return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.break_time.getCode());
     }
 
-    public static void setBreakReason(Long examBreakId, ExceptionEnum breakReason) {
-        redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), "breakReason", breakReason);
+    public static void setBreakReason(Long examBreakId, ExceptionEnum breakReason, boolean update) {
+        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 (ExceptionEnum) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), "breakReason");
+        return (ExceptionEnum) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.break_reason.getCode());
     }
 
-    public static void setResumeReason(Long examBreakId, String resumeReason) {
-        redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), "resumeReason", resumeReason);
+    public static void setResumeReason(Long examBreakId, String resumeReason, boolean update) {
+        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), "resumeReason");
+        return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.resume_reason.getCode());
     }
 
 
-    public static void setPrepareTime(Long examBreakId, Long prepareTime) {
-        redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), "prepareTime", prepareTime);
+    public static void setPrepareTime(Long examBreakId, Long prepareTime, boolean update) {
+        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), "prepareTime");
+        return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.prepare_time.getCode());
     }
 
-
-    public static void setStartTime(Long examBreakId, Long startTime) {
-        redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), "startTime", startTime);
+    public static void setStartTime(Long examBreakId, Long startTime, boolean update) {
+        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), "startTime");
+        return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.start_time.getCode());
     }
 
-    public static void setEntryAuthenticationResult(Long examBreakId, VerifyExceptionEnum entryAuthenticationResult) {
-        redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), "entryAuthenticationResult", entryAuthenticationResult);
+    public static void setEntryAuthenticationResult(Long examBreakId, VerifyExceptionEnum entryAuthenticationResult, boolean update) {
+        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 (VerifyExceptionEnum) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), "entryAuthenticationResult");
+        return (VerifyExceptionEnum) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.entry_authentication_result.getCode());
     }
 
-    public static void setEntryAuthenticationId(Long examBreakId, Long entryAuthenticationId) {
-        redisUtil.set(RedisKeyHelper.examBreakCacheKey(examBreakId), "entryAuthenticationId", entryAuthenticationId);
+    public static void setEntryAuthenticationId(Long examBreakId, Long entryAuthenticationId, boolean update) {
+        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) {
-        return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), "entryAuthenticationId");
+        return (Long) redisUtil.get(RedisKeyHelper.examBreakCacheKey(examBreakId), ExamBreakHistoryFieldEnum.entry_authentication_id.getCode());
     }
-}
+}

+ 4 - 0
themis-business/src/main/java/com/qmth/themis/business/cache/ExamRecordCacheUtil.java

@@ -46,6 +46,10 @@ public class ExamRecordCacheUtil {
         }
     }
 
+    public static Long getFirstStartTime(Long recordId) {
+        return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.first_start_time.getCode());
+    }
+
     public static Integer getDurationSeconds(Long recordId) {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.duration_seconds.getCode());
     }

+ 39 - 0
themis-business/src/main/java/com/qmth/themis/business/enums/ExamBreakHistoryFieldEnum.java

@@ -0,0 +1,39 @@
+package com.qmth.themis.business.enums;
+
+/**
+ * @Description: 断点记录字段
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/9/18
+ */
+public enum ExamBreakHistoryFieldEnum {
+
+    id("id"),
+
+    exam_record_id("examRecordId"),
+
+    break_time("breakTime"),
+
+    break_reason("breakReason"),
+
+    resume_reason("resumeReason"),
+
+    prepare_time("prepareTime"),
+
+    start_time("startTime"),
+
+    entry_authentication_result("entryAuthenticationResult"),
+
+    entry_authentication_id("entryAuthenticationId");
+
+    private String code;
+
+    private ExamBreakHistoryFieldEnum(String code) {
+        this.code = code;
+    }
+
+    public String getCode() {
+        return code;
+    }
+}

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

@@ -48,7 +48,9 @@ public enum MqTagEnum {
     EXAM_STUDENT_EXPORT("考生导出任务标签", "考生导出任务", "normal", 36),
     MARK_RESULT_SIMPLE_EXPORT("成绩查询简版导出任务标签", "成绩查询简版导出任务", "normal", 37),
     MARK_RESULT_STANDARD_EXPORT("成绩查询标准版导出任务标签", "成绩查询标准版导出任务", "normal", 38),
-    EXAM_BREAK_DELAY("断点时间标签", "断点时间", "delay", 39);
+    EXAM_BREAK_DELAY("断点时间标签", "断点时间", "delay", 39),
+    EXAM_BREAK_HISTORY_UPDATE("断点记录数据更新标签", "断点记录数据更新", "normal", 40),
+    EXAM_BREAK_HISTORY_UPDATE_COLUMNS("断点记录多字段数据更新标签", "断点记录多字段数据更新", "normal", 41);
 
     private MqTagEnum(String desc, String code, String type, int id) {
         this.desc = desc;

+ 22 - 2
themis-business/src/main/java/com/qmth/themis/business/service/TOeExamBreakHistoryService.java

@@ -13,11 +13,31 @@ import com.qmth.themis.business.enums.VerifyExceptionEnum;
  */
 public interface TOeExamBreakHistoryService extends IService<TOeExamBreakHistory> {
 
-	/**保存验证信息
+	/**
+	 * 保存验证信息
+	 *
 	 * @param recordId
 	 * @param entryAuthenticationId
 	 * @param entryAuthenticationResult
 	 */
 	void saveAuthenticationResult(Long recordId, Long entryAuthenticationId, VerifyExceptionEnum entryAuthenticationResult);
 
-}
+
+	/**
+	 * 断点记录字段同步消息发送
+	 *
+	 * @param breakId
+	 * @param colName
+	 * @param colValue
+	 */
+	void dataUpdateMq(Long breakId, String colName, Object colValue);
+
+	/**
+	 * 考试记录多字段更新
+	 *
+	 * @param breakId
+	 * @param colNames
+	 * @param colValues
+	 */
+	void dataUpdatesMq(Long breakId, String[] colNames, Object[] colValues);
+}

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

@@ -70,7 +70,7 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
     void dataUpdate(Long recordId, String colName, Object colValue);
 
     /**
-     * 考试记录字段同步消息发送
+     * 考试记录多字段更新
      *
      * @param recordId
      * @param colNames

+ 41 - 21
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -7,10 +7,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.themis.business.bean.backend.OpenExamBean;
 import com.qmth.themis.business.bean.exam.*;
-import com.qmth.themis.business.cache.ExamActivityRecordCacheUtil;
-import com.qmth.themis.business.cache.ExamRecordCacheUtil;
-import com.qmth.themis.business.cache.ExamingDataCacheUtil;
-import com.qmth.themis.business.cache.RedisKeyHelper;
+import com.qmth.themis.business.cache.*;
 import com.qmth.themis.business.cache.bean.*;
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SystemConstant;
@@ -515,19 +512,35 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
             if (lock) {
                 try {
                     // 更新考试记录缓存
-                    Long firstStartTime = System.currentTimeMillis();
-                    ExamRecordCacheUtil.setFirstStartTime(recordId, firstStartTime, false);
+                    Long firstStartTime = ExamRecordCacheUtil.getFirstStartTime(recordId), lastStartTime = null;
+                    String[] columns = null;
+                    Object[] values = null;
                     ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.ANSWERING, false);
-                    Long lastStartTime = System.currentTimeMillis();
-                    ExamRecordCacheUtil.setLastStartTime(recordId, lastStartTime, false);
-                    String[] columns = new String[]{ExamRecordFieldEnum.first_start_time.name(),
-                            ExamRecordFieldEnum.status.name(), ExamRecordFieldEnum.last_start_time.name()};
-                    Object[] values = new Object[]{firstStartTime, ExamRecordStatusEnum.ANSWERING, lastStartTime};
-                    toeExamRecordService.dataUpdatesMq(recordId, columns, values);
-                    //更新场次-考试记录缓存
-                    ExamActivityRecordCacheUtil.setExamRecordStatus(activityId, recordId,
-                            new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
-                                    ExamRecordCacheUtil.getStatus(recordId)));
+                    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};
+                    } 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};
+                    }
+                    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);
+                        }
+                        toeExamRecordService.dataUpdatesMq(recordId, columns, values);
+                        //更新场次-考试记录缓存
+                        ExamActivityRecordCacheUtil.setExamRecordStatus(activityId, recordId,
+                                new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
+                                        ExamRecordCacheUtil.getStatus(recordId)));
+                    }
                     break;
                 } finally {
                     if (Objects.nonNull(recordId)) {
@@ -885,11 +898,18 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
                     String[] columns = new String[]{ExamRecordFieldEnum.last_prepare_time.name(),
                             ExamRecordFieldEnum.status.name()};
                     Object[] values = new Object[]{lastPrepareTime, ExamRecordStatusEnum.RESUME_PREPARE};
-                    toeExamRecordService.dataUpdatesMq(recordId, columns, values);
-                    //更新场次-考试记录缓存
-                    ExamActivityRecordCacheUtil.setExamRecordStatus(es.getExamActivityId(), recordId,
-                            new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
-                                    ExamRecordCacheUtil.getStatus(recordId)));
+                    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);
+                        }
+                        toeExamRecordService.dataUpdatesMq(recordId, columns, values);
+                        //更新场次-考试记录缓存
+                        ExamActivityRecordCacheUtil.setExamRecordStatus(es.getExamActivityId(), recordId,
+                                new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
+                                        ExamRecordCacheUtil.getStatus(recordId)));
+                    }
                     break;
                 } finally {
                     if (Objects.nonNull(recordId)) {

+ 62 - 21
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamBreakHistoryServiceImpl.java

@@ -1,15 +1,23 @@
 package com.qmth.themis.business.service.impl;
 
-import org.springframework.stereotype.Service;
-
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.themis.business.cache.ExamBreakCacheUtil;
 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.MqTagEnum;
+import com.qmth.themis.business.enums.MqTopicEnum;
 import com.qmth.themis.business.enums.VerifyExceptionEnum;
+import com.qmth.themis.business.service.MqDtoService;
 import com.qmth.themis.business.service.TOeExamBreakHistoryService;
 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: 考试断点记录 服务实现类
@@ -20,22 +28,55 @@ import com.qmth.themis.common.exception.BusinessException;
  */
 @Service
 public class TOeExamBreakHistoryServiceImpl extends ServiceImpl<TOeExamBreakHistoryMapper, TOeExamBreakHistory> implements TOeExamBreakHistoryService {
-	
-	/**保存验证信息
-	 * @param recordId
-	 * @param entryAuthenticationId
-	 * @param entryAuthenticationResult
-	 */
-	@Override
-	public void saveAuthenticationResult(Long recordId,Long entryAuthenticationId,VerifyExceptionEnum entryAuthenticationResult) {
-		Long examBreakId=ExamRecordCacheUtil.getLastBreakId(recordId);
-		if(examBreakId==null) {
-			throw new BusinessException("未找到断点ID");
-		}
-		if(ExamBreakCacheUtil.getExamRecordId(examBreakId)==null) {
-			throw new BusinessException("未找到断点信息");
-		}
-		ExamBreakCacheUtil.setEntryAuthenticationId(examBreakId, entryAuthenticationId); 
-		ExamBreakCacheUtil.setEntryAuthenticationResult(examBreakId, entryAuthenticationResult);
-	}
-}
+
+    @Resource
+    MqDtoService mqDtoService;
+
+    /**
+     * 保存验证信息
+     *
+     * @param recordId
+     * @param entryAuthenticationId
+     * @param entryAuthenticationResult
+     */
+    @Override
+    public void saveAuthenticationResult(Long recordId, Long entryAuthenticationId, VerifyExceptionEnum entryAuthenticationResult) {
+        Long examBreakId = ExamRecordCacheUtil.getLastBreakId(recordId);
+        if (examBreakId == null) {
+            throw new BusinessException("未找到断点ID");
+        }
+        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);
+    }
+
+    @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(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK_HISTORY_UPDATE.name(), transMap,
+                MqTagEnum.EXAM_BREAK_HISTORY_UPDATE, breakId.toString(), colName);
+        mqDtoService.assembleSendOneWayMsg(mqDto);
+    }
+
+    @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(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK_HISTORY_UPDATE_COLUMNS.name(),
+                transMap, MqTagEnum.EXAM_BREAK_HISTORY_UPDATE_COLUMNS, breakId.toString(), breakId.toString());
+        mqDtoService.assembleSendOneWayMsg(mqDto);
+    }
+}

+ 53 - 55
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -10,7 +10,6 @@ import com.qmth.themis.business.cache.ExamActivityRecordCacheUtil;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.cache.bean.*;
-import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dao.TOeExamRecordMapper;
 import com.qmth.themis.business.dto.MqDto;
@@ -1033,69 +1032,68 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                     Long lastBreakTimeNow = System.currentTimeMillis();
                     ExamRecordCacheUtil.setLastBreakTime(recordId, lastBreakTimeNow, false);
                     ExamRecordCacheUtil.setAlreadyBreakCount(recordId, alreadyBreakCount, false);
-                    Long lastStartTime = System.currentTimeMillis();
-                    ExamRecordCacheUtil.setLastStartTime(recordId, lastStartTime, false);
                     String[] columns = new String[]{ExamRecordFieldEnum.last_break_id.name(),
                             ExamRecordFieldEnum.status.name(), ExamRecordFieldEnum.last_break_time.name(),
-                            ExamRecordFieldEnum.already_break_count.name(), ExamRecordFieldEnum.last_start_time.name()};
+                            ExamRecordFieldEnum.already_break_count.name()};
                     Object[] values = new Object[]{breakId, ExamRecordStatusEnum.BREAK_OFF, lastBreakTimeNow,
-                            alreadyBreakCount, lastStartTime};
-                    TOeExamRecordService tOeExamRecordService = SpringContextHolder.getBean(TOeExamRecordService.class);
-                    tOeExamRecordService.dataUpdatesMq(recordId, columns, values);
-                    //考试断点异常原因 发送mq start
-                    MqDto mqDtoBreak = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK.name(),
-                            ExceptionEnum.NET_TIME_OUT, MqTagEnum.EXAM_BREAK, String.valueOf(recordId),
-                            String.valueOf(recordId));
-                    MqDtoService mqDtoService = SpringContextHolder.getBean(MqDtoService.class);
-                    mqDtoService.assembleSendOneWayMsg(mqDtoBreak);
-                    //考试断点异常原因 发送mq end
-
-                    Long examId = ExamRecordCacheUtil.getExamId(recordId);
-                    ExamCacheBean ec = examService.getExamCacheBean(examId);//考试缓存
-                    Integer breakExpireSeconds = Objects.isNull(ec.getBreakExpireSeconds()) ?
-                            0 :
-                            ec.getBreakExpireSeconds();
-                    if (breakExpireSeconds.intValue() > 0) {
-                        List<String> list = SystemConstant.mqDelayLevelList.subList(5, 15);
-                        String level = null;
-                        if (breakExpireSeconds.intValue() <= 60) {
-                            level = "1m";
-                        } else {
-                            Integer time = breakExpireSeconds.intValue() / 60;
-                            if (time.intValue() >= 30) {
-                                level = "30m";
+                            alreadyBreakCount};
+                    ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
+                    if (Objects.nonNull(examRecordStatusEnum) && examRecordStatusEnum == ExamRecordStatusEnum.BREAK_OFF) {
+                        this.dataUpdatesMq(recordId, columns, values);
+                        //考试断点异常原因 发送mq start
+                        MqDto mqDtoBreak = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK.name(),
+                                ExceptionEnum.NET_TIME_OUT, MqTagEnum.EXAM_BREAK, String.valueOf(recordId),
+                                String.valueOf(recordId));
+                        mqDtoService.assembleSendOneWayMsg(mqDtoBreak);
+                        //考试断点异常原因 发送mq end
+
+                        Long examId = ExamRecordCacheUtil.getExamId(recordId);
+                        ExamCacheBean ec = examService.getExamCacheBean(examId);//考试缓存
+                        Integer breakExpireSeconds = Objects.isNull(ec.getBreakExpireSeconds()) ?
+                                0 :
+                                ec.getBreakExpireSeconds();
+                        if (breakExpireSeconds.intValue() > 0) {
+                            List<String> list = SystemConstant.mqDelayLevelList.subList(5, 15);
+                            String level = null;
+                            if (breakExpireSeconds.intValue() <= 60) {
+                                level = "1m";
                             } else {
-                                for (String s : list) {
-                                    Integer value = Integer.parseInt(s.substring(0, s.length() - 1));
-                                    if (time.intValue() <= value.intValue()) {
-                                        level = value + "m";
-                                        break;
+                                Integer time = breakExpireSeconds.intValue() / 60;
+                                if (time.intValue() >= 30) {
+                                    level = "30m";
+                                } else {
+                                    for (String s : list) {
+                                        Integer value = Integer.parseInt(s.substring(0, s.length() - 1));
+                                        if (time.intValue() <= value.intValue()) {
+                                            level = value + "m";
+                                            break;
+                                        }
                                     }
                                 }
                             }
+                            Map<String, Object> tranMap = new HashMap<>();
+                            Integer time = SystemConstant.mqDelayLevel.get(level);
+                            LocalDateTime dt = LocalDateTime.now();
+                            if (level.contains("m")) {
+                                dt = dt.plusMinutes(Long.parseLong(level.replace("m", "")));
+                            } else {
+                                dt = dt.plusSeconds(Long.parseLong(level.replace("s", "")));
+                            }
+                            tranMap.put("recordId", recordId);
+                            tranMap.put("timeOut", time);
+                            tranMap.put("mqExecTime", dt.toInstant(ZoneOffset.of("+8")).toEpochMilli());
+                            //考试断点延时消息 发送mq start
+                            MqDto mqDtoBreakDelay = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(),
+                                    MqTagEnum.EXAM_BREAK_DELAY.name(), MqTagEnum.EXAM_BREAK_DELAY, MqTagEnum.EXAM_BREAK_DELAY,
+                                    String.valueOf(recordId), tranMap, String.valueOf(recordId));
+                            mqDtoService.assembleSendAsyncDelayMsg(mqDtoBreakDelay);
+                            //考试断点延时消息 发送mq end
                         }
-                        Map<String, Object> tranMap = new HashMap<>();
-                        Integer time = SystemConstant.mqDelayLevel.get(level);
-                        LocalDateTime dt = LocalDateTime.now();
-                        if (level.contains("m")) {
-                            dt = dt.plusMinutes(Long.parseLong(level.replace("m", "")));
-                        } else {
-                            dt = dt.plusSeconds(Long.parseLong(level.replace("s", "")));
-                        }
-                        tranMap.put("recordId", recordId);
-                        tranMap.put("timeOut", time);
-                        tranMap.put("mqExecTime", dt.toInstant(ZoneOffset.of("+8")).toEpochMilli());
-                        //考试断点延时消息 发送mq start
-                        MqDto mqDtoBreakDelay = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(),
-                                MqTagEnum.EXAM_BREAK_DELAY.name(), MqTagEnum.EXAM_BREAK_DELAY, MqTagEnum.EXAM_BREAK_DELAY,
-                                String.valueOf(recordId), tranMap, String.valueOf(recordId));
-                        mqDtoService.assembleSendAsyncDelayMsg(mqDtoBreakDelay);
-                        //考试断点延时消息 发送mq end
+                        //更新场次-考试记录缓存
+                        ExamActivityRecordCacheUtil.setExamRecordStatus(examActivityId, recordId,
+                                new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
+                                        ExamRecordCacheUtil.getStatus(recordId)));
                     }
-                    //更新场次-考试记录缓存
-                    ExamActivityRecordCacheUtil.setExamRecordStatus(examActivityId, recordId,
-                            new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId),
-                                    ExamRecordCacheUtil.getStatus(recordId)));
                     break;
                 } catch (Exception e) {
                     log.error("请求出错", e);

+ 10 - 2
themis-exam/src/main/java/com/qmth/themis/exam/api/TEExamController.java

@@ -15,6 +15,7 @@ import com.qmth.themis.business.entity.TEExam;
 import com.qmth.themis.business.enums.*;
 import com.qmth.themis.business.service.MqDtoService;
 import com.qmth.themis.business.service.TEExamService;
+import com.qmth.themis.business.service.TOeExamBreakHistoryService;
 import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.JacksonUtil;
 import com.qmth.themis.business.util.RedisUtil;
@@ -50,6 +51,9 @@ public class TEExamController {
     @Resource
     TOeExamRecordService tOeExamRecordService;
 
+    @Resource
+    TOeExamBreakHistoryService tOeExamBreakHistoryService;
+
     @ApiOperation(value = "验证考试口令接口")
     @RequestMapping(value = "/short_code", method = RequestMethod.POST)
     @ApiResponses({ @ApiResponse(code = 200, message = "考试信息", response = TEExam.class) })
@@ -154,8 +158,12 @@ public class TEExamController {
                     ExceptionEnum exceptionEnum = ExceptionEnum
                             .valueOf(ExceptionEnum.convertToName(String.valueOf(jsonObject.get("type"))));
                     String reason = String.valueOf(jsonObject.get("reason"));
-                    ExamBreakCacheUtil.setBreakReason(breakId, exceptionEnum);
-                    ExamBreakCacheUtil.setResumeReason(breakId, 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);
                     //考试断点异常原因 发送mq start
                     MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXCEPTION_LOG.name(),
                             JacksonUtil.parseJson(param), MqTagEnum.EXCEPTION_LOG, String.valueOf(param.getRecordId()),

+ 1 - 1
themis-exam/src/main/java/com/qmth/themis/exam/start/StartRunning.java

@@ -76,7 +76,7 @@ public class StartRunning implements CommandLineRunner {
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_RECORD_PERSISTED_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_RECORD_PERSISTED.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordPersistedConcurrentlyImpl.class));
 
         //考试记录数据更新
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_RECORD_UPDATE_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_RECORD_UPDATE.name() + "||" + MqTagEnum.EXAM_RECORD_UPDATE_COLUMNS.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordUpdateConcurrentlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_RECORD_UPDATE_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), 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, MqGroupEnum.EXAM_RECORD_INIT_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_RECORD_INIT.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordInitConcurrentlyImpl.class));
 

+ 25 - 3
themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java

@@ -262,7 +262,7 @@ public class MqLogicServiceImpl implements MqLogicService {
         ExamRecordStatusEnum status = ExamRecordCacheUtil.getStatus(recordId);
         WebsocketStatusEnum websocketStatusEnum = ExamRecordCacheUtil.getClientWebsocketStatus(recordId);
         if (Objects.nonNull(websocketStatusEnum) && (Objects.equals(websocketStatusEnum, WebsocketStatusEnum.OFF_LINE)
-                || Objects.equals(status, ExamRecordStatusEnum.ANSWERING))) {
+                && Objects.equals(status, ExamRecordStatusEnum.ANSWERING))) {
             examRecordService.sendExamBreakMsg(recordId, true);
             //更新客户端摄像头推流状态为stop
             MonitorStatusSourceEnum cameraStatusSourceEnum = ExamRecordCacheUtil
@@ -622,13 +622,13 @@ public class MqLogicServiceImpl implements MqLogicService {
     public void execMqRecordUpdateLogic(MqDto mqDto, String key) {
         Gson gson = new Gson();
         String tag = mqDto.getTag();
-        if (Objects.equals(tag, MqTagEnum.EXAM_RECORD_UPDATE.name())) {//单字段更新
+        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())) {//多字段更新
+        } 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"));
@@ -641,6 +641,28 @@ public class MqLogicServiceImpl implements MqLogicService {
             }
             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);
         }
         mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
         TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);

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

@@ -103,7 +103,7 @@ public class StartRunning implements CommandLineRunner {
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_RECORD_PERSISTED_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_RECORD_PERSISTED.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordPersistedConcurrentlyImpl.class));
 
         //考试记录数据更新
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_RECORD_UPDATE_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_RECORD_UPDATE.name() + "||" + MqTagEnum.EXAM_RECORD_UPDATE_COLUMNS.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordUpdateConcurrentlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_RECORD_UPDATE_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), 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, MqGroupEnum.EXAM_RECORD_INIT_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_RECORD_INIT.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordInitConcurrentlyImpl.class));