Browse Source

Merge branch 'dev'
111

wangliang 4 years ago
parent
commit
16ca4c2083
28 changed files with 1229 additions and 510 deletions
  1. 39 0
      themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamController.java
  2. 34 65
      themis-backend/src/main/java/com/qmth/themis/backend/api/TIeInvigilateCallMobileController.java
  3. 46 5
      themis-backend/src/main/java/com/qmth/themis/backend/api/TIeInvigilateWarnInfoController.java
  4. 3 0
      themis-backend/src/main/java/com/qmth/themis/backend/start/StartRunning.java
  5. 22 0
      themis-business/src/main/java/com/qmth/themis/business/bean/backend/InvigilateListHistoryBean.java
  6. 33 0
      themis-business/src/main/java/com/qmth/themis/business/bean/backend/InvigilateListVideoBean.java
  7. 11 0
      themis-business/src/main/java/com/qmth/themis/business/bean/backend/InvigilateListWarningBean.java
  8. 17 3
      themis-business/src/main/java/com/qmth/themis/business/dao/TIeExamInvigilateCallMapper.java
  9. 13 0
      themis-business/src/main/java/com/qmth/themis/business/dao/TIeInvigilateWarnInfoMapper.java
  10. 4 0
      themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamRecordMapper.java
  11. 93 0
      themis-business/src/main/java/com/qmth/themis/business/dto/response/TIeWarningNotifyDto.java
  12. 6 1
      themis-business/src/main/java/com/qmth/themis/business/enums/MqGroupEnum.java
  13. 2 1
      themis-business/src/main/java/com/qmth/themis/business/enums/MqTagEnum.java
  14. 8 0
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamService.java
  15. 17 3
      themis-business/src/main/java/com/qmth/themis/business/service/TIeExamInvigilateCallService.java
  16. 12 2
      themis-business/src/main/java/com/qmth/themis/business/service/TIeInvigilateWarnInfoService.java
  17. 28 3
      themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java
  18. 129 19
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java
  19. 21 4
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TIeExamInvigilateCallServiceImpl.java
  20. 15 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TIeInvigilateWarnInfoServiceImpl.java
  21. 70 15
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java
  22. 2 1
      themis-business/src/main/resources/mapper/TEExamReexamMapper.xml
  23. 46 4
      themis-business/src/main/resources/mapper/TIeExamInvigilateCallMapper.xml
  24. 30 0
      themis-business/src/main/resources/mapper/TIeInvigilateWarnInfoMapper.xml
  25. 425 382
      themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml
  26. 8 0
      themis-mq/src/main/java/com/qmth/themis/mq/service/MqLogicService.java
  27. 21 2
      themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java
  28. 74 0
      themis-mq/src/main/java/com/qmth/themis/mq/templete/impl/CalculateScoreConcurrentlyImpl.java

+ 39 - 0
themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamController.java

@@ -67,6 +67,9 @@ public class TEExamController {
 
 
     @Resource
     @Resource
     RedisUtil redisUtil;
     RedisUtil redisUtil;
+    
+    @Resource
+    TBTaskHistoryService taskHistoryService;
 
 
     @ApiOperation(value = "考试批次修改/新增接口")
     @ApiOperation(value = "考试批次修改/新增接口")
     @RequestMapping(value = "/save", method = RequestMethod.POST)
     @RequestMapping(value = "/save", method = RequestMethod.POST)
@@ -441,4 +444,40 @@ public class TEExamController {
         ExamPropCountDto examPropCountDto = new ExamPropCountDto(examId, allCount, prepareCount.get(), examCount.get(), clientWebsocketStatusCount.get(), monitorStatusSourceCount.get(), alreadyComplete.get(), notComplete, completionRate);
         ExamPropCountDto examPropCountDto = new ExamPropCountDto(examId, allCount, prepareCount.get(), examCount.get(), clientWebsocketStatusCount.get(), monitorStatusSourceCount.get(), alreadyComplete.get(), notComplete, completionRate);
         return ResultUtil.ok(examPropCountDto);
         return ResultUtil.ok(examPropCountDto);
     }
     }
+    
+    @ApiOperation(value = "考试重新算分")
+    @RequestMapping(value = "/score/calculate", method = RequestMethod.POST)
+    @Transactional
+    @ApiResponses({@ApiResponse(code = 200, message = "{\"taskId\":0}", response = Result.class)})
+    public Result scoreCalculate(@ApiParam(value = "批次ID", required = true) @RequestParam Long examId) {
+    	//先查询考试相关信息
+        TEExam teExam = teExamService.getById(examId);
+        if (Objects.isNull(teExam)) {
+            throw new BusinessException(ExceptionResultEnum.EXAM_NO);
+        }
+        TBTaskHistory tbTaskHistory = null;
+        Map<String, Object> transMap = new HashMap<String, Object>();
+        try {
+            TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
+            //往任务表里插一条数据
+            tbTaskHistory = new TBTaskHistory(TaskTypeEnum.CALCULATE_EXAM_SCORE, TaskStatusEnum.INIT, "重新算分", 0d, tbUser.getId());
+            tbTaskHistory.setEntityId(examId);
+            taskHistoryService.save(tbTaskHistory);
+            transMap.put("examId", examId);
+            transMap.put(SystemConstant.TASK_ID, tbTaskHistory.getId());
+            //mq发送消息start
+            MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.EXAM_SCORE_CALCULATE.name(), transMap, MqTagEnum.EXAM_SCORE_CALCULATE, String.valueOf(tbTaskHistory.getId()), tbUser.getName());
+            mqDtoService.assembleSendOneWayMsg(mqDto);
+            //mq发送消息end
+        } catch (Exception e) {
+            if (e instanceof BusinessException) {
+                throw new BusinessException(e.getMessage());
+            } else {
+                throw new RuntimeException(e);
+            }
+        }
+        Map<String, Long> map = new HashMap<String, Long>();
+        map.put(SystemConstant.TASK_ID, tbTaskHistory.getId());
+        return ResultUtil.ok(map);
+    }
 }
 }

+ 34 - 65
themis-backend/src/main/java/com/qmth/themis/backend/api/TIeInvigilateCallMobileController.java

@@ -12,11 +12,12 @@ import com.qmth.themis.business.cache.RedisKeyHelper;
 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;
 import com.qmth.themis.business.dto.MqDto;
 import com.qmth.themis.business.dto.MqDto;
-import com.qmth.themis.business.entity.*;
+import com.qmth.themis.business.entity.TBSession;
+import com.qmth.themis.business.entity.TBUser;
+import com.qmth.themis.business.entity.TIeExamInvigilateCall;
+import com.qmth.themis.business.entity.TIeExamInvigilateCallLog;
 import com.qmth.themis.business.enums.*;
 import com.qmth.themis.business.enums.*;
 import com.qmth.themis.business.service.MqDtoService;
 import com.qmth.themis.business.service.MqDtoService;
-import com.qmth.themis.business.service.TBExamInvigilateUserService;
-import com.qmth.themis.business.service.TEExamStudentService;
 import com.qmth.themis.business.service.TIeExamInvigilateCallService;
 import com.qmth.themis.business.service.TIeExamInvigilateCallService;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.business.util.ServletUtil;
 import com.qmth.themis.business.util.ServletUtil;
@@ -32,8 +33,10 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
-import java.util.*;
-import java.util.stream.Collectors;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
 
 
 /**
 /**
  * @Description: mobile监考监控通话信息 前端控制器
  * @Description: mobile监考监控通话信息 前端控制器
@@ -60,21 +63,25 @@ public class TIeInvigilateCallMobileController {
     @Resource
     @Resource
     TencentYunUtil tencentYunUtil;
     TencentYunUtil tencentYunUtil;
 
 
-    @Resource
-    TBExamInvigilateUserService tbExamInvigilateUserService;
-
-    @Resource
-    TEExamStudentService teExamStudentService;
-
     @ApiOperation(value = "监考监控通话查询接口")
     @ApiOperation(value = "监考监控通话查询接口")
     @RequestMapping(value = "/call/list", method = RequestMethod.POST)
     @RequestMapping(value = "/call/list", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "监考监控信息", response = TIeExamInvigilateCall.class)})
     @ApiResponses({@ApiResponse(code = 200, message = "监考监控信息", response = TIeExamInvigilateCall.class)})
-    public Result callList(@ApiParam(value = "考试批次id", required = true) @RequestParam(required = true) Long examId, @ApiParam(value = "分页页码", required = true) @RequestParam int pageNumber, @ApiParam(value = "分页数", required = true) @RequestParam int pageSize) {
+    public Result callList(@ApiParam(value = "考试批次id", required = true) @RequestParam(required = true) Long examId, @ApiParam(value = "通话状态", required = false) @RequestParam(required = false) String callStatus, @ApiParam(value = "分页页码", required = true) @RequestParam int pageNumber, @ApiParam(value = "分页数", required = true) @RequestParam int pageSize) {
         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);
         }
         }
-        Set<Long> examActivityIdSet = this.getExamActivityIds(examId);
-        IPage<TIeExamInvigilateCall> tIeExamInvigilateCallIPage = tIeExamInvigilateCallService.examInvigilateCallQuery(new Page<>(pageNumber, pageSize), examActivityIdSet, MonitorStatusSourceEnum.START.name());
+        if (Objects.nonNull(callStatus) && !Objects.equals(callStatus, "")) {
+            MonitorCallStatusSourceEnum callStatusEnum = MonitorCallStatusSourceEnum.valueOf(callStatus);
+            callStatus = callStatusEnum.name();
+        }
+        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
+        AuthDto authDto = (AuthDto) redisUtil.get(SystemConstant.userOauth + "::" + tbUser.getId());
+        //如果有监考员角色,只能查看自己所监考的考场,巡考员和管理员则可以查看全部考场
+        Long userId = null;
+        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name())) {
+            userId = tbUser.getId();
+        }
+        IPage<TIeExamInvigilateCall> tIeExamInvigilateCallIPage = tIeExamInvigilateCallService.examInvigilateCallQuery(new Page<>(pageNumber, pageSize), examId, userId, tbUser.getOrgId(), MonitorStatusSourceEnum.START.name(), callStatus);
         BasePage basePage = new BasePage(tIeExamInvigilateCallIPage.getRecords(), tIeExamInvigilateCallIPage.getCurrent(), tIeExamInvigilateCallIPage.getSize(), tIeExamInvigilateCallIPage.getTotal());
         BasePage basePage = new BasePage(tIeExamInvigilateCallIPage.getRecords(), tIeExamInvigilateCallIPage.getCurrent(), tIeExamInvigilateCallIPage.getSize(), tIeExamInvigilateCallIPage.getTotal());
         return ResultUtil.ok(basePage);
         return ResultUtil.ok(basePage);
     }
     }
@@ -82,14 +89,22 @@ public class TIeInvigilateCallMobileController {
     @ApiOperation(value = "监考监控通话提醒接口")
     @ApiOperation(value = "监考监控通话提醒接口")
     @RequestMapping(value = "/call/count", method = RequestMethod.POST)
     @RequestMapping(value = "/call/count", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "监考监控信息", response = Integer.class)})
     @ApiResponses({@ApiResponse(code = 200, message = "监考监控信息", response = Integer.class)})
-    public Result callCount(@ApiParam(value = "考试批次id", required = true) @RequestParam Long examId) {
+    public Result callCount(@ApiParam(value = "考试批次id", required = true) @RequestParam Long examId, @ApiParam(value = "通话状态", required = false) @RequestParam(required = false) String callStatus) {
         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);
         }
         }
-        Set<Long> examActivityIdSet = this.getExamActivityIds(examId);
-        QueryWrapper<TIeExamInvigilateCall> examInvigilateCallQueryWrapper = new QueryWrapper<>();
-        examInvigilateCallQueryWrapper.lambda().in(TIeExamInvigilateCall::getExamActivityId, examActivityIdSet).eq(TIeExamInvigilateCall::getStatus, MonitorStatusSourceEnum.START.name());
-        int count = tIeExamInvigilateCallService.count(examInvigilateCallQueryWrapper);
+        if (Objects.nonNull(callStatus) && !Objects.equals(callStatus, "")) {
+            MonitorCallStatusSourceEnum callStatusEnum = MonitorCallStatusSourceEnum.valueOf(callStatus);
+            callStatus = callStatusEnum.name();
+        }
+        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
+        AuthDto authDto = (AuthDto) redisUtil.get(SystemConstant.userOauth + "::" + tbUser.getId());
+        //如果有监考员角色,只能查看自己所监考的考场,巡考员和管理员则可以查看全部考场
+        Long userId = null;
+        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name())) {
+            userId = tbUser.getId();
+        }
+        int count = tIeExamInvigilateCallService.examInvigilateCallQueryCount(examId, userId, tbUser.getOrgId(), MonitorStatusSourceEnum.START.name(), callStatus);
         return ResultUtil.ok(Collections.singletonMap("count", count));
         return ResultUtil.ok(Collections.singletonMap("count", count));
     }
     }
 
 
@@ -160,50 +175,4 @@ public class TIeInvigilateCallMobileController {
         map.put("monitorUserSig", monitorUserSig);
         map.put("monitorUserSig", monitorUserSig);
         return ResultUtil.ok(map);
         return ResultUtil.ok(map);
     }
     }
-
-    /**
-     * 获取考试批次
-     *
-     * @param examId
-     * @return
-     */
-    public Set<Long> getExamActivityIds(Long examId) {
-        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
-        TBSession tbSession = (TBSession) ServletUtil.getRequestSession();
-        if (Objects.isNull(tbSession)) {
-            throw new BusinessException(ExceptionResultEnum.LOGIN_NO);
-        }
-        //首先查询当前用户所要监控的roomCode
-        QueryWrapper<TBExamInvigilateUser> examInvigilateUserQueryWrapper = new QueryWrapper<>();
-        AuthDto authDto = (AuthDto) redisUtil.get(SystemConstant.userOauth + "::" + tbUser.getId());
-        //如果有监考员角色,只能查看自己所监考的考场,巡考员和管理员则可以查看全部考场
-        examInvigilateUserQueryWrapper.lambda().eq(TBExamInvigilateUser::getOrgId, tbUser.getOrgId())
-                .eq(TBExamInvigilateUser::getExamId, examId);
-        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name())) {
-            examInvigilateUserQueryWrapper.lambda().eq(TBExamInvigilateUser::getUserId, tbUser.getId());
-        }
-        List<TBExamInvigilateUser> tbExamInvigilateUserList = tbExamInvigilateUserService.list(examInvigilateUserQueryWrapper);
-        Set<String> roomCodeSet = null;
-        if (Objects.nonNull(tbExamInvigilateUserList) && tbExamInvigilateUserList.size() > 0) {
-            roomCodeSet = tbExamInvigilateUserList.stream().map(s -> s.getRoomCode()).collect(Collectors.toSet());
-        }
-        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name()) && (Objects.isNull(roomCodeSet) || roomCodeSet.size() == 0)) {
-            throw new BusinessException("当前监考老师未设置任何监考考场");
-        } else if (Objects.isNull(roomCodeSet) || roomCodeSet.size() == 0) {
-            throw new BusinessException("当前考试批次未设置任何监考考场");
-        }
-        //根据roomCode获取当前老师所要监考的全部应考学生数
-        QueryWrapper<TEExamStudent> teExamStudentQueryWrapper = new QueryWrapper<>();
-        teExamStudentQueryWrapper.lambda().in(TEExamStudent::getRoomCode, roomCodeSet);
-        List<TEExamStudent> teExamStudentList = teExamStudentService.list(teExamStudentQueryWrapper);
-        Set<Long> examActivityIdSet = null;
-        if (Objects.nonNull(teExamStudentList) && teExamStudentList.size() > 0) {
-            examActivityIdSet = new HashSet<>();
-            Set<Long> finalExamActivityIdSet = examActivityIdSet;
-            teExamStudentList.forEach(s -> {
-                finalExamActivityIdSet.add(s.getExamActivityId());
-            });
-        }
-        return examActivityIdSet;
-    }
 }
 }

+ 46 - 5
themis-backend/src/main/java/com/qmth/themis/backend/api/TIeInvigilateWarnInfoController.java

@@ -1,29 +1,33 @@
 package com.qmth.themis.backend.api;
 package com.qmth.themis.backend.api;
 
 
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 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.ApiJsonProperty;
 import com.qmth.themis.business.base.BasePage;
 import com.qmth.themis.business.base.BasePage;
 import com.qmth.themis.business.bean.backend.InvigilateListWarningBean;
 import com.qmth.themis.business.bean.backend.InvigilateListWarningBean;
 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;
+import com.qmth.themis.business.dto.response.TIeWarningNotifyDto;
 import com.qmth.themis.business.entity.TBUser;
 import com.qmth.themis.business.entity.TBUser;
+import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
 import com.qmth.themis.business.enums.RoleEnum;
 import com.qmth.themis.business.enums.RoleEnum;
 import com.qmth.themis.business.service.TIeInvigilateWarnInfoService;
 import com.qmth.themis.business.service.TIeInvigilateWarnInfoService;
 import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.business.util.ServletUtil;
 import com.qmth.themis.business.util.ServletUtil;
-import com.qmth.themis.common.enums.ExceptionResultEnum;
 import com.qmth.themis.common.exception.BusinessException;
 import com.qmth.themis.common.exception.BusinessException;
 import com.qmth.themis.common.util.Result;
 import com.qmth.themis.common.util.Result;
 import com.qmth.themis.common.util.ResultUtil;
 import com.qmth.themis.common.util.ResultUtil;
 import io.swagger.annotations.*;
 import io.swagger.annotations.*;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 import java.util.Collections;
 import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Objects;
 
 
 /**
 /**
@@ -94,4 +98,41 @@ public class TIeInvigilateWarnInfoController {
         BasePage basePage = new BasePage(invigilateListWarningBeanIPage.getRecords(), invigilateListWarningBeanIPage.getCurrent(), invigilateListWarningBeanIPage.getSize(), invigilateListWarningBeanIPage.getTotal());
         BasePage basePage = new BasePage(invigilateListWarningBeanIPage.getRecords(), invigilateListWarningBeanIPage.getCurrent(), invigilateListWarningBeanIPage.getSize(), invigilateListWarningBeanIPage.getTotal());
         return ResultUtil.ok(basePage);
         return ResultUtil.ok(basePage);
     }
     }
+
+    @ApiOperation(value = "预警消息接口")
+    @RequestMapping(value = "/message", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "预警通知信息", response = TIeWarningNotifyDto.class)})
+    public Result warningMessage(@ApiParam(value = "考试批次id", required = false) @RequestParam(required = false) Long examId) {
+        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
+        AuthDto authDto = (AuthDto) redisUtil.get(SystemConstant.userOauth + "::" + tbUser.getId());
+        //如果有监考员角色,只能查看自己所监考的考场,巡考员和管理员则可以查看全部考场
+        Long userId = null;
+        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name())) {
+            userId = tbUser.getId();
+        }
+        return ResultUtil.ok(tIeInvigilateWarnInfoService.warningMessage(examId, userId, tbUser.getOrgId()));
+    }
+
+    @ApiOperation(value = "预警修改阅读状态接口")
+    @RequestMapping(value = "/save/status", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
+    @Transactional
+    public Result saveWarnStatus(@ApiJsonObject(name = "saveWarnStatus", value = {
+            @ApiJsonProperty(key = "warningId", type = "long", example = "1", description = "预警id", required = true),
+            @ApiJsonProperty(key = "approveStatus", type = "long", example = "1", description = "审阅状态,0:未阅,1:已阅", required = true)
+    }) @ApiParam(value = "监考员信息", required = true) @RequestBody Map<String, Object> mapParameter) {
+        if (Objects.isNull(mapParameter.get("warningIds")) || Objects.equals(mapParameter.get("warningIds"), "")) {
+            throw new BusinessException("预警id不能为空");
+        }
+        List<Long> warningIds = (List<Long>) mapParameter.get("warningIds");
+        if (Objects.isNull(mapParameter.get("approveStatus")) || Objects.equals(mapParameter.get("approveStatus"), "")) {
+            throw new BusinessException("审阅状态不能为空");
+        }
+        Integer approveStatus = Integer.parseInt(String.valueOf(mapParameter.get("approveStatus")));
+        UpdateWrapper<TIeInvigilateWarnInfo> tIeInvigilateWarnInfoUpdateWrapper = new UpdateWrapper<>();
+        tIeInvigilateWarnInfoUpdateWrapper.lambda().set(TIeInvigilateWarnInfo::getApproveStatus, approveStatus)
+                .in(TIeInvigilateWarnInfo::getId, warningIds);
+        tIeInvigilateWarnInfoService.update(tIeInvigilateWarnInfoUpdateWrapper);
+        return ResultUtil.ok(Collections.singletonMap("success", true));
+    }
 }
 }

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

@@ -71,6 +71,9 @@ public class StartRunning implements CommandLineRunner {
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.examRecordUpdateGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.EXAM_RECORD_UPDATE.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordUpdateConcurrentlyImpl.class));
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.examRecordUpdateGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.EXAM_RECORD_UPDATE.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordUpdateConcurrentlyImpl.class));
         //考试记录数据初始化
         //考试记录数据初始化
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.examRecordInitGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.EXAM_RECORD_INIT.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordInitConcurrentlyImpl.class));
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.examRecordInitGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.EXAM_RECORD_INIT.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamRecordInitConcurrentlyImpl.class));
+        
+        //考试重新算分
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.scoreCalculateGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.EXAM_SCORE_CALCULATE.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(CalculateScoreConcurrentlyImpl.class));
         SystemConstant.initTempFiles();
         SystemConstant.initTempFiles();
         log.info("服务器启动时执行 end");
         log.info("服务器启动时执行 end");
     }
     }

+ 22 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/backend/InvigilateListHistoryBean.java

@@ -72,6 +72,28 @@ public class InvigilateListHistoryBean implements Serializable {
     @ApiModelProperty(name = "更新时间")
     @ApiModelProperty(name = "更新时间")
     private Date updateTime;
     private Date updateTime;
 
 
+    @ApiModelProperty(name = "科目代码")
+    private String courseCode;
+
+    @ApiModelProperty(name = "联系电话")
+    private String mobileNumber;
+
+    public String getMobileNumber() {
+        return mobileNumber;
+    }
+
+    public void setMobileNumber(String mobileNumber) {
+        this.mobileNumber = mobileNumber;
+    }
+
+    public String getCourseCode() {
+        return courseCode;
+    }
+
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+
     public String getExamName() {
     public String getExamName() {
         return examName;
         return examName;
     }
     }

+ 33 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/backend/InvigilateListVideoBean.java

@@ -67,6 +67,39 @@ public class InvigilateListVideoBean implements Serializable {
     @ApiModelProperty(name = "更新时间")
     @ApiModelProperty(name = "更新时间")
     private Date updateTime;
     private Date updateTime;
 
 
+    @ApiModelProperty(name = "答题进度")
+    private Double progress;
+
+    @ApiModelProperty(name = "剩余时间")
+    private String remainTime;
+
+    @ApiModelProperty(name = "新增预警")
+    private Integer warningNew;
+
+    public Integer getWarningNew() {
+        return warningNew;
+    }
+
+    public void setWarningNew(Integer warningNew) {
+        this.warningNew = warningNew;
+    }
+
+    public String getRemainTime() {
+        return remainTime;
+    }
+
+    public void setRemainTime(String remainTime) {
+        this.remainTime = remainTime;
+    }
+
+    public Double getProgress() {
+        return progress;
+    }
+
+    public void setProgress(Double progress) {
+        this.progress = progress;
+    }
+
     public String getExamName() {
     public String getExamName() {
         return examName;
         return examName;
     }
     }

+ 11 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/backend/InvigilateListWarningBean.java

@@ -17,6 +17,9 @@ import java.util.Date;
 @ApiModel("预警提醒返回对象")
 @ApiModel("预警提醒返回对象")
 public class InvigilateListWarningBean implements Serializable {
 public class InvigilateListWarningBean implements Serializable {
 
 
+    @ApiModelProperty(name = "预警id")
+    private Long warningId;
+
     @ApiModelProperty(name = "考试id")
     @ApiModelProperty(name = "考试id")
     private Long examId;
     private Long examId;
 
 
@@ -77,6 +80,14 @@ public class InvigilateListWarningBean implements Serializable {
     @ApiModelProperty(value = "审阅状态,0:未阅,1:已阅")
     @ApiModelProperty(value = "审阅状态,0:未阅,1:已阅")
     private Integer approveStatus;
     private Integer approveStatus;
 
 
+    public Long getWarningId() {
+        return warningId;
+    }
+
+    public void setWarningId(Long warningId) {
+        this.warningId = warningId;
+    }
+
     public String getRoomName() {
     public String getRoomName() {
         return roomName;
         return roomName;
     }
     }

+ 17 - 3
themis-business/src/main/java/com/qmth/themis/business/dao/TIeExamInvigilateCallMapper.java

@@ -7,7 +7,6 @@ import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Param;
 
 
 import java.util.Map;
 import java.util.Map;
-import java.util.Set;
 
 
 /**
 /**
  * @Description: 监考 监控通话申请 Mapper 接口
  * @Description: 监考 监控通话申请 Mapper 接口
@@ -23,9 +22,24 @@ public interface TIeExamInvigilateCallMapper extends BaseMapper<TIeExamInvigilat
      * 监考监控通话申请查询
      * 监考监控通话申请查询
      *
      *
      * @param iPage
      * @param iPage
-     * @param examActivityIdSet
+     * @param examId
+     * @param userId
+     * @param orgId
      * @param status
      * @param status
+     * @param callStatus
      * @return
      * @return
      */
      */
-    public IPage<TIeExamInvigilateCall> examInvigilateCallQuery(IPage<Map> iPage, @Param("examActivityIdSet") Set<Long> examActivityIdSet, @Param("status") String status);
+    public IPage<TIeExamInvigilateCall> examInvigilateCallQuery(IPage<Map> iPage, @Param("examId") Long examId, @Param("userId") Long userId, @Param("orgId") Long orgId, @Param("status") String status, @Param("callStatus") String callStatus);
+
+    /**
+     * 监考监控通话count查询
+     *
+     * @param examId
+     * @param userId
+     * @param orgId
+     * @param status
+     * @param callStatus
+     * @return
+     */
+    public Integer examInvigilateCallQueryCount(@Param("examId") Long examId, @Param("userId") Long userId, @Param("orgId") Long orgId, @Param("status") String status, @Param("callStatus") String callStatus);
 }
 }

+ 13 - 0
themis-business/src/main/java/com/qmth/themis/business/dao/TIeInvigilateWarnInfoMapper.java

@@ -1,10 +1,13 @@
 package com.qmth.themis.business.dao;
 package com.qmth.themis.business.dao;
 
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.themis.business.dto.response.TIeWarningNotifyDto;
 import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
 import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Param;
 
 
+import java.util.List;
+
 /**
 /**
  * @Description: 监考预警信息 Mapper 接口
  * @Description: 监考预警信息 Mapper 接口
  * @Param:
  * @Param:
@@ -28,4 +31,14 @@ public interface TIeInvigilateWarnInfoMapper extends BaseMapper<TIeInvigilateWar
                                 @Param("examActivityId") Long examActivityId,
                                 @Param("examActivityId") Long examActivityId,
                                 @Param("roomCode") String roomCode,
                                 @Param("roomCode") String roomCode,
                                 @Param("userId") Long userId);
                                 @Param("userId") Long userId);
+
+    /**
+     * 预警通知
+     *
+     * @param examId
+     * @param userId
+     * @param orgId
+     * @return
+     */
+    public List<TIeWarningNotifyDto> warningMessage(@Param("examId") Long examId, @Param("userId") Long userId, @Param("orgId") Long orgId);
 }
 }

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

@@ -245,5 +245,9 @@ public interface TOeExamRecordMapper extends BaseMapper<TOeExamRecord> {
 	
 	
 	public List<Map<String,Object>> getDoneCountByDay(@Param("examId") Long examId, @Param("activityId") Long activityId,
 	public List<Map<String,Object>> getDoneCountByDay(@Param("examId") Long examId, @Param("activityId") Long activityId,
 			@Param("roomCode") String roomCode,@Param("courseCode")  String courseCode);
 			@Param("roomCode") String roomCode,@Param("courseCode")  String courseCode);
+
+	public Long getCountByExamId(@Param("examId") Long examId);
+	
+	public List<TOeExamRecord> getListByExamIdAndStartId(@Param("examId")Long examId,@Param("startId") Long startId);
 	
 	
 }
 }

+ 93 - 0
themis-business/src/main/java/com/qmth/themis/business/dto/response/TIeWarningNotifyDto.java

@@ -0,0 +1,93 @@
+package com.qmth.themis.business.dto.response;
+
+import com.qmth.themis.business.enums.WarningLevelEnum;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 预警通知response dto
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/9/10
+ */
+public class TIeWarningNotifyDto implements Serializable {
+
+    @ApiModelProperty(name = "考试批次id")
+    private Long examId;//考试批次id
+
+    @ApiModelProperty(name = "考生id")
+    private Long examStudentId;//考生id
+
+    @ApiModelProperty(name = "考生姓名")
+    private String name;//考生姓名
+
+    @ApiModelProperty(name = "预警内容")
+    private String info;//预警内容
+
+    @ApiModelProperty(name = "预警等级")
+    private WarningLevelEnum level;//预警等级
+
+    @ApiModelProperty(name = "预警id")
+    private Long warningId;//预警id
+
+    @ApiModelProperty(name = "预警备注")
+    private String remark;//预警备注
+
+    public Long getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
+
+    public Long getExamStudentId() {
+        return examStudentId;
+    }
+
+    public void setExamStudentId(Long examStudentId) {
+        this.examStudentId = examStudentId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getInfo() {
+        return info;
+    }
+
+    public void setInfo(String info) {
+        this.info = info;
+    }
+
+    public WarningLevelEnum getLevel() {
+        return level;
+    }
+
+    public void setLevel(WarningLevelEnum level) {
+        this.level = level;
+    }
+
+    public Long getWarningId() {
+        return warningId;
+    }
+
+    public void setWarningId(Long warningId) {
+        this.warningId = warningId;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+}

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

@@ -71,7 +71,12 @@ public enum MqGroupEnum {
     /**
     /**
      * 考试记录数据更新
      * 考试记录数据更新
      */
      */
-    examRecordUpdateGroup("themis-group-exam-examRecordUpdate");
+    examRecordUpdateGroup("themis-group-exam-examRecordUpdate"),
+	
+	/**
+     * 考试重新算分
+     */
+    scoreCalculateGroup("themis-group-exam-scoreCalculate");
 
 
     private MqGroupEnum(String code) {
     private MqGroupEnum(String code) {
         this.code = code;
         this.code = code;

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

@@ -38,7 +38,8 @@ public enum MqTagEnum {
     EXAM_RECORD_INIT("考试记录数据初始化", "考试", "normal", 26),
     EXAM_RECORD_INIT("考试记录数据初始化", "考试", "normal", 26),
     WARNING_LOG("预警标签", "预警", "normal", 27),
     WARNING_LOG("预警标签", "预警", "normal", 27),
     EXCEPTION_LOG("异常标签", "异常", "normal", 28),
     EXCEPTION_LOG("异常标签", "异常", "normal", 28),
-    MONITOR_LOG("监考监控标签", "监考监控", "normal", 29);
+    MONITOR_LOG("监考监控标签", "监考监控", "normal", 29),
+    EXAM_SCORE_CALCULATE("重新算分", "考试", "normal", 30);
 
 
     private MqTagEnum(String desc, String code, String type, int id) {
     private MqTagEnum(String desc, String code, String type, int id) {
         this.desc = desc;
         this.desc = desc;

+ 8 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TEExamService.java

@@ -187,4 +187,12 @@ public interface TEExamService extends IService<TEExam> {
      * @return
      * @return
      */
      */
     public List<TEExam> examPrivilegeQuery(Long userId);
     public List<TEExam> examPrivilegeQuery(Long userId);
+    
+	/**重新算分
+	 * @param examId
+	 * @param taskId
+	 */
+	void calculateScore(Long examId, Long taskId);
+	
+	
 }
 }

+ 17 - 3
themis-business/src/main/java/com/qmth/themis/business/service/TIeExamInvigilateCallService.java

@@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.qmth.themis.business.entity.TIeExamInvigilateCall;
 import com.qmth.themis.business.entity.TIeExamInvigilateCall;
 
 
 import java.util.Map;
 import java.util.Map;
-import java.util.Set;
 
 
 /**
 /**
  * @Description: 监考监控通话申请 服务类
  * @Description: 监考监控通话申请 服务类
@@ -20,9 +19,24 @@ public interface TIeExamInvigilateCallService extends IService<TIeExamInvigilate
      * 监考监控通话申请查询
      * 监考监控通话申请查询
      *
      *
      * @param iPage
      * @param iPage
-     * @param examActivityIdSet
+     * @param examId
+     * @param userId
+     * @param orgId
      * @param status
      * @param status
+     * @param callStatus
      * @return
      * @return
      */
      */
-    public IPage<TIeExamInvigilateCall> examInvigilateCallQuery(IPage<Map> iPage, Set<Long> examActivityIdSet, String status);
+    public IPage<TIeExamInvigilateCall> examInvigilateCallQuery(IPage<Map> iPage, Long examId, Long userId, Long orgId, String status, String callStatus);
+
+    /**
+     * 监考监控通话count查询
+     *
+     * @param examId
+     * @param userId
+     * @param orgId
+     * @param status
+     * @param callStatus
+     * @return
+     */
+    public Integer examInvigilateCallQueryCount(Long examId, Long userId, Long orgId, String status, String callStatus);
 }
 }

+ 12 - 2
themis-business/src/main/java/com/qmth/themis/business/service/TIeInvigilateWarnInfoService.java

@@ -1,10 +1,10 @@
 package com.qmth.themis.business.service;
 package com.qmth.themis.business.service;
 
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.themis.business.dto.response.TIeWarningNotifyDto;
 import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
 import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
-import org.apache.ibatis.annotations.Param;
 
 
-import java.util.Set;
+import java.util.List;
 
 
 /**
 /**
  * @Description: 监考预警信息 服务类
  * @Description: 监考预警信息 服务类
@@ -28,4 +28,14 @@ public interface TIeInvigilateWarnInfoService extends IService<TIeInvigilateWarn
                                 Long examActivityId,
                                 Long examActivityId,
                                 String roomCode,
                                 String roomCode,
                                 Long userId);
                                 Long userId);
+
+    /**
+     * 预警通知
+     *
+     * @param examId
+     * @param userId
+     * @param orgId
+     * @return
+     */
+    public List<TIeWarningNotifyDto> warningMessage(Long examId, Long userId, Long orgId);
 }
 }

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

@@ -1,15 +1,21 @@
 package com.qmth.themis.business.service;
 package com.qmth.themis.business.service;
 
 
+import java.util.List;
+import java.util.Map;
+
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.qmth.themis.business.bean.backend.*;
+import com.qmth.themis.business.bean.backend.InvigilateListBean;
+import com.qmth.themis.business.bean.backend.InvigilateListHistoryBean;
+import com.qmth.themis.business.bean.backend.InvigilateListPatrolBean;
+import com.qmth.themis.business.bean.backend.InvigilateListProgressBean;
+import com.qmth.themis.business.bean.backend.InvigilateListVideoBean;
+import com.qmth.themis.business.bean.backend.InvigilateListWarningBean;
 import com.qmth.themis.business.entity.TOeExamRecord;
 import com.qmth.themis.business.entity.TOeExamRecord;
 import com.qmth.themis.business.enums.ExamTypeEnum;
 import com.qmth.themis.business.enums.ExamTypeEnum;
 import com.qmth.themis.business.enums.LivenessTypeEnum;
 import com.qmth.themis.business.enums.LivenessTypeEnum;
 import com.qmth.themis.business.enums.VerifyExceptionEnum;
 import com.qmth.themis.business.enums.VerifyExceptionEnum;
 
 
-import java.util.Map;
-
 /**
 /**
  * @Description: 考试记录 服务类
  * @Description: 考试记录 服务类
  * @Param:
  * @Param:
@@ -292,4 +298,23 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
                                                                       String clientWebsocketStatus,
                                                                       String clientWebsocketStatus,
                                                                       String monitorStatusSource,
                                                                       String monitorStatusSource,
                                                                       Long userId);
                                                                       Long userId);
+
+
+	/**
+	 * 重新算分
+	 */
+	void calculateScore(Long recordId);
+
+	/**获取考试记录数
+	 * @param examId
+	 * @return
+	 */
+	Long getCountByExamId(Long examId);
+
+	/**批量获取考试记录
+	 * @param examId
+	 * @param startId
+	 * @return
+	 */
+	List<TOeExamRecord> getListByExamIdAndStartId(Long examId, Long startId);
 }
 }

+ 129 - 19
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -1,12 +1,53 @@
 package com.qmth.themis.business.service.impl;
 package com.qmth.themis.business.service.impl;
 
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.qmth.themis.business.bean.exam.*;
+import com.qmth.themis.business.bean.exam.AnswerSubmitBean;
+import com.qmth.themis.business.bean.exam.AudioLeftPlayCountSubmitBean;
+import com.qmth.themis.business.bean.exam.ExamFileUploadBean;
+import com.qmth.themis.business.bean.exam.ExamFinishBean;
+import com.qmth.themis.business.bean.exam.ExamPrepareBean;
+import com.qmth.themis.business.bean.exam.ExamResultBean;
+import com.qmth.themis.business.bean.exam.ExamResumeBean;
+import com.qmth.themis.business.bean.exam.ExamStartBean;
+import com.qmth.themis.business.bean.exam.StudentPaperStructBean;
 import com.qmth.themis.business.cache.ExamActivityRecordCacheUtil;
 import com.qmth.themis.business.cache.ExamActivityRecordCacheUtil;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.cache.RedisKeyHelper;
-import com.qmth.themis.business.cache.bean.*;
+import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
+import com.qmth.themis.business.cache.bean.ExamCacheBean;
+import com.qmth.themis.business.cache.bean.ExamCourseCacheBean;
+import com.qmth.themis.business.cache.bean.ExamPaperCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentAnswerCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentPaperStructCacheBean;
 import com.qmth.themis.business.config.SystemConfig;
 import com.qmth.themis.business.config.SystemConfig;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dao.TEExamMapper;
 import com.qmth.themis.business.dao.TEExamMapper;
@@ -16,30 +57,34 @@ import com.qmth.themis.business.dto.response.TEExamActivityDto;
 import com.qmth.themis.business.dto.response.TEExamDto;
 import com.qmth.themis.business.dto.response.TEExamDto;
 import com.qmth.themis.business.dto.response.TEExamQueryDto;
 import com.qmth.themis.business.dto.response.TEExamQueryDto;
 import com.qmth.themis.business.entity.TBSession;
 import com.qmth.themis.business.entity.TBSession;
+import com.qmth.themis.business.entity.TBTaskHistory;
 import com.qmth.themis.business.entity.TEExam;
 import com.qmth.themis.business.entity.TEExam;
 import com.qmth.themis.business.entity.TOeExamRecord;
 import com.qmth.themis.business.entity.TOeExamRecord;
-import com.qmth.themis.business.enums.*;
-import com.qmth.themis.business.service.*;
+import com.qmth.themis.business.enums.EntryAuthenticationPolicyEnum;
+import com.qmth.themis.business.enums.ExamRecordStatusEnum;
+import com.qmth.themis.business.enums.FinishExamResultEnum;
+import com.qmth.themis.business.enums.FinishTypeEnum;
+import com.qmth.themis.business.enums.HardwareTestEnum;
+import com.qmth.themis.business.enums.InvigilateVerifyEnum;
+import com.qmth.themis.business.enums.MonitorVideoSourceEnum;
+import com.qmth.themis.business.enums.MqTagEnum;
+import com.qmth.themis.business.enums.MqTopicEnum;
+import com.qmth.themis.business.enums.ReviewResultEnum;
+import com.qmth.themis.business.enums.SystemOperationEnum;
+import com.qmth.themis.business.enums.TaskStatusEnum;
+import com.qmth.themis.business.service.MqDtoService;
+import com.qmth.themis.business.service.TBTaskHistoryService;
+import com.qmth.themis.business.service.TEExamActivityService;
+import com.qmth.themis.business.service.TEExamCourseService;
+import com.qmth.themis.business.service.TEExamPaperService;
+import com.qmth.themis.business.service.TEExamService;
+import com.qmth.themis.business.service.TEExamStudentService;
+import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.OssUtil;
 import com.qmth.themis.business.util.OssUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.business.util.ServletUtil;
 import com.qmth.themis.business.util.ServletUtil;
 import com.qmth.themis.business.util.TencentYunUtil;
 import com.qmth.themis.business.util.TencentYunUtil;
 import com.qmth.themis.common.exception.BusinessException;
 import com.qmth.themis.common.exception.BusinessException;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.BeanUtils;
-import org.springframework.cache.annotation.CacheEvict;
-import org.springframework.cache.annotation.CachePut;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.annotation.Resource;
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.SimpleDateFormat;
-import java.util.*;
 
 
 /**
 /**
  * @Description: 考试批次 服务实现类
  * @Description: 考试批次 服务实现类
@@ -80,6 +125,9 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 
 
     @Resource
     @Resource
     TencentYunUtil tencentYunUtil;
     TencentYunUtil tencentYunUtil;
+    
+    @Resource
+    private TBTaskHistoryService tbTaskHistoryService;
 
 
     /**
     /**
      * 查询考试批次
      * 查询考试批次
@@ -901,4 +949,66 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         }
         }
         return ret;
         return ret;
     }
     }
+    
+    /**重新算分
+     * @param examId
+     * @param taskId
+     */
+    @Override
+    public void calculateScore(Long examId,Long taskId) {
+    	TBTaskHistory task=tbTaskHistoryService.getById(taskId);
+    	task.setStatus(TaskStatusEnum.RUNNING);
+    	tbTaskHistoryService.saveOrUpdate(task);
+    	Long recordId=null;
+    	try {
+    		Long startId=0L;
+    		Long index=0L;
+    		Long total=toeExamRecordService.getCountByExamId(examId);
+    		if(total>0) {
+    			for(;;) {
+	    			List<TOeExamRecord> list=toeExamRecordService.getListByExamIdAndStartId(examId, startId);
+	    			if(list==null||list.size()==0) {
+	    				break;
+	    			}
+	    			startId=list.get(list.size()-1).getId();
+	    			for(TOeExamRecord rc:list) {
+	    				index++;
+	    				if(ExamRecordStatusEnum.PERSISTED.equals(rc.getStatus())) {
+	    					toeExamRecordService.calculateScore(rc.getId());
+	    				}
+	    			}
+	    			task.setProgress(getPercentage(index, total));
+	    			tbTaskHistoryService.saveOrUpdate(task);
+    			}
+    		}
+			toeExamRecordService.calculateScore(recordId);
+			task.setSummary("处理成功");
+			task.setProgress(100.0);
+			task.setStatus(TaskStatusEnum.FINISH);
+			task.setFinishTime(new Date());
+		} catch (Exception e) {
+			log.error("重新算分出错 recordId:"+(recordId==null?"":recordId), e);
+			task.setSummary("处理出错");
+			task.setStatus(TaskStatusEnum.FINISH);
+			task.setFinishTime(new Date());
+		}
+    	tbTaskHistoryService.saveOrUpdate(task);
+    }
+    
+    private Double getPercentage(Long a, Long b) {
+        if (a == null) {
+            a = 0L;
+        }
+        if (b == null) {
+            return null;
+        }
+        if (b == 0) {
+            return null;
+        }
+        Double da = Double.valueOf(a);
+        Double db = Double.valueOf(b);
+        BigDecimal bd = new BigDecimal(da / db);
+        Double tem = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
+        return tem;
+    }
 }
 }

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

@@ -9,7 +9,6 @@ import org.springframework.stereotype.Service;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 import java.util.Map;
 import java.util.Map;
-import java.util.Set;
 
 
 /**
 /**
  * @Description: 监考监控通话申请 服务实现类
  * @Description: 监考监控通话申请 服务实现类
@@ -28,12 +27,30 @@ public class TIeExamInvigilateCallServiceImpl extends ServiceImpl<TIeExamInvigil
      * 监考监控通话申请查询
      * 监考监控通话申请查询
      *
      *
      * @param iPage
      * @param iPage
-     * @param examActivityIdSet
+     * @param examId
+     * @param userId
+     * @param orgId
      * @param status
      * @param status
+     * @param callStatus
      * @return
      * @return
      */
      */
     @Override
     @Override
-    public IPage<TIeExamInvigilateCall> examInvigilateCallQuery(IPage<Map> iPage, Set<Long> examActivityIdSet, String status) {
-        return tIeExamInvigilateCallMapper.examInvigilateCallQuery(iPage, examActivityIdSet, status);
+    public IPage<TIeExamInvigilateCall> examInvigilateCallQuery(IPage<Map> iPage, Long examId, Long userId, Long orgId, String status, String callStatus) {
+        return tIeExamInvigilateCallMapper.examInvigilateCallQuery(iPage, examId, userId, orgId, status, callStatus);
+    }
+
+    /**
+     * 监考监控通话count查询
+     *
+     * @param examId
+     * @param userId
+     * @param orgId
+     * @param status
+     * @param callStatus
+     * @return
+     */
+    @Override
+    public Integer examInvigilateCallQueryCount(Long examId, Long userId, Long orgId, String status, String callStatus) {
+        return tIeExamInvigilateCallMapper.examInvigilateCallQueryCount(examId, userId, orgId, status, callStatus);
     }
     }
 }
 }

+ 15 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TIeInvigilateWarnInfoServiceImpl.java

@@ -2,11 +2,13 @@ package com.qmth.themis.business.service.impl;
 
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.themis.business.dao.TIeInvigilateWarnInfoMapper;
 import com.qmth.themis.business.dao.TIeInvigilateWarnInfoMapper;
+import com.qmth.themis.business.dto.response.TIeWarningNotifyDto;
 import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
 import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
 import com.qmth.themis.business.service.TIeInvigilateWarnInfoService;
 import com.qmth.themis.business.service.TIeInvigilateWarnInfoService;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
+import java.util.List;
 
 
 /**
 /**
  * @Description: 监考预警信息 服务实现类
  * @Description: 监考预警信息 服务实现类
@@ -34,4 +36,17 @@ public class TIeInvigilateWarnInfoServiceImpl extends ServiceImpl<TIeInvigilateW
     public Integer warningCount(Long examId, Long examActivityId, String roomCode, Long userId) {
     public Integer warningCount(Long examId, Long examActivityId, String roomCode, Long userId) {
         return tIeInvigilateWarnInfoMapper.warningCount(examId, examActivityId, roomCode, userId);
         return tIeInvigilateWarnInfoMapper.warningCount(examId, examActivityId, roomCode, userId);
     }
     }
+
+    /**
+     * 预警通知
+     *
+     * @param examId
+     * @param userId
+     * @param orgId
+     * @return
+     */
+    @Override
+    public List<TIeWarningNotifyDto> warningMessage(Long examId, Long userId, Long orgId) {
+        return tIeInvigilateWarnInfoMapper.warningMessage(examId, userId, orgId);
+    }
 }
 }

+ 70 - 15
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -1,12 +1,39 @@
 package com.qmth.themis.business.service.impl;
 package com.qmth.themis.business.service.impl;
 
 
+import java.io.File;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+
+import javax.annotation.Resource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.qmth.themis.business.bean.backend.*;
+import com.qmth.themis.business.bean.backend.InvigilateListBean;
+import com.qmth.themis.business.bean.backend.InvigilateListHistoryBean;
+import com.qmth.themis.business.bean.backend.InvigilateListPatrolBean;
+import com.qmth.themis.business.bean.backend.InvigilateListProgressBean;
+import com.qmth.themis.business.bean.backend.InvigilateListVideoBean;
+import com.qmth.themis.business.bean.backend.InvigilateListWarningBean;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.cache.RedisKeyHelper;
-import com.qmth.themis.business.cache.bean.*;
+import com.qmth.themis.business.cache.bean.ExamCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentAnswerCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentPaperStructCacheBean;
+import com.qmth.themis.business.cache.bean.ObjectiveAnswerCacheBean;
 import com.qmth.themis.business.config.SystemConfig;
 import com.qmth.themis.business.config.SystemConfig;
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.constant.SystemConstant;
@@ -16,24 +43,24 @@ import com.qmth.themis.business.dto.response.TEExamUnFinishDto;
 import com.qmth.themis.business.entity.TEExamStudent;
 import com.qmth.themis.business.entity.TEExamStudent;
 import com.qmth.themis.business.entity.TOeExamAnswer;
 import com.qmth.themis.business.entity.TOeExamAnswer;
 import com.qmth.themis.business.entity.TOeExamRecord;
 import com.qmth.themis.business.entity.TOeExamRecord;
-import com.qmth.themis.business.enums.*;
-import com.qmth.themis.business.service.*;
+import com.qmth.themis.business.enums.ExamRecordStatusEnum;
+import com.qmth.themis.business.enums.ExamTypeEnum;
+import com.qmth.themis.business.enums.LivenessTypeEnum;
+import com.qmth.themis.business.enums.MqTagEnum;
+import com.qmth.themis.business.enums.MqTopicEnum;
+import com.qmth.themis.business.enums.ObjectiveScorePolicyEnum;
+import com.qmth.themis.business.enums.VerifyExceptionEnum;
+import com.qmth.themis.business.service.MqDtoService;
+import com.qmth.themis.business.service.TEExamPaperService;
+import com.qmth.themis.business.service.TEExamService;
+import com.qmth.themis.business.service.TEExamStudentService;
+import com.qmth.themis.business.service.TOeExamAnswerService;
+import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.OssUtil;
 import com.qmth.themis.business.util.OssUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.common.contanst.Constants;
 import com.qmth.themis.common.contanst.Constants;
 import com.qmth.themis.common.util.FileUtil;
 import com.qmth.themis.common.util.FileUtil;
 import com.qmth.themis.common.util.SimpleBeanUtil;
 import com.qmth.themis.common.util.SimpleBeanUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.BeanUtils;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.annotation.Resource;
-import java.io.File;
-import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.util.*;
 
 
 /**
 /**
  * @Description: 考试记录 服务实现类
  * @Description: 考试记录 服务实现类
@@ -562,4 +589,32 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
     public IPage<InvigilateListHistoryBean> invigilatePageListHistory(IPage<Map> iPage, Long examId, Long examActivityId, String roomCode, String courseCode, String status, Integer breachStatus, String finishType, String name, String identity, Integer minMultipleFaceCount, Integer maxMultipleFaceCount, Integer minExceptionCount, Integer maxExceptionCount, Integer minWarningCount, Integer maxWarningCount, String clientWebsocketStatus, String monitorStatusSource, Long userId) {
     public IPage<InvigilateListHistoryBean> invigilatePageListHistory(IPage<Map> iPage, Long examId, Long examActivityId, String roomCode, String courseCode, String status, Integer breachStatus, String finishType, String name, String identity, Integer minMultipleFaceCount, Integer maxMultipleFaceCount, Integer minExceptionCount, Integer maxExceptionCount, Integer minWarningCount, Integer maxWarningCount, String clientWebsocketStatus, String monitorStatusSource, Long userId) {
         return tOeExamRecordMapper.invigilatePageListHistory(iPage, examId, examActivityId, roomCode, courseCode, status, breachStatus, finishType, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount, maxExceptionCount, minWarningCount, maxWarningCount, clientWebsocketStatus, monitorStatusSource, userId);
         return tOeExamRecordMapper.invigilatePageListHistory(iPage, examId, examActivityId, roomCode, courseCode, status, breachStatus, finishType, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount, maxExceptionCount, minWarningCount, maxWarningCount, clientWebsocketStatus, monitorStatusSource, userId);
     }
     }
+    
+    /**
+     * 重新算分
+     */
+    @Transactional
+    @Override
+    public void calculateScore(Long recordId) {
+    	//TODO
+    }
+    
+    /**获取考试记录数
+     * @param examId
+     * @return
+     */
+    @Override
+    public Long getCountByExamId(Long examId) {
+    	return tOeExamRecordMapper.getCountByExamId(examId);
+    }
+    
+    /**批量获取考试记录
+     * @param examId
+     * @param startId
+     * @return
+     */
+    @Override
+    public List<TOeExamRecord> getListByExamIdAndStartId(Long examId,Long startId) {
+    	return tOeExamRecordMapper.getListByExamIdAndStartId(examId, startId);
+    }
 }
 }

+ 2 - 1
themis-business/src/main/resources/mapper/TEExamReexamMapper.xml

@@ -13,7 +13,8 @@
             teer.exam_student_id as examStudentId,
             teer.exam_student_id as examStudentId,
             teer.exam_record_id as examRecordId,
             teer.exam_record_id as examRecordId,
             tees.course_code as courseCode,
             tees.course_code as courseCode,
-            tees.course_name as courseName
+            tees.course_name as courseName,
+            teer.exam_id as examId
         from
         from
             t_e_exam_reexam teer
             t_e_exam_reexam teer
             left join t_e_exam_student tees on
             left join t_e_exam_student tees on

+ 46 - 4
themis-business/src/main/resources/mapper/TIeExamInvigilateCallMapper.xml

@@ -7,14 +7,56 @@
             tieic.*
             tieic.*
         from
         from
             t_ie_exam_invigilate_call tieic
             t_ie_exam_invigilate_call tieic
+        left join t_e_exam_student tees on
+            tees.id = tieic.exam_student_id
+        left join t_b_exam_invigilate_user tbeiu on
+            tbeiu.exam_id = tieic.exam_id
+        and tbeiu.room_code = tees.room_code
         <where>
         <where>
-            tieic.exam_activity_id in
-            <foreach collection="examActivityIdSet" item="examActivityId" index="index" open="(" close=")" separator=",">
-                #{examActivityId}
-            </foreach>
+            <if test="examId != null and examId != ''">
+                and tieic.exam_id = #{examId}
+            </if>
+            <if test="userId != null and userId != ''">
+                and tbeiu.user_id = #{userId}
+            </if>
+            <if test="orgId != null and orgId != ''">
+                and tbeiu.org_id = #{orgId}
+            </if>
             <if test="status != null and status != ''">
             <if test="status != null and status != ''">
                 and tieic.status = #{status}
                 and tieic.status = #{status}
             </if>
             </if>
+            <if test="callStatus != null and callStatus != ''">
+                and tieic.call_status = #{callStatus}
+            </if>
+        </where>
+    </select>
+
+    <select id="examInvigilateCallQueryCount" resultType="java.lang.Integer">
+        select
+        count(1)
+        from
+        t_ie_exam_invigilate_call tieic
+        left join t_e_exam_student tees on
+        tees.id = tieic.exam_student_id
+        left join t_b_exam_invigilate_user tbeiu on
+        tbeiu.exam_id = tieic.exam_id
+        and tbeiu.room_code = tees.room_code
+        <where>
+            <if test="examId != null and examId != ''">
+                and tieic.exam_id = #{examId}
+            </if>
+            <if test="userId != null and userId != ''">
+                and tbeiu.user_id = #{userId}
+            </if>
+            <if test="orgId != null and orgId != ''">
+                and tbeiu.org_id = #{orgId}
+            </if>
+            <if test="status != null and status != ''">
+                and tieic.status = #{status}
+            </if>
+            <if test="callStatus != null and callStatus != ''">
+                and tieic.call_status = #{callStatus}
+            </if>
         </where>
         </where>
     </select>
     </select>
 </mapper>
 </mapper>

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

@@ -25,4 +25,34 @@
             and tiiwi.approve_status = 0
             and tiiwi.approve_status = 0
         </where>
         </where>
     </select>
     </select>
+
+    <select id="warningMessage" resultType="com.qmth.themis.business.dto.response.TIeWarningNotifyDto">
+        select
+            tees.id as examStudentId,
+            tees.name,
+            tiiwi.info,
+            tiiwi.`level`,
+            tiiwi.id as warningId,
+            tiiwi.remark,
+            tiiwi.exam_id as examId
+        from
+            t_ie_invigilate_warn_info tiiwi
+        left join t_e_exam_student tees on
+            tees.id = tiiwi.exam_student_id
+        left join t_b_exam_invigilate_user tbeiu on
+            tbeiu.exam_id = tiiwi.exam_id
+            and tbeiu.room_code = tees.room_code
+        <where>
+            <if test="examId != null and examId != ''">
+                and tiiwi.exam_id = #{examId}
+            </if>
+            <if test="userId != null and userId != ''">
+                and tbeiu.user_id = #{userId}
+            </if>
+            <if test="orgId != null and orgId != ''">
+                and tbeiu.org_id = #{orgId}
+            </if>
+            and tiiwi.approve_status = 0
+        </where>
+    </select>
 </mapper>
 </mapper>

+ 425 - 382
themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml

@@ -1,401 +1,444 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper
 <mapper
-        namespace="com.qmth.themis.business.dao.TOeExamRecordMapper">
+	namespace="com.qmth.themis.business.dao.TOeExamRecordMapper">
 
 
-    <select id="getUnFinishExam"
-            resultType="com.qmth.themis.business.dto.response.TEExamUnFinishDto">
-        select
-        tee.id,
-        teea.id as examActivityId,
-        toer.id as recordId,
-        tees.id as
-        examStudentId,
-        tee.name,
-        tee.mode,
-        tee.pre_notice as preNotice,
-        tee.pre_notice_stay_seconds as preNoticeStaySeconds,
-        tee.post_notice as
-        postNotice,
-        tee.code as examCode,
-        teea.code as examActivityCode,
-        tee.start_time as examStartTime,
-        tee.end_time as examEndTime,
-        teea.start_time as examActivityStartTime,
-        teea.finish_time as
-        examActivityFinishTime,
-        tees.course_code as courseCode,
-        teec.course_name as courseName,
-        tee.prepare_seconds as prepareSeconds,
-        tee.min_duration_seconds as minDurationSeconds,
-        tee.max_duration_seconds as maxDurationSeconds,
-        tee.exam_count as
-        examCount,
-        tee.force_finish as fouceFinish,
-        tee.entry_authentication_policy as entryAuthenticationPolicy,
-        tee.in_process_face_verify as inProcessFaceVerify,
-        tee.in_process_face_stranger_ignore as inProcessFaceStrangerIgnore,
-        tee.in_process_liveness_verify as inProcessLivenessVerify,
-        tee.in_process_liveness_fixed_range as inProcessLivenessFixedRange,
-        tee.in_process_liveness_judge_policy as inProcessLivenessJudgePolicy,
-        tee.camera_photo_upload as cameraPhotoUpload,
-        tee.mobile_photo_upload
-        as mobilePhotoUpload,
-        tee.break_expire_seconds as breakExpireSeconds,
-        tee.break_resume_count as breakResumeCount,
-        toer.duration_seconds as
-        durationSeconds,
-        toer.client_last_sync_time as clientLastSyncTime
-        from
-        t_oe_exam_record toer
-        left join t_e_exam_student tees on
-        tees.id =
-        toer.exam_student_id
-        left join t_e_exam_course teec on
-        teec.course_code
-        = tees.course_code
-        left join t_e_exam tee on
-        tee.id = tees.exam_id
-        left
-        join t_e_exam_activity teea on
-        teea.id = tees.exam_activity_id
-        <where>
-            <if test="studentId != null and studentId != ''">
-                and tees.student_id = #{studentId}
-            </if>
-            and tee.enable = 1
-            and teea.enable = 1
-            and tees.enable = 1
-            <if test="orgId != null and orgId != ''">
-                and tee.org_id = #{orgId}
-            </if>
-            <if test="examId != null and examId != ''">
-                and tee.id = #{examId}
-            </if>
-        </where>
-    </select>
+	<select id="getUnFinishExam"
+		resultType="com.qmth.themis.business.dto.response.TEExamUnFinishDto">
+		select
+		tee.id,
+		teea.id as examActivityId,
+		toer.id as recordId,
+		tees.id as
+		examStudentId,
+		tee.name,
+		tee.mode,
+		tee.pre_notice as preNotice,
+		tee.pre_notice_stay_seconds as preNoticeStaySeconds,
+		tee.post_notice as
+		postNotice,
+		tee.code as examCode,
+		teea.code as examActivityCode,
+		tee.start_time as examStartTime,
+		tee.end_time as examEndTime,
+		teea.start_time as examActivityStartTime,
+		teea.finish_time as
+		examActivityFinishTime,
+		tees.course_code as courseCode,
+		teec.course_name as courseName,
+		tee.prepare_seconds as prepareSeconds,
+		tee.min_duration_seconds as minDurationSeconds,
+		tee.max_duration_seconds as maxDurationSeconds,
+		tee.exam_count as
+		examCount,
+		tee.force_finish as fouceFinish,
+		tee.entry_authentication_policy as entryAuthenticationPolicy,
+		tee.in_process_face_verify as inProcessFaceVerify,
+		tee.in_process_face_stranger_ignore as inProcessFaceStrangerIgnore,
+		tee.in_process_liveness_verify as inProcessLivenessVerify,
+		tee.in_process_liveness_fixed_range as inProcessLivenessFixedRange,
+		tee.in_process_liveness_judge_policy as inProcessLivenessJudgePolicy,
+		tee.camera_photo_upload as cameraPhotoUpload,
+		tee.mobile_photo_upload
+		as mobilePhotoUpload,
+		tee.break_expire_seconds as breakExpireSeconds,
+		tee.break_resume_count as breakResumeCount,
+		toer.duration_seconds as
+		durationSeconds,
+		toer.client_last_sync_time as clientLastSyncTime
+		from
+		t_oe_exam_record toer
+		left join t_e_exam_student tees on
+		tees.id =
+		toer.exam_student_id
+		left join t_e_exam_course teec on
+		teec.course_code
+		= tees.course_code
+		left join t_e_exam tee on
+		tee.id = tees.exam_id
+		left
+		join t_e_exam_activity teea on
+		teea.id = tees.exam_activity_id
+		<where>
+			<if test="studentId != null and studentId != ''">
+				and tees.student_id = #{studentId}
+			</if>
+			and tee.enable = 1
+			and teea.enable = 1
+			and tees.enable = 1
+			<if test="orgId != null and orgId != ''">
+				and tee.org_id = #{orgId}
+			</if>
+			<if test="examId != null and examId != ''">
+				and tee.id = #{examId}
+			</if>
+		</where>
+	</select>
 
 
-    <update id="dataUpdate">
+	<update id="dataUpdate">
 		update t_oe_exam_record t set
 		update t_oe_exam_record t set
 		t.${colName}=#{colValue} where t.id=#{recordId}
 		t.${colName}=#{colValue} where t.id=#{recordId}
 	</update>
 	</update>
 
 
-    <sql id="invigilatePageHead">
-        select
-            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_name roomName,
-            s.name name,
-            s.course_name courseName,
-            s.course_code courseCode,
-            IFNULL(t.paper_download,1) paperDownload,
-            t.status statusCode,
-            t.answer_progress progress,
-            IFNULL(t.client_current_ip,'无') clientCurrentIp,
-            IFNULL(t.warning_count,0) as warningCount,
-            IFNULL(t.breach_status,1) as breachStatus,
-            IFNULL(t.client_websocket_status,'OFF_LINE') as clientWebsocketStatus,
-            IFNULL(t.monitor_status_source,'STOP') as monitorStatusSource,
-            t.client_last_sync_time as updateTime
-    </sql>
+	<sql id="invigilatePageHead">
+		select
+		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_name roomName,
+		s.name name,
+		s.course_name courseName,
+		s.course_code courseCode,
+		IFNULL(t.paper_download,1) paperDownload,
+		t.status statusCode,
+		t.answer_progress progress,
+		IFNULL(t.client_current_ip,'无') clientCurrentIp,
+		IFNULL(t.warning_count,0) as warningCount,
+		IFNULL(t.breach_status,1) as breachStatus,
+		IFNULL(t.client_websocket_status,'OFF_LINE') as clientWebsocketStatus,
+		IFNULL(t.monitor_status_source,'STOP') as monitorStatusSource,
+		t.client_last_sync_time as updateTime
+	</sql>
 
 
-    <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 tee on tee.id = t.exam_id
-        left join t_e_exam_activity teea on teea.id = t.exam_activity_id
-        inner join (select toer.id from t_oe_exam_record toer where EXISTS(select tees.id from t_e_exam_student tees where EXISTS (select distinct tbeiu.room_code from t_b_exam_invigilate_user tbeiu
-        where
-        <if test="userId != null and userId != ''">
-            tbeiu.user_id = #{userId} and
-        </if>
-        tbeiu.room_code = tees.room_code and toer.exam_student_id = tees.id))) t1 on t1.id = t.id
-    </sql>
+	<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 tee on tee.id = t.exam_id
+		left join t_e_exam_activity teea on teea.id = t.exam_activity_id
+		inner join (select toer.id from t_oe_exam_record toer where EXISTS(select
+		tees.id from t_e_exam_student tees where EXISTS (select distinct
+		tbeiu.room_code from t_b_exam_invigilate_user tbeiu
+		where
+		<if test="userId != null and userId != ''">
+			tbeiu.user_id = #{userId} and
+		</if>
+		tbeiu.room_code = tees.room_code and toer.exam_student_id = tees.id)))
+		t1 on t1.id = t.id
+	</sql>
 
 
-    <sql id="invigilatePageFoot">
-        <where>
-            <if test="examId != null and examId != ''">
-                and t.exam_id = #{examId}
-            </if>
-            <if test="examActivityId != null and examActivityId != ''">
-                and t.exam_activity_id = #{examActivityId}
-            </if>
-            <if test="roomCode != null and roomCode != ''">
-                and s.room_code = #{roomCode}
-            </if>
-            <if test="status != null and status != ''">
-                <choose>
-                    <when test="status == EXAMING">
-                        and (t.status = 'ANSWERING' or t.status = 'RESUME_PREPARE')
-                    </when>
-                    <otherwise>
-                        and t.status = #{status}
-                    </otherwise>
-                </choose>
-            </if>
-            <if test="name != null and name !=''">
-                and s.name like CONCAT('%', #{name},'%')
-            </if>
-            <if test="identity != null and identity !=''">
-                and s.identity like CONCAT('%', #{identity},'%')
-            </if>
-            <if test="maxWarningCount != null and maxWarningCount != ''">
-                and t.warning_count &lt;= #{maxWarningCount}
-            </if>
-            <if test="minWarningCount != null and minWarningCount != ''">
-                and t.warning_count &gt;= #{minWarningCount}
-            </if>
-            <if test="clientWebsocketStatus != null and clientWebsocketStatus != ''">
-                and t.client_websocket_status = #{clientWebsocketStatus}
-            </if>
-            <if test="monitorStatusSource != null and monitorStatusSource != ''">
-                and t.monitor_status_source = #{monitorStatusSource}
-            </if>
-                and s.enable = 1
-                and tee.enable = 1
-                and teea.enable = 1
-                and teea.finish_time > now()
-        </where>
-    </sql>
+	<sql id="invigilatePageFoot">
+		<where>
+			<if test="examId != null and examId != ''">
+				and t.exam_id = #{examId}
+			</if>
+			<if test="examActivityId != null and examActivityId != ''">
+				and t.exam_activity_id = #{examActivityId}
+			</if>
+			<if test="roomCode != null and roomCode != ''">
+				and s.room_code = #{roomCode}
+			</if>
+			<if test="status != null and status != ''">
+				<choose>
+					<when test="status == EXAMING">
+						and (t.status = 'ANSWERING' or t.status = 'RESUME_PREPARE')
+					</when>
+					<otherwise>
+						and t.status = #{status}
+					</otherwise>
+				</choose>
+			</if>
+			<if test="name != null and name !=''">
+				and s.name like CONCAT('%', #{name},'%')
+			</if>
+			<if test="identity != null and identity !=''">
+				and s.identity like CONCAT('%', #{identity},'%')
+			</if>
+			<if test="maxWarningCount != null and maxWarningCount != ''">
+				and t.warning_count &lt;= #{maxWarningCount}
+			</if>
+			<if test="minWarningCount != null and minWarningCount != ''">
+				and t.warning_count &gt;= #{minWarningCount}
+			</if>
+			<if
+				test="clientWebsocketStatus != null and clientWebsocketStatus != ''">
+				and t.client_websocket_status = #{clientWebsocketStatus}
+			</if>
+			<if
+				test="monitorStatusSource != null and monitorStatusSource != ''">
+				and t.monitor_status_source = #{monitorStatusSource}
+			</if>
+			and s.enable = 1
+			and tee.enable = 1
+			and teea.enable = 1
+			and teea.finish_time > now()
+		</where>
+	</sql>
 
 
-    <select id="invigilatePageList" resultType="com.qmth.themis.business.bean.backend.InvigilateListBean">
-        <include refid="invigilatePageHead" />
-        ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.approve_status = 0) as warningNew
-        ,date_format(date_sub(date_add(teea.start_time, interval IFNULL(teea.max_duration_seconds, tee.max_duration_seconds) second), interval teea.max_duration_seconds / 60 - t.duration_seconds minute),'%H:%i:%s') as remainTime
-        <include refid="invigilatePageMiddle" />
-        <include refid="invigilatePageFoot" />
-        <if test="paperDownload != null and paperDownload != ''">
-            and t.paper_download = #{paperDownload}
-        </if>
-        order by s.room_code
-    </select>
+	<select id="invigilatePageList"
+		resultType="com.qmth.themis.business.bean.backend.InvigilateListBean">
+		<include refid="invigilatePageHead" />
+		,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.approve_status = 0) as warningNew
+		,date_format(date_sub(date_add(teea.start_time, interval IFNULL(teea.max_duration_seconds, tee.max_duration_seconds) second), interval teea.max_duration_seconds / 60 - t.duration_seconds minute),'%H:%i:%s') as remainTime
+		<include refid="invigilatePageMiddle" />
+		<include refid="invigilatePageFoot" />
+		<if test="paperDownload != null and paperDownload != ''">
+			and t.paper_download = #{paperDownload}
+		</if>
+		order by s.room_code
+	</select>
 
 
-    <select id="invigilatePageListVideo" resultType="com.qmth.themis.business.bean.backend.InvigilateListVideoBean">
-        <include refid="invigilatePageHead" />
-        ,t.monitor_live_url as monitorLiveUrl
-        <include refid="invigilatePageMiddle" />
-        <include refid="invigilatePageFoot" />
-        <if test="paperDownload != null and paperDownload != ''">
-            and t.paper_download = #{paperDownload}
-        </if>
-        order by s.room_code
-    </select>
+	<select id="invigilatePageListVideo"
+		resultType="com.qmth.themis.business.bean.backend.InvigilateListVideoBean">
+		<include refid="invigilatePageHead" />
+		,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
+		,date_format(date_sub(date_add(teea.start_time, interval IFNULL(teea.max_duration_seconds, tee.max_duration_seconds) second), interval teea.max_duration_seconds / 60 - t.duration_seconds minute),'%H:%i:%s') as remainTime
+		<include refid="invigilatePageMiddle" />
+		<include refid="invigilatePageFoot" />
+		<if test="paperDownload != null and paperDownload != ''">
+			and t.paper_download = #{paperDownload}
+		</if>
+		order by s.room_code
+	</select>
 
 
-    <select id="invigilatePagePatrolList" resultType="com.qmth.themis.business.bean.backend.InvigilateListPatrolBean">
-        select * 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_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.`type` =
-        'FACE_COUNT_ERROR' and tiiwi.`level` = 'D8') as multipleFaceCount
-        <include refid="invigilatePageMiddle"/>
-        <include refid="invigilatePageFoot" />
-            ) t
-        <where>
-            <if test="minMultipleFaceCount != null and minMultipleFaceCount != ''">
-                and t.multipleFaceCount &lt;= #{minMultipleFaceCount}
-            </if>
-            <if test="maxMultipleFaceCount != null and maxMultipleFaceCount != ''">
-                and t.multipleFaceCount &gt;= #{maxMultipleFaceCount}
-            </if>
-            <if test="minExceptionCount != null and minExceptionCount != ''">
-                and t.exceptionCount &lt;= #{minExceptionCount}
-            </if>
-            <if test="maxExceptionCount != null and maxExceptionCount != ''">
-                and t.exceptionCount &gt;= #{maxExceptionCount}
-            </if>
-        </where>
-        order by t.roomCode
-    </select>
+	<select id="invigilatePagePatrolList"
+		resultType="com.qmth.themis.business.bean.backend.InvigilateListPatrolBean">
+		select * 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_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.`type` =
+		'FACE_COUNT_ERROR' and tiiwi.`level` = 'D8') as multipleFaceCount
+		<include refid="invigilatePageMiddle" />
+		<include refid="invigilatePageFoot" />
+		) t
+		<where>
+			<if
+				test="minMultipleFaceCount != null and minMultipleFaceCount != ''">
+				and t.multipleFaceCount &lt;= #{minMultipleFaceCount}
+			</if>
+			<if
+				test="maxMultipleFaceCount != null and maxMultipleFaceCount != ''">
+				and t.multipleFaceCount &gt;= #{maxMultipleFaceCount}
+			</if>
+			<if test="minExceptionCount != null and minExceptionCount != ''">
+				and t.exceptionCount &lt;= #{minExceptionCount}
+			</if>
+			<if test="maxExceptionCount != null and maxExceptionCount != ''">
+				and t.exceptionCount &gt;= #{maxExceptionCount}
+			</if>
+		</where>
+		order by t.roomCode
+	</select>
 
 
-    <select id="invigilatePageWarningList" resultType="com.qmth.themis.business.bean.backend.InvigilateListWarningBean">
-        select * from(select
-           tee.id as examId,
-           tee.name as examName,
-           teea.id as examActivityId,
-           tees.id as examStudentId,
-           teea.code as examActivityCode,
-           tees.room_code as roomCode,
-           tees.room_name as roomName,
-           toer.id as examRecordId,
-           tees.`identity`,
-           tees.name,
-           tees.course_code as courseCode,
-           tees.course_name as courseName,
-           toer.status as statusCode,
-           IFNULL(toer.warning_count,0) as warningCount,
-           IFNULL(toer.breach_status,1) as breachStatus,
-           toer.client_last_sync_time as updateTime,
-           tiiwi.approve_status as approveStatus
-           ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = toer.id and tiiwi.`type` =
-            'FACE_COUNT_ERROR' and tiiwi.`level` = 'D8') as multipleFaceCount
-           ,(select count(1) from t_ie_invigilate_exception_info tiiei where tiiei.exam_record_id = toer.id) as exceptionCount
-         from t_ie_invigilate_warn_info tiiwi
-        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
-        inner join (select toer.id from t_oe_exam_record toer where EXISTS(select tees.id from t_e_exam_student tees where EXISTS (select distinct tbeiu.room_code from t_b_exam_invigilate_user tbeiu
-        where
-        <if test="userId != null and userId != ''">
-            tbeiu.user_id = #{userId} and
-        </if>
-        tbeiu.room_code = tees.room_code and toer.exam_student_id = tees.id))) t on t.id = tiiwi.exam_record_id
-        left join t_oe_exam_record toer on toer.id  = t.id
-        left join t_e_exam_student tees on tees.id = tiiwi.exam_student_id
-        <where>
-                <if test="examId != null and examId != ''">
-                    and tiiwi.exam_id = #{examId}
-                </if>
-                <if test="examActivityId != null and examActivityId != ''">
-                    and tiiwi.exam_activity_id = #{examActivityId}
-                </if>
-                <if test="roomCode != null and roomCode != ''">
-                    and tees.room_code = #{roomCode}
-                </if>
-                <if test="approveStatus != null and approveStatus != ''">
-                    and tiiwi.approve_status = #{approveStatus}
-                </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 != ''">
-                    and toer.warning_count &lt;= #{maxWarningCount}
-                </if>
-                <if test="minWarningCount != null and minWarningCount != ''">
-                    and toer.warning_count &gt;= #{minWarningCount}
-                </if>
-                <if test="clientWebsocketStatus != null and clientWebsocketStatus != ''">
-                    and toer.client_websocket_status = #{clientWebsocketStatus}
-                </if>
-                <if test="monitorStatusSource != null and monitorStatusSource != ''">
-                    and toer.monitor_status_source = #{monitorStatusSource}
-                </if>
-                    and tee.enable = 1
-                    and teea.enable = 1
-                    and tees.enable = 1
-            </where>
-        ) t
-        <where>
-            <if test="minMultipleFaceCount != null and minMultipleFaceCount != ''">
-                and t.multipleFaceCount &lt;= #{minMultipleFaceCount}
-            </if>
-            <if test="maxMultipleFaceCount != null and maxMultipleFaceCount != ''">
-                and t.multipleFaceCount &gt;= #{maxMultipleFaceCount}
-            </if>
-            <if test="minExceptionCount != null and minExceptionCount != ''">
-                and t.exceptionCount &lt;= #{minExceptionCount}
-            </if>
-            <if test="maxExceptionCount != null and maxExceptionCount != ''">
-                and t.exceptionCount &gt;= #{maxExceptionCount}
-            </if>
-        </where>
-        order by t.roomCode
-    </select>
+	<select id="invigilatePageWarningList"
+		resultType="com.qmth.themis.business.bean.backend.InvigilateListWarningBean">
+		select * from(select
+		tiiwi.id as warningId,
+		tee.id as examId,
+		tee.name as examName,
+		teea.id as examActivityId,
+		tees.id as examStudentId,
+		teea.code as examActivityCode,
+		tees.room_code as roomCode,
+		tees.room_name as roomName,
+		toer.id as examRecordId,
+		tees.`identity`,
+		tees.name,
+		tees.course_code as courseCode,
+		tees.course_name as courseName,
+		toer.status as statusCode,
+		IFNULL(toer.warning_count,0) as warningCount,
+		IFNULL(toer.breach_status,1) as breachStatus,
+		toer.client_last_sync_time as updateTime,
+		tiiwi.approve_status as approveStatus
+		,(select count(1) from t_ie_invigilate_warn_info tiiwi where
+		tiiwi.exam_record_id = toer.id and tiiwi.`type` =
+		'FACE_COUNT_ERROR' and tiiwi.`level` = 'D8') as multipleFaceCount
+		,(select count(1) from t_ie_invigilate_exception_info tiiei where
+		tiiei.exam_record_id = toer.id) as exceptionCount
+		from t_ie_invigilate_warn_info tiiwi
+		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
+		inner join (select toer.id from t_oe_exam_record toer where EXISTS(select
+		tees.id from t_e_exam_student tees where EXISTS (select distinct
+		tbeiu.room_code from t_b_exam_invigilate_user tbeiu
+		where
+		<if test="userId != null and userId != ''">
+			tbeiu.user_id = #{userId} and
+		</if>
+		tbeiu.room_code = tees.room_code and toer.exam_student_id = tees.id)))
+		t on t.id = tiiwi.exam_record_id
+		left join t_oe_exam_record toer on toer.id = t.id
+		left join t_e_exam_student tees on tees.id = tiiwi.exam_student_id
+		<where>
+			<if test="examId != null and examId != ''">
+				and tiiwi.exam_id = #{examId}
+			</if>
+			<if test="examActivityId != null and examActivityId != ''">
+				and tiiwi.exam_activity_id = #{examActivityId}
+			</if>
+			<if test="roomCode != null and roomCode != ''">
+				and tees.room_code = #{roomCode}
+			</if>
+			<if test="approveStatus != null and approveStatus != ''">
+				and tiiwi.approve_status = #{approveStatus}
+			</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 != ''">
+				and toer.warning_count &lt;= #{maxWarningCount}
+			</if>
+			<if test="minWarningCount != null and minWarningCount != ''">
+				and toer.warning_count &gt;= #{minWarningCount}
+			</if>
+			<if
+				test="clientWebsocketStatus != null and clientWebsocketStatus != ''">
+				and toer.client_websocket_status = #{clientWebsocketStatus}
+			</if>
+			<if
+				test="monitorStatusSource != null and monitorStatusSource != ''">
+				and toer.monitor_status_source = #{monitorStatusSource}
+			</if>
+			and tee.enable = 1
+			and teea.enable = 1
+			and tees.enable = 1
+		</where>
+		) t
+		<where>
+			<if
+				test="minMultipleFaceCount != null and minMultipleFaceCount != ''">
+				and t.multipleFaceCount &lt;= #{minMultipleFaceCount}
+			</if>
+			<if
+				test="maxMultipleFaceCount != null and maxMultipleFaceCount != ''">
+				and t.multipleFaceCount &gt;= #{maxMultipleFaceCount}
+			</if>
+			<if test="minExceptionCount != null and minExceptionCount != ''">
+				and t.exceptionCount &lt;= #{minExceptionCount}
+			</if>
+			<if test="maxExceptionCount != null and maxExceptionCount != ''">
+				and t.exceptionCount &gt;= #{maxExceptionCount}
+			</if>
+		</where>
+		order by t.roomCode
+	</select>
 
 
-    <select id="invigilatePageProgressList" resultType="com.qmth.themis.business.bean.backend.InvigilateListProgressBean">
-        select
-            distinct tee.id as examId,
-            tee.name as examName,
-            teea.id as examActivityId,
-            teea.code as examActivityCode,
-            tees.room_code as roomCode,
-            tees.room_name as roomName,
-            tees.`identity`,
-            tees.name,
-            tees.course_code as courseCode,
-            tees.course_name as courseName,
-            tees.left_exam_count as leftExamCount,
-            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') > 0),'已完成','未完成') as status
-        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.id = tees.exam_activity_id
-        inner join (select distinct tbeiu.room_code from t_b_exam_invigilate_user tbeiu
-        <if test="userId != null and userId != ''">
-            where tbeiu.user_id = #{userId}
-        </if>
-        ) t on t.room_code = tees.room_code
-        <where>
-            <if test="examId != null and examId != ''">
-                and tees.exam_id = #{examId}
-            </if>
-            <if test="examActivityId != null and examActivityId != ''">
-                and tees.exam_activity_id = #{examActivityId}
-            </if>
-            <if test="roomCode != null and roomCode != ''">
-                and tees.room_code = #{roomCode}
-            </if>
-            <if test="courseCode != null and courseCode != ''">
-                and tees.course_code like CONCAT('%', #{courseCode},'%')
-            </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>
-            and tee.enable = 1
-            and teea.enable = 1
-            and tees.enable = 1
-        </where>
-            order by tees.room_code
-    </select>
+	<select id="invigilatePageProgressList"
+		resultType="com.qmth.themis.business.bean.backend.InvigilateListProgressBean">
+		select
+		distinct tee.id as examId,
+		tee.name as examName,
+		teea.id as examActivityId,
+		teea.code as examActivityCode,
+		tees.room_code as roomCode,
+		tees.room_name as roomName,
+		tees.`identity`,
+		tees.name,
+		tees.course_code as courseCode,
+		tees.course_name as courseName,
+		tees.left_exam_count as leftExamCount,
+		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') >
+		0),'已完成','未完成') as status
+		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.id = tees.exam_activity_id
+		inner join (select distinct tbeiu.room_code from t_b_exam_invigilate_user
+		tbeiu
+		<if test="userId != null and userId != ''">
+			where tbeiu.user_id = #{userId}
+		</if>
+		) t on t.room_code = tees.room_code
+		<where>
+			<if test="examId != null and examId != ''">
+				and tees.exam_id = #{examId}
+			</if>
+			<if test="examActivityId != null and examActivityId != ''">
+				and tees.exam_activity_id = #{examActivityId}
+			</if>
+			<if test="roomCode != null and roomCode != ''">
+				and tees.room_code = #{roomCode}
+			</if>
+			<if test="courseCode != null and courseCode != ''">
+				and tees.course_code like CONCAT('%', #{courseCode},'%')
+			</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>
+			and tee.enable = 1
+			and teea.enable = 1
+			and tees.enable = 1
+		</where>
+		order by tees.room_code
+	</select>
 
 
-    <select id="invigilatePageListHistory" resultType="com.qmth.themis.business.bean.backend.InvigilateListHistoryBean">
-        <include refid="invigilatePageHead" />
-        <include refid="invigilatePageMiddle" />
-        <include refid="invigilatePageFoot" />
-        <if test="breachStatus != null and breachStatus != '' or breachStatus == 0">
-            and t.breach_status = #{breachStatus}
-        </if>
-        <if test="finishType != null and finishType != ''">
-            and t.finish_type = #{finishType}
-        </if>
-        <if test="courseCode != null and courseCode != ''">
-            and tees.course_code like CONCAT('%', #{courseCode},'%')
-        </if>
-        order by s.room_code
-    </select>
-    
-    <select id="getDoneCount" resultType="java.util.Map">
-    	select f.exam_activity_id activityId,count(distinct(f.exam_student_id)) cc from t_oe_exam_record f
-    	left join t_e_exam_student t on f.exam_student_id=t.id
-    	where  f.exam_id = #{examId}
-            <if test="activityId != null and activityId != ''">
-                and f.exam_activity_id = #{activityId}
-            </if>
-            <if test="roomCode != null and roomCode != ''">
-                and t.room_code =#{roomCode}
-            </if>
-            <if test="courseCode != null and courseCode != ''">
-                and t.course_code = #{courseCode}
-            </if>
-            group by f.exam_activity_id
-    </select>
-    <select id="getDoneCountByDay" resultType="java.util.Map">
-    	select DATE_FORMAT(f.first_prepare_time, '%Y-%m-%d') AS day,
+	<select id="invigilatePageListHistory" resultType="com.qmth.themis.business.bean.backend.InvigilateListHistoryBean">
+		<include refid="invigilatePageHead" />
+		,tes.mobile_number as mobileNumber
+		<include refid="invigilatePageMiddle" />
+		left join t_e_student tes on s.student_id = tes.id
+		<include refid="invigilatePageFoot" />
+		<if test="breachStatus != null and breachStatus != '' or breachStatus == 0">
+			and t.breach_status = #{breachStatus}
+		</if>
+		<if test="finishType != null and finishType != ''">
+			and t.finish_type = #{finishType}
+		</if>
+		<if test="courseCode != null and courseCode != ''">
+			and tees.course_code like CONCAT('%', #{courseCode},'%')
+		</if>
+		order by s.room_code
+	</select>
+
+	<select id="getDoneCount" resultType="java.util.Map">
+		select f.exam_activity_id
+		activityId,count(distinct(f.exam_student_id)) cc from t_oe_exam_record
+		f
+		left join t_e_exam_student t on f.exam_student_id=t.id
+		where f.exam_id = #{examId}
+		<if test="activityId != null and activityId != ''">
+			and f.exam_activity_id = #{activityId}
+		</if>
+		<if test="roomCode != null and roomCode != ''">
+			and t.room_code =#{roomCode}
+		</if>
+		<if test="courseCode != null and courseCode != ''">
+			and t.course_code = #{courseCode}
+		</if>
+		group by f.exam_activity_id
+	</select>
+
+	<select id="getDoneCountByDay" resultType="java.util.Map">
+		select DATE_FORMAT(f.first_prepare_time, '%Y-%m-%d') AS day,
 		count(DISTINCT(f.exam_student_id)) count from t_oe_exam_record f
 		count(DISTINCT(f.exam_student_id)) count from t_oe_exam_record f
-    	left join t_e_exam_student t on f.exam_student_id=t.id
-    	where  f.exam_id = #{examId}
-            <if test="activityId != null and activityId != ''">
-                and f.exam_activity_id = #{activityId}
-            </if>
-            <if test="roomCode != null and roomCode != ''">
-                and t.room_code =#{roomCode}
-            </if>
-            <if test="courseCode != null and courseCode != ''">
-                and t.course_code = #{courseCode}
-            </if>
-            group by day
-            ORDER BY day
-    </select>
-    
+		left join t_e_exam_student t on f.exam_student_id=t.id
+		where f.exam_id = #{examId}
+		<if test="activityId != null and activityId != ''">
+			and f.exam_activity_id = #{activityId}
+		</if>
+		<if test="roomCode != null and roomCode != ''">
+			and t.room_code =#{roomCode}
+		</if>
+		<if test="courseCode != null and courseCode != ''">
+			and t.course_code = #{courseCode}
+		</if>
+		group by day
+		ORDER BY day
+	</select>
+
+	<select id="getCountByExamId" resultType="java.lang.Long">
+		select count(1) from t_oe_exam_record f
+		where f.exam_id = #{examId}
+	</select>
+
+	<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>
 </mapper>
 </mapper>

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

@@ -106,4 +106,12 @@ public interface MqLogicService {
      * @param key
      * @param key
      */
      */
     public void execMqLogLogic(MqDto mqDto, String key);
     public void execMqLogLogic(MqDto mqDto, String key);
+
+	/**
+	 * 重新算分
+	 *
+	 * @param mqDto
+	 * @param key
+	 */
+	void execMqCalculateScoreLogic(MqDto mqDto, String key);
 }
 }

+ 21 - 2
themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java

@@ -258,8 +258,6 @@ public class MqLogicServiceImpl implements MqLogicService {
         Gson gson = new Gson();
         Gson gson = new Gson();
         Map<String, Object> param = (Map<String, Object>) mqDto.getBody();
         Map<String, Object> param = (Map<String, Object>) mqDto.getBody();
         examRecordService.calculateObjectiveScore(param);
         examRecordService.calculateObjectiveScore(param);
-        Long recordId = (Long) param.get("recordId");
-        commonService.persisted(recordId);
         mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
         mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
         TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
         TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
         tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
         tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
@@ -511,4 +509,25 @@ public class MqLogicServiceImpl implements MqLogicService {
         tmRocketMessageService.saveOrUpdate(tmRocketMessage);
         tmRocketMessageService.saveOrUpdate(tmRocketMessage);
         redisUtil.delete(key, mqDto.getId());
         redisUtil.delete(key, mqDto.getId());
     }
     }
+    
+    /**
+     * 重新算分
+     *
+     * @param mqDto
+     * @param key
+     */
+    @Override
+    @Transactional
+    public void execMqCalculateScoreLogic(MqDto mqDto, String key) {
+        Gson gson = new Gson();
+        Map<String, Object> param = (Map<String, Object>) mqDto.getBody();
+        Long examId = (Long) param.get("examId");
+        Long taskId = (Long) param.get("taskId");
+        teExamService.calculateScore(examId,taskId);
+        mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
+        TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
+        tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
+        tmRocketMessageService.saveOrUpdate(tmRocketMessage);
+        redisUtil.delete(key, mqDto.getId());
+    }
 }
 }

+ 74 - 0
themis-mq/src/main/java/com/qmth/themis/mq/templete/impl/CalculateScoreConcurrentlyImpl.java

@@ -0,0 +1,74 @@
+package com.qmth.themis.mq.templete.impl;
+
+import com.qmth.themis.business.constant.SpringContextHolder;
+import com.qmth.themis.business.constant.SystemConstant;
+import com.qmth.themis.business.dto.MqDto;
+import com.qmth.themis.business.util.JacksonUtil;
+import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.contanst.Constants;
+import com.qmth.themis.mq.service.MqLogicService;
+import com.qmth.themis.mq.templete.Concurrently;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * 重新算分
+ *
+ * @Description:
+ * @Author: xiatian
+ * @Date: 2020-07-30
+ */
+@Service
+public class CalculateScoreConcurrentlyImpl implements Concurrently {
+    private final static Logger log = LoggerFactory.getLogger(CalculateScoreConcurrentlyImpl.class);
+
+    @Override
+    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
+                                                    ConsumeConcurrentlyContext consumeConcurrentlyContext) {
+        RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);
+        MqLogicService mqLogicService = SpringContextHolder.getBean(MqLogicService.class);
+        MqDto mqDto = null;
+        try {
+            long threadId = Thread.currentThread().getId();
+            String threadName = Thread.currentThread().getName();
+            for (MessageExt messageExt : msgs) {
+                log.debug(":{}-:{} CalculateObjectiveScore 重试次数:{}", threadId, threadName,
+                        messageExt.getReconsumeTimes());
+                mqDto = JacksonUtil.readJson(new String(messageExt.getBody(), Constants.CHARSET), MqDto.class);
+                log.debug(":{}-:{} CalculateObjectiveScore 接收到的消息:{}", threadId, threadName,
+                        JacksonUtil.parseJson(mqDto));
+                int reconsumeTime = messageExt.getReconsumeTimes();
+                if (reconsumeTime >= SystemConstant.MAXRECONSUMETIMES) {
+                    mqLogicService.execMqMaxReconsumeTime(mqDto, SystemConstant.MQ_TOPIC_BUFFER_LIST);
+                } else {
+                    if (Objects.nonNull(mqDto.getAck()) && mqDto.getAck().intValue() != SystemConstant.STANDARD_ACK_TYPE
+                            && Objects.nonNull(redisUtil.get(SystemConstant.MQ_TOPIC_BUFFER_LIST, mqDto.getId()))
+                            && redisUtil.lock(SystemConstant.REDIS_LOCK_MQ_PREFIX + mqDto.getId(),
+                            SystemConstant.REDIS_LOCK_MQ_TIME_OUT)) {
+                        log.debug(":{}-:{} 更新db", threadId, threadName);
+                        mqLogicService.execMqCalculateObjectiveScoreLogic(mqDto, SystemConstant.MQ_TOPIC_BUFFER_LIST);
+                        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
+                    } else {
+                        log.debug(":{}-:{} 消息ack未确认,重发", threadId, threadName);
+                        return ConsumeConcurrentlyStatus.RECONSUME_LATER;// 重试
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.error("mq 重新算分,消息消费出错", e);
+            return ConsumeConcurrentlyStatus.RECONSUME_LATER;//重试
+        } finally {
+            if (Objects.nonNull(mqDto)) {
+                redisUtil.releaseLock(SystemConstant.REDIS_LOCK_MQ_PREFIX + mqDto.getId());
+            }
+        }
+        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;// 成功
+    }
+}