Explorar o código

Merge branch 'dev_v1.2.8' into release_v1.2.8
merge

wangliang hai 1 ano
pai
achega
68615c4962
Modificáronse 59 ficheiros con 1142 adicións e 912 borrados
  1. 1 5
      themis-admin/src/main/java/com/qmth/themis/admin/api/TBUserController.java
  2. 26 11
      themis-admin/src/main/java/com/qmth/themis/admin/api/TEExamController.java
  3. 1 1
      themis-admin/src/main/java/com/qmth/themis/admin/api/TEExamStudentController.java
  4. 19 11
      themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateController.java
  5. 23 29
      themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateWarnInfoController.java
  6. 52 0
      themis-business/src/main/java/com/qmth/themis/business/bean/admin/ExamInfoBean.java
  7. 59 0
      themis-business/src/main/java/com/qmth/themis/business/bean/admin/OrgSummaryBean.java
  8. 0 41
      themis-business/src/main/java/com/qmth/themis/business/bean/status/AlreadyBreakCountBean.java
  9. 0 41
      themis-business/src/main/java/com/qmth/themis/business/bean/status/ExceptionCountBean.java
  10. 0 41
      themis-business/src/main/java/com/qmth/themis/business/bean/status/InProcessLivenessVerifyCountBean.java
  11. 0 41
      themis-business/src/main/java/com/qmth/themis/business/bean/status/WarningCountBean.java
  12. 0 41
      themis-business/src/main/java/com/qmth/themis/business/bean/status/WarningMultipleFaceCountBean.java
  13. 0 41
      themis-business/src/main/java/com/qmth/themis/business/bean/status/WarningUnreadBean.java
  14. 47 149
      themis-business/src/main/java/com/qmth/themis/business/cache/ExamRecordCacheUtil.java
  15. 2 1
      themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java
  16. 17 0
      themis-business/src/main/java/com/qmth/themis/business/dao/TEExamActivityMapper.java
  17. 9 0
      themis-business/src/main/java/com/qmth/themis/business/dao/TEExamStudentMapper.java
  18. 8 14
      themis-business/src/main/java/com/qmth/themis/business/dao/TEOrgSummaryMapper.java
  19. 1 1
      themis-business/src/main/java/com/qmth/themis/business/dao/TERegionSummaryMapper.java
  20. 32 0
      themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamRecordMapper.java
  21. 3 3
      themis-business/src/main/java/com/qmth/themis/business/dto/ExamPropCountDto.java
  22. 13 1
      themis-business/src/main/java/com/qmth/themis/business/dto/response/TEExamWaitDto.java
  23. 14 0
      themis-business/src/main/java/com/qmth/themis/business/entity/TEOrgSummary.java
  24. 17 0
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamActivityService.java
  25. 9 0
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamStudentService.java
  26. 3 1
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamSummaryService.java
  27. 18 1
      themis-business/src/main/java/com/qmth/themis/business/service/TEOrgSummaryService.java
  28. 4 1
      themis-business/src/main/java/com/qmth/themis/business/service/TERegionSummaryService.java
  29. 35 2
      themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java
  30. 37 15
      themis-business/src/main/java/com/qmth/themis/business/service/ThemisCacheService.java
  31. 17 5
      themis-business/src/main/java/com/qmth/themis/business/service/impl/AuthInfoServiceImpl.java
  32. 4 4
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TBAttachmentServiceImpl.java
  33. 33 10
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamActivityServiceImpl.java
  34. 32 25
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java
  35. 12 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamStudentServiceImpl.java
  36. 18 6
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamSummaryServiceImpl.java
  37. 57 19
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEOrgSummaryServiceImpl.java
  38. 5 2
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TERegionSummaryServiceImpl.java
  39. 37 25
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TIeReportServiceImpl.java
  40. 62 82
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java
  41. 94 68
      themis-business/src/main/java/com/qmth/themis/business/service/impl/ThemisCacheServiceImpl.java
  42. 8 8
      themis-business/src/main/java/com/qmth/themis/business/templete/impl/TaskExamPaperImportTemplete.java
  43. 1 1
      themis-business/src/main/java/com/qmth/themis/business/templete/impl/TaskExamStudentImportTemplete.java
  44. 14 14
      themis-business/src/main/java/com/qmth/themis/business/templete/service/impl/TempleteLogicServiceImpl.java
  45. 43 0
      themis-business/src/main/java/com/qmth/themis/business/util/RedisUtil.java
  46. 4 0
      themis-business/src/main/resources/db/log/1.2.8.log
  47. 23 0
      themis-business/src/main/resources/mapper/TEExamActivityMapper.xml
  48. 18 4
      themis-business/src/main/resources/mapper/TEExamStudentMapper.xml
  49. 54 50
      themis-business/src/main/resources/mapper/TEOrgSummaryMapper.xml
  50. 6 0
      themis-business/src/main/resources/mapper/TERegionSummaryMapper.xml
  51. 3 3
      themis-business/src/main/resources/mapper/TIeInvigilateWarnInfoMapper.xml
  52. 74 26
      themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml
  53. 9 0
      themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java
  54. 8 9
      themis-task/src/main/java/com/qmth/themis/task/listener/service/impl/MqTaskLogicServiceImpl.java
  55. 2 0
      themis-task/src/main/java/com/qmth/themis/task/quartz/ExamListJob.java
  56. 21 19
      themis-task/src/main/java/com/qmth/themis/task/quartz/ExamSummaryJob.java
  57. 23 24
      themis-task/src/main/java/com/qmth/themis/task/quartz/MqActivityJob.java
  58. 9 15
      themis-task/src/main/java/com/qmth/themis/task/quartz/service/impl/QuartzLogicServiceImpl.java
  59. 1 1
      themis-task/src/main/java/com/qmth/themis/task/start/StartRunning.java

+ 1 - 5
themis-admin/src/main/java/com/qmth/themis/admin/api/TBUserController.java

@@ -450,14 +450,12 @@ public class TBUserController {
     //        teExamStudent.setEnable(1);
     //        teExamStudentService.save(teExamStudent);
     //
-    //        //todo
     ////        MTEStudentEntity mteStudentEntity = gson.fromJson(gson.toJson(teStudent), MTEStudentEntity.class);
     ////        MTEExamEntity mteExamEntity = gson.fromJson(gson.toJson(teExam), MTEExamEntity.class);
     ////        MTEExamActivityEntity mteExamActivityEntity = gson.fromJson(gson.toJson(teExamActivity), MTEExamActivityEntity.class);
     ////        MTEExamPaperEntity mteExamPaperEntity = gson.fromJson(gson.toJson(teExamPaper), MTEExamPaperEntity.class);
     ////        MTEExamCourseEntity mteExamCourseEntity = gson.fromJson(gson.toJson(teExamCourse), MTEExamCourseEntity.class);
     ////        MTEExamStudentEntity mteExamStudentEntity = gson.fromJson(gson.toJson(teExamStudent), MTEExamStudentEntity.class);
-    //        //todo
     //
     ////        List list = Arrays.asList(mteExamPaperEntity);
     ////        mteExamCourseEntity.setMteExamPaperEntityList(list);
@@ -471,7 +469,6 @@ public class TBUserController {
     ////        mteExamStudentEntity.setMteStudentEntity(mteStudentEntity);
     ////        mteExamStudentEntity.setMteExamCourseEntityList(list);
     //
-    //        //todo
     ////        mongoTemplate.save(mteStudentEntity);
     ////        mongoTemplate.save(mteExamEntity);
     ////        mongoTemplate.save(mteExamActivityEntity);
@@ -522,7 +519,6 @@ public class TBUserController {
     ////            MTEExamStudentEntity t = gson.fromJson(gson.toJson(s), MTEExamStudentEntity.class);
     ////            ps1.add(t);
     ////        });
-    //        //todo
     ////        teExamActivityService.dropTable(tableName);
     //        return ResultUtil.ok(SystemConstant.SUCCESS);
     //    }
@@ -786,7 +782,7 @@ public class TBUserController {
         TBUser currentUser = (TBUser) ServletUtil.getRequestAccount();
         tbUser.setPassword(password);
         tbUser.setUpdateId(currentUser.getId());
-        tbUser.setPwdForce(true);
+        tbUser.setPwdForce(false);
         tbUserService.updateById(tbUser);
 
         AuthDto authDto = themisCacheService.addAccountAuthCache(tbUser.getId());

+ 26 - 11
themis-admin/src/main/java/com/qmth/themis/admin/api/TEExamController.java

@@ -230,9 +230,9 @@ public class TEExamController {
             List<TEExamActivity> teExamActivityList = teExamActivityService.list(new QueryWrapper<TEExamActivity>().lambda().eq(TEExamActivity::getExamId, teExam.getId()).eq(TEExamActivity::getEnable, 1));
             for (TEExamActivity t : teExamActivityList) {
                 if (Objects.nonNull(t.getEnable()) && t.getEnable().intValue() == 1 && (Objects.nonNull(t.getFinishTime()) && t.getFinishTime().longValue() > System.currentTimeMillis())) {
-                    themisCacheService.updateTodayExamListCache(t.getExamId().toString(), t.getId());
+                    themisCacheService.updateCurrentExamListCache(t.getExamId().toString(), t.getId());
                 } else {
-                    themisCacheService.removeTodayExamListCache(t.getExamId().toString(), t.getId());
+                    themisCacheService.removeCurrentExamListCache(t.getExamId().toString(), t.getId());
                 }
                 themisCacheService.updateOrgExamListCache(teExam.getOrgId().toString(), t.getExamId().toString(), t.getId());
             }
@@ -345,9 +345,9 @@ public class TEExamController {
         List<TEExamActivity> teExamActivityList = teExamActivityService.list(new QueryWrapper<TEExamActivity>().lambda().eq(TEExamActivity::getExamId, teExam.getId()).eq(TEExamActivity::getEnable, 1));
         for (TEExamActivity t : teExamActivityList) {
             if (Objects.nonNull(t.getEnable()) && t.getEnable().intValue() == 1 && (Objects.nonNull(t.getFinishTime()) && t.getFinishTime().longValue() > System.currentTimeMillis())) {
-                themisCacheService.updateTodayExamListCache(t.getExamId().toString(), t.getId());
+                themisCacheService.updateCurrentExamListCache(t.getExamId().toString(), t.getId());
             } else {
-                themisCacheService.removeTodayExamListCache(t.getExamId().toString(), t.getId());
+                themisCacheService.removeCurrentExamListCache(t.getExamId().toString(), t.getId());
             }
             themisCacheService.updateOrgExamListCache(teExam.getOrgId().toString(), t.getExamId().toString(), t.getId());
         }
@@ -502,22 +502,37 @@ public class TEExamController {
         if (Objects.nonNull(examId) && Objects.nonNull(examActivityId) && !CollectionUtils.isEmpty(roomCodeSet)) {
             for (String s : roomCodeSet) {
                 if (freshen) {
-                    teExamSummaryService.examSummary(examId, examActivityId, Objects.nonNull(s) ? new HashSet<>(Arrays.asList(s)) : null);
+                    teExamSummaryService.examSummary(examId, examActivityId, Objects.nonNull(s) ? new HashSet<>(Arrays.asList(s)) : null, true);
                 }
-                teExamSummaryAllList.addAll(themisCacheService.addExamSummaryCache(examId, examActivityId, s));
+                List<TEExamSummary> teExamSummaryList = themisCacheService.getExamSummaryCache(examId, examActivityId, s);
+                if (!CollectionUtils.isEmpty(teExamSummaryList)) {
+                    teExamSummaryService.examSummary(examId, examActivityId, Objects.nonNull(s) ? new HashSet<>(Arrays.asList(s)) : null, true);
+                    teExamSummaryList = themisCacheService.getExamSummaryCache(examId, examActivityId, s);
+                }
+                teExamSummaryAllList.addAll(teExamSummaryList);
             }
         } else if (Objects.nonNull(examId) && Objects.nonNull(examActivityId)) {
             if (freshen) {
-                teExamSummaryService.examSummary(examId, examActivityId, null);
+                teExamSummaryService.examSummary(examId, examActivityId, null, true);
+            }
+            List<TEExamSummary> teExamSummaryList = themisCacheService.getExamSummaryCache(examId, examActivityId);
+            if (!CollectionUtils.isEmpty(teExamSummaryList)) {
+                teExamSummaryService.examSummary(examId, examActivityId, null, true);
+                teExamSummaryList = themisCacheService.getExamSummaryCache(examId, examActivityId);
             }
-            teExamSummaryAllList.addAll(themisCacheService.addExamSummaryCache(examId, examActivityId));
+            teExamSummaryAllList.addAll(teExamSummaryList);
         } else {
             if (freshen) {
-                teExamSummaryService.examSummary(examId, null, null);
+                teExamSummaryService.examSummary(examId, null, null, true);
+            }
+            List<TEExamSummary> teExamSummaryList = themisCacheService.getExamSummaryCache(examId);
+            if (!CollectionUtils.isEmpty(teExamSummaryList)) {
+                teExamSummaryService.examSummary(examId, null, null, true);
+                teExamSummaryList = themisCacheService.getExamSummaryCache(examId);
             }
-            teExamSummaryAllList.addAll(themisCacheService.addExamSummaryCache(examId));
+            teExamSummaryAllList.addAll(teExamSummaryList);
         }
-        ExamPropCountDto examPropCountDto = new ExamPropCountDto(examId, 0, 0, 0, 0, 0, new BigDecimal(0));
+        ExamPropCountDto examPropCountDto = new ExamPropCountDto(examId, 0, 0, 0, 0, 0, BigDecimal.valueOf(0));
         if (!CollectionUtils.isEmpty(teExamSummaryAllList)) {
             Integer allCount = 0, prepareCount = 0, examCount = 0, alreadyComplete = 0, notComplete = 0;
             for (TEExamSummary t : teExamSummaryAllList) {

+ 1 - 1
themis-admin/src/main/java/com/qmth/themis/admin/api/TEExamStudentController.java

@@ -321,7 +321,7 @@ public class TEExamStudentController {
         for (TEExamStudent es : teExamStudentList) {
             teExamStudentService.updateExamStudentCacheBean(es.getId());
             //加入更新考试列表缓存方法
-            themisCacheService.updateTodayExamListCache(es.getExamId().toString(), es.getExamActivityId());
+            themisCacheService.updateCurrentExamListCache(es.getExamId().toString(), es.getExamActivityId());
             ExamCacheBean examCacheBean = teExamService.getExamCacheBean(es.getExamId());
             themisCacheService.updateOrgExamListCache(examCacheBean.getOrgId().toString(), es.getExamId().toString(), es.getExamActivityId());
         }

+ 19 - 11
themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateController.java

@@ -97,6 +97,9 @@ public class TIeInvigilateController {
     @Resource
     TIeExamMediaLogService tIeExamMediaLogService;
 
+    @Resource
+    TEExamSummaryService teExamSummaryService;
+
     @ApiOperation(value = "实时监控台视频列表接口")
     @RequestMapping(value = "/list/video", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "监考监控信息", response = InvigilateListVideoBean.class)})
@@ -301,12 +304,10 @@ public class TIeInvigilateController {
             throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
         }
         //获取考试记录缓存
-        Long examId = ExamRecordCacheUtil.getExamId(examRecordId);
+        Long examId = ExamRecordCacheUtil.getExamId(examRecordId), examStudentId = null, examActivityId = null;
         TOeExamRecord tOeExamRecord = null;
-        Long examStudentId = null;
-        Long examActivityId = null;
         ExamRecordStatusEnum status = null;
-        Integer breachStatus = null;
+        Integer breachStatus = null, warningMultipleFaceCount = null, exceptionCount = null, warningCount = null;
         if (Objects.isNull(examId)) {
             tOeExamRecord = tOeExamRecordService.getById(examRecordId);
             examId = tOeExamRecord.getExamId();
@@ -314,11 +315,17 @@ public class TIeInvigilateController {
             examActivityId = tOeExamRecord.getExamActivityId();
             status = tOeExamRecord.getStatus();
             breachStatus = Objects.isNull(tOeExamRecord.getBreachStatus()) ? 1 : tOeExamRecord.getBreachStatus();
+            warningCount = Objects.nonNull(tOeExamRecord.getWarningCount()) ? tOeExamRecord.getWarningCount() : 0;
+            warningMultipleFaceCount = Objects.nonNull(tOeExamRecord.getWarningMultipleFaceCount()) ? tOeExamRecord.getWarningMultipleFaceCount() : 0;
+            exceptionCount = Objects.nonNull(tOeExamRecord.getExceptionCount()) ? tOeExamRecord.getExceptionCount() : 0;
         } else {
             examStudentId = ExamRecordCacheUtil.getExamStudentId(examRecordId);
             examActivityId = ExamRecordCacheUtil.getExamActivityId(examRecordId);
             status = ExamRecordCacheUtil.getStatus(examRecordId);
             breachStatus = Objects.isNull(ExamRecordCacheUtil.getBreachStatus(examRecordId)) ? 1 : ExamRecordCacheUtil.getBreachStatus(examRecordId);
+            warningCount = Objects.isNull(ExamRecordCacheUtil.getWarningCount(examRecordId)) ? 0 : ExamRecordCacheUtil.getWarningCount(examRecordId);
+            warningMultipleFaceCount = Objects.isNull(ExamRecordCacheUtil.getWarningMultipleFaceCount(examRecordId)) ? 0 : ExamRecordCacheUtil.getWarningMultipleFaceCount(examRecordId);
+            exceptionCount = Objects.isNull(ExamRecordCacheUtil.getExceptionCount(examRecordId)) ? 0 : ExamRecordCacheUtil.getExceptionCount(examRecordId);
         }
         ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
         TEStudentCacheDto teStudent = themisCacheService.addStudentAccountCache(examStudentCacheBean.getStudentId());
@@ -370,12 +377,9 @@ public class TIeInvigilateController {
         Collections.sort(teExamStudentLogList);
         invigilateListDetailBean.setExamStudentLogList(teExamStudentLogList);
         //预警、异常、人脸
-        List<Integer> list = tIeInvigilateWarnInfoService.findWarnAndExceptionInfo(examRecordId, VerifyExceptionEnum.FACE_COUNT_ERROR, WarningLevelEnum.D8);
-        if (Objects.nonNull(list) && list.size() > 0) {
-            invigilateListDetailBean.setWarningCount(list.get(0));
-            invigilateListDetailBean.setExceptionCount(list.get(1));
-            invigilateListDetailBean.setMultipleFaceCount(list.get(2));
-        }
+        invigilateListDetailBean.setWarningCount(warningCount);
+        invigilateListDetailBean.setMultipleFaceCount(warningMultipleFaceCount);
+        invigilateListDetailBean.setExceptionCount(exceptionCount);
 
         //2020/11/24新增管理员不清除预警状态
         TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
@@ -386,7 +390,11 @@ public class TIeInvigilateController {
             tIeExamInvigilateNoticeUpdateWrapper.lambda().set(TIeInvigilateWarnInfo::getApproveStatus, 1)
                     .eq(TIeInvigilateWarnInfo::getExamRecordId, examRecordId);
             tIeInvigilateWarnInfoService.update(tIeExamInvigilateNoticeUpdateWrapper);
-            tOeExamRecordService.updateWarningUnreadCache(examRecordId, 0);
+            tOeExamRecordService.updateWarningUnreadByDb(examRecordId, 0);
+            tOeExamRecordService.updateWarningUnreadCache(examRecordId, 0, false);
+
+            Set<String> roomCodeSet = new HashSet<>(Arrays.asList(examStudentCacheBean.getRoomCode().split(", ")));
+            teExamSummaryService.examSummary(examId, examActivityId, roomCodeSet, true);
         }
         invigilateListDetailBean.setMonitorVideoSource(examCacheBean.getMonitorVideoSource());
         invigilateListDetailBean.setMonitorRecord(examCacheBean.getMonitorRecord());

+ 23 - 29
themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateWarnInfoController.java

@@ -3,6 +3,7 @@ package com.qmth.themis.admin.api;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.qmth.themis.business.bean.admin.ExamInfoBean;
 import com.qmth.themis.business.bean.admin.InvigilateListWarningBean;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.AuthDto;
@@ -54,10 +55,13 @@ public class TIeInvigilateWarnInfoController {
     TBExamInvigilateUserService tbExamInvigilateUserService;
 
     @Resource
-    TEExamSummaryService teExamSummaryService;
+    TEExamActivityService teExamActivityService;
 
     @Resource
-    TEExamActivityService teExamActivityService;
+    TEExamService teExamService;
+
+    @Resource
+    TEExamStudentService teExamStudentService;
 
     @ApiOperation(value = "预警提醒接口")
     @RequestMapping(value = "/notify", method = RequestMethod.POST)
@@ -81,14 +85,26 @@ public class TIeInvigilateWarnInfoController {
                 for (TBExamInvigilateUser t : tbExamInvigilateUserList) {
                     List<TEExamActivity> teExamActivityList = teExamActivityService.list(new QueryWrapper<TEExamActivity>().lambda().eq(TEExamActivity::getExamId, t.getExamId()));
                     for (TEExamActivity teExamActivity : teExamActivityList) {
-                        teExamSummaryService.examSummary(t.getExamId(), teExamActivity.getId(), new HashSet<>(Arrays.asList(t.getRoomCode())));
-                        teExamSummaryAllList.addAll(themisCacheService.addExamSummaryCache(t.getExamId(), teExamActivity.getId(), t.getRoomCode()));
+                        teExamSummaryAllList.addAll(themisCacheService.getExamSummaryCache(t.getExamId(), teExamActivity.getId(), t.getRoomCode()));
                     }
                 }
                 count = teExamSummaryAllList.stream().mapToInt(s -> s.getWarningUnread()).sum();
             }
         } else {
-            count = tIeInvigilateWarnInfoService.warningCount(examId, examActivityId, roomCode, userId, tbUser.getOrgId());
+            //取当前用户机构id所属考试id集合
+            List<ExamInfoBean> examInfoBeanList = teExamStudentService.getExamInfo(tbUser.getOrgId());
+            if (!CollectionUtils.isEmpty(examInfoBeanList)) {
+                List<TEExamSummary> teExamSummaryAllList = new ArrayList<>();
+                for (ExamInfoBean t : examInfoBeanList) {
+                    if (Objects.nonNull(t.getRoomCodes())) {
+                        Set<String> roomCodeSet = new HashSet<>(Arrays.asList(t.getRoomCodes().split(", ")));
+                        for (String s : roomCodeSet) {
+                            teExamSummaryAllList.addAll(themisCacheService.getExamSummaryCache(t.getExamId(), t.getExamActivityId(), s));
+                        }
+                    }
+                }
+                count = teExamSummaryAllList.stream().mapToInt(s -> s.getWarningUnread()).sum();
+            }
         }
         return ResultUtil.ok(Collections.singletonMap(SystemConstant.COUNT, count));
     }
@@ -154,25 +170,9 @@ public class TIeInvigilateWarnInfoController {
             tIeInvigilateWarnInfoUpdateWrapper.lambda().set(TIeInvigilateWarnInfo::getApproveStatus, warnInfoParams.getApproveStatus());
             if (!CollectionUtils.isEmpty(warnInfoParams.getWarningIds())) {
                 List<Long> warningTranIds = warnInfoParams.getWarningIds().stream().map(x -> Long.parseLong(x)).collect(Collectors.toList());
-                List<TIeInvigilateWarnInfo> tIeInvigilateWarnInfoList = tIeInvigilateWarnInfoService.listByIds(warningTranIds);
-                if (!CollectionUtils.isEmpty(tIeInvigilateWarnInfoList)) {
-                    Map<Long, Integer> map = new HashMap<>();
-                    for (TIeInvigilateWarnInfo t : tIeInvigilateWarnInfoList) {
-                        if (map.containsKey(t.getExamRecordId())) {
-                            Integer number = map.get(t.getExamRecordId());
-                            map.put(t.getExamRecordId(), number + 1);
-                        } else {
-                            map.put(t.getExamRecordId(), 1);
-                        }
-                    }
-                    map.forEach((k, v) -> {
-                        tOeExamRecordService.updateWarningUnreadCache(k, v);
-                    });
-                }
                 tIeInvigilateWarnInfoUpdateWrapper.lambda().in(TIeInvigilateWarnInfo::getId, warningTranIds);
             } else if (Objects.nonNull(warnInfoParams.getExamRecordId())) {
                 tIeInvigilateWarnInfoUpdateWrapper.lambda().eq(TIeInvigilateWarnInfo::getExamRecordId, warnInfoParams.getExamRecordId());
-                tOeExamRecordService.updateWarningUnreadCache(warnInfoParams.getExamRecordId(), 0);
             }
             tIeInvigilateWarnInfoService.update(tIeInvigilateWarnInfoUpdateWrapper);
         }
@@ -203,15 +203,9 @@ public class TIeInvigilateWarnInfoController {
         }
         //2020/11/24新增管理员不清除预警状态
         if (!authDto.getRoleCodes().toString().contains(RoleEnum.ADMIN.name())) {
-            QueryWrapper<TOeExamRecord> tOeExamRecordQueryWrapper = new QueryWrapper<>();
-            if (Objects.nonNull(examId)) {
-                tOeExamRecordQueryWrapper.lambda().eq(TOeExamRecord::getExamId, examId);
-            } else if (Objects.nonNull(examActivityId)) {
-                tOeExamRecordQueryWrapper.lambda().eq(TOeExamRecord::getExamActivityId, examActivityId);
-            }
-            List<TOeExamRecord> tOeExamRecordList = tOeExamRecordService.list(tOeExamRecordQueryWrapper);
+            List<TOeExamRecord> tOeExamRecordList = tOeExamRecordService.findExamRecordByWarning(examId, examActivityId, roomCode, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount, maxExceptionCount, minWarningCount, maxWarningCount, userId, tbUser.getOrgId());
             for (TOeExamRecord t : tOeExamRecordList) {
-                tOeExamRecordService.updateWarningUnreadCache(t.getId(), 0);
+                tOeExamRecordService.updateWarningUnreadCache(t.getId(), 0, true);
             }
             tOeExamRecordService.approveStatusListUpdate(examId, examActivityId, roomCode, approveStatus, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount, maxExceptionCount, minWarningCount, maxWarningCount, userId, tbUser.getOrgId());
         }

+ 52 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/admin/ExamInfoBean.java

@@ -0,0 +1,52 @@
+package com.qmth.themis.business.bean.admin;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 考试信息bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/4/20
+ */
+public class ExamInfoBean implements Serializable {
+
+    @ApiModelProperty(name = "考试批次id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long examId;
+
+    @ApiModelProperty(name = "考试场次id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long examActivityId;
+
+    @ApiModelProperty(name = "考场编码数")
+    private String roomCodes;
+
+    public Long getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
+
+    public Long getExamActivityId() {
+        return examActivityId;
+    }
+
+    public void setExamActivityId(Long examActivityId) {
+        this.examActivityId = examActivityId;
+    }
+
+    public String getRoomCodes() {
+        return roomCodes;
+    }
+
+    public void setRoomCodes(String roomCodes) {
+        this.roomCodes = roomCodes;
+    }
+}

+ 59 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/admin/OrgSummaryBean.java

@@ -0,0 +1,59 @@
+package com.qmth.themis.business.bean.admin;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 机构统计bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/4/20
+ */
+public class OrgSummaryBean implements Serializable {
+
+    @ApiModelProperty(name = "在线人数")
+    private Integer onlineCount = 0;
+
+    @ApiModelProperty(name = "考试人数")
+    private Integer examCount = 0;
+
+    @ApiModelProperty(name = "考试科次人数")
+    private Integer finishCount = 0;
+
+    @ApiModelProperty(name = "考生完成人数")
+    private Integer finishStudentCount = 0;
+
+    public Integer getOnlineCount() {
+        return onlineCount;
+    }
+
+    public void setOnlineCount(Integer onlineCount) {
+        this.onlineCount = onlineCount;
+    }
+
+    public Integer getExamCount() {
+        return examCount;
+    }
+
+    public void setExamCount(Integer examCount) {
+        this.examCount = examCount;
+    }
+
+    public Integer getFinishCount() {
+        return finishCount;
+    }
+
+    public void setFinishCount(Integer finishCount) {
+        this.finishCount = finishCount;
+    }
+
+    public Integer getFinishStudentCount() {
+        return finishStudentCount;
+    }
+
+    public void setFinishStudentCount(Integer finishStudentCount) {
+        this.finishStudentCount = finishStudentCount;
+    }
+}

+ 0 - 41
themis-business/src/main/java/com/qmth/themis/business/bean/status/AlreadyBreakCountBean.java

@@ -1,41 +0,0 @@
-package com.qmth.themis.business.bean.status;
-
-import java.io.Serializable;
-
-/**
- * @Description: 已断点续考次数bean
- * @Param:
- * @return:
- * @Author: wangliang
- * @Date: 2022/5/5
- */
-public class AlreadyBreakCountBean implements Serializable {
-
-    Integer number;
-    Long timestamp;//时间戳
-
-    public AlreadyBreakCountBean() {
-
-    }
-
-    public AlreadyBreakCountBean(Integer number, Long timestamp) {
-        this.number = number;
-        this.timestamp = timestamp;
-    }
-
-    public Integer getNumber() {
-        return number;
-    }
-
-    public void setNumber(Integer number) {
-        this.number = number;
-    }
-
-    public Long getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(Long timestamp) {
-        this.timestamp = timestamp;
-    }
-}

+ 0 - 41
themis-business/src/main/java/com/qmth/themis/business/bean/status/ExceptionCountBean.java

@@ -1,41 +0,0 @@
-package com.qmth.themis.business.bean.status;
-
-import java.io.Serializable;
-
-/**
- * @Description: 异常数bean
- * @Param:
- * @return:
- * @Author: wangliang
- * @Date: 2022/5/5
- */
-public class ExceptionCountBean implements Serializable {
-
-    Integer number;
-    Long timestamp;//时间戳
-
-    public ExceptionCountBean() {
-
-    }
-
-    public ExceptionCountBean(Integer number, Long timestamp) {
-        this.number = number;
-        this.timestamp = timestamp;
-    }
-
-    public Integer getNumber() {
-        return number;
-    }
-
-    public void setNumber(Integer number) {
-        this.number = number;
-    }
-
-    public Long getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(Long timestamp) {
-        this.timestamp = timestamp;
-    }
-}

+ 0 - 41
themis-business/src/main/java/com/qmth/themis/business/bean/status/InProcessLivenessVerifyCountBean.java

@@ -1,41 +0,0 @@
-package com.qmth.themis.business.bean.status;
-
-import java.io.Serializable;
-
-/**
- * @Description: 已完成过程活体验证次数bean
- * @Param:
- * @return:
- * @Author: wangliang
- * @Date: 2022/5/5
- */
-public class InProcessLivenessVerifyCountBean implements Serializable {
-
-    Integer number;
-    Long timestamp;//时间戳
-
-    public InProcessLivenessVerifyCountBean() {
-
-    }
-
-    public InProcessLivenessVerifyCountBean(Integer number, Long timestamp) {
-        this.number = number;
-        this.timestamp = timestamp;
-    }
-
-    public Integer getNumber() {
-        return number;
-    }
-
-    public void setNumber(Integer number) {
-        this.number = number;
-    }
-
-    public Long getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(Long timestamp) {
-        this.timestamp = timestamp;
-    }
-}

+ 0 - 41
themis-business/src/main/java/com/qmth/themis/business/bean/status/WarningCountBean.java

@@ -1,41 +0,0 @@
-package com.qmth.themis.business.bean.status;
-
-import java.io.Serializable;
-
-/**
- * @Description: 预警数bean
- * @Param:
- * @return:
- * @Author: wangliang
- * @Date: 2022/5/5
- */
-public class WarningCountBean implements Serializable {
-
-    Integer number;
-    Long timestamp;//时间戳
-
-    public WarningCountBean() {
-
-    }
-
-    public WarningCountBean(Integer number, Long timestamp) {
-        this.number = number;
-        this.timestamp = timestamp;
-    }
-
-    public Integer getNumber() {
-        return number;
-    }
-
-    public void setNumber(Integer number) {
-        this.number = number;
-    }
-
-    public Long getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(Long timestamp) {
-        this.timestamp = timestamp;
-    }
-}

+ 0 - 41
themis-business/src/main/java/com/qmth/themis/business/bean/status/WarningMultipleFaceCountBean.java

@@ -1,41 +0,0 @@
-package com.qmth.themis.business.bean.status;
-
-import java.io.Serializable;
-
-/**
- * @Description: 陌生人脸预警数bean
- * @Param:
- * @return:
- * @Author: wangliang
- * @Date: 2022/5/5
- */
-public class WarningMultipleFaceCountBean implements Serializable {
-
-    Integer number;
-    Long timestamp;//时间戳
-
-    public WarningMultipleFaceCountBean() {
-
-    }
-
-    public WarningMultipleFaceCountBean(Integer number, Long timestamp) {
-        this.number = number;
-        this.timestamp = timestamp;
-    }
-
-    public Integer getNumber() {
-        return number;
-    }
-
-    public void setNumber(Integer number) {
-        this.number = number;
-    }
-
-    public Long getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(Long timestamp) {
-        this.timestamp = timestamp;
-    }
-}

+ 0 - 41
themis-business/src/main/java/com/qmth/themis/business/bean/status/WarningUnreadBean.java

@@ -1,41 +0,0 @@
-package com.qmth.themis.business.bean.status;
-
-import java.io.Serializable;
-
-/**
- * @Description: 预警未读数bean
- * @Param:
- * @return:
- * @Author: wangliang
- * @Date: 2022/5/5
- */
-public class WarningUnreadBean implements Serializable {
-
-    Integer number;
-    Long timestamp;//时间戳
-
-    public WarningUnreadBean() {
-
-    }
-
-    public WarningUnreadBean(Integer number, Long timestamp) {
-        this.number = number;
-        this.timestamp = timestamp;
-    }
-
-    public Integer getNumber() {
-        return number;
-    }
-
-    public void setNumber(Integer number) {
-        this.number = number;
-    }
-
-    public Long getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(Long timestamp) {
-        this.timestamp = timestamp;
-    }
-}

+ 47 - 149
themis-business/src/main/java/com/qmth/themis/business/cache/ExamRecordCacheUtil.java

@@ -242,77 +242,20 @@ public class ExamRecordCacheUtil {
     }
 
     public static Integer getAlreadyBreakCount(Long recordId) {
-        AlreadyBreakCountBean alreadyBreakCountBean = getAlreadyBreakCountBean(recordId);
-        if (Objects.isNull(alreadyBreakCountBean) || Objects.isNull(alreadyBreakCountBean.getNumber())) {
-            return null;
-        } else {
-            return alreadyBreakCountBean.getNumber();
-        }
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.already_break_count.getCode())) ?
+                Integer.parseInt(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.already_break_count.getCode()).toString()) : null;
     }
 
-    public static void setAlreadyBreakCount(Long recordId, Integer alreadyBreakCount, Long timestamp) {
-        AlreadyBreakCountBean alreadyBreakCountBean = getAlreadyBreakCountBean(recordId);
-        if (Objects.isNull(alreadyBreakCountBean)) {
-            alreadyBreakCountBean = new AlreadyBreakCountBean(alreadyBreakCount, timestamp);
+    public static void setAlreadyBreakCount(Long recordId, Integer alreadyBreakCount) {
+        Integer alreadyBreakCountCache = ExamRecordCacheUtil.getAlreadyBreakCount(recordId);
+        if (Objects.isNull(alreadyBreakCountCache)) {
+            redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.already_break_count.getCode(), alreadyBreakCount);
         } else {
-            if (Objects.nonNull(alreadyBreakCountBean.getTimestamp()) && alreadyBreakCountBean.getTimestamp().longValue() < timestamp
-                    .longValue()) {
-                alreadyBreakCountBean.setNumber(alreadyBreakCount);
-                alreadyBreakCountBean.setTimestamp(timestamp);
-            }
+            redisUtil.setInc(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.already_break_count.getCode(), Long.parseLong(alreadyBreakCount.toString()));
         }
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.already_break_count.getCode(), alreadyBreakCountBean);
-    }
-
-    public static AlreadyBreakCountBean getAlreadyBreakCountBean(Long recordId) {
-        return Objects.nonNull(
-                redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.already_break_count.getCode())) ?
-                (AlreadyBreakCountBean) redisUtil
-                        .get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.already_break_count.getCode()) :
-                null;
-    }
-
-    public static InProcessLivenessVerifyCountBean getInProcessLivenessVerifyCountBean(Long recordId) {
-        return Objects.nonNull(
-                redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_count.getCode())) ?
-                (InProcessLivenessVerifyCountBean) redisUtil
-                        .get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_count.getCode()) :
-                null;
-    }
-
-    public static WarningCountBean getWarningCountBean(Long recordId) {
-        return Objects.nonNull(
-                redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode())) ?
-                (WarningCountBean) redisUtil
-                        .get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode()) :
-                null;
-    }
-
-    public static WarningUnreadBean getWarningUnreadBean(Long recordId) {
-        return Objects.nonNull(
-                redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_unread.getCode())) ?
-                (WarningUnreadBean) redisUtil
-                        .get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_unread.getCode()) :
-                null;
-    }
-
-    public static WarningMultipleFaceCountBean getWarningMultipleFaceCountBean(Long recordId) {
-        return Objects.nonNull(
-                redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_multiple_face_count.getCode())) ?
-                (WarningMultipleFaceCountBean) redisUtil
-                        .get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_multiple_face_count.getCode()) :
-                null;
-    }
-
-    public static ExceptionCountBean getExceptionCountBean(Long recordId) {
-        return Objects.nonNull(
-                redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exception_count.getCode())) ?
-                (ExceptionCountBean) redisUtil
-                        .get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exception_count.getCode()) :
-                null;
     }
 
-    public static ExamStatusBean getStatusBean(Long recordId) {
+    private static ExamStatusBean getStatusBean(Long recordId) {
         return Objects.nonNull(
                 redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.status.getCode())) ?
                 (ExamStatusBean) redisUtil
@@ -320,7 +263,7 @@ public class ExamRecordCacheUtil {
                 null;
     }
 
-    public static BreachStatusBean getBreachStatusBean(Long recordId) {
+    private static BreachStatusBean getBreachStatusBean(Long recordId) {
         return Objects.nonNull(
                 redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.breach_status.getCode())) ?
                 (BreachStatusBean) redisUtil
@@ -359,96 +302,60 @@ public class ExamRecordCacheUtil {
                 .get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exam_activity_id.getCode());
     }
 
-    public static void setWarningCount(Long recordId, Integer warningCount, Long timestamp) {
-        WarningCountBean warningCountBean = getWarningCountBean(recordId);
-        if (Objects.isNull(warningCountBean)) {
-            warningCountBean = new WarningCountBean(warningCount, timestamp);
+    public static void setWarningCount(Long recordId, Integer warningCount) {
+        Integer warningCountCache = ExamRecordCacheUtil.getWarningCount(recordId);
+        if (Objects.isNull(warningCountCache)) {
+            redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode(), warningCount);
         } else {
-            if (Objects.nonNull(warningCountBean.getTimestamp()) && warningCountBean.getTimestamp().longValue() < timestamp
-                    .longValue()) {
-                warningCountBean.setNumber(warningCount);
-                warningCountBean.setTimestamp(timestamp);
-            }
+            redisUtil.setInc(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode(), Long.parseLong(warningCount.toString()));
         }
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode(), warningCountBean);
     }
 
     public static Integer getWarningCount(Long recordId) {
-        WarningCountBean warningCountBean = getWarningCountBean(recordId);
-        if (Objects.isNull(warningCountBean) || Objects.isNull(warningCountBean.getNumber())) {
-            return null;
-        } else {
-            return warningCountBean.getNumber();
-        }
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode())) ?
+                Integer.parseInt(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode()).toString()) : null;
     }
 
-    public static void setWarningUnread(Long recordId, Integer warningUnread, Long timestamp) {
-        WarningUnreadBean warningUnreadBean = getWarningUnreadBean(recordId);
-        if (Objects.isNull(warningUnreadBean)) {
-            warningUnreadBean = new WarningUnreadBean(warningUnread, timestamp);
+    public static void setWarningUnread(Long recordId, Integer warningUnread) {
+        Integer warningUnreadCache = ExamRecordCacheUtil.getWarningUnread(recordId);
+        if (Objects.isNull(warningUnreadCache)) {
+            redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_unread.getCode(), warningUnread);
         } else {
-            if (Objects.nonNull(warningUnreadBean.getTimestamp()) && warningUnreadBean.getTimestamp().longValue() < timestamp
-                    .longValue()) {
-                warningUnreadBean.setNumber(warningUnread);
-                warningUnreadBean.setTimestamp(timestamp);
-            }
+            redisUtil.setInc(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_unread.getCode(), Long.parseLong(warningUnread.toString()));
         }
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_unread.getCode(), warningUnreadBean);
     }
 
     public static Integer getWarningUnread(Long recordId) {
-        WarningUnreadBean warningUnreadBean = getWarningUnreadBean(recordId);
-        if (Objects.isNull(warningUnreadBean) || Objects.isNull(warningUnreadBean.getNumber())) {
-            return null;
-        } else {
-            return warningUnreadBean.getNumber();
-        }
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_unread.getCode())) ?
+                Integer.parseInt(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_unread.getCode()).toString()) : null;
     }
 
-    public static void setWarningMultipleFaceCount(Long recordId, Integer warningMultipleFaceCount, Long timestamp) {
-        WarningMultipleFaceCountBean warningMultipleFaceCountBean = getWarningMultipleFaceCountBean(recordId);
-        if (Objects.isNull(warningMultipleFaceCountBean)) {
-            warningMultipleFaceCountBean = new WarningMultipleFaceCountBean(warningMultipleFaceCount, timestamp);
+    public static void setWarningMultipleFaceCount(Long recordId, Integer warningMultipleFaceCount) {
+        Integer warningMultipleFaceCountCache = ExamRecordCacheUtil.getWarningMultipleFaceCount(recordId);
+        if (Objects.isNull(warningMultipleFaceCountCache)) {
+            redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_multiple_face_count.getCode(), warningMultipleFaceCount);
         } else {
-            if (Objects.nonNull(warningMultipleFaceCountBean.getTimestamp()) && warningMultipleFaceCountBean.getTimestamp().longValue() < timestamp
-                    .longValue()) {
-                warningMultipleFaceCountBean.setNumber(warningMultipleFaceCount);
-                warningMultipleFaceCountBean.setTimestamp(timestamp);
-            }
+            redisUtil.setInc(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_multiple_face_count.getCode(), Long.parseLong(warningMultipleFaceCount.toString()));
         }
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_multiple_face_count.getCode(), warningMultipleFaceCountBean);
     }
 
     public static Integer getWarningMultipleFaceCount(Long recordId) {
-        WarningMultipleFaceCountBean warningMultipleFaceCountBean = getWarningMultipleFaceCountBean(recordId);
-        if (Objects.isNull(warningMultipleFaceCountBean) || Objects.isNull(warningMultipleFaceCountBean.getNumber())) {
-            return null;
-        } else {
-            return warningMultipleFaceCountBean.getNumber();
-        }
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_multiple_face_count.getCode())) ?
+                Integer.parseInt(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_multiple_face_count.getCode()).toString()) : null;
     }
 
-    public static void setExceptionCount(Long recordId, Integer exceptionCount, Long timestamp) {
-        ExceptionCountBean exceptionCountBean = getExceptionCountBean(recordId);
-        if (Objects.isNull(exceptionCountBean)) {
-            exceptionCountBean = new ExceptionCountBean(exceptionCount, timestamp);
+    public static void setExceptionCount(Long recordId, Integer exceptionCount) {
+        Integer exceptionCountCache = ExamRecordCacheUtil.getExceptionCount(recordId);
+        if (Objects.isNull(exceptionCountCache)) {
+            redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exception_count.getCode(), exceptionCount);
         } else {
-            if (Objects.nonNull(exceptionCountBean.getTimestamp()) && exceptionCountBean.getTimestamp().longValue() < timestamp
-                    .longValue()) {
-                exceptionCountBean.setNumber(exceptionCount);
-                exceptionCountBean.setTimestamp(timestamp);
-            }
+            redisUtil.setInc(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exception_count.getCode(), Long.parseLong(exceptionCount.toString()));
         }
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exception_count.getCode(), exceptionCountBean);
     }
 
     public static Integer getExceptionCount(Long recordId) {
-        ExceptionCountBean exceptionCountBean = getExceptionCountBean(recordId);
-        if (Objects.isNull(exceptionCountBean) || Objects.isNull(exceptionCountBean.getNumber())) {
-            return null;
-        } else {
-            return exceptionCountBean.getNumber();
-        }
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exception_count.getCode())) ?
+                Integer.parseInt(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exception_count.getCode()).toString()) : null;
     }
 
     public static void setBreachStatus(Long recordId, Integer breachStatus, Long timestamp) {
@@ -474,27 +381,18 @@ public class ExamRecordCacheUtil {
         }
     }
 
-    public static void setInProcessLivenessVerifyCount(Long recordId, Integer inProcessLivenessVerifyCount, Long timestamp) {
-        InProcessLivenessVerifyCountBean inProcessLivenessVerifyCountBean = getInProcessLivenessVerifyCountBean(recordId);
-        if (Objects.isNull(inProcessLivenessVerifyCountBean)) {
-            inProcessLivenessVerifyCountBean = new InProcessLivenessVerifyCountBean(inProcessLivenessVerifyCount, timestamp);
+    public static void setInProcessLivenessVerifyCount(Long recordId, Integer inProcessLivenessVerifyCount) {
+        Integer inProcessLivenessVerifyCountCache = ExamRecordCacheUtil.getInProcessLivenessVerifyCount(recordId);
+        if (Objects.isNull(inProcessLivenessVerifyCountCache)) {
+            redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_count.getCode(), inProcessLivenessVerifyCount);
         } else {
-            if (Objects.nonNull(inProcessLivenessVerifyCountBean.getTimestamp()) && inProcessLivenessVerifyCountBean.getTimestamp().longValue() < timestamp
-                    .longValue()) {
-                inProcessLivenessVerifyCountBean.setNumber(inProcessLivenessVerifyCount);
-                inProcessLivenessVerifyCountBean.setTimestamp(timestamp);
-            }
+            redisUtil.setInc(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_count.getCode(), Long.parseLong(inProcessLivenessVerifyCount.toString()));
         }
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_count.getCode(), inProcessLivenessVerifyCountBean);
     }
 
     public static Integer getInProcessLivenessVerifyCount(Long recordId) {
-        InProcessLivenessVerifyCountBean inProcessLivenessVerifyCountBean = getInProcessLivenessVerifyCountBean(recordId);
-        if (Objects.isNull(inProcessLivenessVerifyCountBean) || Objects.isNull(inProcessLivenessVerifyCountBean.getNumber())) {
-            return null;
-        } else {
-            return inProcessLivenessVerifyCountBean.getNumber();
-        }
+        return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_count.getCode())) ?
+                Integer.parseInt(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_count.getCode()).toString()) : null;
     }
 
     public static void setMonitorKey(Long recordId, String monitorKey) {
@@ -558,7 +456,7 @@ public class ExamRecordCacheUtil {
         }
     }
 
-    public static MonitorCallStatusBean getMonitorCallStatusBean(Long recordId, MonitorVideoSourceEnum source) {
+    private 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),
@@ -584,7 +482,7 @@ public class ExamRecordCacheUtil {
         }
     }
 
-    public static MobileWebsocketStatusBean getMobileFirstWebsocketStatusBean(Long recordId) {
+    private static MobileWebsocketStatusBean getMobileFirstWebsocketStatusBean(Long recordId) {
         return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId),
                 ExamRecordFieldEnum.mobile_first_websocket_status.getCode())) ?
                 (MobileWebsocketStatusBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId),
@@ -618,7 +516,7 @@ public class ExamRecordCacheUtil {
         }
     }
 
-    public static ClientWebsocketStatusBean getClientWebsocketStatusBean(Long recordId) {
+    private static ClientWebsocketStatusBean getClientWebsocketStatusBean(Long recordId) {
         return Objects.nonNull(redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId),
                 ExamRecordFieldEnum.client_websocket_status.getCode())) ?
                 (ClientWebsocketStatusBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId),

+ 2 - 1
themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java

@@ -109,6 +109,7 @@ public class SystemConstant {
     public static final String TENCENT_CLOUD_SDK_TRTC_REGION = "tencentcloud.sdk.trtcRegion";
     public static final String CLIENT_DB_UPLOAD_LOCATION = "client.db.upload.location";
     public static final String CDN_URL = "cdn.url";
+    public static final String WAITING_EXAM_DAY = "waiting.exam.day";
 
     public static final String DENY_LIST_FILE_NAME = "denyList.json";
     public static final String EXAM_CONFIG_FILE_NAME = "examConfig.json";
@@ -216,7 +217,7 @@ public class SystemConstant {
     public static final String BLACK_LIST_CACHE = "blacklist:cache";
     public static final String SYS_NOTIFY_CACHE = "sys:notify:cache";
     public static final String PROBLEM_CACHE = "problem:cache";
-    public static final String TODAY_EXAM_LIST_MAP_CACHE = "today:exam:list:map:cache";
+    public static final String CURRENT_EXAM_LIST_MAP_CACHE = "current:exam:list:map:cache";
     public static final String ORG_EXAM_LIST_MAP_CACHE = "org:exam:list:map:cache:";
 
     public volatile static Searcher SEARCHER = null;

+ 17 - 0
themis-business/src/main/java/com/qmth/themis/business/dao/TEExamActivityMapper.java

@@ -100,4 +100,21 @@ public interface TEExamActivityMapper extends BaseMapper<TEExamActivity> {
     public List<Map<String, Long>> findMinStartTimeAndMaxFinshTimeByExamId(@Param("examId") Long examId);
 
     public List<Long> findExamIdToday(@Param("startTime") Long startTime, @Param("endTime") Long endTime);
+
+    /**
+     * 查找当前待考列表
+     *
+     * @param startTime
+     * @param endTime
+     * @return
+     */
+    List<TEExamActivity> findCurrentExamActivity(@Param("startTime") Long startTime, @Param("endTime") Long endTime);
+
+    /**
+     * 根据天数获取待考列表
+     *
+     * @param day
+     * @return
+     */
+    List<TEExamActivity> findWaitingExamList(@Param("day") Integer day);
 }

+ 9 - 0
themis-business/src/main/java/com/qmth/themis/business/dao/TEExamStudentMapper.java

@@ -3,6 +3,7 @@ package com.qmth.themis.business.dao;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.qmth.themis.business.base.CustomBaseMapper;
 import com.qmth.themis.business.bean.admin.ExamDeficiencyListBean;
+import com.qmth.themis.business.bean.admin.ExamInfoBean;
 import com.qmth.themis.business.bean.admin.ExamStudentLogListBean;
 import com.qmth.themis.business.bean.admin.ExamViewCountListBean;
 import com.qmth.themis.business.dto.MarkResultSimpleExportDto;
@@ -150,4 +151,12 @@ public interface TEExamStudentMapper extends CustomBaseMapper<TEExamStudent> {
      * @return
      */
     public Integer getAbsentCount(@Param("examId") Long examId, @Param("examActivityId") Long examActivityId, @Param("roomCode") String roomCode);
+
+    /**
+     * 获取考试相关信息
+     *
+     * @param orgId
+     * @return
+     */
+    public List<ExamInfoBean> getExamInfo(@Param("orgId") Long orgId);
 }

+ 8 - 14
themis-business/src/main/java/com/qmth/themis/business/dao/TEOrgSummaryMapper.java

@@ -1,11 +1,11 @@
 package com.qmth.themis.business.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.themis.business.bean.admin.OrgSummaryBean;
 import com.qmth.themis.business.entity.TEOrgSummary;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
-import java.util.Set;
 
 /**
  * <p>
@@ -20,18 +20,12 @@ public interface TEOrgSummaryMapper extends BaseMapper<TEOrgSummary> {
     /**
      * 机构统计考试次数和考试人数信息
      *
+     * @param orgId
      * @param examIdSet
+     * @param all
      * @return
      */
-    List<Integer> orgSummaryByFinishCountAndFinishStudentCount(@Param("examIdSet") List<Long> examIdSet);
-
-    /**
-     * 统计全局考试科次
-     *
-     * @param examIdSet
-     * @return
-     */
-    Integer orgSummaryByFinishCount(@Param("examIdSet") List<Long> examIdSet);
+    OrgSummaryBean orgSummary(@Param("orgId") Long orgId, @Param("examIdSet") List<Long> examIdSet, boolean all);
 
     /**
      * 统计全局考试科次
@@ -39,15 +33,15 @@ public interface TEOrgSummaryMapper extends BaseMapper<TEOrgSummary> {
      * @param examIdSet
      * @return
      */
-    Integer orgSummaryByOnlineCount(@Param("examIdSet") List<Long> examIdSet);
+    Integer orgSummaryByFinishCount(@Param("orgId") Long orgId, @Param("examIdSet") List<Long> examIdSet);
 
     /**
-     * 统计全局考试科次
+     * 统计全局考生完成数
      *
      * @param examIdSet
      * @return
      */
-    Integer orgSummaryByExamCount(@Param("examIdSet") List<Long> examIdSet);
+    Integer orgSummaryByFinishStudentCount(@Param("orgId") Long orgId, @Param("examIdSet") List<Long> examIdSet);
 
     /**
      * 保存机构统计信息
@@ -80,5 +74,5 @@ public interface TEOrgSummaryMapper extends BaseMapper<TEOrgSummary> {
      *
      * @param finishStudentCount
      */
-    public void updateOrgZeroSummary(@Param("finishStudentCount") Integer finishStudentCount);
+    public void updateOrgZeroSummary(@Param("orgId") Long orgId, @Param("finishStudentCount") Integer finishStudentCount);
 }

+ 1 - 1
themis-business/src/main/java/com/qmth/themis/business/dao/TERegionSummaryMapper.java

@@ -21,7 +21,7 @@ public interface TERegionSummaryMapper extends BaseMapper<TERegionSummary> {
      *
      * @return
      */
-    List<TERegionSummary> regionSummary();
+    List<TERegionSummary> regionSummary(@Param("examId") Long examId,@Param("examActivityId") Long examActivityId);
 
     /**
      * 保存地区统计信息

+ 32 - 0
themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamRecordMapper.java

@@ -601,4 +601,36 @@ public interface TOeExamRecordMapper extends BaseMapper<TOeExamRecord> {
      * @param number
      */
     void updateWarningUnread(@Param("id") Long id, @Param("number") Integer number);
+
+    /**
+     * 根据预警条件清除未阅
+     *
+     * @param examId
+     * @param examActivityId
+     * @param roomCode
+     * @param name
+     * @param identity
+     * @param minMultipleFaceCount
+     * @param maxMultipleFaceCount
+     * @param minExceptionCount
+     * @param maxExceptionCount
+     * @param minWarningCount
+     * @param maxWarningCount
+     * @param userId
+     * @param orgId
+     * @return
+     */
+    List<TOeExamRecord> findExamRecordByWarning(@Param("examId") Long examId,
+                                                @Param("examActivityId") Long examActivityId,
+                                                @Param("roomCode") String roomCode,
+                                                @Param("name") String name,
+                                                @Param("identity") String identity,
+                                                @Param("minMultipleFaceCount") Integer minMultipleFaceCount,
+                                                @Param("maxMultipleFaceCount") Integer maxMultipleFaceCount,
+                                                @Param("minExceptionCount") Integer minExceptionCount,
+                                                @Param("maxExceptionCount") Integer maxExceptionCount,
+                                                @Param("minWarningCount") Integer minWarningCount,
+                                                @Param("maxWarningCount") Integer maxWarningCount,
+                                                @Param("userId") Long userId,
+                                                @Param("orgId") Long orgId);
 }

+ 3 - 3
themis-business/src/main/java/com/qmth/themis/business/dto/ExamPropCountDto.java

@@ -48,7 +48,7 @@ public class ExamPropCountDto implements Serializable {
     private Set<String> roomCodes;//虚拟考场代码
 
     @ApiModelProperty(name = "完成率")
-    private BigDecimal completionRate = new BigDecimal(0);//完成率
+    private BigDecimal completionRate = BigDecimal.valueOf(0);//完成率
 
     @ApiModelProperty(name = "重考审核")
     private Integer reexamCount = 0;//重考审核
@@ -105,8 +105,8 @@ public class ExamPropCountDto implements Serializable {
         this.alreadyComplete = alreadyComplete;
         this.notComplete = notComplete;
         if (this.allCount.intValue() > 0) {
-            BigDecimal completionRate = new BigDecimal(this.alreadyComplete)
-                    .divide(new BigDecimal(this.allCount), 2, BigDecimal.ROUND_HALF_UP)
+            BigDecimal completionRate = BigDecimal.valueOf(this.alreadyComplete)
+                    .divide(BigDecimal.valueOf(this.allCount), 2, BigDecimal.ROUND_HALF_UP)
                     .setScale(2, BigDecimal.ROUND_HALF_UP);
             this.completionRate = completionRate;
         }

+ 13 - 1
themis-business/src/main/java/com/qmth/themis/business/dto/response/TEExamWaitDto.java

@@ -3,6 +3,7 @@ package com.qmth.themis.business.dto.response;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import io.swagger.annotations.ApiModelProperty;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.Serializable;
 import java.util.List;
@@ -15,7 +16,7 @@ import java.util.Objects;
  * @Author: wangliang
  * @Date: 2020/8/3
  */
-public class TEExamWaitDto implements Serializable {
+public class TEExamWaitDto implements Serializable, Comparable<TEExamWaitDto> {
 
     @JsonSerialize(using = ToStringSerializer.class)
     @ApiModelProperty(name = "考试批次id")
@@ -88,4 +89,15 @@ public class TEExamWaitDto implements Serializable {
     public void setActivities(List<TEExamActivityWaitDto> activities) {
         this.activities = activities;
     }
+
+    @Override
+    public int compareTo(@NotNull TEExamWaitDto o) {
+        if (o.getId() < this.getId()) {
+            return 1;
+        } else if (o.getId() > this.getId()) {
+            return -1;
+        } else {
+            return 0;
+        }
+    }
 }

+ 14 - 0
themis-business/src/main/java/com/qmth/themis/business/entity/TEOrgSummary.java

@@ -3,6 +3,7 @@ package com.qmth.themis.business.entity;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.themis.business.bean.admin.OrgSummaryBean;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -50,6 +51,19 @@ public class TEOrgSummary implements Serializable {
         this.finishStudentCount = Objects.isNull(finishStudentCount) ? 0 : finishStudentCount;
     }
 
+    public TEOrgSummary(Long orgId, OrgSummaryBean orgSummaryBean) {
+        this.orgId = orgId;
+        this.onlineCount = orgSummaryBean.getOnlineCount();
+        this.examCount = orgSummaryBean.getExamCount();
+        this.finishCount = orgSummaryBean.getFinishCount();
+        this.finishStudentCount = orgSummaryBean.getFinishStudentCount();
+    }
+
+    public TEOrgSummary(Long orgId) {
+        this.orgId = orgId;
+    }
+
+
     public Long getOrgId() {
         return orgId;
     }

+ 17 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TEExamActivityService.java

@@ -124,4 +124,21 @@ public interface TEExamActivityService extends IService<TEExamActivity> {
     void saveExamActivity(List<TEExamActivity> teExamActivityList);
 
     List<Long> findExamIdToday();
+
+    /**
+     * 查找当前待考列表
+     *
+     * @param startTime
+     * @param endTime
+     * @return
+     */
+    List<TEExamActivity> findCurrentExamActivity(Long startTime, Long endTime);
+
+    /**
+     * 根据天数获取待考列表
+     *
+     * @param day
+     * @return
+     */
+    List<TEExamActivity> findWaitingExamList(Integer day);
 }

+ 9 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TEExamStudentService.java

@@ -2,6 +2,7 @@ package com.qmth.themis.business.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.themis.business.bean.admin.ExamInfoBean;
 import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.dto.MarkResultSimpleExportDto;
 import com.qmth.themis.business.dto.response.MarkResultDto;
@@ -131,4 +132,12 @@ public interface TEExamStudentService extends IService<TEExamStudent> {
      * @return
      */
     public Integer getAbsentCount(Long examId, Long examActivityId, String roomCode);
+
+    /**
+     * 根据机构获取考试相关信息
+     *
+     * @param orgId
+     * @return
+     */
+    public List<ExamInfoBean> getExamInfo(Long orgId);
 }

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

@@ -21,6 +21,8 @@ public interface TEExamSummaryService extends IService<TEExamSummary> {
      * @param examId
      * @param examActivityId
      * @param roomCodeSet
+     * @param freshen
+     * @return
      */
-    void examSummary(Long examId, Long examActivityId, Set<String> roomCodeSet);
+    boolean examSummary(Long examId, Long examActivityId, Set<String> roomCodeSet, boolean freshen);
 }

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

@@ -23,10 +23,27 @@ public interface TEOrgSummaryService extends IService<TEOrgSummary> {
      */
     public void orgSummary(Long orgId, List<Long> examIdSet);
 
+    /**
+     * 根据机构id统计信息
+     *
+     * @param orgId
+     */
+    public void orgSummary(Long orgId);
+
     /**
      * 更新全局机构考试完成数量和考生完成数量
      *
+     * @param orgId
      * @param finishStudentCount
      */
-    public void updateOrgZeroSummary(Integer finishStudentCount);
+    public void updateOrgZeroSummary(Long orgId, Integer finishStudentCount);
+
+    /**
+     * 根据机构id更新在线和考试人数
+     *
+     * @param orgId
+     * @param onlineCount
+     * @param examCount
+     */
+    public void updateOrgSummary(Long orgId, Integer onlineCount, Integer examCount);
 }

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

@@ -15,6 +15,9 @@ public interface TERegionSummaryService extends IService<TERegionSummary> {
 
     /**
      * 保存地区统计信息
+     *
+     * @param examId
+     * @param examActivityId
      */
-    public void regionSummary();
+    public void regionSummary(Long examId, Long examActivityId);
 }

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

@@ -24,7 +24,7 @@ import java.util.Set;
  */
 public interface TOeExamRecordService extends IService<TOeExamRecord> {
 
-    Long saveByPrepare(Long examId, Long examActivityId, Long examStudentId, Long paperId, Integer serialNumber, Long studentId, Integer mobilePhotoUpload);
+    TOeExamRecord saveByPrepare(Long examId, Long examActivityId, Long examStudentId, Long paperId, Integer serialNumber, Long studentId, Integer mobilePhotoUpload);
 
     /**
      * 计算客观分
@@ -655,8 +655,9 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
      *
      * @param id
      * @param number
+     * @param updateDb
      */
-    void updateWarningUnreadCache(Long id, Integer number);
+    void updateWarningUnreadCache(Long id, Integer number, Boolean updateDb);
 
     /**
      * 更新陌生人脸预警总数
@@ -671,4 +672,36 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
      * @param id
      */
     void updateExceptionCountCache(Long id);
+
+    /**
+     * 根据预警条件清除未阅
+     *
+     * @param examId
+     * @param examActivityId
+     * @param roomCode
+     * @param name
+     * @param identity
+     * @param minMultipleFaceCount
+     * @param maxMultipleFaceCount
+     * @param minExceptionCount
+     * @param maxExceptionCount
+     * @param minWarningCount
+     * @param maxWarningCount
+     * @param userId
+     * @param orgId
+     * @return
+     */
+    List<TOeExamRecord> findExamRecordByWarning(Long examId,
+                                                Long examActivityId,
+                                                String roomCode,
+                                                String name,
+                                                String identity,
+                                                Integer minMultipleFaceCount,
+                                                Integer maxMultipleFaceCount,
+                                                Integer minExceptionCount,
+                                                Integer maxExceptionCount,
+                                                Integer minWarningCount,
+                                                Integer maxWarningCount,
+                                                Long userId,
+                                                Long orgId);
 }

+ 37 - 15
themis-business/src/main/java/com/qmth/themis/business/service/ThemisCacheService.java

@@ -308,9 +308,16 @@ public interface ThemisCacheService {
     public void removeProblemCache();
 
     /**
-     * 设置当考试缓存
+     * 设置当考试缓存
      */
-    public void setTodayExamCache();
+    public void setCurrentExamListCache();
+
+    /**
+     * 获取当前考试列表缓存
+     *
+     * @return
+     */
+    public Map<String, List<ExamListBean>> getCurrentExamListCache();
 
     /**
      * 设置机构考试列表缓存
@@ -368,34 +375,34 @@ public interface ThemisCacheService {
     public void removeOrgExamListCache(String orgId, String examId, Long examActivityId);
 
     /**
-     * 获取当考试缓存
+     * 获取当考试缓存
      *
      * @param examId
      * @return
      */
-    public List<ExamListBean> getTodayExamListCache(String examId);
+    public List<ExamListBean> getCurrentExamListCache(String examId);
 
     /**
-     * 更新当考试缓存
+     * 更新当考试缓存
      *
      * @param examId
      * @param examActivityId
      */
-    public void updateTodayExamListCache(String examId, Long examActivityId);
+    public void updateCurrentExamListCache(String examId, Long examActivityId);
 
     /**
-     * 删除当考试缓存
+     * 删除当考试缓存
      *
      * @return
      */
-    public void removeTodayExamListCache(String examId);
+    public void removeCurrentExamListCache(String examId);
 
     /**
-     * 删除当考试缓存
+     * 删除当考试缓存
      *
      * @return
      */
-    public void removeTodayExamListCache(String examId, Long examActivityId);
+    public void removeCurrentExamListCache(String examId, Long examActivityId);
 
     /**
      * 获取考试统计缓存
@@ -403,7 +410,7 @@ public interface ThemisCacheService {
      * @param examId
      * @return
      */
-    public List<TEExamSummary> addExamSummaryCache(Long examId);
+    public List<TEExamSummary> getExamSummaryCache(Long examId);
 
     /**
      * 获取考试统计缓存
@@ -412,7 +419,7 @@ public interface ThemisCacheService {
      * @param examActivityId
      * @return
      */
-    public List<TEExamSummary> addExamSummaryCache(Long examId, Long examActivityId);
+    public List<TEExamSummary> getExamSummaryCache(Long examId, Long examActivityId);
 
     /**
      * 获取考试统计缓存
@@ -422,7 +429,7 @@ public interface ThemisCacheService {
      * @param roomCode
      * @return
      */
-    public List<TEExamSummary> addExamSummaryCache(Long examId, Long examActivityId, String roomCode);
+    public List<TEExamSummary> getExamSummaryCache(Long examId, Long examActivityId, String roomCode);
 
     /**
      * 修改考试统计缓存
@@ -481,7 +488,7 @@ public interface ThemisCacheService {
      * @param orgId
      * @return
      */
-    public TEOrgSummary addOrgSummaryCache(Long orgId);
+    public TEOrgSummary getOrgSummaryCache(Long orgId);
 
     /**
      * 更新机构统计缓存
@@ -503,7 +510,7 @@ public interface ThemisCacheService {
      *
      * @return
      */
-    public List<TERegionSummary> addRegionSummaryCache();
+    public List<TERegionSummary> getRegionSummaryCache();
 
     /**
      * 更新地区统计缓存
@@ -525,4 +532,19 @@ public interface ThemisCacheService {
      * @param roomCode
      */
     public void removeExamSummaryAllCache(Long examId, Long examActivityId, String roomCode);
+
+    /**
+     * 考试记录改变cache
+     *
+     * @param key
+     * @param timestamp
+     */
+    public void addExamRecordChangeCache(String key, Long timestamp);
+
+    /**
+     * 获取考试记录score
+     *
+     * @param key
+     */
+    public Long getExamRecordChangeCache(String key);
 }

+ 17 - 5
themis-business/src/main/java/com/qmth/themis/business/service/impl/AuthInfoServiceImpl.java

@@ -8,13 +8,11 @@ import com.qmth.boot.core.solar.service.SolarService;
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.entity.TBOrg;
+import com.qmth.themis.business.entity.TEOrgSummary;
 import com.qmth.themis.business.entity.TSAuth;
 import com.qmth.themis.business.enums.AuthEnum;
 import com.qmth.themis.business.enums.UploadFileEnum;
-import com.qmth.themis.business.service.AuthInfoService;
-import com.qmth.themis.business.service.ThemisCacheService;
-import com.qmth.themis.business.service.TBOrgService;
-import com.qmth.themis.business.service.TSAuthService;
+import com.qmth.themis.business.service.*;
 import com.qmth.themis.business.util.OssUtil;
 import com.qmth.themis.common.enums.ExceptionResultEnum;
 import com.qmth.themis.common.exception.BusinessException;
@@ -61,6 +59,9 @@ public class AuthInfoServiceImpl implements AuthInfoService {
     @Resource
     OssUtil ossUtil;
 
+    @Resource
+    TEOrgSummaryService teOrgSummaryService;
+
     /**
      * 授权信息初始化
      *
@@ -214,11 +215,12 @@ public class AuthInfoServiceImpl implements AuthInfoService {
                     tbOrg.setLogo(o.getLogoUrl());
                 }
                 tbOrgSet.add(tbOrg);
-            } else {
                 tbOrg.setAccessKey(o.getAccessKey());
                 tbOrg.setAccessSecret(o.getAccessSecret());
                 tbOrg.setLogo(Objects.nonNull(o.getLogoUrl()) ? o.getLogoUrl() : tbOrg.getLogo());
                 tbOrgSet.add(tbOrg);
+            } else {
+                tbOrgSet.add(tbOrg);
             }
         }
 
@@ -227,11 +229,21 @@ public class AuthInfoServiceImpl implements AuthInfoService {
             tsAuthService.saveOrUpdateBatch(tsAuthList);
 
             if (!CollectionUtils.isEmpty(tbOrgSet)) {
+                for (TBOrg tbOrg : tbOrgSet) {
+                    TEOrgSummary teOrgSummary = teOrgSummaryService.getOne(new QueryWrapper<TEOrgSummary>().lambda().eq(TEOrgSummary::getOrgId, tbOrg.getId()));
+                    if (Objects.isNull(teOrgSummary)) {
+                        teOrgSummaryService.orgSummary(tbOrg.getId());
+                    }
+                }
                 tbOrgService.saveOrUpdateBatch(tbOrgSet);
                 themisCacheService.removeOrgIdCache();
                 themisCacheService.removeOrgCodeCache();
             }
 
+            TEOrgSummary teOrgSummary = teOrgSummaryService.getOne(new QueryWrapper<TEOrgSummary>().lambda().eq(TEOrgSummary::getOrgId, 0L));
+            if (Objects.isNull(teOrgSummary)) {
+                teOrgSummaryService.orgSummary(0L);
+            }
             AuthInfoService authInfoService = SpringContextHolder.getBean(AuthInfoService.class);
             authInfoService.updateSchoolEnable(orgCodesMap);
         }

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

@@ -83,8 +83,8 @@ public class TBAttachmentServiceImpl extends ServiceImpl<TBAttachmentMapper, TBA
                 throw new BusinessException("文件名长度不能超过64个字符");
             }
             long size = file.getSize();
-            BigDecimal b = new BigDecimal(size);
-            BigDecimal num = new BigDecimal(1024);
+            BigDecimal b = BigDecimal.valueOf(size);
+            BigDecimal num = BigDecimal.valueOf(1024);
             b = b.divide(num, 2, BigDecimal.ROUND_HALF_UP).divide(num, 2, BigDecimal.ROUND_HALF_UP)
                     .setScale(2, BigDecimal.ROUND_HALF_UP);
             if (b.doubleValue() > 200) {
@@ -177,8 +177,8 @@ public class TBAttachmentServiceImpl extends ServiceImpl<TBAttachmentMapper, TBA
                 }
             }
             long size = file.length();
-            BigDecimal b = new BigDecimal(size);
-            BigDecimal num = new BigDecimal(1024);
+            BigDecimal b = BigDecimal.valueOf(size);
+            BigDecimal num = BigDecimal.valueOf(1024);
             b = b.divide(num).divide(num).setScale(2, BigDecimal.ROUND_HALF_UP);
             if (b.doubleValue() > 200) {
                 throw new BusinessException("文件大小不能超过200MB");

+ 33 - 10
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamActivityServiceImpl.java

@@ -417,20 +417,20 @@ public class TEExamActivityServiceImpl extends ServiceImpl<TEExamActivityMapper,
                 //加入更新考试列表缓存方法
                 ExamActivityCacheBean examActivityCacheBean = this.getExamActivityCacheBean(ac.getId());
                 if (Objects.nonNull(examActivityCacheBean.getEnable()) && examActivityCacheBean.getEnable().intValue() == 1 && Objects.nonNull(examActivityCacheBean.getFinishTime()) && examActivityCacheBean.getFinishTime().longValue() > System.currentTimeMillis()) {
-                    themisCacheService.updateTodayExamListCache(ac.getExamId().toString(), ac.getId());
+                    themisCacheService.updateCurrentExamListCache(ac.getExamId().toString(), ac.getId());
                 } else {
-                    themisCacheService.removeTodayExamListCache(ac.getExamId().toString(), ac.getId());
+                    themisCacheService.removeCurrentExamListCache(ac.getExamId().toString(), ac.getId());
                 }
                 themisCacheService.updateOrgExamListCache(teExam.getOrgId().toString(), ac.getExamId().toString(), ac.getId());
 
-                //最后开考时间发送定时任务
-                //删除再新增quartz任务,发送mq消息start
-                Map<String, Object> prop = new HashMap<>();
-                prop.put(SystemConstant.OPER, SystemConstant.INSERT);
-                prop.put(SystemConstant.EXAM, teExam);
-                MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME.name(), JacksonUtil.parseJson(ac), MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME, String.valueOf(teExam.getId()), prop, tbUser.getName());
-                mqDtoService.assembleSendAsyncOrderMsg(mqDto);
-                //删除再新增quartz任务,发送mq消息end
+//                //最后开考时间发送定时任务
+//                //删除再新增quartz任务,发送mq消息start
+//                Map<String, Object> prop = new HashMap<>();
+//                prop.put(SystemConstant.OPER, SystemConstant.INSERT);
+//                prop.put(SystemConstant.EXAM, teExam);
+//                MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME.name(), JacksonUtil.parseJson(ac), MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME, String.valueOf(teExam.getId()), prop, tbUser.getName());
+//                mqDtoService.assembleSendAsyncOrderMsg(mqDto);
+//                //删除再新增quartz任务,发送mq消息end
             }
 
             if (!CollectionUtils.isEmpty(teAudioList)) {
@@ -489,4 +489,27 @@ public class TEExamActivityServiceImpl extends ServiceImpl<TEExamActivityMapper,
         }
         return null;
     }
+
+    /**
+     * 查找当前待考列表
+     *
+     * @param startTime
+     * @param endTime
+     * @return
+     */
+    @Override
+    public List<TEExamActivity> findCurrentExamActivity(Long startTime, Long endTime) {
+        return this.baseMapper.findCurrentExamActivity(startTime, endTime);
+    }
+
+    /**
+     * 根据天数获取待考列表
+     *
+     * @param day
+     * @return
+     */
+    @Override
+    public List<TEExamActivity> findWaitingExamList(Integer day) {
+        return this.baseMapper.findWaitingExamList(day);
+    }
 }

+ 32 - 25
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -50,7 +50,6 @@ import java.math.BigDecimal;
 import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import java.util.stream.Collectors;
 
 /**
  * @Description: 考试批次 服务实现类
@@ -110,6 +109,9 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
     @Resource
     ThemisCacheService themisCacheService;
 
+    @Resource
+    TEExamService teExamService;
+
     /**
      * 查询考试批次
      *
@@ -157,22 +159,21 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         if (Objects.isNull(examId)) {
             Map<String, Set<Long>> examList = themisCacheService.getOrgExamListCache(orgId.toString());
             if (!CollectionUtils.isEmpty(examList)) {
-                examList = examList.entrySet().stream()
-                        .sorted(Map.Entry.comparingByKey())
-                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
+                Set<Long> examActivityIds = new HashSet<>();
                 for (Map.Entry<String, Set<Long>> entry : examList.entrySet()) {
-                    List<TEExamActivityWaitDto> teExamActivityWaitList = teExamActivityService.getWaitingExam(studentId, entry.getValue(), null);
-                    list = this.waitingExamCommon(list, teExamActivityWaitList);
+                    examActivityIds.addAll(entry.getValue());
                 }
+                List<TEExamActivityWaitDto> teExamActivityWaitList = teExamActivityService.getWaitingExam(studentId, examActivityIds, orgId);
+                list = this.waitingExamCommon(list, teExamActivityWaitList);
             }
         } else {
             Set<Long> examActivityIdSet = themisCacheService.getOrgExamListCache(orgId.toString(), examId.toString());
             if (!CollectionUtils.isEmpty(examActivityIdSet)) {
-                examActivityIdSet = examActivityIdSet.stream().sorted().collect(Collectors.toCollection(LinkedHashSet::new));
-                List<TEExamActivityWaitDto> teExamActivityWaitList = teExamActivityService.getWaitingExam(studentId, examActivityIdSet, null);
+                List<TEExamActivityWaitDto> teExamActivityWaitList = teExamActivityService.getWaitingExam(studentId, examActivityIdSet, orgId);
                 list = this.waitingExamCommon(list, teExamActivityWaitList);
             }
         }
+        Collections.sort(list);
         return list;
     }
 
@@ -190,17 +191,13 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
             teExamActivityWaitList.forEach(i -> {
                 ExamCacheBean examCache = getExamCacheBeanNative(i.getExamId());
                 TEExamWaitDto teExamWaitDto = new TEExamWaitDto(i.getExamId(), i.getExamActivityId(), examCache.getName(), examCache.getCode());
-                if (Objects.nonNull(examCache.getEnable()) && Objects.nonNull(i.getEnable())
-                        && examCache.getEnable().intValue() == 1 && i.getEnable().intValue() == 1
-                        && i.getFinishTime().longValue() > System.currentTimeMillis()) {
-                    setMap.put(i.getExamId(), teExamWaitDto);
-                    Set<TEExamActivityWaitDto> teExamActivityWaitDtos = Objects.nonNull(map.get(i.getExamId())) ? map.get(i.getExamId()) : new LinkedHashSet<>();
-                    teExamActivityWaitDtos.add(i);
-                    map.put(i.getExamId(), teExamActivityWaitDtos);
-                    ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(i.getExamStudentId());
-                    Integer leftExamCount = examCache.getExamCount().intValue() - examStudentCacheBean.getAlreadyExamCount().intValue() < 0 ? 0 : examCache.getExamCount().intValue() - examStudentCacheBean.getAlreadyExamCount().intValue();
-                    i.setLeftExamCount(leftExamCount);
-                }
+                setMap.put(i.getExamId(), teExamWaitDto);
+                Set<TEExamActivityWaitDto> teExamActivityWaitDtos = Objects.nonNull(map.get(i.getExamId())) ? map.get(i.getExamId()) : new LinkedHashSet<>();
+                teExamActivityWaitDtos.add(i);
+                map.put(i.getExamId(), teExamActivityWaitDtos);
+                ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(i.getExamStudentId());
+                Integer leftExamCount = examCache.getExamCount().intValue() - examStudentCacheBean.getAlreadyExamCount().intValue() < 0 ? 0 : examCache.getExamCount().intValue() - examStudentCacheBean.getAlreadyExamCount().intValue();
+                i.setLeftExamCount(leftExamCount);
             });
             setMap.forEach((k, v) -> {
                 v.setActivities(new ArrayList<>(map.get(k)));
@@ -298,6 +295,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
                 } else {
                     cache = true;
                 }
+
                 SysConfig sysConfig = themisCacheService.addSysConfigCache(SystemConstant.MONITOR_CONFIG_PREFIX);
                 Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置监控前缀"));
                 TEExamActivityDto teExamActivityDto = new TEExamActivityDto(examCache, ac, examStudentCacheBean,
@@ -360,10 +358,10 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         //            throw new BusinessException("试卷答案未上传:" + paperId);
         //        }
 
-        Long recordId = toeExamRecordService
+        tOeExamRecord = toeExamRecordService
                 .saveByPrepare(es.getExamId(), es.getExamActivityId(), examStudentId, paperId,
                         es.getAlreadyExamCount() + 1, studentId, ec.getMobilePhotoUpload());
-
+        Long recordId = tOeExamRecord.getId();
         es.setCurrentRecordId(recordId);
         // 更新考生缓存
         redisUtil.set(RedisKeyHelper.examStudentCacheKey(examStudentId), es);
@@ -394,6 +392,15 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.STUDENT.name(), SystemOperationEnum.FIRST_PREPARE, MqTagEnum.STUDENT, String.valueOf(teStudentCacheDto.getId()), IpUtil.getRemoteIp(ServletUtil.getRequest()));
         this.sendOeLogMessage(SystemOperationEnum.FIRST_PREPARE, examStudentId, recordId, mqDto);
         //mq发送消息end
+
+        //最后开考时间发送定时任务
+        //删除再新增quartz任务,发送mq消息start
+        Map<String, Object> prop = new HashMap<>();
+        prop.put(SystemConstant.OPER, SystemConstant.INSERT);
+        prop.put(SystemConstant.EXAM, teExamService.getById(es.getExamId()));
+        MqDto mqDtoFinalPrepare = new MqDto(mqUtil.getTopic(), MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME.name(), JacksonUtil.parseJson(tOeExamRecord), MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME, String.valueOf(tOeExamRecord.getId()), prop, String.valueOf(tOeExamRecord.getId()));
+        mqDtoService.assembleSendAsyncOrderMsg(mqDtoFinalPrepare);
+        //删除再新增quartz任务,发送mq消息end
         return prepare;
     }
 
@@ -415,9 +422,9 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
      * 根据设定几率取出一套试卷
      */
     private int getPaperByWeight(List<Double> paperWeight) {
-        BigDecimal r = new BigDecimal(new Random().nextInt(101));
+        BigDecimal r = BigDecimal.valueOf(new Random().nextInt(101));
         for (int i = 0; i < paperWeight.size(); i++) {
-            r = r.subtract(new BigDecimal(paperWeight.get(i)));
+            r = r.subtract(BigDecimal.valueOf(paperWeight.get(i)));
             if (r.doubleValue() <= 0.0d) {
                 return i;// 选中
             }
@@ -773,7 +780,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
                     if (r == 1) {
                         answer.setScore(cb.getScore());
                     } else if (r == 0) {
-                        BigDecimal b = new BigDecimal(cb.getScore()).divide(new BigDecimal("2"), 1, BigDecimal.ROUND_UP);
+                        BigDecimal b = BigDecimal.valueOf(cb.getScore()).divide(new BigDecimal("2"), 1, BigDecimal.ROUND_UP);
                         answer.setScore(b.doubleValue());
                     } else {
                         answer.setScore(0.0);
@@ -1618,7 +1625,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         }
         Double da = Double.valueOf(a * 100);
         Double db = Double.valueOf(b);
-        BigDecimal bd = new BigDecimal(da / db);
+        BigDecimal bd = BigDecimal.valueOf(da / db);
         Double tem = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
         return tem;
     }

+ 12 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamStudentServiceImpl.java

@@ -2,6 +2,7 @@ package com.qmth.themis.business.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.themis.business.bean.admin.ExamInfoBean;
 import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
@@ -246,4 +247,15 @@ public class TEExamStudentServiceImpl extends ServiceImpl<TEExamStudentMapper, T
     public Integer getAbsentCount(Long examId, Long examActivityId, String roomCode) {
         return this.baseMapper.getAbsentCount(examId, examActivityId, roomCode);
     }
+
+    /**
+     * 根据机构获取考试相关信息
+     *
+     * @param orgId
+     * @return
+     */
+    @Override
+    public List<ExamInfoBean> getExamInfo(Long orgId) {
+        return this.baseMapper.getExamInfo(orgId);
+    }
 }

+ 18 - 6
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamSummaryServiceImpl.java

@@ -47,16 +47,30 @@ public class TEExamSummaryServiceImpl extends ServiceImpl<TEExamSummaryMapper, T
      * @param examId
      * @param examActivityId
      * @param roomCodeSet
+     * @param freshen
+     * @return
      */
     @Override
-    public void examSummary(Long examId, Long examActivityId, Set<String> roomCodeSet) {
+    public boolean examSummary(Long examId, Long examActivityId, Set<String> roomCodeSet, boolean freshen) {
+        boolean updateCache = false;
         if (!CollectionUtils.isEmpty(roomCodeSet)) {
             for (String s : roomCodeSet) {
-                //根据考试批次、场次、考场编码统计信息
-                TEExamSummary teExamSummary = this.baseMapper.examSummary(examId, examActivityId, s);
-                this.examSummaryCommon(examId, examActivityId, s, teExamSummary);
+                Long l = themisCacheService.getExamRecordChangeCache(examActivityId + "_" + s);
+                if ((Objects.nonNull(l) && System.currentTimeMillis() - l.longValue() <= 1000 * 60 * 1) || freshen) {
+                    //根据考试批次、场次、考场编码统计信息
+                    TEExamSummary teExamSummary = this.baseMapper.examSummary(examId, examActivityId, s);
+                    this.examSummaryCommon(examId, examActivityId, s, teExamSummary);
+                    updateCache = true;
+                } else {
+                    themisCacheService.getExamSummaryCache(examId, examActivityId, s);
+                }
+            }
+            if (updateCache) {
+                themisCacheService.updateExamSummaryCache(examId);
+                themisCacheService.updateExamSummaryCache(examId, examActivityId);
             }
         }
+        return updateCache;
     }
 
     /**
@@ -94,8 +108,6 @@ public class TEExamSummaryServiceImpl extends ServiceImpl<TEExamSummaryMapper, T
                 teExamSummaryDb.setId(id);
             }
             this.saveOrUpdate(teExamSummaryDb);
-            themisCacheService.updateExamSummaryCache(examId);
-            themisCacheService.updateExamSummaryCache(examId, examActivityId);
             themisCacheService.updateExamSummaryCache(examId, examActivityId, s);
         }
     }

+ 57 - 19
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEOrgSummaryServiceImpl.java

@@ -1,9 +1,13 @@
 package com.qmth.themis.business.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.themis.business.bean.admin.OrgSummaryBean;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.dao.TEOrgSummaryMapper;
 import com.qmth.themis.business.entity.TBOrg;
+import com.qmth.themis.business.entity.TEExam;
 import com.qmth.themis.business.entity.TEExamSummary;
 import com.qmth.themis.business.entity.TEOrgSummary;
 import com.qmth.themis.business.service.TEExamService;
@@ -15,7 +19,9 @@ import org.springframework.util.CollectionUtils;
 import org.springframework.util.LinkedMultiValueMap;
 
 import javax.annotation.Resource;
+import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -46,17 +52,14 @@ public class TEOrgSummaryServiceImpl extends ServiceImpl<TEOrgSummaryMapper, TEO
     @Override
     public void orgSummary(Long orgId, List<Long> examIdSet) {
         if (orgId.longValue() == 0) {//全局机构
-            Integer onlineCount = this.baseMapper.orgSummaryByOnlineCount(examIdSet);
-            Integer examCount = this.baseMapper.orgSummaryByExamCount(examIdSet);
-            List<Integer> finishCountList = this.baseMapper.orgSummaryByFinishCountAndFinishStudentCount(examIdSet);
-            TEOrgSummary teOrgSummary = new TEOrgSummary(orgId, onlineCount, examCount, finishCountList.get(0), finishCountList.get(1));
-            teOrgSummaryService.saveOrUpdate(teOrgSummary);
+            OrgSummaryBean orgSummaryBean = this.baseMapper.orgSummary(orgId, examIdSet, false);
+            this.updateOrgSummary(orgId, orgSummaryBean.getOnlineCount(), orgSummaryBean.getExamCount());
         } else {
             LinkedMultiValueMap<Long, Long> orgExamIdMap = new LinkedMultiValueMap<>();
             boolean reloadDb = false;
             //先查询考试批次统计缓存
             for (Long l : examIdSet) {
-                List<TEExamSummary> teExamSummaryList = themisCacheService.addExamSummaryCache(l);
+                List<TEExamSummary> teExamSummaryList = themisCacheService.getExamSummaryCache(l);
                 if (!CollectionUtils.isEmpty(teExamSummaryList)) {//如果没有该批次的考试统计缓存信息,则自己从数据库取
                     ExamCacheBean examCacheBean = teExamService.getExamCacheBean(l);
                     TBOrg tbOrg = themisCacheService.addOrgCache(examCacheBean.getOrgId());
@@ -67,39 +70,74 @@ public class TEOrgSummaryServiceImpl extends ServiceImpl<TEOrgSummaryMapper, TEO
                 }
             }
             if (reloadDb) {//没有该批次的考试统计缓存信息,则从数据库取数据
-                Integer onlineCount = this.baseMapper.orgSummaryByOnlineCount(examIdSet);
-                Integer examCount = this.baseMapper.orgSummaryByExamCount(examIdSet);
-                List<Integer> finishCountList = this.baseMapper.orgSummaryByFinishCountAndFinishStudentCount(examIdSet);
-                TEOrgSummary teOrgSummary = new TEOrgSummary(orgId, onlineCount, examCount, finishCountList.get(0), finishCountList.get(1));
-                teOrgSummaryService.saveOrUpdate(teOrgSummary);
+                OrgSummaryBean orgSummaryBean = this.baseMapper.orgSummary(orgId, examIdSet, false);
+                this.updateOrgSummary(orgId, orgSummaryBean.getOnlineCount(), orgSummaryBean.getExamCount());
             } else {
                 orgExamIdMap.forEach((k, v) -> {//从考试批次缓存信息里拿取在线人数、考试人数、完成考生数
-                    Integer onlineCount = 0, examCount = 0, finishStudentCount = 0;
+                    Integer onlineCount = 0, examCount = 0;
                     for (Long l : v) {
-                        List<TEExamSummary> teExamSummaryList = themisCacheService.addExamSummaryCache(l);
+                        List<TEExamSummary> teExamSummaryList = themisCacheService.getExamSummaryCache(l);
                         for (TEExamSummary t : teExamSummaryList) {
                             onlineCount = onlineCount + t.getOnlineCount();
                             examCount = examCount + t.getExamCount();
-                            finishStudentCount = finishStudentCount + t.getFinishCount();
                         }
                     }
-                    Integer finishCount = this.baseMapper.orgSummaryByFinishCount(v);
-                    TEOrgSummary teOrgSummary = new TEOrgSummary(orgId, onlineCount, examCount, finishCount, finishStudentCount);
-                    teOrgSummaryService.saveOrUpdate(teOrgSummary);
+                    this.updateOrgSummary(orgId, onlineCount, examCount);
                 });
             }
         }
         themisCacheService.updateOrgSummaryCache(orgId);
     }
 
+    /**
+     * 根据机构id统计信息
+     *
+     * @param orgId
+     */
+    @Override
+    public void orgSummary(Long orgId) {
+        List<Long> examIdSet = null;
+        if (orgId.longValue() != 0) {//全局机构
+            List<TEExam> teExamList = teExamService.list(new QueryWrapper<TEExam>().lambda().eq(TEExam::getOrgId, orgId));
+            if (!CollectionUtils.isEmpty(teExamList)) {
+                examIdSet = teExamList.stream().map(s -> s.getId()).collect(Collectors.toList());
+            } else {
+                examIdSet = Arrays.asList(-1L);
+            }
+        }
+        OrgSummaryBean orgSummaryBean = this.baseMapper.orgSummary(orgId, examIdSet, true);
+        Integer finishStudentCount = this.baseMapper.orgSummaryByFinishStudentCount(orgId, examIdSet);
+        orgSummaryBean.setFinishStudentCount(finishStudentCount);
+        TEOrgSummary teOrgSummary = new TEOrgSummary(orgId, orgSummaryBean);
+        teOrgSummaryService.save(teOrgSummary);
+        themisCacheService.updateOrgSummaryCache(orgId);
+    }
+
     /**
      * 更新全局机构考试完成数量和考生完成数量
      *
+     * @param orgId
      * @param finishStudentCount
      */
     @Override
     @Transactional
-    public void updateOrgZeroSummary(Integer finishStudentCount) {
-        this.baseMapper.updateOrgZeroSummary(finishStudentCount);
+    public void updateOrgZeroSummary(Long orgId, Integer finishStudentCount) {
+        this.baseMapper.updateOrgZeroSummary(orgId, finishStudentCount);
+    }
+
+    /**
+     * 根据机构id更新在线和考试人数
+     *
+     * @param orgId
+     * @param onlineCount
+     * @param examCount
+     */
+    @Override
+    public void updateOrgSummary(Long orgId, Integer onlineCount, Integer examCount) {
+        UpdateWrapper<TEOrgSummary> teOrgSummaryUpdateWrapper = new UpdateWrapper<>();
+        teOrgSummaryUpdateWrapper.lambda().set(TEOrgSummary::getOnlineCount, onlineCount)
+                .set(TEOrgSummary::getExamCount, examCount)
+                .eq(TEOrgSummary::getOrgId, orgId);
+        teOrgSummaryService.update(teOrgSummaryUpdateWrapper);
     }
 }

+ 5 - 2
themis-business/src/main/java/com/qmth/themis/business/service/impl/TERegionSummaryServiceImpl.java

@@ -31,10 +31,13 @@ public class TERegionSummaryServiceImpl extends ServiceImpl<TERegionSummaryMappe
 
     /**
      * 保存地区统计信息
+     *
+     * @param examId
+     * @param examActivityId
      */
     @Override
-    public void regionSummary() {
-        List<TERegionSummary> teRegionSummaryList = this.baseMapper.regionSummary();
+    public void regionSummary(Long examId, Long examActivityId) {
+        List<TERegionSummary> teRegionSummaryList = this.baseMapper.regionSummary(examId, examActivityId);
         if (!CollectionUtils.isEmpty(teRegionSummaryList)) {
             for (TERegionSummary t : teRegionSummaryList) {
                 TERegionSummary teRegionSummaryDb = this.getOne(new QueryWrapper<TERegionSummary>().lambda()

+ 37 - 25
themis-business/src/main/java/com/qmth/themis/business/service/impl/TIeReportServiceImpl.java

@@ -1,6 +1,7 @@
 package com.qmth.themis.business.service.impl;
 
 import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qmth.themis.business.bean.admin.*;
@@ -9,10 +10,7 @@ import com.qmth.themis.business.bean.result.TimeScaleDataResult;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dao.*;
-import com.qmth.themis.business.entity.SysConfig;
-import com.qmth.themis.business.entity.TBOrg;
-import com.qmth.themis.business.entity.TBUser;
-import com.qmth.themis.business.entity.TEExamActivity;
+import com.qmth.themis.business.entity.*;
 import com.qmth.themis.business.enums.InvigilateMonitorStatusEnum;
 import com.qmth.themis.business.service.*;
 import com.qmth.themis.business.util.ServletUtil;
@@ -69,10 +67,10 @@ public class TIeReportServiceImpl implements TIeReportService {
     TOeExamRecordMapper tOeExamRecordMapper;
 
     @Resource
-    TOeExamRecordService tOeExamRecordService;
+    ThemisCacheService themisCacheService;
 
     @Resource
-    ThemisCacheService themisCacheService;
+    TEExamService teExamService;
 
     /**
      * 考试概览
@@ -90,17 +88,13 @@ public class TIeReportServiceImpl implements TIeReportService {
     public Map<String, Object> examView(Long orgId, Long examId, Long examActivityId, String roomCode, String courseCode,
                                         String name, String identity) {
         // 缺考人数
-        Integer examTotal = 0, actualExamTotal = 0, absentNum = 0, completeOffExamTotal = 0;
+        Integer examTotal = 0, actualExamTotal = 0, absentNum = 0;
         ExamCacheBean exam = examService.getExamCacheBean(examId);
-        // 应考人数&实考人数
-        List<Integer> list = tOeExamRecordService.findByViewAdmin(orgId, examId, examActivityId, roomCode, courseCode, exam.getMonitorStatus());
-        if (Objects.nonNull(list) && list.size() > 0) {
-            examTotal = list.get(0);
-            actualExamTotal = list.get(1);
-            completeOffExamTotal = list.get(2);
-        }
-        if (exam.getMonitorStatus() == InvigilateMonitorStatusEnum.FINISHED) {// 结束监考的,未考试的都是缺考
-            absentNum = examTotal.intValue() - actualExamTotal.intValue();
+        List<TEExamSummary> teExamSummaryList = themisCacheService.getExamSummaryCache(examId, examActivityId, roomCode);
+        for (TEExamSummary t : teExamSummaryList) {
+            examTotal = examTotal + t.getTotalCount();
+            absentNum = absentNum + t.getAbsentCount();
+            actualExamTotal = examTotal.intValue() - absentNum.intValue();
         }
         // 每日已考人数
         List<Map<String, Object>> doneCountByDay = tOeExamRecordMapper.getDoneCountByDay(orgId, examId, examActivityId, roomCode, courseCode);
@@ -110,8 +104,7 @@ public class TIeReportServiceImpl implements TIeReportService {
         ret.put("examTotal", examTotal.intValue());
         ret.put("actualExamTotal", actualExamTotal.intValue());
         ret.put("deficiencyExamTotal", absentNum.intValue());
-//        ret.put("completeOffExamTotal", examTotal.intValue() - actualExamTotal.intValue() - absentNum.intValue());
-        ret.put("completeOffExamTotal", completeOffExamTotal);
+        ret.put("completeOffExamTotal", absentNum);
         ret.put("examTotalList", doneCountByDay);
         return ret;
     }
@@ -424,19 +417,38 @@ public class TIeReportServiceImpl implements TIeReportService {
             TBOrg tbOrg = themisCacheService.addOrgCache(tbUser.getOrgId());
             ret = new ExaminationMonitorCountBean(tbOrg.getId(), tbOrg.getName(), tbOrg.getCode());
         }
-        List<Long> countList = tOeExamRecordService.findByOrgId(tbUser.getOrgId());
-        if (Objects.nonNull(countList) && countList.size() > 0) {
+        List<TEExam> teExamList = teExamService.list(new QueryWrapper<TEExam>().lambda().eq(TEExam::getOrgId, tbUser.getOrgId()));
+        if (!CollectionUtils.isEmpty(teExamList)) {
+            List<TEExamSummary> teExamSummaryAllList = new ArrayList<>();
+            for (TEExam t : teExamList) {
+                List<ExamListBean> examListBeanList = themisCacheService.getCurrentExamListCache(t.getId().toString());
+                if (!CollectionUtils.isEmpty(examListBeanList)) {
+                    for (ExamListBean e : examListBeanList) {
+                        Set<String> roomCodeSet = new HashSet<>(Arrays.asList(e.getRoomCode().split(", ")));
+                        for (String s : roomCodeSet) {
+                            teExamSummaryAllList.addAll(themisCacheService.getExamSummaryCache(t.getId(), e.getExamActivityId(), s));
+                        }
+                    }
+                }
+            }
+            Integer onlineCount = 0, waitingCount = 0, examingCount = 0, warnCount = 0;
+            for (TEExamSummary t : teExamSummaryAllList) {
+                onlineCount = onlineCount + t.getOnlineCount();
+                waitingCount = waitingCount + t.getPrepareCount();
+                examingCount = examingCount + t.getExamCount();
+                warnCount = warnCount + t.getWarningCount();
+            }
             // 在线人数
-            ret.setOnlineCount(countList.get(0));
+            ret.setOnlineCount(Long.parseLong(onlineCount.toString()));
             // 待考人数
-            ret.setWaitingCount(countList.get(1));
+            ret.setWaitingCount(Long.parseLong(waitingCount.toString()));
             // 考试人数
-            ret.setExamingCount(countList.get(2));
+            ret.setExamingCount(Long.parseLong(examingCount.toString()));
+            // 预警人数
+            ret.setWarnCount(Long.parseLong(warnCount.toString()));
         }
 //         通讯故障人数
 //        ret.setExceptionCount(tOeExamRecordMapper.getExceptionCount(tbUser.getOrgId()));
-        // 预警人数
-        ret.setWarnCount(tOeExamRecordMapper.getWarnCount(tbUser.getOrgId()));
 //         机构在考人数
 //        ret.setOrgExamingCount(tOeExamRecordMapper.getOrgExamingCount(tbUser.getOrgId()));
         //违纪人数

+ 62 - 82
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -120,8 +120,8 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
 
     @Transactional
     @Override
-    public Long saveByPrepare(Long examId, Long examActivityId, Long examStudentId, Long paperId,
-                              Integer serialNumber, Long studentId, Integer mobilePhotoUpload) {
+    public TOeExamRecord saveByPrepare(Long examId, Long examActivityId, Long examStudentId, Long paperId,
+                                       Integer serialNumber, Long studentId, Integer mobilePhotoUpload) {
         ExamActivityCacheBean ac = examActivityService.getExamActivityCacheBean(examActivityId);
         ExamCacheBean exam = examService.getExamCacheBean(examId);
         TOeExamRecord er = new TOeExamRecord();
@@ -168,7 +168,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
 
         //2022-04-15新增
         ExamingDataCacheUtil.setExamingRecordId(studentId, er.getId());
-        return er.getId();
+        return er;
     }
 
     /**
@@ -428,14 +428,21 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
             //更新考生信息
             teExamStudentService.updateExamStudentByCache(er.getExamStudentId());
             ExamStudentCacheBean examStudentCache = (ExamStudentCacheBean) redisUtil.get(RedisKeyHelper.examStudentCacheKey(er.getExamStudentId()));
+            ExamCacheBean examCacheBean = examService.getExamCacheBean(ExamRecordCacheUtil.getExamId(recordId));
             if (Objects.nonNull(examStudentCache.getAlreadyExamCount()) &&
                     examStudentCache.getAlreadyExamCount().longValue() == 1) {
-                teOrgSummaryService.updateOrgZeroSummary(1);
+                teOrgSummaryService.updateOrgZeroSummary(examCacheBean.getOrgId(), 1);
+                teOrgSummaryService.updateOrgZeroSummary(0L, 1);
             } else {
-                teOrgSummaryService.updateOrgZeroSummary(0);
+                teOrgSummaryService.updateOrgZeroSummary(examCacheBean.getOrgId(), 0);
+                teOrgSummaryService.updateOrgZeroSummary(0L, 0);
             }
             themisCacheService.updateOrgSummaryCache(0L);
 
+            Long examActivityId = ExamRecordCacheUtil.getExamActivityId(recordId);
+            String examRecordChangeKey = examActivityId + "_" + examStudentCache.getRoomCode();
+            themisCacheService.addExamRecordChangeCache(examRecordChangeKey, timestamp);
+
             //上传个人试卷结构
             if (Objects.nonNull(struct)) {
                 ossUtil.upload(false, structFilePath, struct.getContent());
@@ -499,30 +506,6 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
             if (Objects.nonNull(o) && o instanceof BreachStatusBean) {
                 record.put(ExamRecordFieldEnum.breach_status.getCode(), ((BreachStatusBean) o).getStatus());
             }
-            o = redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode());
-            if (Objects.nonNull(o) && o instanceof WarningCountBean) {
-                record.put(ExamRecordFieldEnum.warning_count.getCode(), ((WarningCountBean) o).getNumber());
-            }
-            o = redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_unread.getCode());
-            if (Objects.nonNull(o) && o instanceof WarningUnreadBean) {
-                record.put(ExamRecordFieldEnum.warning_unread.getCode(), ((WarningUnreadBean) o).getNumber());
-            }
-            o = redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_multiple_face_count.getCode());
-            if (Objects.nonNull(o) && o instanceof WarningMultipleFaceCountBean) {
-                record.put(ExamRecordFieldEnum.warning_multiple_face_count.getCode(), ((WarningMultipleFaceCountBean) o).getNumber());
-            }
-            o = redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.exception_count.getCode());
-            if (Objects.nonNull(o) && o instanceof ExceptionCountBean) {
-                record.put(ExamRecordFieldEnum.exception_count.getCode(), ((ExceptionCountBean) o).getNumber());
-            }
-            o = redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.already_break_count.getCode());
-            if (Objects.nonNull(o) && o instanceof AlreadyBreakCountBean) {
-                record.put(ExamRecordFieldEnum.already_break_count.getCode(), ((AlreadyBreakCountBean) o).getNumber());
-            }
-            o = redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.in_process_liveness_verify_count.getCode());
-            if (Objects.nonNull(o) && o instanceof InProcessLivenessVerifyCountBean) {
-                record.put(ExamRecordFieldEnum.in_process_liveness_verify_count.getCode(), ((InProcessLivenessVerifyCountBean) o).getNumber());
-            }
             er = GsonUtil.fromJson(GsonUtil.toJson(record), TOeExamRecord.class);
         }
         return er;
@@ -576,26 +559,15 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
      */
     @Override
     public void updateWarningCountCache(Long id, TIeInvigilateWarnInfo tIeInvigilateWarnInfo) {
-        Integer warningCount = ExamRecordCacheUtil.getWarningCount(id);
         ExamRecordStatusEnum status = ExamRecordCacheUtil.getStatus(id);
         if (Objects.nonNull(status) && status != ExamRecordStatusEnum.PERSISTED) {
-            long timestamp = System.currentTimeMillis();
-            if (Objects.nonNull(warningCount)) {
-                ExamRecordCacheUtil.setWarningCount(id, warningCount + 1, timestamp);
-            } else {
-                ExamRecordCacheUtil.setWarningCount(id, 1, timestamp);
-            }
-            Integer warningUnread = ExamRecordCacheUtil.getWarningUnread(id);
-            if (Objects.nonNull(warningUnread)) {
-                ExamRecordCacheUtil.setWarningUnread(id, warningUnread + 1, timestamp);
-            } else {
-                ExamRecordCacheUtil.setWarningUnread(id, 1, timestamp);
-            }
+            ExamRecordCacheUtil.setWarningCount(id, 1);
+            ExamRecordCacheUtil.setWarningUnread(id, 1);
             if (Objects.nonNull(tIeInvigilateWarnInfo) && tIeInvigilateWarnInfo.getType() == VerifyExceptionEnum.FACE_COUNT_ERROR
                     && Objects.equals(tIeInvigilateWarnInfo.getLevel(), "D8")) {
                 this.updateWarningMultipleFaceCountCache(id);
             }
-            this.sendExamRecordDataSaveMq(id, timestamp);
+            this.sendExamRecordDataSaveMq(id, System.currentTimeMillis());
         } else {
             //已经结束了直接更新数据库
             this.sendExamRecordDataUpdateWarningCountMq(id);
@@ -607,24 +579,28 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
      *
      * @param id
      * @param number
+     * @param updateDb
      */
     @Override
-    public void updateWarningUnreadCache(Long id, Integer number) {
+    public void updateWarningUnreadCache(Long id, Integer number, Boolean updateDb) {
         Integer warningUnread = ExamRecordCacheUtil.getWarningUnread(id);
         ExamRecordStatusEnum status = ExamRecordCacheUtil.getStatus(id);
         if (Objects.nonNull(status) && status != ExamRecordStatusEnum.PERSISTED) {
-            long timestamp = System.currentTimeMillis();
             if (Objects.nonNull(warningUnread) && number.intValue() == 0) {
-                ExamRecordCacheUtil.setWarningUnread(id, number, timestamp);
+                ExamRecordCacheUtil.setWarningUnread(id, -warningUnread);
             } else if (Objects.nonNull(warningUnread) && number.intValue() > 0) {
-                ExamRecordCacheUtil.setWarningUnread(id, warningUnread - number, timestamp);
+                ExamRecordCacheUtil.setWarningUnread(id, -(warningUnread - number));
             } else {
-                ExamRecordCacheUtil.setWarningUnread(id, 0, timestamp);
+                ExamRecordCacheUtil.setWarningUnread(id, 0);
+            }
+            if (Objects.nonNull(updateDb) && updateDb) {
+                this.sendExamRecordDataSaveMq(id, System.currentTimeMillis());
             }
-            this.sendExamRecordDataSaveMq(id, timestamp);
         } else {
-            //已经结束了直接更新数据库
-            this.sendExamRecordDataUpdateWarningUnreadMq(id, number);
+            if (Objects.nonNull(updateDb) && updateDb) {
+                //已经结束了直接更新数据库
+                this.sendExamRecordDataUpdateWarningUnreadMq(id, number);
+            }
         }
     }
 
@@ -635,15 +611,9 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
      */
     @Override
     public void updateWarningMultipleFaceCountCache(Long id) {
-        Integer warningMultipleFaceCount = ExamRecordCacheUtil.getWarningMultipleFaceCount(id);
         ExamRecordStatusEnum status = ExamRecordCacheUtil.getStatus(id);
         if (Objects.nonNull(status) && status != ExamRecordStatusEnum.PERSISTED) {
-            long timestamp = System.currentTimeMillis();
-            if (Objects.nonNull(warningMultipleFaceCount)) {
-                ExamRecordCacheUtil.setWarningMultipleFaceCount(id, warningMultipleFaceCount + 1, timestamp);
-            } else {
-                ExamRecordCacheUtil.setWarningMultipleFaceCount(id, 1, timestamp);
-            }
+            ExamRecordCacheUtil.setWarningMultipleFaceCount(id, 1);
         }
     }
 
@@ -654,18 +624,35 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
      */
     @Override
     public void updateExceptionCountCache(Long id) {
-        Integer exceptionCount = ExamRecordCacheUtil.getExceptionCount(id);
         ExamRecordStatusEnum status = ExamRecordCacheUtil.getStatus(id);
         if (Objects.nonNull(status) && status != ExamRecordStatusEnum.PERSISTED) {
-            long timestamp = System.currentTimeMillis();
-            if (Objects.nonNull(exceptionCount)) {
-                ExamRecordCacheUtil.setExceptionCount(id, exceptionCount + 1, timestamp);
-            } else {
-                ExamRecordCacheUtil.setExceptionCount(id, 1, timestamp);
-            }
+            ExamRecordCacheUtil.setExceptionCount(id, 1);
         }
     }
 
+    /**
+     * 根据预警条件清除未阅
+     *
+     * @param examId
+     * @param examActivityId
+     * @param roomCode
+     * @param name
+     * @param identity
+     * @param minMultipleFaceCount
+     * @param maxMultipleFaceCount
+     * @param minExceptionCount
+     * @param maxExceptionCount
+     * @param minWarningCount
+     * @param maxWarningCount
+     * @param userId
+     * @param orgId
+     * @return
+     */
+    @Override
+    public List<TOeExamRecord> findExamRecordByWarning(Long examId, Long examActivityId, String roomCode, String name, String identity, Integer minMultipleFaceCount, Integer maxMultipleFaceCount, Integer minExceptionCount, Integer maxExceptionCount, Integer minWarningCount, Integer maxWarningCount, Long userId, Long orgId) {
+        return this.baseMapper.findExamRecordByWarning(examId, examActivityId, roomCode, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount, maxExceptionCount, minWarningCount, maxWarningCount, userId, orgId);
+    }
+
     @Override
     public void saveFaceVerify(ExamTypeEnum type, Long recordId, Long entryAuthenticationId,
                                VerifyExceptionEnum entryAuthenticationResult) {
@@ -683,8 +670,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
             ExamRecordCacheUtil.setEntryAuthenticationId(recordId, entryAuthenticationId);
             ExamRecordCacheUtil.setEntryAuthenticationResult(recordId, entryAuthenticationResult);
         } else if (LivenessTypeEnum.IN_PROCESS.equals(type)) {
-            Integer count = Objects.isNull(ExamRecordCacheUtil.getInProcessLivenessVerifyCount(recordId)) ? 0 : ExamRecordCacheUtil.getInProcessLivenessVerifyCount(recordId);
-            ExamRecordCacheUtil.setInProcessLivenessVerifyCount(recordId, count + 1, System.currentTimeMillis());
+            ExamRecordCacheUtil.setInProcessLivenessVerifyCount(recordId, 1);
         }
         this.sendExamRecordDataSaveMq(recordId, System.currentTimeMillis());
     }
@@ -1093,11 +1079,11 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
             log.info("no ObjectiveAnswer for calculateObjectiveScore recordId:" + recordId);
             return;
         }
-        BigDecimal tatolscore = new BigDecimal(0.0);
+        BigDecimal tatolscore = BigDecimal.valueOf(0.0);
         for (TOeExamAnswer answer : answers) {
             Double score = calculateScoreForQuestion(answer, map);
             if (score != null) {
-                tatolscore = tatolscore.add(new BigDecimal(score));
+                tatolscore = tatolscore.add(BigDecimal.valueOf(score));
             }
         }
 
@@ -1142,7 +1128,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                     if (r == 1) {
                         answer.setScore(cb.getScore());
                     } else if (r == 0) {
-                        BigDecimal b = new BigDecimal(cb.getScore()).divide(new BigDecimal("2"), 1, BigDecimal.ROUND_UP);
+                        BigDecimal b = BigDecimal.valueOf(cb.getScore()).divide(new BigDecimal("2"), 1, BigDecimal.ROUND_UP);
                         answer.setScore(b.doubleValue());
                     } else {
                         answer.setScore(0.0);
@@ -1287,12 +1273,6 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         return tOeExamRecord;
     }
 
-    public static void main(String[] args) {
-        Integer i = 0;
-//        System.out.println(i++);
-        System.out.println(i + 1);
-    }
-
     /**
      * 设置断点信息
      *
@@ -1313,7 +1293,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                     ExamRecordCacheUtil.setLastBreakId(recordId, breakId);
                     ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.BREAK_OFF, lastBreakTimeNow);
                     ExamRecordCacheUtil.setLastBreakTime(recordId, lastBreakTimeNow);
-                    ExamRecordCacheUtil.setAlreadyBreakCount(recordId, alreadyBreakCount + 1, lastBreakTimeNow);
+                    ExamRecordCacheUtil.setAlreadyBreakCount(recordId, 1);
 
                     Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
                     Long examId = ExamRecordCacheUtil.getExamId(recordId);
@@ -1759,10 +1739,10 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
      */
     @Override
     public List<Long> dataCount() {
-        TEOrgSummary teOrgSummary = themisCacheService.addOrgSummaryCache(0L);
+        TEOrgSummary teOrgSummary = themisCacheService.getOrgSummaryCache(0L);
         if (Objects.isNull(teOrgSummary)) {
             teOrgSummaryService.orgSummary(0L, null);//第一次进来没数据,强制统计一次
-            teOrgSummary = themisCacheService.addOrgSummaryCache(0L);
+            teOrgSummary = themisCacheService.getOrgSummaryCache(0L);
         }
         List<Long> list = new ArrayList<>();
         list.add(Objects.nonNull(teOrgSummary) && Objects.nonNull(teOrgSummary.getOnlineCount()) ? Long.parseLong(teOrgSummary.getOnlineCount().toString()) : 0L);
@@ -1779,7 +1759,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
      */
     @Override
     public List<OrgDataCountBean> orgDataCount() {
-        Set<String> examIdSetSet = redisUtil.getHashKeys(SystemConstant.TODAY_EXAM_LIST_MAP_CACHE);
+        Set<String> examIdSetSet = redisUtil.getHashKeys(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE);
         if (!CollectionUtils.isEmpty(examIdSetSet)) {
             Set<Long> examIdSet = examIdSetSet.stream().map(s -> Long.parseLong(s)).collect(Collectors.toSet());
             LinkedMultiValueMap<Long, Long> orgExamIdMap = tbOrgService.mergeOrgId(examIdSet);
@@ -1787,7 +1767,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                 List<OrgDataCountBean> orgDataCountBeanList = new ArrayList<>();
                 //统计机构信息
                 orgExamIdMap.forEach((k, v) -> {
-                    TEOrgSummary teOrgSummary = themisCacheService.addOrgSummaryCache(k);
+                    TEOrgSummary teOrgSummary = themisCacheService.getOrgSummaryCache(k);
                     if (Objects.nonNull(teOrgSummary) && ((Objects.nonNull(teOrgSummary.getExamCount()) &&
                             teOrgSummary.getExamCount().intValue() > 0)
                             || (Objects.nonNull(teOrgSummary) && Objects.nonNull(teOrgSummary.getOnlineCount()) &&
@@ -1809,7 +1789,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
      */
     @Override
     public List<MapDataCountBean> mapDataCount() {
-        List<TERegionSummary> teRegionSummaryList = themisCacheService.addRegionSummaryCache();
+        List<TERegionSummary> teRegionSummaryList = themisCacheService.getRegionSummaryCache();
         if (!CollectionUtils.isEmpty(teRegionSummaryList)) {
             return GsonUtil.fromJson(GsonUtil.toJson(teRegionSummaryList), new TypeToken<List<MapDataCountBean>>() {
             }.getType());

+ 94 - 68
themis-business/src/main/java/com/qmth/themis/business/service/impl/ThemisCacheServiceImpl.java

@@ -608,48 +608,45 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
     }
 
     /**
-     * 设置当考试缓存
+     * 设置当考试缓存
      */
     @Override
-    public void setTodayExamCache() {
+    public void setCurrentExamListCache() {
         try {
             Date now = new Date();
             SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
-            String today = sdf1.format(now);
+            String current = sdf1.format(now);
             SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-            Long startTime = sdf2.parse(today + " 00:00:00").getTime();
-            Long endTime = sdf2.parse(today + " 23:59:59").getTime();
-            List<TEExamActivity> teExamActivityList = teExamActivityService.list(new QueryWrapper<TEExamActivity>().lambda().ge(TEExamActivity::getStartTime, startTime).le(TEExamActivity::getStartTime, endTime).eq(TEExamActivity::getEnable, 1));
+            Long startTime = sdf2.parse(current + " 00:00:00").getTime();
+            Long endTime = sdf2.parse(current + " 23:59:59").getTime();
+            List<TEExamActivity> teExamActivityList = teExamActivityService.findCurrentExamActivity(startTime, endTime);
             //统计当天00:00:00~23:59:59可以进行的考试批次、场次、考场编码信息
             if (!CollectionUtils.isEmpty(teExamActivityList)) {
-                LinkedMultiValueMap<Long, ExamListBean> todayExamListMap = new LinkedMultiValueMap<>();//考试批次、场次集合/考场编码集合
+                LinkedMultiValueMap<Long, ExamListBean> currentExamListMap = new LinkedMultiValueMap<>();//考试批次、场次集合/考场编码集合
                 Map<Long, Set<Long>> examActivityIdMap = new HashMap<>();//考试批次id,场次id集合
                 Map<Long, Set<String>> roomCodeMap = new HashMap<>();//考试场次id,考场编码集合
                 for (TEExamActivity t : teExamActivityList) {
-                    ExamCacheBean examCacheBean = teExamService.getExamCacheBean(t.getExamId());
-                    if (Objects.nonNull(examCacheBean.getEnable()) && examCacheBean.getEnable().intValue() == 1 && Objects.nonNull(t.getEnable()) && t.getEnable().intValue() == 1) {
-                        List<TEExamStudent> teExamStudentList = teExamStudentService.list(new QueryWrapper<TEExamStudent>().lambda().eq(TEExamStudent::getExamId, t.getExamId()).eq(TEExamStudent::getExamActivityId, t.getId()));
-                        if (!CollectionUtils.isEmpty(teExamStudentList)) {
-                            Set<String> roomCodeSet = teExamStudentList.stream().map(s -> s.getRoomCode()).collect(Collectors.toSet());
-                            if (examActivityIdMap.containsKey(t.getExamId())) {
-                                Set<Long> examActivityIdSet = examActivityIdMap.get(t.getExamId());
-                                examActivityIdSet.add(t.getId());
-                                examActivityIdMap.put(t.getExamId(), examActivityIdSet);
-                            } else {
-                                examActivityIdMap.put(t.getExamId(), new HashSet<>(Arrays.asList(t.getId())));
-                            }
-                            roomCodeMap.put(t.getId(), roomCodeSet);
+                    List<TEExamStudent> teExamStudentList = teExamStudentService.list(new QueryWrapper<TEExamStudent>().lambda().eq(TEExamStudent::getExamId, t.getExamId()).eq(TEExamStudent::getExamActivityId, t.getId()));
+                    if (!CollectionUtils.isEmpty(teExamStudentList)) {
+                        Set<String> roomCodeSet = teExamStudentList.stream().map(s -> s.getRoomCode()).collect(Collectors.toSet());
+                        if (examActivityIdMap.containsKey(t.getExamId())) {
+                            Set<Long> examActivityIdSet = examActivityIdMap.get(t.getExamId());
+                            examActivityIdSet.add(t.getId());
+                            examActivityIdMap.put(t.getExamId(), examActivityIdSet);
+                        } else {
+                            examActivityIdMap.put(t.getExamId(), new HashSet<>(Arrays.asList(t.getId())));
                         }
+                        roomCodeMap.put(t.getId(), roomCodeSet);
                     }
                 }
                 examActivityIdMap.forEach((k, v) -> {
                     for (Long l : v) {
                         String s = StringUtils.join(roomCodeMap.get(l)).replaceAll("\\[", "").replaceAll("\\]", "");
-                        todayExamListMap.add(k, new ExamListBean(l, s));
+                        currentExamListMap.add(k, new ExamListBean(l, s));
                     }
                 });
-                todayExamListMap.forEach((k, v) -> {
-                    redisUtil.set(SystemConstant.TODAY_EXAM_LIST_MAP_CACHE, k.toString(), v);
+                currentExamListMap.forEach((k, v) -> {
+                    redisUtil.set(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE, k.toString(), v);
                 });
             }
         } catch (Exception e) {
@@ -657,33 +654,44 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
         }
     }
 
+    /**
+     * 获取当前考试列表缓存
+     *
+     * @return
+     */
+    @Override
+    public Map<String, List<ExamListBean>> getCurrentExamListCache() {
+        return redisUtil.getHashEntries(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE);
+    }
+
     /**
      * 设置考试列表缓存
      */
     @Override
     public void setOrgExamListCache() {
-        //查询考试场次结束时间大于当前时间的所有考试
-        List<TEExamActivity> teExamActivityList = teExamActivityService.list(new QueryWrapper<TEExamActivity>().lambda().gt(TEExamActivity::getFinishTime, System.currentTimeMillis()).eq(TEExamActivity::getEnable, 1));
+        SysConfig sysConfig = this.addSysConfigCache(SystemConstant.WAITING_EXAM_DAY);
+        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置待考列表天数"));
+
+        //查询提前3天待考的考试列表
+        List<TEExamActivity> teExamActivityList = teExamActivityService.findWaitingExamList(Integer.parseInt(sysConfig.getConfigValue()));
         if (!CollectionUtils.isEmpty(teExamActivityList)) {
             Map<Long, Set<Long>> orgMap = new HashMap<>();//机构id,考试批次id集合
             Map<Long, Set<Long>> examMap = new HashMap<>();//考试批次id,场次id集合
             for (TEExamActivity t : teExamActivityList) {
                 ExamCacheBean examCacheBean = teExamService.getExamCacheBean(t.getExamId());
-                if (Objects.nonNull(examCacheBean.getEnable()) && examCacheBean.getEnable().intValue() == 1) {
-                    if (orgMap.containsKey(examCacheBean.getOrgId())) {
-                        Set<Long> examIdSet = orgMap.get(examCacheBean.getOrgId());
-                        examIdSet.add(t.getExamId());
-                        orgMap.put(examCacheBean.getOrgId(), examIdSet);
-                    } else {
-                        orgMap.put(examCacheBean.getOrgId(), new HashSet<>(Arrays.asList(t.getExamId())));
-                    }
-                    if (examMap.containsKey(t.getExamId())) {
-                        Set<Long> examActivityIdSet = examMap.get(examCacheBean.getId());
-                        examActivityIdSet.add(t.getId());
-                        examMap.put(t.getExamId(), examActivityIdSet);
-                    } else {
-                        examMap.put(t.getExamId(), new HashSet<>(Arrays.asList(t.getId())));
-                    }
+                if (orgMap.containsKey(examCacheBean.getOrgId())) {
+                    Set<Long> examIdSet = orgMap.get(examCacheBean.getOrgId());
+                    examIdSet.add(t.getExamId());
+                    orgMap.put(examCacheBean.getOrgId(), examIdSet);
+                } else {
+                    orgMap.put(examCacheBean.getOrgId(), new HashSet<>(Arrays.asList(t.getExamId())));
+                }
+                if (examMap.containsKey(t.getExamId())) {
+                    Set<Long> examActivityIdSet = examMap.get(examCacheBean.getId());
+                    examActivityIdSet.add(t.getId());
+                    examMap.put(t.getExamId(), examActivityIdSet);
+                } else {
+                    examMap.put(t.getExamId(), new HashSet<>(Arrays.asList(t.getId())));
                 }
             }
             orgMap.forEach((k, v) -> {
@@ -714,7 +722,7 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
      */
     @Override
     public Set<Long> getOrgExamListCache(String orgId, String examId) {
-        Map<String, Set<Long>> map = redisUtil.getHashEntries(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + orgId);
+        Map<String, Set<Long>> map = this.getOrgExamListCache(orgId);
         return !CollectionUtils.isEmpty(map) ? map.get(examId) : null;
     }
 
@@ -725,7 +733,7 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
      */
     @Override
     public void updateOrgExamListCache(String orgId, String examId, Long examActivityId) {
-        Map<String, Set<Long>> map = redisUtil.getHashEntries(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + orgId);
+        Map<String, Set<Long>> map = this.getOrgExamListCache(orgId);
         if (CollectionUtils.isEmpty(map)) {
             redisUtil.set(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + orgId, examId, new HashSet<>(Arrays.asList(examActivityId)));
         } else {
@@ -768,7 +776,7 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
      */
     @Override
     public void removeOrgExamListCache(String orgId, String examId, Long examActivityId) {
-        Map<String, Set<Long>> map = redisUtil.getHashEntries(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + orgId);
+        Map<String, Set<Long>> map = this.getOrgExamListCache(orgId);
         CopyOnWriteArraySet<Long> examActivityIdSet = new CopyOnWriteArraySet<>();
         examActivityIdSet.addAll(map.get(examId));
         for (Long l : examActivityIdSet) {
@@ -786,33 +794,33 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
     }
 
     /**
-     * 获取当考试列表缓存
+     * 获取当考试列表缓存
      *
      * @param examId
      * @return
      */
     @Override
-    public List<ExamListBean> getTodayExamListCache(String examId) {
-        Map<String, List<ExamListBean>> map = redisUtil.getHashEntries(SystemConstant.TODAY_EXAM_LIST_MAP_CACHE);
+    public List<ExamListBean> getCurrentExamListCache(String examId) {
+        Map<String, List<ExamListBean>> map = this.getCurrentExamListCache();
         return !CollectionUtils.isEmpty(map) ? map.get(examId) : null;
     }
 
     /**
-     * 更新当考试缓存
+     * 更新当考试缓存
      *
      * @param examId
      * @return
      */
     @Override
-    public void updateTodayExamListCache(String examId, Long examActivityId) {
+    public void updateCurrentExamListCache(String examId, Long examActivityId) {
         List<TEExamStudent> teExamStudentList = teExamStudentService.list(new QueryWrapper<TEExamStudent>().lambda().eq(TEExamStudent::getExamId, Long.parseLong(examId)).eq(TEExamStudent::getExamActivityId, examActivityId));
         if (!CollectionUtils.isEmpty(teExamStudentList)) {
             Set<String> roomCodeSet = teExamStudentList.stream().map(s -> s.getRoomCode()).collect(Collectors.toSet());
-            this.removeTodayExamListCache(examId, examActivityId);
-            List<ExamListBean> examListBeanList = this.getTodayExamListCache(examId);
+            this.removeCurrentExamListCache(examId, examActivityId);
+            List<ExamListBean> examListBeanList = this.getCurrentExamListCache(examId);
             CopyOnWriteArrayList<ExamListBean> copyOnWriteArrayList = !CollectionUtils.isEmpty(examListBeanList) ? new CopyOnWriteArrayList(examListBeanList) : new CopyOnWriteArrayList();
             copyOnWriteArrayList.add(new ExamListBean(examActivityId, StringUtils.join(roomCodeSet).replaceAll("\\[", "").replaceAll("\\]", "")));
-            redisUtil.set(SystemConstant.TODAY_EXAM_LIST_MAP_CACHE, examId, new LinkedList<>(copyOnWriteArrayList));
+            redisUtil.set(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE, examId, new LinkedList<>(copyOnWriteArrayList));
         }
     }
 
@@ -822,8 +830,8 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
      * @param examId
      */
     @Override
-    public void removeTodayExamListCache(String examId) {
-        redisUtil.delete(SystemConstant.TODAY_EXAM_LIST_MAP_CACHE, examId);
+    public void removeCurrentExamListCache(String examId) {
+        redisUtil.delete(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE, examId);
     }
 
     /**
@@ -833,8 +841,8 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
      * @param examActivityId
      */
     @Override
-    public void removeTodayExamListCache(String examId, Long examActivityId) {
-        List<ExamListBean> examListBeanList = this.getTodayExamListCache(examId);
+    public void removeCurrentExamListCache(String examId, Long examActivityId) {
+        List<ExamListBean> examListBeanList = this.getCurrentExamListCache(examId);
         if (!CollectionUtils.isEmpty(examListBeanList)) {
             CopyOnWriteArrayList<ExamListBean> copyOnWriteArrayList = new CopyOnWriteArrayList(examListBeanList);
             for (ExamListBean e : copyOnWriteArrayList) {
@@ -844,9 +852,9 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
                 }
             }
             if (!CollectionUtils.isEmpty(copyOnWriteArrayList)) {
-                redisUtil.set(SystemConstant.TODAY_EXAM_LIST_MAP_CACHE, examId, new LinkedList<>(copyOnWriteArrayList));
+                redisUtil.set(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE, examId, new LinkedList<>(copyOnWriteArrayList));
             } else {
-                this.removeTodayExamListCache(examId);
+                this.removeCurrentExamListCache(examId);
             }
         }
     }
@@ -868,12 +876,7 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
         if (Objects.nonNull(roomCode)) {
             teExamSummaryQueryWrapper.lambda().eq(TEExamSummary::getRoomCode, roomCode);
         }
-        List<TEExamSummary> teExamSummaryList = teExamSummaryService.list(teExamSummaryQueryWrapper);
-        if (CollectionUtils.isEmpty(teExamSummaryList)) {
-            teExamSummaryService.examSummary(examId, examActivityId, Objects.nonNull(roomCode) ? new HashSet<>(Arrays.asList(roomCode)) : null);
-            teExamSummaryList = teExamSummaryService.list(teExamSummaryQueryWrapper);
-        }
-        return teExamSummaryList;
+        return teExamSummaryService.list(teExamSummaryQueryWrapper);
     }
 
     /**
@@ -884,7 +887,7 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
      */
     @Override
     @Cacheable(value = SystemConstant.examSummaryCache, key = "#p0", unless = "#result?.size() == 0")
-    public List<TEExamSummary> addExamSummaryCache(Long examId) {
+    public List<TEExamSummary> getExamSummaryCache(Long examId) {
         return this.examSummaryQueryCommon(examId, null, null);
     }
 
@@ -897,7 +900,7 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
      */
     @Override
     @Cacheable(value = SystemConstant.examSummaryCache, key = "#p0 + '-' + #p1", unless = "#result?.size() == 0")
-    public List<TEExamSummary> addExamSummaryCache(Long examId, Long examActivityId) {
+    public List<TEExamSummary> getExamSummaryCache(Long examId, Long examActivityId) {
         return this.examSummaryQueryCommon(examId, examActivityId, null);
     }
 
@@ -911,7 +914,7 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
      */
     @Override
     @Cacheable(value = SystemConstant.examSummaryCache, key = "#p0 + '-' + #p1 + '-' + #p2", unless = "#result?.size() == 0")
-    public List<TEExamSummary> addExamSummaryCache(Long examId, Long examActivityId, String roomCode) {
+    public List<TEExamSummary> getExamSummaryCache(Long examId, Long examActivityId, String roomCode) {
         return this.examSummaryQueryCommon(examId, examActivityId, roomCode);
     }
 
@@ -998,7 +1001,7 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
      */
     @Override
     @Cacheable(value = SystemConstant.orgSummaryCache, key = "#p0", unless = "#result == null")
-    public TEOrgSummary addOrgSummaryCache(Long orgId) {
+    public TEOrgSummary getOrgSummaryCache(Long orgId) {
         return teOrgSummaryService.getOne(new QueryWrapper<TEOrgSummary>().lambda().eq(TEOrgSummary::getOrgId, orgId));
     }
 
@@ -1032,7 +1035,7 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
      */
     @Override
     @Cacheable(value = SystemConstant.regionSummaryCache, unless = "#result?.size() == 0")
-    public List<TERegionSummary> addRegionSummaryCache() {
+    public List<TERegionSummary> getRegionSummaryCache() {
         return teRegionSummaryService.list();
     }
 
@@ -1069,4 +1072,27 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
         this.removeExamSummaryCache(examId, examActivityId);
         this.removeExamSummaryCache(examId, examActivityId, roomCode);
     }
+
+    /**
+     * 考试记录改变cache
+     *
+     * @param key
+     * @param timestamp
+     */
+    @Override
+    public void addExamRecordChangeCache(String key, Long timestamp) {
+        redisUtil.setZset(key, key, timestamp);
+    }
+
+    /**
+     * 获取考试记录score
+     *
+     * @param key
+     * @return
+     */
+    @Override
+    public Long getExamRecordChangeCache(String key) {
+        Double d = redisUtil.getZset(key, key);
+        return Objects.nonNull(d) ? d.longValue() : null;
+    }
 }

+ 8 - 8
themis-business/src/main/java/com/qmth/themis/business/templete/impl/TaskExamPaperImportTemplete.java

@@ -216,8 +216,8 @@ public class TaskExamPaperImportTemplete implements TaskImportTemplete {
     }
 
     private Map<Long, Double> paperWeight(List<TEExamPaper> list) {
-        BigDecimal b1 = new BigDecimal(100.0);// 基数总数
-        BigDecimal b2 = new BigDecimal(list.size());// 份数
+        BigDecimal b1 = BigDecimal.valueOf(100.0);// 基数总数
+        BigDecimal b2 = BigDecimal.valueOf(list.size());// 份数
         BigDecimal b3 = b1.divide(b2, 0, BigDecimal.ROUND_FLOOR);// 平均数
         BigDecimal b4 = b1.subtract(b3.multiply(b2).setScale(0, BigDecimal.ROUND_FLOOR));// 余数
         Map<Long, Double> map = new HashMap<Long, Double>();
@@ -406,8 +406,8 @@ public class TaskExamPaperImportTemplete implements TaskImportTemplete {
     }
 
     private void disposeStruct(String rootDir, TEExamPaper paper, File paperFile) throws IOException {
-        BigDecimal obTotal = new BigDecimal(0);
-        BigDecimal subTotal = new BigDecimal(0);
+        BigDecimal obTotal = BigDecimal.valueOf(0);
+        BigDecimal subTotal = BigDecimal.valueOf(0);
         if (paperFile == null) {
             return;
         }
@@ -426,9 +426,9 @@ public class TaskExamPaperImportTemplete implements TaskImportTemplete {
                 Integer structType = question.getInteger(SystemConstant.STRUCT_TYPE);
                 if (structType.intValue() != 1 && structType.intValue() != 2 && structType.intValue() != 3
                         && structType.intValue() != 6 && structType.intValue() != 8) {//主观题
-                    subTotal = subTotal.add(new BigDecimal(score));
+                    subTotal = subTotal.add(BigDecimal.valueOf(score));
                 } else {//客观题
-                    obTotal = obTotal.add(new BigDecimal(score));
+                    obTotal = obTotal.add(BigDecimal.valueOf(score));
                 }
                 if (structType.intValue() == 6 || structType.intValue() == 8) {
                     JSONArray subQuestions = question.getJSONArray(SystemConstant.SUB_QUESTIONS);
@@ -443,9 +443,9 @@ public class TaskExamPaperImportTemplete implements TaskImportTemplete {
                         Integer subStructType = subquestion.getInteger(SystemConstant.STRUCT_TYPE);
                         if (subStructType.intValue() != 1 && subStructType.intValue() != 2
                                 && subStructType.intValue() != 3) {//主观题
-                            subTotal = subTotal.add(new BigDecimal(subScore));
+                            subTotal = subTotal.add(BigDecimal.valueOf(subScore));
                         } else {//客观题
-                            obTotal = obTotal.add(new BigDecimal(subScore));
+                            obTotal = obTotal.add(BigDecimal.valueOf(subScore));
                         }
                     }
                 }

+ 1 - 1
themis-business/src/main/java/com/qmth/themis/business/templete/impl/TaskExamStudentImportTemplete.java

@@ -144,7 +144,7 @@ public class TaskExamStudentImportTemplete implements TaskImportTemplete {
                 List<TEExamActivity> teExamActivityList = GsonUtil.fromJson(GsonUtil.toJson(teExamActivityMap.values()), new TypeToken<List<TEExamActivity>>() {
                 }.getType());
                 for (TEExamActivity t : teExamActivityList) {
-                    themisCacheService.updateTodayExamListCache(String.valueOf(examId), t.getId());
+                    themisCacheService.updateCurrentExamListCache(String.valueOf(examId), t.getId());
                     ExamCacheBean examCacheBean = teExamService.getExamCacheBean(examId);
                     themisCacheService.updateOrgExamListCache(examCacheBean.getOrgId().toString(), examId.toString(), t.getId());
                 }

+ 14 - 14
themis-business/src/main/java/com/qmth/themis/business/templete/service/impl/TempleteLogicServiceImpl.java

@@ -446,9 +446,9 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
             Integer totalTaskSize = jsonObject.getInteger("totalTaskSize");
             Integer currentTaskSize = jsonObject.getInteger("currentTaskSize");
 
-            BigDecimal progress = new BigDecimal(0);
-            BigDecimal b = new BigDecimal(100);
-            progress = new BigDecimal(currentTaskSize).divide(new BigDecimal(totalTaskSize), 2, BigDecimal.ROUND_HALF_UP).multiply(b);
+            BigDecimal progress = BigDecimal.valueOf(0);
+            BigDecimal b = BigDecimal.valueOf(100);
+            progress = BigDecimal.valueOf(currentTaskSize).divide(BigDecimal.valueOf(totalTaskSize), 2, BigDecimal.ROUND_HALF_UP).multiply(b);
             if (Objects.isNull(tbTaskHistory.getProgress()) || (Objects.nonNull(tbTaskHistory.getProgress()) && tbTaskHistory.getProgress().doubleValue() < progress.doubleValue())) {
                 tbTaskHistory.setProgress(progress.doubleValue());
                 tbTaskHistoryService.updateById(tbTaskHistory);
@@ -520,8 +520,8 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
         TBTaskHistory tbTaskHistory = (TBTaskHistory) map.get("tbTaskHistory");
         Boolean objectiveScorePush = (Boolean) map.get(SystemConstant.OBJECTIVE_SCORE_PUSH);
 
-        BigDecimal progress = new BigDecimal(0);
-        BigDecimal b = new BigDecimal(100);
+        BigDecimal progress = BigDecimal.valueOf(0);
+        BigDecimal b = BigDecimal.valueOf(100);
         TBOrg tbOrg = themisCacheService.addOrgCache(orgId);
 
         Integer totalTaskSize = jsonObject.getInteger("totalTaskSize");
@@ -591,7 +591,7 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
                     }
                 }
             }
-            progress = new BigDecimal(currentTaskSize).divide(new BigDecimal(totalTaskSize), 2, BigDecimal.ROUND_HALF_UP).multiply(b);
+            progress = BigDecimal.valueOf(currentTaskSize).divide(BigDecimal.valueOf(totalTaskSize), 2, BigDecimal.ROUND_HALF_UP).multiply(b);
             if (Objects.isNull(tbTaskHistory.getProgress()) || (Objects.nonNull(tbTaskHistory.getProgress()) && tbTaskHistory.getProgress().doubleValue() < progress.doubleValue())) {
                 tbTaskHistory.setProgress(progress.doubleValue());
                 tbTaskHistoryService.updateById(tbTaskHistory);
@@ -723,8 +723,8 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
             map.put("paperJsonList", paperJsonList);
             examPaperIdSet = new HashSet<>(teExamPaperList.size());
 
-            BigDecimal progress = new BigDecimal(0);
-            BigDecimal b = new BigDecimal(100);
+            BigDecimal progress = BigDecimal.valueOf(0);
+            BigDecimal b = BigDecimal.valueOf(100);
 
             int min = 0;
             int max = SystemConstant.MAX_IMPORT_SIZE, size = teExamPaperList.size();
@@ -787,7 +787,7 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
                         tbTaskHistory.setRemark(jsonObject.toJSONString());
                     }
                 }
-                progress = new BigDecimal(currentTaskSize).divide(new BigDecimal(totalTaskSize), 2, BigDecimal.ROUND_HALF_UP).multiply(b);
+                progress = BigDecimal.valueOf(currentTaskSize).divide(BigDecimal.valueOf(totalTaskSize), 2, BigDecimal.ROUND_HALF_UP).multiply(b);
                 if (Objects.isNull(tbTaskHistory.getProgress()) || (Objects.nonNull(tbTaskHistory.getProgress()) && tbTaskHistory.getProgress().doubleValue() < progress.doubleValue())) {
                     tbTaskHistory.setProgress(progress.doubleValue());
                     tbTaskHistoryService.updateById(tbTaskHistory);
@@ -910,8 +910,8 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
      * @return
      */
     public List<String> importProgress(int max, int min, int size, List<String> txtList, TBTaskHistory tbTaskHistory) {
-        BigDecimal bigDecimal = new BigDecimal(100);
-        BigDecimal progress = new BigDecimal(Double.valueOf(new BigDecimal(max).divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP).multiply(bigDecimal).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue())).setScale(0, BigDecimal.ROUND_HALF_UP);
+        BigDecimal bigDecimal = BigDecimal.valueOf(100);
+        BigDecimal progress = BigDecimal.valueOf(Double.valueOf(BigDecimal.valueOf(max).divide(BigDecimal.valueOf(size), 2, BigDecimal.ROUND_HALF_UP).multiply(bigDecimal).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue())).setScale(0, BigDecimal.ROUND_HALF_UP);
         if (progress.intValue() == 100) {
             tbTaskHistory.setStatus(TaskStatusEnum.FINISH);
             tbTaskHistory.setSummary("共处理了" + size + "条数据");
@@ -937,12 +937,12 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
      * @return
      */
     public List<String> exportProgress(int max, int min, int size, List<String> txtList, TBTaskHistory tbTaskHistory) {
-        BigDecimal bigDecimal = new BigDecimal(100);
+        BigDecimal bigDecimal = BigDecimal.valueOf(100);
         BigDecimal progress = null;
         if (size > 0) {
-            progress = new BigDecimal(Double.valueOf(new BigDecimal(max).divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP).multiply(bigDecimal).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue())).setScale(0, BigDecimal.ROUND_HALF_UP);
+            progress = BigDecimal.valueOf(Double.valueOf(BigDecimal.valueOf(max).divide(BigDecimal.valueOf(size), 2, BigDecimal.ROUND_HALF_UP).multiply(bigDecimal).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue())).setScale(0, BigDecimal.ROUND_HALF_UP);
         } else {
-            progress = new BigDecimal(-1);
+            progress = BigDecimal.valueOf(-1);
         }
         if (progress.intValue() == 100) {
             tbTaskHistory.setStatus(TaskStatusEnum.FINISH);

+ 43 - 0
themis-business/src/main/java/com/qmth/themis/business/util/RedisUtil.java

@@ -90,6 +90,49 @@ public class RedisUtil {
         redisTemplate.opsForHash().put(key, hashKey, hashValue);
     }
 
+    /**
+     * 设置zset
+     *
+     * @param key
+     * @param hashValue
+     * @param score
+     */
+    public void setZset(String key, Object hashValue, double score) {
+        redisTemplate.opsForZSet().add(key, hashValue, score);
+        this.expire(key, 1, TimeUnit.HOURS);
+    }
+
+    /**
+     * 获取zset
+     *
+     * @param key
+     * @param hashValue
+     */
+    public Double getZset(String key, Object hashValue) {
+        return redisTemplate.opsForZSet().score(key, hashValue);
+    }
+
+    /**
+     * 获取zset大小
+     *
+     * @param key
+     */
+    public Long getZsetSize(String key) {
+        return redisTemplate.opsForZSet().size(key);
+    }
+
+
+    /**
+     * 设置hash
+     *
+     * @param key
+     * @param hashKey
+     * @param count
+     */
+    public void setInc(String key, String hashKey, Long count) {
+        redisTemplate.opsForHash().increment(key, hashKey, count);
+    }
+
     /**
      * 获取hash
      *

+ 4 - 0
themis-business/src/main/resources/db/log/1.2.8.log

@@ -119,6 +119,10 @@ UPDATE sys_config
 SET org_id=NULL, config_key='exam.no.auth.urls', config_name='exam无需鉴权的url', config_value='/webjars/**,/druid/**,/swagger-ui.html,/doc.html,/swagger-resources/**,/v2/api-docs,/webjars/springfox-swagger-ui/**,/api/oe/student/login,/api/oe/sys/env,/file/**,/upload/**,/client/**,/base_photo/**,/frontend/**,/api/oe/exam/short_code,/api/mobile/authorization,/api/oe/black/list/select,/api/oe/sys/school/list,/api/oe/sys/upload/package/callback,/api/oe/sys/file/upload', enable=1, create_id=1, create_time=NULL, update_id=NULL, update_time=NULL, remark=NULL, sort=1, editor=0
 WHERE id=17;
 
+INSERT INTO sys_config
+(id, org_id, config_key, config_name, config_value, enable, create_id, create_time, update_id, update_time, remark, sort, editor)
+VALUES(33, NULL, 'waiting.exam.day', '待考列表天数', '3', 1, 1, NULL, NULL, NULL, NULL, 1, 0);
+
 /*删除进度查询菜单*/
 INSERT INTO t_b_role_privilege
 (id, role_code, privilege_id)

+ 23 - 0
themis-business/src/main/resources/mapper/TEExamActivityMapper.xml

@@ -214,4 +214,27 @@
           and t.enable = 1
           and f.enable = 1
     </select>
+
+    <select id="findCurrentExamActivity" resultType="com.qmth.themis.business.entity.TEExamActivity">
+        SELECT
+        teea.*
+        FROM
+        t_e_exam_activity teea
+        left join t_e_exam tee on tee.id = teea.exam_id
+        WHERE
+        (teea.start_time <![CDATA[ >= ]]> #{startTime}
+        AND teea.start_time <![CDATA[ <= ]]> #{endTime})
+        OR (teea.start_time <![CDATA[ <= ]]> #{startTime}
+        AND teea.finish_time <![CDATA[ >= ]]> #{endTime})
+        AND teea.enable = 1
+        and teea.enable = 1
+    </select>
+
+    <select id="findWaitingExamList" resultType="com.qmth.themis.business.entity.TEExamActivity">
+        SELECT teea.* FROM t_e_exam_activity teea
+        left join t_e_exam tee on tee.id = teea.exam_id
+        where teea.enable = 1 and teea.enable = 1
+        and datediff(now(), FROM_UNIXTIME(tee.start_time / 1000, '%Y-%m-%d %H:%i:%s')) <![CDATA[ >= ]]> #{day}
+        and datediff(now(), FROM_UNIXTIME(tee.end_time / 1000, '%Y-%m-%d %H:%i:%s')) <![CDATA[ <= ]]> 0
+    </select>
 </mapper>

+ 18 - 4
themis-business/src/main/resources/mapper/TEExamStudentMapper.xml

@@ -97,17 +97,17 @@
         t.exam_activity_id examActivityId,
         t.room_code roomCode,
         t.room_name roomName,
-        count(1) examTotal,
+        count(distinct t.id) examTotal,
         teea.code as examActivityCode,
         tee.monitor_status as monitorStatus,
-        count(toer.exam_student_id) as actualExamTotal,
-        if(teea.finish_time <![CDATA[ <= ]]> (unix_timestamp(current_timestamp()) * 1000),count(1)- count(distinct toer.exam_student_id),0) as deficiencyExamTotal,
+        count(distinct toer.exam_student_id) as actualExamTotal,
+        if(teea.finish_time <![CDATA[ <= ]]> (unix_timestamp(current_timestamp()) * 1000),count(distinct t.id) - count(distinct toer.exam_student_id),0) as deficiencyExamTotal,
         CONCAT(t.room_name,'(',t.room_code,')') as roomNameCode
         from t_e_exam_student t
         left join t_e_student h on t.student_id = h.id
         left join t_e_exam_activity teea on teea.id = t.exam_activity_id
         join t_e_exam tee on tee.id = t.exam_id
-        left join t_oe_exam_record toer on toer.exam_student_id = t.id and toer.exam_id = tee.id and toer.exam_activity_id = teea.id and toer.first_start_time is not null
+        left join t_oe_exam_record toer on toer.exam_student_id = t.id and toer.first_start_time is not null
         where t.exam_id = #{examId}
         <if test="orgId != null">
             and h.org_id=#{orgId}
@@ -499,4 +499,18 @@
             and (toer.id is null or (toer.status in ('FIRST_PREPARE', 'JUNK') and toer.client_websocket_status = 'OFF_LINE' and t.already_exam_count = 0))
         </where>
     </select>
+
+    <select id="getExamInfo" resultType="com.qmth.themis.business.bean.admin.ExamInfoBean">
+        select distinct tees.exam_id as examId,
+                     tees.exam_activity_id as examActivityId,
+                     group_concat(distinct tees.room_code) as roomCodes
+        from t_e_exam_student tees
+            left join t_e_exam tee on tee.id = tees.exam_id
+            left join t_e_exam_activity teea on teea.exam_id = tee.id
+        where
+            tee.org_id = #{orgId}
+            and tee.enable = 1
+            and teea.enable = 1
+        group by tees.exam_id,tees.exam_activity_id
+    </select>
 </mapper>

+ 54 - 50
themis-business/src/main/resources/mapper/TEOrgSummaryMapper.xml

@@ -2,64 +2,68 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.themis.business.dao.TEOrgSummaryMapper">
 
-    <select id="orgSummaryByFinishCountAndFinishStudentCount" resultType="java.lang.Integer">
-        select count(1) as finishCount
-        from t_oe_exam_record toer
-        where toer.STATUS in ('FINISHED', 'PERSISTED')
-        <if test="examIdSet != null and examIdSet != '' and examIdSet.size > 0">
-            and toer.exam_id in
-            <foreach collection="examIdSet" item="examId" index="index" open="(" close=")" separator=",">
-                #{examId}
-            </foreach>
-        </if>
-        union all
-        select count(distinct tees.id) as finishStudentCount
-        from t_e_exam_student tees
-        left join t_oe_exam_record toer on toer.exam_student_id = tees.id
-        where toer.STATUS in ('FINISHED', 'PERSISTED')
-        <if test="examIdSet != null and examIdSet != '' and examIdSet.size > 0">
-            and toer.exam_id in
-            <foreach collection="examIdSet" item="examId" index="index" open="(" close=")" separator=",">
-                #{examId}
-            </foreach>
-        </if>
+    <select id="orgSummary" resultType="com.qmth.themis.business.bean.admin.OrgSummaryBean">
+        select
+            sum(case when (toer.client_websocket_status = 'ON_LINE'
+            <if test="examIdSet != null and examIdSet != '' and examIdSet.size > 0">
+                and toer.exam_id in
+                <foreach collection="examIdSet" item="examId" index="index" open="(" close=")" separator=",">
+                    #{examId}
+                </foreach>
+            </if>) then 1 else 0 end) as onlineCount,
+            sum(case when (toer.status = 'ANSWERING' and toer.client_websocket_status = 'ON_LINE') or toer.status = 'RESUME_PREPARE' or toer.status = 'BREAK_OFF'
+            <if test="examIdSet != null and examIdSet != '' and examIdSet.size > 0">
+                and toer.exam_id in
+                <foreach collection="examIdSet" item="examId" index="index" open="(" close=")" separator=",">
+                    #{examId}
+                </foreach>
+            </if> then 1 else 0 end) as examCount
+            <if test="all != null and all != '' and all == 1">
+                   ,
+                sum(case when (toer.status in ('FINISHED', 'PERSISTED')
+                <if test="orgId != null and orgId != '' and orgId > 0">
+                    <if test="examIdSet != null and examIdSet != '' and examIdSet.size > 0">
+                        and toer.exam_id in
+                        <foreach collection="examIdSet" item="examId" index="index" open="(" close=")" separator=",">
+                            #{examId}
+                        </foreach>
+                    </if>
+                </if>) then 1 else 0 end) as finishCount
+            </if>
+            from t_oe_exam_record toer
     </select>
 
-    <select id="orgSummaryByFinishCount" resultType="java.lang.Integer">
-        select count(1) as finishCount
-        from t_oe_exam_record toer
+    <select id="orgSummaryByFinishStudentCount" resultType="java.lang.Integer">
+        select count(tees.id) as c
+        from t_e_exam_student tees
+        left join t_oe_exam_record toer on toer.exam_student_id = tees.id and tees.current_record_id = toer.id
         where toer.STATUS in ('FINISHED', 'PERSISTED')
-        <if test="examIdSet != null and examIdSet != '' and examIdSet.size > 0">
-            and toer.exam_id in
-            <foreach collection="examIdSet" item="examId" index="index" open="(" close=")" separator=",">
-                #{examId}
-            </foreach>
+        <if test="orgId != null and orgId != ''">
+            <if test="examIdSet != null and examIdSet != '' and examIdSet.size > 0">
+                and toer.exam_id in
+                <foreach collection="examIdSet" item="examId" index="index" open="(" close=")" separator=",">
+                    #{examId}
+                </foreach>
+            </if>
         </if>
     </select>
 
-    <select id="orgSummaryByOnlineCount" resultType="java.lang.Integer">
-        select count(1) as onlineCount
-        from t_oe_exam_record toer
-        where toer.client_websocket_status = 'ON_LINE'
-        <if test="examIdSet != null and examIdSet != '' and examIdSet.size > 0">
-            and toer.exam_id in
-            <foreach collection="examIdSet" item="examId" index="index" open="(" close=")" separator=",">
-                #{examId}
-            </foreach>
-        </if>
+    <select id="orgSummaryByFinishCount" resultType="java.lang.Integer">
+        <include refid="orgSummaryByFinishCountCommon" />
     </select>
 
-    <select id="orgSummaryByExamCount" resultType="java.lang.Integer">
-        select count(1) as examCount
-        from t_oe_exam_record toer
-        where (toer.STATUS = 'ANSWERING' and toer.client_websocket_status = 'ON_LINE') or toer.status = 'RESUME_PREPARE' or toer.status = 'BREAK_OFF'
-        <if test="examIdSet != null and examIdSet != '' and examIdSet.size > 0">
-            and toer.exam_id in
-            <foreach collection="examIdSet" item="examId" index="index" open="(" close=")" separator=",">
-                #{examId}
-            </foreach>
+    <sql id="orgSummaryByFinishCountCommon">
+        select count(1) as finishCount from t_oe_exam_record toer
+        where toer.STATUS in ('FINISHED', 'PERSISTED')
+        <if test="orgId != null and orgId != '' and orgId > 0">
+            <if test="examIdSet != null and examIdSet != '' and examIdSet.size > 0">
+                and toer.exam_id in
+                <foreach collection="examIdSet" item="examId" index="index" open="(" close=")" separator=",">
+                    #{examId}
+                </foreach>
+            </if>
         </if>
-    </select>
+    </sql>
 
     <insert id="saveOrgSummary">
         INSERT INTO t_e_org_summary
@@ -87,6 +91,6 @@
     </select>
 
     <update id="updateOrgZeroSummary">
-        update t_e_org_summary set finish_count = finish_count + 1,finish_student_count = finish_student_count + #{finishStudentCount} where org_id = 0
+        update t_e_org_summary set finish_count = finish_count + 1,finish_student_count = finish_student_count + #{finishStudentCount} where org_id = #{orgId}
     </update>
 </mapper>

+ 6 - 0
themis-business/src/main/resources/mapper/TERegionSummaryMapper.xml

@@ -9,6 +9,12 @@
         from t_ip_region tir
         join t_oe_exam_record toer on tir.exam_record_id = toer.id
         WHERE toer.client_websocket_status = 'ON_LINE'
+            <if test="examId != null and examId != ''">
+                and toer.exam_id = #{examId}
+            </if>
+            <if test="examActivityId != null and examActivityId != ''">
+                and toer.exam_activity_id = #{examActivityId}
+            </if>
         group by
         tir.country,
         tir.province

+ 3 - 3
themis-business/src/main/resources/mapper/TIeInvigilateWarnInfoMapper.xml

@@ -72,8 +72,8 @@
         tiiwi.remark,
         tiiwi.exam_id as examId,
         tiiwi.exam_record_id as examRecordId
-        from
-        t_ie_invigilate_warn_info tiiwi
+        from t_e_exam_student tees
+        left join t_ie_invigilate_warn_info tiiwi on tees.id = tiiwi.exam_student_id
         <!--2022/09/03新增 start
         join
         (
@@ -87,7 +87,7 @@
         tiiwi.exam_record_id) temp on
         temp.warningId = tiiwi.id
         2022/09/03新增 end-->
-        left join t_e_exam_student tees on tees.id = tiiwi.exam_student_id
+        left join t_oe_exam_record toer on toer.id = tiiwi.exam_record_id
         left join t_b_exam_invigilate_user tbeiu on tbeiu.exam_id = tiiwi.exam_id and tbeiu.room_code = tees.room_code
         join t_e_exam tee on tee.id = tiiwi.exam_id
         <where> 1 = 1

+ 74 - 26
themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml

@@ -4,7 +4,7 @@
         namespace="com.qmth.themis.business.dao.TOeExamRecordMapper">
 
     <sql id="invigilatePageHead">
-        select distinct t.exam_id          examId,
+        select t.exam_id          examId,
                         tee.name  as       examName,
                         t.exam_activity_id examActivityId,
                         teea.code as       examActivityCode,
@@ -30,15 +30,14 @@
 
     <sql id="invigilatePageMiddle">
         from t_oe_exam_record t
-		left join t_e_exam_student s on t.exam_student_id = s.id
+		left join t_e_exam_student s on t.id = s.current_record_id
 		left join t_e_exam tee on tee.id = t.exam_id
 		left join t_e_exam_activity teea on teea.id = t.exam_activity_id
     </sql>
 
     <select id="invigilatePageListVideo" resultType="com.qmth.themis.business.bean.admin.InvigilateListVideoBean">
         select (@i := @i + 1) as seq,t.* from(
-        select
-        distinct s.exam_id as examId,
+        select s.exam_id as examId,
         tee.name as examName,
         s.exam_activity_id as examActivityId,
         teea.code as examActivityCode,
@@ -72,7 +71,7 @@
         <if test="userId != null and userId != ''">
             left join t_b_exam_invigilate_user tbeiu on tbeiu.exam_id = s.exam_id
         </if>
-        left join t_oe_exam_record toer on toer.exam_student_id = s.id
+        left join t_oe_exam_record toer on toer.id = s.current_record_id
         WHERE 1 = 1
         <if test="examId != null and examId != ''">
             and s.exam_id = #{examId}
@@ -141,9 +140,9 @@
         <if test="mobileSecondMonitorStatus != null and mobileSecondMonitorStatus != ''">
             and toer.mobile_second_monitor_status = upper(#{mobileSecondMonitorStatus})
         </if>
+        order by s.identity desc
         ) t,
         (SELECT @i := 0) as i
-        order by t.identity desc
     </select>
 
     <select id="invigilatePageListVideoRandom" resultType="com.qmth.themis.business.bean.admin.InvigilateListVideoBean">
@@ -158,7 +157,7 @@
             <if test="orgId != null and orgId != ''">
                 and tee.org_id = #{orgId}
             </if>
-            and ((toer.status = 'FIRST_PREPARE' and toer.client_websocket_status = 'ON_LINE') or toer.status in ('ANSWERING', 'BREAK_OFF', 'RESUME_PREPARE'))
+            and ((t.status = 'FIRST_PREPARE' and t.client_websocket_status = 'ON_LINE') or t.status in ('ANSWERING', 'BREAK_OFF', 'RESUME_PREPARE'))
         </where>
         ORDER BY RAND() LIMIT #{randomNum}
     </select>
@@ -273,8 +272,7 @@
     </select>
 
     <select id="invigilatePageWarningList" resultType="com.qmth.themis.business.bean.admin.InvigilateListWarningBean">
-        select (@i := @i + 1) as seq,t.* from(select
-        distinct
+        select (@i := @i + 1) as seq,t.* from(select distinct
         tee.id as examId,
         tee.name as examName,
         teea.id as examActivityId,
@@ -294,11 +292,11 @@
         tiiwi.approve_status as approveStatus,
         IFNULL(toer.exception_count,0) as exceptionCount,
         IFNULL(toer.warning_multiple_face_count,0) as multipleFaceCount
-        from t_ie_invigilate_warn_info tiiwi
+        from t_e_exam_student tees
+        left join t_ie_invigilate_warn_info tiiwi on tees.id = tiiwi.exam_student_id
         left join t_e_exam tee on tee.id = tiiwi.exam_id
         left join t_e_exam_activity teea on teea.id = tiiwi.exam_activity_id
         left join t_oe_exam_record toer on toer.id = tiiwi.exam_record_id
-        left join t_e_exam_student tees on tees.id = tiiwi.exam_student_id
         <if test="userId != null and userId != ''">
             left join t_b_exam_invigilate_user tbeiu on tbeiu.exam_id = tees.exam_id
         </if>
@@ -364,11 +362,11 @@
         left join t_oe_exam_record toer on toer.id = tiiwi.exam_record_id
         left join t_e_exam_student tees on tees.id = tiiwi.exam_student_id
         <if test="userId != null and userId != ''">
-            left join t_b_exam_invigilate_user tbeiu on tbeiu.exam_id = tees.exam_id
+            left join t_b_exam_invigilate_user tbeiu on tbeiu.exam_id = tee.id
         </if>
         <where>1 = 1
             <if test="examId != null and examId != ''">
-                and tiiwi.exam_id = #{examId}
+                and tee.id = #{examId}
             </if>
             <if test="userId != null and userId != ''">
                 and tbeiu.user_id = #{userId}
@@ -377,7 +375,7 @@
                 and tee.org_id = #{orgId}
             </if>
             <if test="examActivityId != null and examActivityId != ''">
-                and tiiwi.exam_activity_id = #{examActivityId}
+                and teea.id = #{examActivityId}
             </if>
             <if test="roomCode != null and roomCode != ''">
                 and tees.room_code = #{roomCode}
@@ -397,23 +395,23 @@
             <if test="minWarningCount != null and minWarningCount != '' or minWarningCount == 0">
                 and toer.warning_count &gt;= #{minWarningCount}
             </if>
-        </where>
-        ) t
-        <where>1 = 1
             <if test="minMultipleFaceCount != null and minMultipleFaceCount != '' or minMultipleFaceCount == 0">
-                and t.multipleFaceCount &gt;= #{minMultipleFaceCount}
+                and toer.warning_multiple_face_count &gt;= #{minMultipleFaceCount}
             </if>
             <if test="maxMultipleFaceCount != null and maxMultipleFaceCount != '' or maxMultipleFaceCount == 0">
-                and t.multipleFaceCount &lt;= #{maxMultipleFaceCount}
+                and toer.warning_multiple_face_count &lt;= #{maxMultipleFaceCount}
             </if>
             <if test="minExceptionCount != null and minExceptionCount != '' or minExceptionCount == 0">
-                and t.exceptionCount &gt;= #{minExceptionCount}
+                and toer.exception_count &gt;= #{minExceptionCount}
             </if>
             <if test="maxExceptionCount != null and maxExceptionCount != '' or maxExceptionCount == 0">
-                and t.exceptionCount &lt;= #{maxExceptionCount}
+                and toer.exception_count &lt;= #{maxExceptionCount}
             </if>
         </where>
-        and t.warningId = tiiwi.id)
+        ) t
+        <where> 1 = 1
+            and t.warningId = tiiwi.id
+        </where>)
     </update>
 
     <select id="invigilatePageProgressList" resultType="com.qmth.themis.business.bean.admin.InvigilateListProgressBean">
@@ -496,7 +494,7 @@
 
     <select id="invigilatePageProgressListExport"
             resultType="com.qmth.themis.business.bean.admin.InvigilateListProgressExcelBean">
-        select distinct tee.id as examId,
+        select tee.id as examId,
         tee.name as examName,
         teea.id as examActivityId,
         teea.code as examActivityCode,
@@ -519,7 +517,7 @@
         left join t_e_exam_activity teea on
         teea.id = tees.exam_activity_id
         left join t_e_student tes on tees.student_id = tes.id
-        left join t_oe_exam_record t on t.exam_id = tees.exam_id and t.exam_activity_id = tees.exam_activity_id and
+        left join t_oe_exam_record t on t.exam_student_id = tees.id
         t.exam_student_id = tees.id
         <if test="userId != null and userId != ''">
             left join t_b_exam_invigilate_user tbeiu on tbeiu.exam_id = tees.exam_id
@@ -579,8 +577,7 @@
 
     <sql id="invigilatePageListHistorySql">
         select (@i := @i + 1) as seq,t.* from(
-        select
-        distinct s.exam_id as examId,
+        select s.exam_id as examId,
         tee.name as examName,
         s.exam_activity_id as examActivityId,
         teea.code as examActivityCode,
@@ -1697,4 +1694,55 @@
         </choose>
             where id = #{id}
     </update>
+
+    <select id="findExamRecordByWarning" resultType="com.qmth.themis.business.entity.TOeExamRecord">
+        select toer.* from t_oe_exam_record toer
+             left join t_e_exam tee on tee.id = toer.exam_id
+             left join t_e_exam_activity teea on teea.id = toer.exam_activity_id
+             left join t_e_exam_student tees on tees.id = toer.exam_student_id
+            <if test="userId != null and userId != ''">
+                left join t_b_exam_invigilate_user tbeiu on tbeiu.exam_id = tee.id
+            </if>
+        <where>1 = 1
+            <if test="examId != null and examId != ''">
+                and tee.id = #{examId}
+            </if>
+            <if test="userId != null and userId != ''">
+                and tbeiu.user_id = #{userId}
+            </if>
+            <if test="orgId != null and orgId != ''">
+                and tee.org_id = #{orgId}
+            </if>
+            <if test="examActivityId != null and examActivityId != ''">
+                and teea.id = #{examActivityId}
+            </if>
+            <if test="roomCode != null and roomCode != ''">
+                and tees.room_code = #{roomCode}
+            </if>
+            <if test="name != null and name !=''">
+                and tees.name like CONCAT('%', #{name},'%')
+            </if>
+            <if test="identity != null and identity !=''">
+                and tees.identity like CONCAT('%', #{identity},'%')
+            </if>
+            <if test="maxWarningCount != null and maxWarningCount != '' or maxWarningCount == 0">
+                and toer.warning_count &lt;= #{maxWarningCount}
+            </if>
+            <if test="minWarningCount != null and minWarningCount != '' or minWarningCount == 0">
+                and toer.warning_count &gt;= #{minWarningCount}
+            </if>
+            <if test="minMultipleFaceCount != null and minMultipleFaceCount != '' or minMultipleFaceCount == 0">
+                and toer.warning_multiple_face_count &gt;= #{minMultipleFaceCount}
+            </if>
+            <if test="maxMultipleFaceCount != null and maxMultipleFaceCount != '' or maxMultipleFaceCount == 0">
+                and toer.warning_multiple_face_count &lt;= #{maxMultipleFaceCount}
+            </if>
+            <if test="minExceptionCount != null and minExceptionCount != '' or minExceptionCount == 0">
+                and toer.exception_count &gt;= #{minExceptionCount}
+            </if>
+            <if test="maxExceptionCount != null and maxExceptionCount != '' or maxExceptionCount == 0">
+                and toer.exception_count &lt;= #{maxExceptionCount}
+            </if>
+        </where>
+    </select>
 </mapper>

+ 9 - 0
themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java

@@ -135,6 +135,9 @@ public class MqLogicServiceImpl implements MqLogicService {
     @Resource
     TIeExamMediaLogService tIeExamMediaLogService;
 
+    @Resource
+    ThemisCacheService themisCacheService;
+
     /**
      * mq最大重试次数逻辑
      *
@@ -669,6 +672,7 @@ public class MqLogicServiceImpl implements MqLogicService {
             Long recordId = Long.parseLong(String.valueOf(param.get(SystemConstant.RECORD_ID)));
             Long studentId = Long.parseLong(String.valueOf(param.get(SystemConstant.STUDENT_ID)));
             commonService.persisted(recordId, studentId);
+
             tmRocketMessageService.saveMqMessageSuccess(mqDto, key);
         } catch (Exception e) {
             log.error(SystemConstant.LOG_ERROR, e);
@@ -712,6 +716,11 @@ public class MqLogicServiceImpl implements MqLogicService {
                 examRecordService.examRecordDataSave(recordId);
             }
             tIpRegionService.saveIpRegion(recordId);
+            Long examActivityId = ExamRecordCacheUtil.getExamActivityId(recordId);
+            Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
+            String examRecordChangeKey = examActivityId + "_" + examStudentCacheBean.getRoomCode();
+            themisCacheService.addExamRecordChangeCache(examRecordChangeKey, mqDto.getTimestamp().longValue());
         }
         tmRocketMessageService.saveMqMessageSuccess(mqDto, key);
     }

+ 8 - 9
themis-task/src/main/java/com/qmth/themis/task/listener/service/impl/MqTaskLogicServiceImpl.java

@@ -9,6 +9,7 @@ import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.MqDto;
 import com.qmth.themis.business.entity.TEExam;
 import com.qmth.themis.business.entity.TEExamActivity;
+import com.qmth.themis.business.entity.TOeExamRecord;
 import com.qmth.themis.business.enums.MqTagEnum;
 import com.qmth.themis.business.service.TMRocketMessageService;
 import com.qmth.themis.business.util.JacksonUtil;
@@ -94,17 +95,15 @@ public class MqTaskLogicServiceImpl implements MqTaskLogicService {
             }
         } else if (Objects.equals(tag, MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME.name())) {//考场最后开考时间任务
             JSONObject jsonObject = JSONObject.parseObject(String.valueOf(mqDto.getBody()));
-            TEExamActivity teExamActivity = JSONObject.toJavaObject(jsonObject, TEExamActivity.class);
+            TOeExamRecord tOeExamRecord = JSONObject.toJavaObject(jsonObject, TOeExamRecord.class);
             if (Objects.equals(SystemConstant.DELETE, oper)) {
-                quartzService.deleteJob(teExamActivity.getId() + "-" + teExamActivity.getExamId(), QuartzTaskEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME_JOB_GROUP_NAME.name());
+                quartzService.deleteJob(String.valueOf(tOeExamRecord.getId()), QuartzTaskEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME_JOB_GROUP_NAME.name());
             } else if (Objects.equals(SystemConstant.INSERT, oper)) {
-                quartzService.deleteJob(teExamActivity.getId() + "-" + teExamActivity.getExamId(), QuartzTaskEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME_JOB_GROUP_NAME.name());
-                if (Objects.nonNull(teExamActivity.getEnable()) && teExamActivity.getEnable().intValue() == 1) {
-                    Integer openingSecondsTemp = teExamActivity.getOpeningSeconds();
-                    openingSecondsTemp = Objects.nonNull(openingSecondsTemp) && openingSecondsTemp.intValue() == 0 ? SystemConstant.DEFAULT_OPENING_SECONDS : openingSecondsTemp;
-                    Long finalPrepareTime = teExamActivity.getStartTime() + (openingSecondsTemp * 1000);
-                    this.setCron(finalPrepareTime, teExamActivity.getId() + "-" + teExamActivity.getExamId(), ExamActivityFinalPrepareTimeJob.class, QuartzTaskEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME_JOB_GROUP_NAME);
-                }
+                quartzService.deleteJob(String.valueOf(tOeExamRecord.getId()), QuartzTaskEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME_JOB_GROUP_NAME.name());
+                Integer openingSecondsTemp = tOeExamRecord.getOpeningSeconds();
+                openingSecondsTemp = Objects.nonNull(openingSecondsTemp) && openingSecondsTemp.intValue() == 0 ? SystemConstant.DEFAULT_OPENING_SECONDS : openingSecondsTemp;
+                Long finalPrepareTime = tOeExamRecord.getStartTime() + (openingSecondsTemp * 1000);
+                this.setCron(finalPrepareTime, String.valueOf(tOeExamRecord.getId()), ExamActivityFinalPrepareTimeJob.class, QuartzTaskEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME_JOB_GROUP_NAME);
             }
         }
 //        else if (Objects.equals(tag, MqTagEnum.EXAM_AUDIO.name())) {//考试语音

+ 2 - 0
themis-task/src/main/java/com/qmth/themis/task/quartz/ExamListJob.java

@@ -27,6 +27,8 @@ public class ExamListJob extends QuartzJobBean {
     @Override
     protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
         log.info("ExamListJob,context:{}", context);
+        //每小时统计当前考试列表和机构考试列表
+        themisCacheService.setCurrentExamListCache();
         themisCacheService.setOrgExamListCache();
     }
 }

+ 21 - 19
themis-task/src/main/java/com/qmth/themis/task/quartz/ExamSummaryJob.java

@@ -7,7 +7,6 @@ import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.entity.TBOrg;
 import com.qmth.themis.business.service.*;
-import com.qmth.themis.business.util.RedisUtil;
 import org.quartz.JobExecutionContext;
 import org.quartz.JobExecutionException;
 import org.slf4j.Logger;
@@ -49,13 +48,10 @@ public class ExamSummaryJob extends QuartzJobBean {
     @Resource
     TERegionSummaryService teRegionSummaryService;
 
-    @Resource
-    RedisUtil redisUtil;
-
     @Override
     protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
         log.info("ExamSummaryJob进来了,context:{}", context);
-        Map<String, List<ExamListBean>> examListMap = redisUtil.getHashEntries(SystemConstant.TODAY_EXAM_LIST_MAP_CACHE);
+        Map<String, List<ExamListBean>> examListMap = themisCacheService.getCurrentExamListCache();
         //获取当天考试列表
         if (!CollectionUtils.isEmpty(examListMap)) {
             LinkedMultiValueMap<Long, Long> orgExamIdMap = new LinkedMultiValueMap<>();//机构/考试批次id列表map
@@ -63,14 +59,14 @@ public class ExamSummaryJob extends QuartzJobBean {
                 Long examId = Long.parseLong(entry.getKey());
                 ExamCacheBean examCacheBean = teExamService.getExamCacheBean(examId);
                 //不在考试时间范围内或者禁用,则删除当前考试批次id,更新缓存
-                if (examCacheBean.getEnable().intValue() == 0 || examCacheBean.getEndTime().longValue() <= System.currentTimeMillis()) {
-                    themisCacheService.removeTodayExamListCache(entry.getKey());
+                if (examCacheBean.getEndTime().longValue() <= System.currentTimeMillis()) {
+                    themisCacheService.removeCurrentExamListCache(entry.getKey());
                     continue;
                 }
                 TBOrg tbOrg = themisCacheService.addOrgCache(examCacheBean.getOrgId());
                 orgExamIdMap.add(tbOrg.getId(), examId);
 
-                List<ExamListBean> examListBeanList = themisCacheService.getTodayExamListCache(entry.getKey());
+                List<ExamListBean> examListBeanList = themisCacheService.getCurrentExamListCache(entry.getKey());
                 if (!CollectionUtils.isEmpty(examListBeanList)) {
                     for (ExamListBean e : examListBeanList) {
                         Set<String> roomCodeSet = new HashSet<>(Arrays.asList(e.getRoomCode().split(", ")));
@@ -81,23 +77,29 @@ public class ExamSummaryJob extends QuartzJobBean {
                         long timestamp = System.currentTimeMillis();
                         //当考试场次开始时间和场次结束时间在范围内,则统计
                         log.info("examSummaryJob examId:{},examActivityId:{},startTime:{},endTime:{}", examId, e.getExamActivityId(), DateUtil.format(new Date(startTime), "yyyy-MM-dd HH:mm:ss"), DateUtil.format(new Date(endTime), "yyyy-MM-dd HH:mm:ss"));
-                        if (ac.getEnable().intValue() == 1 && startTime <= timestamp && endTime >= timestamp) {
+                        if (startTime <= timestamp && endTime >= timestamp) {
                             log.info("examSummaryJob examId:{},examActivityId:{},roomCodeSet:{} 开始统计", examId, e.getExamActivityId(), roomCodeSet);
-                            teExamSummaryService.examSummary(examId, e.getExamActivityId(), roomCodeSet);
-                            teRegionSummaryService.regionSummary();
-                        } else if (ac.getEnable().intValue() == 0 || endTime <= timestamp) {//禁用或超过考试结束时间则删除考试场次缓存
-                            themisCacheService.removeTodayExamListCache(entry.getKey(), e.getExamActivityId());
+                            boolean change = teExamSummaryService.examSummary(examId, e.getExamActivityId(), roomCodeSet, false);
+                            if (change) {
+                                teRegionSummaryService.regionSummary(examId, e.getExamActivityId());
+                                //统计机构信息
+                                if (orgExamIdMap.size() > 0) {
+                                    List<Long> examIdAll = new ArrayList<>();
+                                    orgExamIdMap.forEach((k, v) -> {
+                                        teOrgSummaryService.orgSummary(k, v);
+                                        examIdAll.addAll(v);
+                                    });
+                                    teOrgSummaryService.orgSummary(0L, examIdAll);
+                                }
+                            }
+                        } else if (endTime <= timestamp) {//超过考试结束时间则删除考试场次缓存
+                            themisCacheService.removeCurrentExamListCache(entry.getKey(), e.getExamActivityId());
                         }
                     }
                 } else {
-                    themisCacheService.removeTodayExamListCache(entry.getKey());
+                    themisCacheService.removeCurrentExamListCache(entry.getKey());
                 }
             }
-            //统计机构信息
-            orgExamIdMap.forEach((k, v) -> {
-                teOrgSummaryService.orgSummary(k, v);
-            });
-            teOrgSummaryService.orgSummary(0L, null);
         }
     }
 }

+ 23 - 24
themis-task/src/main/java/com/qmth/themis/task/quartz/MqActivityJob.java

@@ -63,30 +63,29 @@ public class MqActivityJob extends QuartzJobBean {
     @Override
     protected void executeInternal(JobExecutionContext context) {
         log.info("mq_activity_job进来了,context:{}", context);
-        themisCacheService.setTodayExamCache();
-        //每天凌晨清理考试缓存数据
-        Map<String, List<ExamListBean>> examListMap = redisUtil.getHashEntries(SystemConstant.TODAY_EXAM_LIST_MAP_CACHE);
-        if (!CollectionUtils.isEmpty(examListMap)) {
-            for (Map.Entry<String, List<ExamListBean>> entry : examListMap.entrySet()) {
-                Long examId = Long.parseLong(entry.getKey());
-                ExamCacheBean examCacheBean = teExamService.getExamCacheBean(examId);
-                if (examCacheBean.getEnable().intValue() == 0 || examCacheBean.getEndTime().longValue() <= System.currentTimeMillis()) {
-                    themisCacheService.removeTodayExamListCache(entry.getKey());
-                    continue;
-                }
-                List<ExamListBean> examListBeanList = themisCacheService.getTodayExamListCache(entry.getKey());
-                if (!CollectionUtils.isEmpty(examListBeanList)) {
-                    for (ExamListBean e : examListBeanList) {
-                        ExamActivityCacheBean examActivityCacheBean = teExamActivityService.getExamActivityCacheBean(e.getExamActivityId());
-                        if (examActivityCacheBean.getEnable().intValue() == 0 || examActivityCacheBean.getFinishTime().longValue() <= System.currentTimeMillis()) {
-                            themisCacheService.removeTodayExamListCache(entry.getKey(), e.getExamActivityId());
-                        }
-                    }
-                } else {
-                    themisCacheService.removeTodayExamListCache(entry.getKey());
-                }
-            }
-        }
+//        //每天凌晨清理考试缓存数据
+//        Map<String, List<ExamListBean>> examListMap = themisCacheService.getCurrentExamListCache();
+//        if (!CollectionUtils.isEmpty(examListMap)) {
+//            for (Map.Entry<String, List<ExamListBean>> entry : examListMap.entrySet()) {
+//                Long examId = Long.parseLong(entry.getKey());
+//                ExamCacheBean examCacheBean = teExamService.getExamCacheBean(examId);
+//                if (examCacheBean.getEnable().intValue() == 0 || examCacheBean.getEndTime().longValue() <= System.currentTimeMillis()) {
+//                    themisCacheService.removeCurrentExamListCache(entry.getKey());
+//                    continue;
+//                }
+//                List<ExamListBean> examListBeanList = themisCacheService.getCurrentExamListCache(entry.getKey());
+//                if (!CollectionUtils.isEmpty(examListBeanList)) {
+//                    for (ExamListBean e : examListBeanList) {
+//                        ExamActivityCacheBean examActivityCacheBean = teExamActivityService.getExamActivityCacheBean(e.getExamActivityId());
+//                        if (examActivityCacheBean.getEnable().intValue() == 0 || examActivityCacheBean.getFinishTime().longValue() <= System.currentTimeMillis()) {
+//                            themisCacheService.removeCurrentExamListCache(entry.getKey(), e.getExamActivityId());
+//                        }
+//                    }
+//                } else {
+//                    themisCacheService.removeCurrentExamListCache(entry.getKey());
+//                }
+//            }
+//        }
         Long finishTime = System.currentTimeMillis();
         QueryWrapper<TEExam> teExamQueryWrapper = new QueryWrapper<>();
         teExamQueryWrapper.lambda().eq(TEExam::getEnable, 1)

+ 9 - 15
themis-task/src/main/java/com/qmth/themis/task/quartz/service/impl/QuartzLogicServiceImpl.java

@@ -217,21 +217,15 @@ public class QuartzLogicServiceImpl implements QuartzLogicService {
     @Override
     public void execExamActivityFinalPrepareTimeJobLogic(String key) {
         String[] strings = key.split("\\.");
-        String[] exams = strings[1].split("-");
-        ExamActivityCacheBean examActivityCacheBean = teExamActivityService.getExamActivityCacheBean(Long.parseLong(exams[0]));
-        ExamCacheBean examCacheBean = teExamService.getExamCacheBean(Long.parseLong(exams[1]));
-        List<TOeExamRecord> tOeExamRecordList = tOeExamRecordService.list(new QueryWrapper<TOeExamRecord>().lambda()
-                .eq(TOeExamRecord::getExamId, examCacheBean.getId())
-                .eq(TOeExamRecord::getExamActivityId, examActivityCacheBean.getId())
-                .eq(TOeExamRecord::getStatus, ExamRecordStatusEnum.FIRST_PREPARE)
-                .eq(TOeExamRecord::getClientWebsocketStatus, WebsocketStatusEnum.ON_LINE));
-        if (!CollectionUtils.isEmpty(tOeExamRecordList)) {
-            for (TOeExamRecord t : tOeExamRecordList) {
-                Map<String, Object> properties = new HashMap<>();
-                properties.put(SystemConstant.RECORD_ID, t.getId());
-                MqDto clientMqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.EXAM_EXIT.name(), t.getId(), MqTagEnum.EXAM_EXIT, String.valueOf(t.getId()), properties, String.valueOf(t.getId()));
-                mqDtoService.assembleSendAsyncOrderMsg(clientMqDto);
-            }
+        String[] examRecordIds = strings[1].split("-");
+        TOeExamRecord tOeExamRecord = tOeExamRecordService.getById(Long.parseLong(examRecordIds[0]));
+        if (Objects.nonNull(tOeExamRecord)
+                && tOeExamRecord.getStatus() == ExamRecordStatusEnum.FIRST_PREPARE
+                && tOeExamRecord.getClientWebsocketStatus() == WebsocketStatusEnum.ON_LINE) {
+            Map<String, Object> properties = new HashMap<>();
+            properties.put(SystemConstant.RECORD_ID, tOeExamRecord.getId());
+            MqDto clientMqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.EXAM_EXIT.name(), tOeExamRecord.getId(), MqTagEnum.EXAM_EXIT, String.valueOf(tOeExamRecord.getId()), properties, String.valueOf(tOeExamRecord.getId()));
+            mqDtoService.assembleSendAsyncOrderMsg(clientMqDto);
         }
     }
 

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

@@ -58,7 +58,7 @@ public class StartRunning implements CommandLineRunner {
     public void run(String... args) throws Exception {
         log.info("服务器启动时执行 start");
         log.info("增加mqjob start");
-        themisCacheService.setTodayExamCache();
+        themisCacheService.setCurrentExamListCache();
         themisCacheService.setOrgExamListCache();
 
         Map mqMap = new HashMap();