瀏覽代碼

巡考监考优化

wangliang 3 年之前
父節點
當前提交
6442cf8ed3
共有 15 個文件被更改,包括 538 次插入295 次删除
  1. 37 88
      themis-admin/src/main/java/com/qmth/themis/admin/api/TEExamController.java
  2. 3 0
      themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateController.java
  3. 3 0
      themis-admin/src/main/java/com/qmth/themis/admin/api/TIeReportController.java
  4. 81 0
      themis-business/src/main/java/com/qmth/themis/business/bean/admin/CountStopBean.java
  5. 3 3
      themis-business/src/main/java/com/qmth/themis/business/bean/admin/ExaminationMonitorCountBean.java
  6. 5 10
      themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java
  7. 27 0
      themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamRecordMapper.java
  8. 8 8
      themis-business/src/main/java/com/qmth/themis/business/dto/ExamPropCountDto.java
  9. 27 0
      themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java
  10. 6 6
      themis-business/src/main/java/com/qmth/themis/business/service/impl/CommonServiceImpl.java
  11. 3 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java
  12. 28 83
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TIeReportServiceImpl.java
  13. 35 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java
  14. 29 20
      themis-business/src/main/java/com/qmth/themis/business/threadPool/MyThreadPool.java
  15. 243 77
      themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml

+ 37 - 88
themis-admin/src/main/java/com/qmth/themis/admin/api/TEExamController.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qmth.themis.business.annotation.ApiJsonObject;
 import com.qmth.themis.business.annotation.ApiJsonObject;
 import com.qmth.themis.business.annotation.ApiJsonProperty;
 import com.qmth.themis.business.annotation.ApiJsonProperty;
+import com.qmth.themis.business.bean.admin.CountStopBean;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.AuthDto;
 import com.qmth.themis.business.dto.AuthDto;
@@ -81,6 +82,9 @@ public class TEExamController {
     @Resource
     @Resource
     CacheService cacheService;
     CacheService cacheService;
 
 
+//    @Resource
+//    MyThreadPool myThreadPool;
+
     @ApiOperation(value = "考试批次修改/新增接口")
     @ApiOperation(value = "考试批次修改/新增接口")
     @RequestMapping(value = "/save", method = RequestMethod.POST)
     @RequestMapping(value = "/save", method = RequestMethod.POST)
     @Transactional
     @Transactional
@@ -417,6 +421,7 @@ public class TEExamController {
     @RequestMapping(value = "/prop/count", method = RequestMethod.POST)
     @RequestMapping(value = "/prop/count", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "考试属性信息", response = ExamPropCountDto.class)})
     @ApiResponses({@ApiResponse(code = 200, message = "考试属性信息", response = ExamPropCountDto.class)})
     public Result propCount(@ApiParam(value = "考试id", required = true) @RequestParam Long examId) {
     public Result propCount(@ApiParam(value = "考试id", required = true) @RequestParam Long examId) {
+        long start = System.currentTimeMillis();
         if (Objects.isNull(examId) || Objects.equals(examId, "")) {
         if (Objects.isNull(examId) || Objects.equals(examId, "")) {
             throw new BusinessException(ExceptionResultEnum.EXAM_ID_IS_NULL);
             throw new BusinessException(ExceptionResultEnum.EXAM_ID_IS_NULL);
         }
         }
@@ -444,104 +449,48 @@ public class TEExamController {
                 || roomCodeSet.size() == 0)) {
                 || roomCodeSet.size() == 0)) {
             throw new BusinessException("当前监考老师未设置任何监考考场");
             throw new BusinessException("当前监考老师未设置任何监考考场");
         }
         }
-        ExamPropCountDto examPropCountDto = null;
+        AtomicReference<ExamPropCountDto> examPropCountDto = new AtomicReference(new ExamPropCountDto(examId, 0, 0, 0, 0, 0, 0, 0, new BigDecimal(0)));
+        examPropCountDto.get().setExamId(examId);
         if (Objects.nonNull(roomCodeSet) && roomCodeSet.size() > 0) {
         if (Objects.nonNull(roomCodeSet) && roomCodeSet.size() > 0) {
             //根据roomCode获取当前老师所要监考的全部应考学生数
             //根据roomCode获取当前老师所要监考的全部应考学生数
             QueryWrapper<TEExamStudent> teExamStudentQueryWrapper = new QueryWrapper<>();
             QueryWrapper<TEExamStudent> teExamStudentQueryWrapper = new QueryWrapper<>();
             teExamStudentQueryWrapper.lambda().eq(TEExamStudent::getExamId, examId)
             teExamStudentQueryWrapper.lambda().eq(TEExamStudent::getExamId, examId)
                     .in(TEExamStudent::getRoomCode, roomCodeSet);
                     .in(TEExamStudent::getRoomCode, roomCodeSet);
-            List<TEExamStudent> teExamStudentList = teExamStudentService.list(teExamStudentQueryWrapper);
-            Set<String> studentSet = null;
-            Set<Long> examActivityIdSet = null;
-            Integer allCount = 0;
-            AtomicReference<Integer> prepareCount = new AtomicReference<>(0);
-            AtomicReference<Integer> examCount = new AtomicReference<>(0);
-            AtomicReference<Integer> clientWebsocketStatusCount = new AtomicReference<>(0);
-            AtomicReference<Integer> monitorStatusSourceCount = new AtomicReference<>(0);
-            Integer notComplete = 0;
+            List<TEExamStudent> teExamStudentList = new ArrayList<>(50000);
+            teExamStudentList = teExamStudentService.list(teExamStudentQueryWrapper);
             if (Objects.nonNull(teExamStudentList) && teExamStudentList.size() > 0) {
             if (Objects.nonNull(teExamStudentList) && teExamStudentList.size() > 0) {
-                studentSet = new HashSet<>();
-                examActivityIdSet = new HashSet<>();
-                Set<Long> finalExamActivityIdSet = examActivityIdSet;
-                Set<String> finalStudentSet = studentSet;
-                teExamStudentList.forEach(s -> {
-                    finalStudentSet.add(SystemConstant.STUDENT + s.getStudentId());
-                    finalExamActivityIdSet.add(s.getExamActivityId());
-                });
-                allCount = studentSet.size();
+                examPropCountDto.get().setAllCount(teExamStudentList.size());
             }
             }
 
 
-            Set<Long> alreadyComplete = null;
-            if (Objects.nonNull(examActivityIdSet)) {
-                alreadyComplete = new HashSet<>();
-                //获取已待考、考试中、已完成学生
-                Set<Long> finalAlreadyComplete = alreadyComplete;
-                QueryWrapper<TOeExamRecord> tOeExamRecordQueryWrapper = new QueryWrapper<>();
-                tOeExamRecordQueryWrapper.lambda().in(TOeExamRecord::getExamActivityId, examActivityIdSet);
-                List<TOeExamRecord> examRecordList = tOeExamRecordService.list(tOeExamRecordQueryWrapper);
-                examRecordList.forEach(s -> {
-//                    Map<String, Object> objectMap = redisUtil
-//                            .getHashEntries(RedisKeyHelper.examActivityRecordCacheKey(s));
-//                    if (Objects.nonNull(objectMap) && objectMap.size() > 0) {
-//                        objectMap.forEach((k, v) -> {
-//                            Long recordId = Long.parseLong(k);
-//                            ExamActivityRecordCacheBean examActivityRecordCacheBean = (ExamActivityRecordCacheBean) v;
-                    ExamRecordStatusEnum examRecordStatusEnum = s.getStatus();
-//                            ExamStudentCacheBean examStudentCacheBean = teExamStudentService
-//                                    .getExamStudentCacheBean(examActivityRecordCacheBean.getExamStudentId());
-//                            if (Objects.nonNull(examStudentCacheBean)
-//                                    && examStudentCacheBean.getEnable().intValue() == 1) {
-                    //客户端通讯状态
-                    WebsocketStatusEnum clientStatus = Objects.isNull(s.getClientWebsocketStatus()) ? null : s.getClientWebsocketStatus();
-                    if (Objects
-                            .nonNull(examRecordStatusEnum) && !Objects
-                            .equals(examRecordStatusEnum, ExamRecordStatusEnum.PERSISTED) && !Objects
-                            .equals(examRecordStatusEnum, ExamRecordStatusEnum.FINISHED)) {
-                        if (Objects.nonNull(clientStatus) && Objects
-                                .equals(clientStatus, WebsocketStatusEnum.OFF_LINE)) {
-                            clientWebsocketStatusCount.getAndSet(clientWebsocketStatusCount.get() + 1);
-                        }
-                        //监控端通讯状态
-                        if (Objects.nonNull(s.getCameraMonitorStatus()) && Objects.equals(s.getCameraMonitorStatus(), MonitorStatusSourceEnum.STOP)) {
-                            monitorStatusSourceCount.getAndSet(monitorStatusSourceCount.get() + 1);
-                        } else if (Objects.nonNull(s.getScreenMonitorStatus()) && Objects.equals(s.getScreenMonitorStatus(), MonitorStatusSourceEnum.STOP)) {
-                            monitorStatusSourceCount.getAndSet(monitorStatusSourceCount.get() + 1);
-                        } else if (Objects.nonNull(s.getMobileFirstMonitorStatus()) && Objects.equals(s.getMobileFirstMonitorStatus(), MonitorStatusSourceEnum.STOP)) {
-                            monitorStatusSourceCount.getAndSet(monitorStatusSourceCount.get() + 1);
-                        } else if (Objects.nonNull(s.getMobileSecondMonitorStatus()) && Objects.equals(s.getMobileSecondMonitorStatus(), MonitorStatusSourceEnum.STOP)) {
-                            monitorStatusSourceCount.getAndSet(monitorStatusSourceCount.get() + 1);
-                        }
-                    }
-                    //已待考
-                    if (Objects.equals(examRecordStatusEnum, ExamRecordStatusEnum.FIRST_PREPARE) && Objects.nonNull(clientStatus) && Objects
-                            .equals(clientStatus, WebsocketStatusEnum.ON_LINE)) {
-                        prepareCount.getAndSet(prepareCount.get() + 1);
-                    }
-                    //考试中
-                    else if (Objects.equals(examRecordStatusEnum, ExamRecordStatusEnum.ANSWERING) && Objects.nonNull(clientStatus) && Objects
-                            .equals(clientStatus, WebsocketStatusEnum.ON_LINE)) {
-                        examCount.getAndSet(examCount.get() + 1);
-                    }
-                    //已完成
-                    else if (Objects.equals(examRecordStatusEnum, ExamRecordStatusEnum.FINISHED) || Objects
-                            .equals(examRecordStatusEnum, ExamRecordStatusEnum.PERSISTED)) {
-                        finalAlreadyComplete.add(s.getExamStudentId());
-                    }
-//                            }
-//                        });
-//                    }
-                });
+            List<CountStopBean> countStopBeanList = tOeExamRecordService.findByStopInfo(examId, roomCodeSet);
+            if (Objects.nonNull(countStopBeanList) && countStopBeanList.size() > 0) {
+                AtomicReference<Integer> clientWebsocketStatusCount = new AtomicReference<>(0);
+                AtomicReference<Integer> monitorStatusSourceCount = new AtomicReference<>(0);
+                for (CountStopBean c : countStopBeanList) {
+                    clientWebsocketStatusCount.getAndSet(clientWebsocketStatusCount.get() + c.getClientWebsocketStatusOffCount());
+                    monitorStatusSourceCount.getAndSet(monitorStatusSourceCount.get() + c.getCameraMonitorStatusStop());
+                    monitorStatusSourceCount.getAndSet(monitorStatusSourceCount.get() + c.getScreenMonitorStatusStop());
+                    monitorStatusSourceCount.getAndSet(monitorStatusSourceCount.get() + c.getMobileFirstMonitorStatusStop());
+                    monitorStatusSourceCount.getAndSet(monitorStatusSourceCount.get() + c.getMobileSecondMonitorStatusStop());
+                }
+                examPropCountDto.get().setClientWebsocketStatusCount(clientWebsocketStatusCount.get());
+                examPropCountDto.get().setMonitorStatusSourceCount(monitorStatusSourceCount.get());
+            }
+            List<Integer> list = tOeExamRecordService.findByOnlineInfo(examId, roomCodeSet);
+            if (Objects.nonNull(list) && list.size() > 0) {
+                examPropCountDto.get().setPrepareCount(list.get(0));
+                examPropCountDto.get().setExamCount(list.get(1));
+                examPropCountDto.get().setAlreadyComplete(list.get(2));
             }
             }
-            notComplete = allCount - alreadyComplete.size();
-            BigDecimal completionRate = new BigDecimal(alreadyComplete.size())
-                    .divide(new BigDecimal(allCount), 2, BigDecimal.ROUND_HALF_UP)
-                    .setScale(2, BigDecimal.ROUND_HALF_UP);
-            examPropCountDto = new ExamPropCountDto(examId, allCount, prepareCount.get(), examCount.get(),
-                    clientWebsocketStatusCount.get(), monitorStatusSourceCount.get(), alreadyComplete.size(),
-                    notComplete, completionRate);
-        } else {
-            examPropCountDto = new ExamPropCountDto(examId, 0, 0, 0, 0, 0, 0, 0, new BigDecimal(0));
         }
         }
+        Integer notComplete = examPropCountDto.get().getAllCount() - examPropCountDto.get().getAlreadyComplete();
+        BigDecimal completionRate = new BigDecimal(examPropCountDto.get().getAlreadyComplete())
+                .divide(new BigDecimal(examPropCountDto.get().getAllCount()), 2, BigDecimal.ROUND_HALF_UP)
+                .setScale(2, BigDecimal.ROUND_HALF_UP);
+        examPropCountDto.get().setNotComplete(notComplete);
+        examPropCountDto.get().setCompletionRate(completionRate);
+        long end = System.currentTimeMillis();
+        log.info("============prop/count耗时============:{}秒", (end - start) / 1000);
         return ResultUtil.ok(examPropCountDto);
         return ResultUtil.ok(examPropCountDto);
     }
     }
 
 

+ 3 - 0
themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateController.java

@@ -186,6 +186,7 @@ public class TIeInvigilateController {
     @RequestMapping(value = "/list/video/random", method = RequestMethod.POST)
     @RequestMapping(value = "/list/video/random", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "监考监控信息", response = InvigilateListVideoBean.class)})
     @ApiResponses({@ApiResponse(code = 200, message = "监考监控信息", response = InvigilateListVideoBean.class)})
     public Result listVideoRandom(@ApiParam(value = "考试批次id", required = false) @RequestParam(required = false) Long examId, @ApiParam(value = "随机数", required = true) @RequestParam Integer randomNum) {
     public Result listVideoRandom(@ApiParam(value = "考试批次id", required = false) @RequestParam(required = false) Long examId, @ApiParam(value = "随机数", required = true) @RequestParam Integer randomNum) {
+        long startTime = System.currentTimeMillis();
         if (Objects.isNull(randomNum) || Objects.equals(randomNum, "")) {
         if (Objects.isNull(randomNum) || Objects.equals(randomNum, "")) {
             throw new BusinessException("随机数不能为空");
             throw new BusinessException("随机数不能为空");
         }
         }
@@ -221,6 +222,8 @@ public class TIeInvigilateController {
                 }
                 }
             });
             });
         }
         }
+        long end = System.currentTimeMillis();
+        log.info("============list/video/random耗时============:{}秒", (end - startTime) / 1000);
         return ResultUtil.ok(invigilateListVideoBeanList);
         return ResultUtil.ok(invigilateListVideoBeanList);
     }
     }
 
 

+ 3 - 0
themis-admin/src/main/java/com/qmth/themis/admin/api/TIeReportController.java

@@ -1,5 +1,6 @@
 package com.qmth.themis.admin.api;
 package com.qmth.themis.admin.api;
 
 
+import com.qmth.themis.business.bean.admin.ExaminationMonitorWarnMsgBean;
 import com.qmth.themis.business.bean.admin.InvigilateListPatrolReportBean;
 import com.qmth.themis.business.bean.admin.InvigilateListPatrolReportBean;
 import com.qmth.themis.business.entity.TBUser;
 import com.qmth.themis.business.entity.TBUser;
 import com.qmth.themis.business.service.TIeReportService;
 import com.qmth.themis.business.service.TIeReportService;
@@ -15,6 +16,8 @@ import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
 
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 import java.util.Objects;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;

+ 81 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/admin/CountStopBean.java

@@ -0,0 +1,81 @@
+package com.qmth.themis.business.bean.admin;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: websocket count
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/4/20
+ */
+public class CountStopBean implements Serializable {
+
+    @ApiModelProperty(name = "客户端websocket不在线")
+    private Integer clientWebsocketStatusOffCount;
+
+    @ApiModelProperty(name = "客户端websocket在线")
+    private Integer clientWebsocketStatusOnCount;
+
+    @ApiModelProperty(name = "客户端摄像头状态")
+    private Integer cameraMonitorStatusStop;
+
+    @ApiModelProperty(name = "客户端屏幕状态")
+    private Integer screenMonitorStatusStop;
+
+    @ApiModelProperty(name = "移动端第一机位状态")
+    private Integer mobileFirstMonitorStatusStop;
+
+    @ApiModelProperty(name = "移动端第二机位状态")
+    private Integer mobileSecondMonitorStatusStop;
+
+    public Integer getClientWebsocketStatusOffCount() {
+        return clientWebsocketStatusOffCount;
+    }
+
+    public void setClientWebsocketStatusOffCount(Integer clientWebsocketStatusOffCount) {
+        this.clientWebsocketStatusOffCount = clientWebsocketStatusOffCount;
+    }
+
+    public Integer getClientWebsocketStatusOnCount() {
+        return clientWebsocketStatusOnCount;
+    }
+
+    public void setClientWebsocketStatusOnCount(Integer clientWebsocketStatusOnCount) {
+        this.clientWebsocketStatusOnCount = clientWebsocketStatusOnCount;
+    }
+
+    public Integer getCameraMonitorStatusStop() {
+        return cameraMonitorStatusStop;
+    }
+
+    public void setCameraMonitorStatusStop(Integer cameraMonitorStatusStop) {
+        this.cameraMonitorStatusStop = cameraMonitorStatusStop;
+    }
+
+    public Integer getScreenMonitorStatusStop() {
+        return screenMonitorStatusStop;
+    }
+
+    public void setScreenMonitorStatusStop(Integer screenMonitorStatusStop) {
+        this.screenMonitorStatusStop = screenMonitorStatusStop;
+    }
+
+    public Integer getMobileFirstMonitorStatusStop() {
+        return mobileFirstMonitorStatusStop;
+    }
+
+    public void setMobileFirstMonitorStatusStop(Integer mobileFirstMonitorStatusStop) {
+        this.mobileFirstMonitorStatusStop = mobileFirstMonitorStatusStop;
+    }
+
+    public Integer getMobileSecondMonitorStatusStop() {
+        return mobileSecondMonitorStatusStop;
+    }
+
+    public void setMobileSecondMonitorStatusStop(Integer mobileSecondMonitorStatusStop) {
+        this.mobileSecondMonitorStatusStop = mobileSecondMonitorStatusStop;
+    }
+}

+ 3 - 3
themis-business/src/main/java/com/qmth/themis/business/bean/admin/ExaminationMonitorCountBean.java

@@ -7,11 +7,11 @@ import io.swagger.annotations.ApiModelProperty;
 
 
 public class ExaminationMonitorCountBean {
 public class ExaminationMonitorCountBean {
 	@ApiModelProperty(name = "在线人数")
 	@ApiModelProperty(name = "在线人数")
-	private Long onlineCount;
+	private Long onlineCount = 0L;
 	@ApiModelProperty(name = "待考人数")
 	@ApiModelProperty(name = "待考人数")
-	private Long waitingCount;
+	private Long waitingCount = 0L;
 	@ApiModelProperty(name = "考试中人数")
 	@ApiModelProperty(name = "考试中人数")
-	private Long examingCount;
+	private Long examingCount = 0L;
 	@ApiModelProperty(name = "通讯故障人数")
 	@ApiModelProperty(name = "通讯故障人数")
 	private Long exceptionCount;
 	private Long exceptionCount;
 	@ApiModelProperty(name = "预警人数")
 	@ApiModelProperty(name = "预警人数")

+ 5 - 10
themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java

@@ -347,16 +347,11 @@ public class SystemConstant {
     /**
     /**
      * 线程池配置
      * 线程池配置
      */
      */
-    //    public static final String THREAD_POOL_NAME = "arbitrateThreadPool";
-    //
-    //    public static final int THREAD_POOL_CORE_POOL_SIZE = 20;
-    //
-    //    public static final int THREAD_POOL_MAX_POOL_SIZE = 40;
-    //
-    //    public static final int THREAD_POOL_KEEP_ALIVE_SECONDS = 60;
-    //
-    //    public static final int THREAD_POOL_QUEUE_CAPACITY = 100;
-
+    public static final String THREAD_POOL_NAME = "taskThreadPool";
+    //    public static final int THREAD_POOL_CORE_POOL_SIZE = 5;
+//    public static final int THREAD_POOL_MAX_POOL_SIZE = 100;
+    public static final int THREAD_POOL_KEEP_ALIVE_SECONDS = 10;
+    public static final int THREAD_POOL_QUEUE_CAPACITY = 500;
     /**
     /**
      * websocket
      * websocket
      */
      */

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

@@ -10,6 +10,7 @@ import org.apache.ibatis.annotations.Param;
 
 
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.util.Set;
 
 
 /**
 /**
  * @Description: 考试记录 Mapper 接口
  * @Description: 考试记录 Mapper 接口
@@ -366,4 +367,30 @@ public interface TOeExamRecordMapper extends BaseMapper<TOeExamRecord> {
      * @return
      * @return
      */
      */
     public List<TOeExamRecord> findMaxObjectiveScore(@Param("examId") Long examId, @Param("examStudentId") Long examStudentId);
     public List<TOeExamRecord> findMaxObjectiveScore(@Param("examId") Long examId, @Param("examStudentId") Long examStudentId);
+
+    /**
+     * 根据orgId查找 在线人数/已待考/考试人数
+     *
+     * @param orgId
+     * @return
+     */
+    List<Long> findByOrgId(@Param("orgId") Long orgId);
+
+    /**
+     * 查找监控消息
+     *
+     * @param examId
+     * @param roomCodeSet
+     * @return
+     */
+    List<CountStopBean> findByStopInfo(@Param("examId") Long examId, @Param("roomCodeSet") Set<String> roomCodeSet);
+
+    /**
+     * 查找在线消息
+     *
+     * @param examId
+     * @param roomCodeSet
+     * @return
+     */
+    List<Integer> findByOnlineInfo(@Param("examId") Long examId, @Param("roomCodeSet") Set<String> roomCodeSet);
 }
 }

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

@@ -24,31 +24,31 @@ public class ExamPropCountDto implements Serializable {
     private Long examId;//考试批次id
     private Long examId;//考试批次id
 
 
     @ApiModelProperty(name = "应考人数")
     @ApiModelProperty(name = "应考人数")
-    private Integer allCount;//应考人数
+    private Integer allCount = 0;//应考人数
 
 
     @ApiModelProperty(name = "已待考")
     @ApiModelProperty(name = "已待考")
-    private Integer prepareCount;//已待考
+    private Integer prepareCount = 0;//已待考
 
 
     @ApiModelProperty(name = "考试中")
     @ApiModelProperty(name = "考试中")
-    private Integer examCount;//考试中
+    private Integer examCount = 0;//考试中
 
 
     @ApiModelProperty(name = "客户端通讯故障")
     @ApiModelProperty(name = "客户端通讯故障")
-    private Integer clientWebsocketStatusCount;//客户端通讯故障
+    private Integer clientWebsocketStatusCount = 0;//客户端通讯故障
 
 
     @ApiModelProperty(name = "监控设备通讯故障")
     @ApiModelProperty(name = "监控设备通讯故障")
-    private Integer monitorStatusSourceCount;//监控设备通讯故障
+    private Integer monitorStatusSourceCount = 0;//监控设备通讯故障
 
 
     @ApiModelProperty(name = "已完成")
     @ApiModelProperty(name = "已完成")
-    private Integer alreadyComplete;//已完成
+    private Integer alreadyComplete = 0;//已完成
 
 
     @ApiModelProperty(name = "未完成")
     @ApiModelProperty(name = "未完成")
-    private Integer notComplete;//未完成
+    private Integer notComplete = 0;//未完成
 
 
     @ApiModelProperty(name = "虚拟考场代码")
     @ApiModelProperty(name = "虚拟考场代码")
     private Set<String> roomCodes;//虚拟考场代码
     private Set<String> roomCodes;//虚拟考场代码
 
 
     @ApiModelProperty(name = "完成率")
     @ApiModelProperty(name = "完成率")
-    private BigDecimal completionRate;//完成率
+    private BigDecimal completionRate = new BigDecimal(0);//完成率
 
 
     @ApiModelProperty(name = "重考审核")
     @ApiModelProperty(name = "重考审核")
     private Integer reexamCount;//重考审核
     private Integer reexamCount;//重考审核

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

@@ -9,6 +9,7 @@ import com.qmth.themis.business.enums.*;
 
 
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.util.Set;
 
 
 /**
 /**
  * @Description: 考试记录 服务类
  * @Description: 考试记录 服务类
@@ -401,4 +402,30 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
      * @return
      * @return
      */
      */
     Boolean examBreakLogic(Long recordId, boolean setBreak);
     Boolean examBreakLogic(Long recordId, boolean setBreak);
+
+    /**
+     * 根据orgId查找 在线人数/已待考/考试人数
+     *
+     * @param orgId
+     * @return
+     */
+    List<Long> findByOrgId(Long orgId);
+
+    /**
+     * 查找监控消息
+     *
+     * @param examId
+     * @param roomCodeSet
+     * @return
+     */
+    List<CountStopBean> findByStopInfo(Long examId, Set<String> roomCodeSet);
+
+    /**
+     * 查找在线消息
+     *
+     * @param examId
+     * @param roomCodeSet
+     * @return
+     */
+    List<Integer> findByOnlineInfo(Long examId, Set<String> roomCodeSet);
 }
 }

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

@@ -91,12 +91,12 @@ public class CommonServiceImpl implements CommonService {
             redisUtil.delete(RedisKeyHelper.faceVerifyCacheKey(recordId));
             redisUtil.delete(RedisKeyHelper.faceVerifyCacheKey(recordId));
             //2021-03-01新增
             //2021-03-01新增
             redisUtil.delete(RedisKeyHelper.studentPaperStructKey(recordId));
             redisUtil.delete(RedisKeyHelper.studentPaperStructKey(recordId));
-            TEStudentCacheDto teStudentCacheDto = ExamingDataCacheUtil.getStudentExaming(studentId);
-            //2022-04-15新增
-            if (Objects.nonNull(teStudentCacheDto)) {
-                teStudentCacheDto.setExamingRecordId(null);
-                ExamingDataCacheUtil.setStudentExaming(studentId, teStudentCacheDto);
-            }
+//            TEStudentCacheDto teStudentCacheDto = ExamingDataCacheUtil.getStudentExaming(studentId);
+//            //2022-04-15新增
+//            if (Objects.nonNull(teStudentCacheDto)) {
+//                teStudentCacheDto.setExamingRecordId(null);
+//                ExamingDataCacheUtil.setStudentExaming(studentId, teStudentCacheDto);
+//            }
 
 
 //            redisUtil.delete(RedisKeyHelper.examStudentCacheKey(examStudentId));
 //            redisUtil.delete(RedisKeyHelper.examStudentCacheKey(examStudentId));
             //先查询之前的断点记录
             //先查询之前的断点记录

+ 3 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -1195,6 +1195,9 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         //判断当前结束的考试记录ID是否是未完成的考试记录ID
         //判断当前结束的考试记录ID是否是未完成的考试记录ID
         if (recordId.equals(ExamingDataCacheUtil.getUnFinishedRecordId(studentId))) {
         if (recordId.equals(ExamingDataCacheUtil.getUnFinishedRecordId(studentId))) {
             ExamingDataCacheUtil.deleteUnFinishedRecordId(studentId);
             ExamingDataCacheUtil.deleteUnFinishedRecordId(studentId);
+            //2022-04-15新增
+            teStudentCacheDto.setExamingRecordId(null);
+            ExamingDataCacheUtil.setStudentExaming(studentId, teStudentCacheDto);
         }
         }
 
 
         Map<String, Object> properties = new HashMap<>();
         Map<String, Object> properties = new HashMap<>();

+ 28 - 83
themis-business/src/main/java/com/qmth/themis/business/service/impl/TIeReportServiceImpl.java

@@ -1,34 +1,35 @@
 package com.qmth.themis.business.service.impl;
 package com.qmth.themis.business.service.impl;
 
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.OrderItem;
 import com.baomidou.mybatisplus.core.metadata.OrderItem;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qmth.themis.business.bean.admin.*;
 import com.qmth.themis.business.bean.admin.*;
 import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
 import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
-import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dao.*;
 import com.qmth.themis.business.dao.*;
 import com.qmth.themis.business.entity.TBUser;
 import com.qmth.themis.business.entity.TBUser;
-import com.qmth.themis.business.entity.TEExam;
 import com.qmth.themis.business.entity.TEExamActivity;
 import com.qmth.themis.business.entity.TEExamActivity;
-import com.qmth.themis.business.entity.TOeExamRecord;
-import com.qmth.themis.business.enums.*;
+import com.qmth.themis.business.enums.BreachCancelTypeEnum;
+import com.qmth.themis.business.enums.BreachTypeEnum;
+import com.qmth.themis.business.enums.ExceptionEnum;
+import com.qmth.themis.business.enums.InvigilateMonitorStatusEnum;
 import com.qmth.themis.business.service.*;
 import com.qmth.themis.business.service.*;
 import com.qmth.themis.business.util.ServletUtil;
 import com.qmth.themis.business.util.ServletUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.time.DateUtils;
 import org.apache.commons.lang3.time.DateUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.*;
-import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 @Service
 @Service
 public class TIeReportServiceImpl implements TIeReportService {
 public class TIeReportServiceImpl implements TIeReportService {
+    private final static Logger log = LoggerFactory.getLogger(TIeReportServiceImpl.class);
 
 
     @Resource
     @Resource
     TEExamStudentMapper examStudentMapper;
     TEExamStudentMapper examStudentMapper;
@@ -399,95 +400,30 @@ public class TIeReportServiceImpl implements TIeReportService {
      */
      */
     @Override
     @Override
     public ExaminationMonitorCountBean examinationMonitorCount() {
     public ExaminationMonitorCountBean examinationMonitorCount() {
+//        long start = System.currentTimeMillis();
         TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
         TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
         Long orgId = tbUser.getOrgId();
         Long orgId = tbUser.getOrgId();
         ExaminationMonitorCountBean ret = new ExaminationMonitorCountBean();
         ExaminationMonitorCountBean ret = new ExaminationMonitorCountBean();
-        //在线人数
-        QueryWrapper<TEExam> teExamQueryWrapper = new QueryWrapper<>();
-        teExamQueryWrapper.lambda().eq(TEExam::getOrgId, orgId);
-        List<TEExam> teExamList = examService.list(teExamQueryWrapper);
-        List<TEExamActivity> teExamActivityList = null;
-        if (Objects.isNull(teExamList) || teExamList.size() == 0) {
+        if (Objects.isNull(orgId)) {
             return ret;
             return ret;
-        } else {
-            Set<Long> examIdSet = teExamList.stream().map(TEExam::getId).collect(Collectors.toSet());
-            QueryWrapper<TEExamActivity> teExamActivityQueryWrapper = new QueryWrapper<>();
-            teExamActivityQueryWrapper.lambda().in(TEExamActivity::getExamId, examIdSet);
-            teExamActivityList = examActivityService.list(teExamActivityQueryWrapper);
         }
         }
-        if (Objects.isNull(teExamActivityList)) {
-            return ret;
+        List<Long> countList = tOeExamRecordService.findByOrgId(orgId);
+        if (Objects.nonNull(countList) && countList.size() > 0) {
+            // 在线人数
+            ret.setOnlineCount(countList.get(0));
+            // 待考人数
+            ret.setWaitingCount(countList.get(1));
+            // 考试人数
+            ret.setExamingCount(countList.get(2));
         }
         }
-        AtomicReference<Integer> onlineCount = new AtomicReference<>(0);
-        AtomicReference<Integer> examingCount = new AtomicReference<>(0);
-        AtomicReference<Integer> prepareCount = new AtomicReference<>(0);
-//        AtomicReference<Integer> orgExamingCount = new AtomicReference<>(0);
-        Set<Long> examActivityIdSet = teExamActivityList.stream().map(TEExamActivity::getId).collect(Collectors.toSet());
-        QueryWrapper<TOeExamRecord> tOeExamRecordQueryWrapper = new QueryWrapper<>();
-        tOeExamRecordQueryWrapper.lambda().in(TOeExamRecord::getExamActivityId, examActivityIdSet);
-        List<TOeExamRecord> examRecordList = tOeExamRecordService.list(tOeExamRecordQueryWrapper);
-        examRecordList.forEach(s -> {
-//            Map<String, Object> objectMap = redisUtil
-//                    .getHashEntries(RedisKeyHelper.examActivityRecordCacheKey(s));
-//            if (Objects.nonNull(objectMap) && objectMap.size() > 0) {
-//                objectMap.forEach((k, v) -> {
-//                    Long recordId = Long.parseLong(k);
-//                    ExamActivityRecordCacheBean examActivityRecordCacheBean = (ExamActivityRecordCacheBean) v;
-            ExamRecordStatusEnum examRecordStatusEnum = s.getStatus();
-            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(s.getExamStudentId());
-            if (Objects.nonNull(examStudentCacheBean)
-                    && examStudentCacheBean.getEnable().intValue() == 1) {
-                //客户端通讯状态
-                WebsocketStatusEnum clientStatus = Objects.isNull(s.getClientWebsocketStatus()) ? null : s.getClientWebsocketStatus();
-                // 在线人数
-                if (Objects
-                        .nonNull(examRecordStatusEnum) && !Objects
-                        .equals(examRecordStatusEnum, ExamRecordStatusEnum.PERSISTED) && !Objects
-                        .equals(examRecordStatusEnum, ExamRecordStatusEnum.FINISHED) && Objects.nonNull(clientStatus) && Objects
-                        .equals(clientStatus, WebsocketStatusEnum.ON_LINE)) {
-                    onlineCount.getAndSet(onlineCount.get() + 1);
-                }
-//                        // 机构在考人数
-//                        if (Objects
-//                                .nonNull(examRecordStatusEnum) && Objects
-//                                .equals(examRecordStatusEnum, ExamRecordStatusEnum.ANSWERING)) {
-//                            orgExamingCount.getAndSet(orgExamingCount.get() + 1);
-//                        }
-                //已待考
-                if (Objects.equals(examRecordStatusEnum, ExamRecordStatusEnum.FIRST_PREPARE) && Objects.nonNull(clientStatus) && Objects
-                        .equals(clientStatus, WebsocketStatusEnum.ON_LINE)) {
-                    prepareCount.getAndSet(prepareCount.get() + 1);
-                }
-                // 考试人数
-                else if (Objects.equals(examRecordStatusEnum, ExamRecordStatusEnum.ANSWERING) && Objects.nonNull(clientStatus) && Objects
-                        .equals(clientStatus, WebsocketStatusEnum.ON_LINE)) {
-                    examingCount.getAndSet(examingCount.get() + 1);
-                }
-            }
-//                });
-//            }
-        });
-//        Long onlineCount = tOeExamRecordMapper.getOnlineCount(orgId);
-//        if (onlineCount == null) {
-//            onlineCount = 0L;
-//        }
-        ret.setOnlineCount(onlineCount.get().longValue());
-//        // 考试人数
-//        Long examingCount = tOeExamRecordMapper.getExamingCount(orgId);
-//        if (examingCount == null) {
-//            examingCount = 0L;
-//        }
-        ret.setExamingCount(examingCount.get().longValue());
-
-        // 待考人数
-        ret.setWaitingCount(prepareCount.get().longValue());
-
         // 通讯故障人数
         // 通讯故障人数
         ret.setExceptionCount(tOeExamRecordMapper.getExceptionCount(orgId));
         ret.setExceptionCount(tOeExamRecordMapper.getExceptionCount(orgId));
         // 预警人数
         // 预警人数
         ret.setWarnCount(tOeExamRecordMapper.getWarnCount(orgId));
         ret.setWarnCount(tOeExamRecordMapper.getWarnCount(orgId));
         // 机构在考人数
         // 机构在考人数
         ret.setOrgExamingCount(tOeExamRecordMapper.getOrgExamingCount(orgId));
         ret.setOrgExamingCount(tOeExamRecordMapper.getOrgExamingCount(orgId));
+//        long end = System.currentTimeMillis();
+//        log.info("============examinationMonitorCount耗时============:{}秒", (end - start) / 1000);
         return ret;
         return ret;
     }
     }
 
 
@@ -496,12 +432,15 @@ public class TIeReportServiceImpl implements TIeReportService {
      */
      */
     @Override
     @Override
     public ExaminationMonitorWarnDistributionBean warnDistribution() {
     public ExaminationMonitorWarnDistributionBean warnDistribution() {
+//        long start = System.currentTimeMillis();
         TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
         TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
         Long orgId = tbUser.getOrgId();
         Long orgId = tbUser.getOrgId();
         ExaminationMonitorWarnDistributionBean ret = new ExaminationMonitorWarnDistributionBean();
         ExaminationMonitorWarnDistributionBean ret = new ExaminationMonitorWarnDistributionBean();
         ret.setOrgDistribution(tOeExamRecordMapper.getOrgDistribution(orgId));
         ret.setOrgDistribution(tOeExamRecordMapper.getOrgDistribution(orgId));
         List<Map<String, Object>> typeList = tOeExamRecordMapper.getTypeDistribution(orgId);
         List<Map<String, Object>> typeList = tOeExamRecordMapper.getTypeDistribution(orgId);
         ret.setTypeDistribution(typeList);
         ret.setTypeDistribution(typeList);
+//        long end = System.currentTimeMillis();
+//        log.info("============warnDistribution耗时============:{}秒", (end - start) / 1000);
         return ret;
         return ret;
     }
     }
 
 
@@ -510,6 +449,7 @@ public class TIeReportServiceImpl implements TIeReportService {
      */
      */
     @Override
     @Override
     public List<ExaminationMonitorHourWarnCountBean> warnTrend() {
     public List<ExaminationMonitorHourWarnCountBean> warnTrend() {
+//        long startTime = System.currentTimeMillis();
         TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
         TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
         Long orgId = tbUser.getOrgId();
         Long orgId = tbUser.getOrgId();
         List<ExaminationMonitorHourWarnCountBean> ret = new ArrayList<ExaminationMonitorHourWarnCountBean>();
         List<ExaminationMonitorHourWarnCountBean> ret = new ArrayList<ExaminationMonitorHourWarnCountBean>();
@@ -541,11 +481,14 @@ public class TIeReportServiceImpl implements TIeReportService {
                 b.setHour(b.getHour() + ":00");
                 b.setHour(b.getHour() + ":00");
             }
             }
         }
         }
+//        long end = System.currentTimeMillis();
+//        log.info("============warnTrend耗时============:{}秒", (end - startTime) / 1000);
         return ret;
         return ret;
     }
     }
 
 
     @Override
     @Override
     public List<ExaminationMonitorWarnMsgBean> warnMsg() {
     public List<ExaminationMonitorWarnMsgBean> warnMsg() {
+//        long startTime = System.currentTimeMillis();
         TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
         TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
         Long orgId = tbUser.getOrgId();
         Long orgId = tbUser.getOrgId();
         List<ExaminationMonitorWarnMsgBean> ret = new ArrayList<ExaminationMonitorWarnMsgBean>();
         List<ExaminationMonitorWarnMsgBean> ret = new ArrayList<ExaminationMonitorWarnMsgBean>();
@@ -576,6 +519,8 @@ public class TIeReportServiceImpl implements TIeReportService {
                 ret.add(bean);
                 ret.add(bean);
             }
             }
         }
         }
+//        long end = System.currentTimeMillis();
+//        log.info("============warnMsg耗时============:{}秒", (end - startTime) / 1000);
         return ret;
         return ret;
     }
     }
 }
 }

+ 35 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -1270,6 +1270,41 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         return finished;
         return finished;
     }
     }
 
 
+    /**
+     * 根据orgId查找 在线人数/已待考/考试人数
+     *
+     * @param orgId
+     * @return
+     */
+    @Override
+    public List<Long> findByOrgId(Long orgId) {
+        return tOeExamRecordMapper.findByOrgId(orgId);
+    }
+
+    /**
+     * 查找监控消息
+     *
+     * @param examId
+     * @param roomCodeSet
+     * @return
+     */
+    @Override
+    public List<CountStopBean> findByStopInfo(Long examId, Set<String> roomCodeSet) {
+        return tOeExamRecordMapper.findByStopInfo(examId, roomCodeSet);
+    }
+
+    /**
+     * 查找在线消息
+     *
+     * @param examId
+     * @param roomCodeSet
+     * @return
+     */
+    @Override
+    public List<Integer> findByOnlineInfo(Long examId, Set<String> roomCodeSet) {
+        return tOeExamRecordMapper.findByOnlineInfo(examId, roomCodeSet);
+    }
+
     /**
     /**
      * 取最高分
      * 取最高分
      *
      *

+ 29 - 20
themis-business/src/main/java/com/qmth/themis/business/threadPool/MyThreadPool.java

@@ -1,11 +1,16 @@
 //package com.qmth.themis.business.threadPool;
 //package com.qmth.themis.business.threadPool;
 //
 //
 //import com.qmth.themis.business.constant.SystemConstant;
 //import com.qmth.themis.business.constant.SystemConstant;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+//import org.springframework.beans.factory.annotation.Value;
 //import org.springframework.context.annotation.Bean;
 //import org.springframework.context.annotation.Bean;
 //import org.springframework.context.annotation.Configuration;
 //import org.springframework.context.annotation.Configuration;
+//import org.springframework.context.annotation.Primary;
 //import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 //import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 //
 //
 //import javax.annotation.PostConstruct;
 //import javax.annotation.PostConstruct;
+//import java.util.Objects;
 //import java.util.concurrent.Executor;
 //import java.util.concurrent.Executor;
 //import java.util.concurrent.ThreadPoolExecutor;
 //import java.util.concurrent.ThreadPoolExecutor;
 //
 //
@@ -18,34 +23,38 @@
 // */
 // */
 //@Configuration
 //@Configuration
 //public class MyThreadPool extends ThreadPoolTaskExecutor {
 //public class MyThreadPool extends ThreadPoolTaskExecutor {
-//
-//    public MyThreadPool arbitratePoolTaskExecutor = null;
-//
-//    @PostConstruct
-//    public void init() {
-//        arbitrateThreadPool();
-//    }
+//    private final static Logger log = LoggerFactory.getLogger(MyThreadPool.class);
+//    private MyThreadPool threadPoolTaskExecutor = null;
+//    static final int cpuNum = Runtime.getRuntime().availableProcessors();
 //
 //
 //    /**
 //    /**
-//     * 仲裁线程池
+//     * 线程池
 //     *
 //     *
 //     * @return
 //     * @return
 //     */
 //     */
 //    @Bean
 //    @Bean
-//    public Executor arbitrateThreadPool() {
-//        if (arbitratePoolTaskExecutor == null) {
-//            arbitratePoolTaskExecutor = new MyThreadPool();
-//            arbitratePoolTaskExecutor.setCorePoolSize(SystemConstant.THREAD_POOL_CORE_POOL_SIZE);//核心线程数
-//            arbitratePoolTaskExecutor.setMaxPoolSize(SystemConstant.THREAD_POOL_MAX_POOL_SIZE);//最大线程数
-//            arbitratePoolTaskExecutor.setKeepAliveSeconds(SystemConstant.THREAD_POOL_KEEP_ALIVE_SECONDS);//线程空闲时间
-//            arbitratePoolTaskExecutor.setQueueCapacity(SystemConstant.THREAD_POOL_QUEUE_CAPACITY);//队列容量
-//            arbitratePoolTaskExecutor.setThreadNamePrefix(SystemConstant.THREAD_POOL_NAME);
-//
+//    @Primary
+//    public Executor taskThreadPool() {
+//        if (Objects.isNull(threadPoolTaskExecutor)) {
+//            log.info("cpuNum:{}", cpuNum);
+//            threadPoolTaskExecutor = new MyThreadPool();
+//            threadPoolTaskExecutor.setCorePoolSize(cpuNum);//核心线程数
+//            threadPoolTaskExecutor.setMaxPoolSize(cpuNum * 2);//最大线程数
+//            threadPoolTaskExecutor.setKeepAliveSeconds(SystemConstant.THREAD_POOL_KEEP_ALIVE_SECONDS);//线程空闲时间
+//            threadPoolTaskExecutor.setQueueCapacity(SystemConstant.THREAD_POOL_QUEUE_CAPACITY);//队列容量
+//            threadPoolTaskExecutor.setThreadNamePrefix(SystemConstant.THREAD_POOL_NAME);
+//            threadPoolTaskExecutor.setAllowCoreThreadTimeOut(true);//设置是否允许核心线程超时。若允许,核心线程超时后,会被销毁。默认为不允许(fasle)
+//            threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);//设置shutdown时是否等到所有任务完成再真正关闭
+//            threadPoolTaskExecutor.setAwaitTerminationSeconds(60);//当setWaitForTasksToCompleteOnShutdown(true)时,setAwaitTerminationSeconds 设置在 shutdown 之后最多等待多长时间后再真正关闭线程池
 //            // rejection-policy:当pool已经达到max size的时候,如何处理新任务
 //            // rejection-policy:当pool已经达到max size的时候,如何处理新任务
 //            // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
 //            // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
-//            arbitratePoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
-//            arbitratePoolTaskExecutor.initialize();
+//            threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+//            threadPoolTaskExecutor.initialize();
 //        }
 //        }
-//        return arbitratePoolTaskExecutor;
+//        return threadPoolTaskExecutor;
+//    }
+//
+//    public MyThreadPool getThreadPoolTaskExecutor() {
+//        return threadPoolTaskExecutor;
 //    }
 //    }
 //}
 //}

+ 243 - 77
themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml

@@ -77,19 +77,19 @@
     </select>
     </select>
 
 
     <update id="dataUpdate">
     <update id="dataUpdate">
-		update t_oe_exam_record t set
-		t.${colName}=#{colValue} where t.id=#{recordId}
-	</update>
+        update t_oe_exam_record t
+        set t.${colName}=#{colValue}
+        where t.id = #{recordId}
+    </update>
 
 
     <sql id="invigilatePageHead">
     <sql id="invigilatePageHead">
-		select
-		distinct t.exam_id examId,
-		tee.name as examName,
-		t.exam_activity_id examActivityId,
-		teea.code as examActivityCode,
-		t.exam_student_id examStudentId,
-		t.id examRecordId,
-		s.identity identity,
+        select distinct t.exam_id          examId,
+                        tee.name  as       examName,
+                        t.exam_activity_id examActivityId,
+                        teea.code as       examActivityCode,
+                        t.exam_student_id  examStudentId,
+                        t.id               examRecordId,
+                        s.identity identity,
 		s.room_code roomCode,
 		s.room_code roomCode,
 		s.room_name roomName,
 		s.room_name roomName,
 		s.name name,
 		s.name name,
@@ -105,14 +105,14 @@
 		t.client_last_sync_time as updateTime,
 		t.client_last_sync_time as updateTime,
 		t.monitor_video_source as monitorVideoSource,
 		t.monitor_video_source as monitorVideoSource,
         t.monitor_record as monitorRecord
         t.monitor_record as monitorRecord
-	</sql>
+    </sql>
 
 
     <sql id="invigilatePageMiddle">
     <sql id="invigilatePageMiddle">
-		from t_oe_exam_record t
+        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.exam_student_id = s.id
 		left join t_e_exam tee on tee.id = t.exam_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
 		left join t_e_exam_activity teea on teea.id = t.exam_activity_id
-	</sql>
+    </sql>
 
 
     <sql id="invigilatePageFoot">
     <sql id="invigilatePageFoot">
         <where>
         <where>
@@ -163,7 +163,7 @@
     </sql>
     </sql>
 
 
     <sql id="invigilatePageHistoryFoot">
     <sql id="invigilatePageHistoryFoot">
-        <where> 1 = 1
+        <where>1 = 1
             <if test="examId != null and examId != ''">
             <if test="examId != null and examId != ''">
                 and t.exam_id = #{examId}
                 and t.exam_id = #{examId}
             </if>
             </if>
@@ -221,7 +221,8 @@
             and t.paper_download = #{paperDownload}
             and t.paper_download = #{paperDownload}
         </if>
         </if>
         <if test="status == null or status == ''">
         <if test="status == null or status == ''">
-            and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status = 'RESUME_PREPARE')
+            and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status =
+            'RESUME_PREPARE')
         </if>
         </if>
         ) t,
         ) t,
         (SELECT @i := 0) as i
         (SELECT @i := 0) as i
@@ -234,16 +235,18 @@
         t.*
         t.*
         from
         from
         (
         (
-        <include refid="invigilatePageHead" />
+        <include refid="invigilatePageHead"/>
         <!--,t.monitor_live_url as monitorLiveUrl-->
         <!--,t.monitor_live_url as monitorLiveUrl-->
-        ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.approve_status = 0) as warningNew
-        <include refid="invigilatePageMiddle" />
-        <include refid="invigilatePageFoot" />
+        ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and
+        tiiwi.approve_status = 0) as warningNew
+        <include refid="invigilatePageMiddle"/>
+        <include refid="invigilatePageFoot"/>
         <if test="paperDownload != null and paperDownload != '' or paperDownload == 0">
         <if test="paperDownload != null and paperDownload != '' or paperDownload == 0">
             and t.paper_download = #{paperDownload}
             and t.paper_download = #{paperDownload}
         </if>
         </if>
         <if test="status == null or status == ''">
         <if test="status == null or status == ''">
-            and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status = 'RESUME_PREPARE')
+            and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status =
+            'RESUME_PREPARE')
         </if>
         </if>
         <if test="cameraMonitorStatus != null and cameraMonitorStatus != ''">
         <if test="cameraMonitorStatus != null and cameraMonitorStatus != ''">
             and t.camera_monitor_status = upper(#{cameraMonitorStatus})
             and t.camera_monitor_status = upper(#{cameraMonitorStatus})
@@ -263,31 +266,35 @@
     </select>
     </select>
 
 
     <select id="invigilatePageListVideoRandom" resultType="com.qmth.themis.business.bean.admin.InvigilateListVideoBean">
     <select id="invigilatePageListVideoRandom" resultType="com.qmth.themis.business.bean.admin.InvigilateListVideoBean">
-        <include refid="invigilatePageHead" />
+        <include refid="invigilatePageHead"/>
         <!--,t.monitor_live_url as monitorLiveUrl-->
         <!--,t.monitor_live_url as monitorLiveUrl-->
-        ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.approve_status = 0) as warningNew
-        <include refid="invigilatePageMiddle" />
-        <where> 1 = 1
+        ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and
+        tiiwi.approve_status = 0) as warningNew
+        <include refid="invigilatePageMiddle"/>
+        <where>1 = 1
             <if test="examId != null and examId != ''">
             <if test="examId != null and examId != ''">
                 and t.exam_id = #{examId}
                 and t.exam_id = #{examId}
             </if>
             </if>
             <if test="orgId != null and orgId != ''">
             <if test="orgId != null and orgId != ''">
                 and tee.org_id = #{orgId}
                 and tee.org_id = #{orgId}
             </if>
             </if>
-            and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status = 'RESUME_PREPARE')
+            and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status =
+            'RESUME_PREPARE')
         </where>
         </where>
         ORDER BY RAND() LIMIT #{randomNum}
         ORDER BY RAND() LIMIT #{randomNum}
     </select>
     </select>
 
 
     <select id="invigilatePagePatrolList" resultType="com.qmth.themis.business.bean.admin.InvigilateListPatrolBean">
     <select id="invigilatePagePatrolList" resultType="com.qmth.themis.business.bean.admin.InvigilateListPatrolBean">
-        select (@i := @i + 1) as seq,t.* from(<include refid="invigilatePageHead" />
+        select (@i := @i + 1) as seq,t.* from(
+        <include refid="invigilatePageHead"/>
         ,(select count(1) from t_ie_invigilate_exception_info tiiei where tiiei.exam_record_id = t.id) as exceptionCount
         ,(select count(1) from t_ie_invigilate_exception_info tiiei where tiiei.exam_record_id = t.id) as exceptionCount
         ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.`type` =
         ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.`type` =
         'FACE_COUNT_ERROR' and tiiwi.`level` = 'D8') as multipleFaceCount
         'FACE_COUNT_ERROR' and tiiwi.`level` = 'D8') as multipleFaceCount
-        <include refid="invigilatePageMiddle" />
-        <include refid="invigilatePageFoot" />
+        <include refid="invigilatePageMiddle"/>
+        <include refid="invigilatePageFoot"/>
         <if test="status == null or status == ''">
         <if test="status == null or status == ''">
-            and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status = 'RESUME_PREPARE')
+            and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status =
+            'RESUME_PREPARE')
         </if>
         </if>
         ) t,(SELECT @i := 0) as i
         ) t,(SELECT @i := 0) as i
         <where>
         <where>
@@ -337,7 +344,7 @@
         left join t_e_exam_activity teea on teea.id = tiiwi.exam_activity_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_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
         left join t_e_exam_student tees on tees.id = tiiwi.exam_student_id
-        <where> 1 = 1
+        <where>1 = 1
             <if test="examId != null and examId != ''">
             <if test="examId != null and examId != ''">
                 and tiiwi.exam_id = #{examId}
                 and tiiwi.exam_id = #{examId}
             </if>
             </if>
@@ -399,7 +406,7 @@
         left join t_e_exam_activity teea on teea.id = tiiwi.exam_activity_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_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
         left join t_e_exam_student tees on tees.id = tiiwi.exam_student_id
-        <where> 1 = 1
+        <where>1 = 1
             <if test="examId != null and examId != ''">
             <if test="examId != null and examId != ''">
                 and tiiwi.exam_id = #{examId}
                 and tiiwi.exam_id = #{examId}
             </if>
             </if>
@@ -434,7 +441,7 @@
             </if>
             </if>
         </where>
         </where>
         ) t
         ) t
-        <where> 1 = 1
+        <where>1 = 1
             <if test="minMultipleFaceCount != null and minMultipleFaceCount != '' or minMultipleFaceCount == 0">
             <if test="minMultipleFaceCount != null and minMultipleFaceCount != '' or minMultipleFaceCount == 0">
                 and t.multipleFaceCount &gt;= #{minMultipleFaceCount}
                 and t.multipleFaceCount &gt;= #{minMultipleFaceCount}
             </if>
             </if>
@@ -463,7 +470,8 @@
         tees.name,
         tees.name,
         tees.course_code as courseCode,
         tees.course_code as courseCode,
         tees.course_name as courseName,
         tees.course_name as courseName,
-        if(tee.exam_count - tees.already_exam_count <![CDATA[ < ]]> 0,0,tee.exam_count - tees.already_exam_count) as leftExamCount,
+        if(tee.exam_count - tees.already_exam_count <![CDATA[ < ]]> 0,0,tee.exam_count - tees.already_exam_count) as
+        leftExamCount,
         if((select count(1) from t_oe_exam_record toer where toer.exam_student_id =
         if((select count(1) from t_oe_exam_record toer where toer.exam_student_id =
         tees.id and (toer.status = 'FINISHED' or toer.status = 'PERSISTED') >
         tees.id and (toer.status = 'FINISHED' or toer.status = 'PERSISTED') >
         0),'已完成','未完成') as status,
         0),'已完成','未完成') as status,
@@ -475,7 +483,7 @@
         left join t_e_exam_activity teea on
         left join t_e_exam_activity teea on
         teea.id = tees.exam_activity_id
         teea.id = tees.exam_activity_id
         left join t_e_student tes on tees.student_id = tes.id
         left join t_e_student tes on tees.student_id = tes.id
-        <where> 1 = 1
+        <where>1 = 1
             <if test="examId != null and examId != ''">
             <if test="examId != null and examId != ''">
                 and tees.exam_id = #{examId}
                 and tees.exam_id = #{examId}
             </if>
             </if>
@@ -507,7 +515,8 @@
         order by tees.room_code
         order by tees.room_code
     </select>
     </select>
 
 
-    <select id="invigilatePageProgressListExport" resultType="com.qmth.themis.business.bean.admin.InvigilateListProgressExcelBean">
+    <select id="invigilatePageProgressListExport"
+            resultType="com.qmth.themis.business.bean.admin.InvigilateListProgressExcelBean">
         select
         select
         distinct tee.id as examId,
         distinct tee.id as examId,
         tee.name as examName,
         tee.name as examName,
@@ -518,7 +527,8 @@
         tees.`identity`,
         tees.`identity`,
         tees.name,
         tees.name,
         group_concat(tees.course_name,CONCAT(CONCAT('(',tees.course_code),')')) as courseName,
         group_concat(tees.course_name,CONCAT(CONCAT('(',tees.course_code),')')) as courseName,
-        if(tee.exam_count - tees.already_exam_count <![CDATA[ < ]]> 0,0,tee.exam_count - tees.already_exam_count) as leftExamCount,
+        if(tee.exam_count - tees.already_exam_count <![CDATA[ < ]]> 0,0,tee.exam_count - tees.already_exam_count) as
+        leftExamCount,
         if((select count(1) from t_oe_exam_record toer where toer.exam_student_id =
         if((select count(1) from t_oe_exam_record toer where toer.exam_student_id =
         tees.id and (toer.status = 'FINISHED' or toer.status = 'PERSISTED') >
         tees.id and (toer.status = 'FINISHED' or toer.status = 'PERSISTED') >
         0),'已完成','未完成') as status,
         0),'已完成','未完成') as status,
@@ -530,7 +540,7 @@
         left join t_e_exam_activity teea on
         left join t_e_exam_activity teea on
         teea.id = tees.exam_activity_id
         teea.id = tees.exam_activity_id
         left join t_e_student tes on tees.student_id = tes.id
         left join t_e_student tes on tees.student_id = tes.id
-        <where> 1 = 1
+        <where>1 = 1
             <if test="examId != null and examId != ''">
             <if test="examId != null and examId != ''">
                 and tees.exam_id = #{examId}
                 and tees.exam_id = #{examId}
             </if>
             </if>
@@ -559,21 +569,22 @@
             </if>
             </if>
             and tee.monitor_status <![CDATA[ <> ]]> 'FINISHED'
             and tee.monitor_status <![CDATA[ <> ]]> 'FINISHED'
         </where>
         </where>
-        group by tee.id,tees.room_code,tee.name,teea.id,teea.code,tees.`identity`,tees.name,leftExamCount,status,tes.mobile_number
+        group by
+        tee.id,tees.room_code,tee.name,teea.id,teea.code,tees.`identity`,tees.name,leftExamCount,status,tes.mobile_number
         order by tees.room_code
         order by tees.room_code
     </select>
     </select>
 
 
     <select id="invigilatePageListHistory" resultType="com.qmth.themis.business.bean.admin.InvigilateListHistoryBean">
     <select id="invigilatePageListHistory" resultType="com.qmth.themis.business.bean.admin.InvigilateListHistoryBean">
         select (@i := @i + 1) as seq,t.* from(
         select (@i := @i + 1) as seq,t.* from(
-        <include refid="invigilatePageHead" />
+        <include refid="invigilatePageHead"/>
         ,tes.mobile_number as mobileNumber
         ,tes.mobile_number as mobileNumber
         ,t.finish_type as finishType
         ,t.finish_type as finishType
         ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.`type` =
         ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.`type` =
         'FACE_COUNT_ERROR' and tiiwi.`level` = 'D8') as multipleFaceCount
         'FACE_COUNT_ERROR' and tiiwi.`level` = 'D8') as multipleFaceCount
         ,(select count(1) from t_ie_invigilate_exception_info tiiei where tiiei.exam_record_id = t.id) as exceptionCount
         ,(select count(1) from t_ie_invigilate_exception_info tiiei where tiiei.exam_record_id = t.id) as exceptionCount
-        <include refid="invigilatePageMiddle" />
+        <include refid="invigilatePageMiddle"/>
         left join t_e_student tes on s.student_id = tes.id
         left join t_e_student tes on s.student_id = tes.id
-        <include refid="invigilatePageHistoryFoot" />
+        <include refid="invigilatePageHistoryFoot"/>
         <if test="breachStatus != null and breachStatus != '' or breachStatus == 0">
         <if test="breachStatus != null and breachStatus != '' or breachStatus == 0">
             <if test="breachStatus == 0">
             <if test="breachStatus == 0">
                 and t.breach_status = #{breachStatus}
                 and t.breach_status = #{breachStatus}
@@ -653,9 +664,10 @@
     </select>
     </select>
 
 
     <select id="getCountByExamId" resultType="java.lang.Long">
     <select id="getCountByExamId" resultType="java.lang.Long">
-		select count(1) from t_oe_exam_record f
-		where f.exam_id = #{examId}
-	</select>
+        select count(1)
+        from t_oe_exam_record f
+        where f.exam_id = #{examId}
+    </select>
 
 
     <select id="findOneByExamId" resultType="com.qmth.themis.business.entity.TOeExamRecord">
     <select id="findOneByExamId" resultType="com.qmth.themis.business.entity.TOeExamRecord">
         select f.* from t_oe_exam_record f
         select f.* from t_oe_exam_record f
@@ -671,28 +683,32 @@
     </select>
     </select>
 
 
     <select id="getListByExamIdAndStartId" resultType="com.qmth.themis.business.entity.TOeExamRecord">
     <select id="getListByExamIdAndStartId" resultType="com.qmth.themis.business.entity.TOeExamRecord">
-		select f.* from t_oe_exam_record f
-		where f.exam_id = #{examId} and f.id>#{startId}
-		order by f.id
-		limit 500
-	</select>
+        select f.*
+        from t_oe_exam_record f
+        where f.exam_id = #{examId}
+          and f.id > #{startId}
+        order by f.id limit 500
+    </select>
 
 
     <update id="updateObjectiveScore">
     <update id="updateObjectiveScore">
-		update t_oe_exam_record t set t.objective_score=#{score} where t.id=#{recordId}
-	</update>
+        update t_oe_exam_record t
+        set t.objective_score=#{score}
+        where t.id = #{recordId}
+    </update>
 
 
     <select id="findOneByPaperId" resultType="com.qmth.themis.business.entity.TOeExamRecord">
     <select id="findOneByPaperId" resultType="com.qmth.themis.business.entity.TOeExamRecord">
-		select f.* from t_oe_exam_record f
-		where f.paper_id = #{paperId}
-		limit 1
-	</select>
+        select f.*
+        from t_oe_exam_record f
+        where f.paper_id = #{paperId} limit 1
+    </select>
 
 
     <select id="patrolReport" resultType="com.qmth.themis.business.bean.admin.InvigilateListPatrolReportBean">
     <select id="patrolReport" resultType="com.qmth.themis.business.bean.admin.InvigilateListPatrolReportBean">
         select
         select
         t.roomCode,
         t.roomCode,
         t.roomName,
         t.roomName,
         sum(t.warningCount) as warningCount,
         sum(t.warningCount) as warningCount,
-        count((t.client_websocket_status = 'OFF_LINE' or t.client_websocket_status is null) or null) as clientWebsocketStatusCount
+        count((t.client_websocket_status = 'OFF_LINE' or t.client_websocket_status is null) or null) as
+        clientWebsocketStatusCount
         from
         from
         (
         (
         select
         select
@@ -715,8 +731,12 @@
                 where tbeiu.user_id = #{userId}
                 where tbeiu.user_id = #{userId}
                 and tbeiu.exam_id = t.exam_id and tbeiu.room_code = s.room_code)
                 and tbeiu.exam_id = t.exam_id and tbeiu.room_code = s.room_code)
             </if>
             </if>
-            and (t.status <![CDATA[ <> ]]> 'PERSISTED' and t.status <![CDATA[ <> ]]> 'FINISHED')
-        </where> ) t
+            and (t.STATUS = 'FIRST_PREPARE'
+            or t.STATUS = 'ANSWERING'
+            or t.STATUS = 'BREAK_OFF'
+            or t.STATUS = 'RESUME_PREPARE')
+        </where>
+        ) t
         group by
         group by
         t.roomCode,
         t.roomCode,
         t.roomName
         t.roomName
@@ -746,12 +766,12 @@
         t_oe_exam_record f
         t_oe_exam_record f
         LEFT JOIN t_ie_invigilate_exception_info t ON f.id = t.exam_record_id
         LEFT JOIN t_ie_invigilate_exception_info t ON f.id = t.exam_record_id
         left join t_e_exam h on f.exam_id=h.id
         left join t_e_exam h on f.exam_id=h.id
-        WHERE
-        f. STATUS != 'FINISHED'
+        WHERE 1 = 1
         <if test="orgId != null">
         <if test="orgId != null">
             and h.org_id=#{orgId}
             and h.org_id=#{orgId}
         </if>
         </if>
-        AND f. STATUS != 'PERSISTED'
+        and (f.STATUS = 'FIRST_PREPARE' or f.STATUS = 'ANSWERING'
+        or f.STATUS = 'BREAK_OFF' or f.STATUS = 'RESUME_PREPARE')
         AND t.id IS NOT NULL
         AND t.id IS NOT NULL
     </select>
     </select>
     <select id="getWarnCount" resultType="java.lang.Long">
     <select id="getWarnCount" resultType="java.lang.Long">
@@ -761,12 +781,12 @@
         t_oe_exam_record f
         t_oe_exam_record f
         LEFT JOIN t_ie_invigilate_warn_info t ON f.id = t.exam_record_id
         LEFT JOIN t_ie_invigilate_warn_info t ON f.id = t.exam_record_id
         left join t_e_exam h on f.exam_id=h.id
         left join t_e_exam h on f.exam_id=h.id
-        WHERE
-        f. STATUS != 'FINISHED'
+        WHERE 1 = 1
         <if test="orgId != null">
         <if test="orgId != null">
             and h.org_id=#{orgId}
             and h.org_id=#{orgId}
         </if>
         </if>
-        AND f. STATUS != 'PERSISTED'
+        and (f.STATUS = 'FIRST_PREPARE' or f.STATUS = 'ANSWERING'
+        or f.STATUS = 'BREAK_OFF' or f.STATUS = 'RESUME_PREPARE')
         AND t.type!='NONE'
         AND t.type!='NONE'
         AND t.id IS NOT NULL
         AND t.id IS NOT NULL
     </select>
     </select>
@@ -783,12 +803,12 @@
         t_oe_exam_record f
         t_oe_exam_record f
         LEFT JOIN t_e_exam_student t ON f.exam_student_id = t.id
         LEFT JOIN t_e_exam_student t ON f.exam_student_id = t.id
         LEFT JOIN t_e_student h ON t.student_id = h.id
         LEFT JOIN t_e_student h ON t.student_id = h.id
-        WHERE
-        f. STATUS != 'FINISHED'
+        WHERE 1 = 1
         <if test="orgId != null">
         <if test="orgId != null">
             and h.org_id=#{orgId}
             and h.org_id=#{orgId}
         </if>
         </if>
-        AND f. STATUS != 'PERSISTED'
+        and (f.STATUS = 'FIRST_PREPARE' or f.STATUS = 'ANSWERING'
+        or f.STATUS = 'BREAK_OFF' or f.STATUS = 'RESUME_PREPARE')
         AND f.client_websocket_status='ON_LINE'
         AND f.client_websocket_status='ON_LINE'
         GROUP BY
         GROUP BY
         h.org_id
         h.org_id
@@ -809,12 +829,12 @@
         LEFT JOIN t_ie_invigilate_warn_info w ON f.id = w.exam_record_id
         LEFT JOIN t_ie_invigilate_warn_info w ON f.id = w.exam_record_id
         LEFT JOIN t_e_exam_student t ON f.exam_student_id = t.id
         LEFT JOIN t_e_exam_student t ON f.exam_student_id = t.id
         LEFT JOIN t_e_student h ON t.student_id = h.id
         LEFT JOIN t_e_student h ON t.student_id = h.id
-        WHERE
-        f. STATUS != 'FINISHED'
+        WHERE 1 = 1
         <if test="orgId != null">
         <if test="orgId != null">
             and h.org_id=#{orgId}
             and h.org_id=#{orgId}
         </if>
         </if>
-        AND f. STATUS != 'PERSISTED'
+        and (f.STATUS = 'FIRST_PREPARE' or f.STATUS = 'ANSWERING'
+        or f.STATUS = 'BREAK_OFF' or f.STATUS = 'RESUME_PREPARE')
         AND w.id IS NOT NULL
         AND w.id IS NOT NULL
         AND w.type!='NONE'
         AND w.type!='NONE'
         GROUP BY
         GROUP BY
@@ -830,12 +850,12 @@
         t_oe_exam_record f
         t_oe_exam_record f
         LEFT JOIN t_ie_invigilate_warn_info w ON f.id = w.exam_record_id
         LEFT JOIN t_ie_invigilate_warn_info w ON f.id = w.exam_record_id
         left join t_e_exam h on f.exam_id=h.id
         left join t_e_exam h on f.exam_id=h.id
-        WHERE
-        f. STATUS != 'FINISHED'
+        WHERE 1 = 1
         <if test="orgId != null">
         <if test="orgId != null">
             and h.org_id=#{orgId}
             and h.org_id=#{orgId}
         </if>
         </if>
-        AND f. STATUS != 'PERSISTED'
+        and (f.STATUS = 'FIRST_PREPARE' or f.STATUS = 'ANSWERING'
+        or f.STATUS = 'BREAK_OFF' or f.STATUS = 'RESUME_PREPARE')
         AND w.id IS NOT NULL
         AND w.id IS NOT NULL
         AND w.type!='NONE'
         AND w.type!='NONE'
         GROUP BY
         GROUP BY
@@ -845,7 +865,7 @@
         SELECT
         SELECT
         FROM_UNIXTIME(w.create_time / 1000,'%H') hour,
         FROM_UNIXTIME(w.create_time / 1000,'%H') hour,
         count(1) count
         count(1) count
-        FROM  t_ie_invigilate_warn_info w
+        FROM t_ie_invigilate_warn_info w
         left join t_e_exam h on w.exam_id=h.id
         left join t_e_exam h on w.exam_id=h.id
         WHERE w.type!='NONE' and w.create_time&gt;=#{startTime}
         WHERE w.type!='NONE' and w.create_time&gt;=#{startTime}
         <if test="orgId != null">
         <if test="orgId != null">
@@ -856,8 +876,10 @@
     </select>
     </select>
 
 
     <update id="updateHasAnswerFile">
     <update id="updateHasAnswerFile">
-		update t_oe_exam_record t set t.has_answer_file=#{hasAnswerFile} where t.id=#{recordId}
-	</update>
+        update t_oe_exam_record t
+        set t.has_answer_file=#{hasAnswerFile}
+        where t.id = #{recordId}
+    </update>
 
 
     <select id="findExamRecordNeedMark" resultType="com.qmth.themis.business.bean.admin.OpenRecordNeedMarkBean">
     <select id="findExamRecordNeedMark" resultType="com.qmth.themis.business.bean.admin.OpenRecordNeedMarkBean">
         SELECT t.id              as id,
         SELECT t.id              as id,
@@ -891,4 +913,148 @@
         group by
         group by
         toer.id,toer.paper_id,toer.finish_time order by toer.objective_score desc,toer.finish_time desc
         toer.id,toer.paper_id,toer.finish_time order by toer.objective_score desc,toer.finish_time desc
     </select>
     </select>
+
+    <select id="findByOrgId" resultType="java.lang.Long">
+        select count(1) as c
+        from t_oe_exam_record toer
+        where exists(
+                select teea.id
+                from t_e_exam_activity teea
+                where exists(
+                        select tee.id
+                        from t_e_exam tee
+                        where tee.org_id = #{orgId}
+                          and tee.id = teea.exam_id
+                    )
+                  and toer.exam_activity_id = teea.id)
+          and (toer.STATUS = 'FIRST_PREPARE'
+            or toer.STATUS = 'ANSWERING'
+            or toer.STATUS = 'BREAK_OFF'
+            or toer.STATUS = 'RESUME_PREPARE')
+          and toer.client_websocket_status = 'ON_LINE'
+        union all
+        select count(1) as c
+        from t_oe_exam_record toer
+        where exists(
+                select teea.id
+                from t_e_exam_activity teea
+                where exists(
+                        select tee.id
+                        from t_e_exam tee
+                        where tee.org_id = #{orgId}
+                          and tee.id = teea.exam_id
+                    )
+                  and toer.exam_activity_id = teea.id)
+          and toer.STATUS = 'FIRST_PREPARE'
+          and toer.client_websocket_status = 'ON_LINE'
+        union all
+        select count(1) as c
+        from t_oe_exam_record toer
+        where exists(
+                select teea.id
+                from t_e_exam_activity teea
+                where exists(
+                        select tee.id
+                        from t_e_exam tee
+                        where tee.org_id = #{orgId}
+                          and tee.id = teea.exam_id
+                    )
+                  and toer.exam_activity_id = teea.id)
+          and toer.STATUS = 'ANSWERING'
+          and toer.client_websocket_status = 'ON_LINE'
+    </select>
+
+    <select id="findByStopInfo" resultType="com.qmth.themis.business.bean.admin.CountStopBean">
+        select
+        count((t.client_websocket_status = 'OFF_LINE' or t.client_websocket_status is null) or null) as
+        clientWebsocketStatusOffCount,
+        count(t.client_websocket_status = 'ON_LINE') as clientWebsocketStatusOnCount,
+        count(t.camera_monitor_status = 'STOP') as cameraMonitorStatusStop,
+        count(t.screen_monitor_status = 'STOP') as screenMonitorStatusStop,
+        count(t.mobile_first_monitor_status = 'STOP') as mobileFirstMonitorStatusStop,
+        count(t.mobile_second_monitor_status = 'STOP') as mobileSecondMonitorStatusStop
+        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 tee on
+        tee.id = t.exam_id
+        left join t_e_exam_activity teea on
+        teea.id = t.exam_activity_id
+        where
+        t.exam_id = #{examId}
+        and s.room_code in
+        <foreach collection="roomCodeSet" item="roomCode" index="index" open="(" close=")" separator=",">
+            #{roomCode}
+        </foreach>
+        and (t.STATUS = 'FIRST_PREPARE'
+        or t.STATUS = 'ANSWERING'
+        or t.STATUS = 'BREAK_OFF'
+        or t.STATUS = 'RESUME_PREPARE')
+        group by
+        t.client_websocket_status,
+        t.camera_monitor_status,
+        t.screen_monitor_status,
+        t.mobile_first_monitor_status,
+        t.mobile_second_monitor_status
+    </select>
+
+    <select id="findByOnlineInfo" resultType="java.lang.Integer">
+        select
+        count(1) as c
+        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 tee on
+        tee.id = t.exam_id
+        left join t_e_exam_activity teea on
+        teea.id = t.exam_activity_id
+        where
+        t.exam_id = #{examId}
+        and s.room_code in
+        <foreach collection="roomCodeSet" item="roomCode" index="index" open="(" close=")" separator=",">
+            #{roomCode}
+        </foreach>
+        and t.STATUS = 'FIRST_PREPARE'
+        and t.client_websocket_status = 'ON_LINE'
+        union all
+        select
+        count(1) as c
+        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 tee on
+        tee.id = t.exam_id
+        left join t_e_exam_activity teea on
+        teea.id = t.exam_activity_id
+        where
+        t.exam_id = #{examId}
+        and s.room_code in
+        <foreach collection="roomCodeSet" item="roomCode" index="index" open="(" close=")" separator=",">
+            #{roomCode}
+        </foreach>
+        and t.STATUS = 'ANSWERING'
+        and t.client_websocket_status = 'ON_LINE'
+        union all
+        select
+        count(1) as c
+        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 tee on
+        tee.id = t.exam_id
+        left join t_e_exam_activity teea on
+        teea.id = t.exam_activity_id
+        where
+        t.exam_id = #{examId}
+        and s.room_code in
+        <foreach collection="roomCodeSet" item="roomCode" index="index" open="(" close=")" separator=",">
+            #{roomCode}
+        </foreach>
+        and (t.STATUS = 'FINISHED'
+        or t.STATUS = 'PERSISTED')
+    </select>
 </mapper>
 </mapper>