Parcourir la source

监控台明细修改

wangliang il y a 4 ans
Parent
commit
467c610008

+ 7 - 28
themis-backend/src/main/java/com/qmth/themis/backend/api/TIeInvigilateController.java

@@ -196,44 +196,30 @@ public class TIeInvigilateController {
         String courseNameCode = examStudentCacheBean.getCourseName() + "(" + examStudentCacheBean.getCourseCode() + ")";
         String roomCode = examStudentCacheBean.getRoomCode();
         String roomName = examStudentCacheBean.getRoomName();
-        Long studentId = examStudentCacheBean.getStudentId();
         ExamActivityCacheBean examActivityCacheBean = teExamActivityService.getExamActivityCacheBean(examActivityId);
         ExamCacheBean examCacheBean = teExamService.getExamCacheBean(examId);
         InvigilateListDetailBean invigilateListDetailBean = new InvigilateListDetailBean(examCacheBean.getName(), examActivityCacheBean.getCode(), examId, examActivityId, examStudentId, examRecordId, identity, examStudentName, courseNameCode, status, roomCode, roomName, breachStatus);
 
         //考生轨迹
-
+        QueryWrapper<TEExamStudentLog> teExamStudentLogQueryWrapper = new QueryWrapper<>();
+        teExamStudentLogQueryWrapper.lambda().eq(TEExamStudentLog::getExamRecordId,examRecordId)
+                .eq(TEExamStudentLog::getExamStudentId,examStudentId);
+        List<TEExamStudentLog> teExamStudentLogList = teExamStudentLogService.list(teExamStudentLogQueryWrapper);
+        invigilateListDetailBean.setTeExamStudentLogList(teExamStudentLogList);
 
         //预警、异常、人脸
         //预警
         QueryWrapper<TIeInvigilateWarnInfo> tIeInvigilateWarnInfoQueryWrapper = new QueryWrapper<>();
         tIeInvigilateWarnInfoQueryWrapper.lambda().eq(TIeInvigilateWarnInfo::getExamRecordId, examRecordId);
-        List<TIeInvigilateWarnInfo> tIeInvigilateWarnInfoList = tIeInvigilateWarnInfoService.list(tIeInvigilateWarnInfoQueryWrapper);
-        Integer warningCount = 0;
-        if (Objects.nonNull(tIeInvigilateWarnInfoList) && tIeInvigilateWarnInfoList.size() > 0) {
-            warningCount = tIeInvigilateWarnInfoList.size();
-        }
+        int warningCount = tIeInvigilateWarnInfoService.count(tIeInvigilateWarnInfoQueryWrapper);
         invigilateListDetailBean.setWarningCount(warningCount);
 
-        Gson gson = new Gson();
-        List<InvigilateListDetailBean.InvigilateWarnInfoBean> invigilateWarnInfoBeanList = gson.fromJson(gson.toJson(tIeInvigilateWarnInfoList), new TypeToken<List<InvigilateListDetailBean.InvigilateWarnInfoBean>>() {
-        }.getType());
-//        invigilateListDetailBean.setWarningInfos(invigilateWarnInfoBeanList);
-
         //异常
         QueryWrapper<TIeInvigilateExceptionInfo> tIeInvigilateExceptionInfoQueryWrapper = new QueryWrapper<>();
         tIeInvigilateExceptionInfoQueryWrapper.lambda().eq(TIeInvigilateExceptionInfo::getExamRecordId, examRecordId);
-        List<TIeInvigilateExceptionInfo> tIeInvigilateExceptionInfoList = tIeInvigilateExceptionInfoService.list(tIeInvigilateExceptionInfoQueryWrapper);
-        Integer exceptionCount = 0;
-        if (Objects.nonNull(tIeInvigilateExceptionInfoList) && tIeInvigilateExceptionInfoList.size() > 0) {
-            exceptionCount = tIeInvigilateExceptionInfoList.size();
-        }
+        int exceptionCount = tIeInvigilateExceptionInfoService.count(tIeInvigilateExceptionInfoQueryWrapper);
         invigilateListDetailBean.setExceptionCount(exceptionCount);
 
-        List<InvigilateListDetailBean.InvigilateExceptionInfoBean> invigilateExceptionInfoBeanList = gson.fromJson(gson.toJson(tIeInvigilateExceptionInfoList), new TypeToken<List<InvigilateListDetailBean.InvigilateExceptionInfoBean>>() {
-        }.getType());
-//        invigilateListDetailBean.setExceptionInfos(invigilateExceptionInfoBeanList);
-
         //陌生人脸
         tIeInvigilateWarnInfoQueryWrapper = new QueryWrapper<>();
         tIeInvigilateWarnInfoQueryWrapper.lambda().eq(TIeInvigilateWarnInfo::getExamRecordId, examRecordId)
@@ -242,13 +228,6 @@ public class TIeInvigilateController {
         int multipleFaceCount = tIeInvigilateWarnInfoService.count(tIeInvigilateWarnInfoQueryWrapper);
         invigilateListDetailBean.setMultipleFaceCount(multipleFaceCount);
 
-        //考生轨迹
-//        QueryWrapper<TEExamStudentLog> teExamStudentLogQueryWrapper = new QueryWrapper<>();
-//        teExamStudentLogQueryWrapper.lambda().and(Wrapper -> Wrapper.eq(TEExamStudentLog::getExamRecordId, examRecordId).or().eq(TEExamStudentLog::getStudentId, studentId)).orderByAsc(TEExamStudentLog::getCreateTime);
-//        List<TEExamStudentLog> teExamStudentLogList = teExamStudentLogService.list(teExamStudentLogQueryWrapper);
-//        List<InvigilateListDetailBean.StudentLogBean> studentLogBeanList = gson.fromJson(gson.toJson(teExamStudentLogList), new TypeToken<List<InvigilateListDetailBean.StudentLogBean>>() {
-//        }.getType());
-//        invigilateListDetailBean.setStudentLogs(studentLogBeanList);
         return ResultUtil.ok(invigilateListDetailBean);
     }
 

+ 10 - 292
themis-business/src/main/java/com/qmth/themis/business/bean/backend/InvigilateListDetailBean.java

@@ -1,5 +1,6 @@
 package com.qmth.themis.business.bean.backend;
 
+import com.qmth.themis.business.entity.TEExamStudentLog;
 import com.qmth.themis.business.enums.ExamRecordStatusEnum;
 import com.qmth.themis.business.enums.ExamTypeEnum;
 import com.qmth.themis.business.enums.ExceptionEnum;
@@ -73,7 +74,15 @@ public class InvigilateListDetailBean implements Serializable {
     private Integer breachStatus;
 
     @ApiModelProperty(name = "考生轨迹")
-    private List<ExamStudentTrailBean> examStudentTrailBean;
+    private List<TEExamStudentLog> teExamStudentLogList;
+
+    public List<TEExamStudentLog> getTeExamStudentLogList() {
+        return teExamStudentLogList;
+    }
+
+    public void setTeExamStudentLogList(List<TEExamStudentLog> teExamStudentLogList) {
+        this.teExamStudentLogList = teExamStudentLogList;
+    }
 
     public InvigilateListDetailBean(String examName, String examActivityCode, Long examId, Long examActivityId, Long examStudentId, Long examRecordId, String identity, String examStudentName, String courseNameCode, ExamRecordStatusEnum statusCode, String roomCode, String roomName, Integer breachStatus) {
         this.examName = examName;
@@ -115,14 +124,6 @@ public class InvigilateListDetailBean implements Serializable {
         this.roomName = roomName;
     }
 
-    public List<ExamStudentTrailBean> getExamStudentTrailBean() {
-        return examStudentTrailBean;
-    }
-
-    public void setExamStudentTrailBean(List<ExamStudentTrailBean> examStudentTrailBean) {
-        this.examStudentTrailBean = examStudentTrailBean;
-    }
-
     public Integer getBreachStatus() {
         return breachStatus;
     }
@@ -237,287 +238,4 @@ public class InvigilateListDetailBean implements Serializable {
     public void setStatusCode(ExamRecordStatusEnum statusCode) {
         this.statusCode = statusCode;
     }
-
-    /**
-    * @Description: 考生轨迹bean
-    * @Param:
-    * @return:
-    * @Author: wangliang
-    * @Date: 2020/9/15
-    */
-    private class ExamStudentTrailBean implements Serializable{
-
-        @ApiModelProperty(value = "考生轨迹信息")
-        private StudentLogBean studentLogBean;
-
-        @ApiModelProperty(value = "异常信息")
-        private InvigilateExceptionInfoBean invigilateExceptionInfoBean;
-
-        @ApiModelProperty(value = "预警信息")
-        private List<InvigilateWarnInfoBean> invigilateWarnInfoBeanList;
-
-        @ApiModelProperty(value = "创建时间")
-        private Date createTime;
-    }
-
-    /**
-     * @Description: 预警bean
-     * @Param:
-     * @return:
-     * @Author: wangliang
-     * @Date: 2020/8/24
-     */
-    public class InvigilateWarnInfoBean implements Serializable {
-
-        @ApiModelProperty(value = "预警信息")
-        private String info;
-
-        @ApiModelProperty(value = "预警级别")
-        private String level;
-
-        @ApiModelProperty(value = "类别")
-        private VerifyExceptionEnum type;
-
-        @ApiModelProperty(value = "备注")
-        private String remark;
-
-        @ApiModelProperty(value = "审阅状态,0:未阅,1:已阅")
-        private Integer approveStatus;
-
-        @ApiModelProperty(value = "创建时间")
-        private Date createTime;
-
-        @ApiModelProperty(value = "图片url")
-        private String photoUrl;
-
-        @ApiModelProperty(value = "视频url")
-        private String videoUrl;
-
-        public String getPhotoUrl() {
-            return photoUrl;
-        }
-
-        public void setPhotoUrl(String photoUrl) {
-            this.photoUrl = photoUrl;
-        }
-
-        public String getVideoUrl() {
-            return videoUrl;
-        }
-
-        public void setVideoUrl(String videoUrl) {
-            this.videoUrl = videoUrl;
-        }
-
-        public String getInfo() {
-            return info;
-        }
-
-        public void setInfo(String info) {
-            this.info = info;
-        }
-
-        public String getLevel() {
-            return level;
-        }
-
-        public void setLevel(String level) {
-            this.level = level;
-        }
-
-        public VerifyExceptionEnum getType() {
-            return type;
-        }
-
-        public void setType(VerifyExceptionEnum type) {
-            this.type = type;
-        }
-
-        public String getRemark() {
-            return remark;
-        }
-
-        public void setRemark(String remark) {
-            this.remark = remark;
-        }
-
-        public Integer getApproveStatus() {
-            return approveStatus;
-        }
-
-        public void setApproveStatus(Integer approveStatus) {
-            this.approveStatus = approveStatus;
-        }
-
-        public Date getCreateTime() {
-            return createTime;
-        }
-
-        public void setCreateTime(Date createTime) {
-            this.createTime = createTime;
-        }
-    }
-
-    /**
-     * @Description: 异常bean
-     * @Param:
-     * @return:
-     * @Author: wangliang
-     * @Date: 2020/8/24
-     */
-    public class InvigilateExceptionInfoBean implements Serializable {
-
-        @ApiModelProperty(value = "异常信息")
-        private String info;
-
-        @ApiModelProperty(value = "类别")
-        private ExceptionEnum type;
-
-        @ApiModelProperty(value = "备注")
-        private String remark;
-
-        @ApiModelProperty(value = "创建时间")
-        private Date createTime;
-
-        @ApiModelProperty(value = "处理时差,单位秒")
-        private Integer difference;
-
-        @ApiModelProperty(value = "图片url")
-        private String photoUrl;
-
-        @ApiModelProperty(value = "视频url")
-        private String videoUrl;
-
-        public String getPhotoUrl() {
-            return photoUrl;
-        }
-
-        public void setPhotoUrl(String photoUrl) {
-            this.photoUrl = photoUrl;
-        }
-
-        public String getVideoUrl() {
-            return videoUrl;
-        }
-
-        public void setVideoUrl(String videoUrl) {
-            this.videoUrl = videoUrl;
-        }
-
-        public Integer getDifference() {
-            return difference;
-        }
-
-        public void setDifference(Integer difference) {
-            this.difference = difference;
-        }
-
-        public String getInfo() {
-            return info;
-        }
-
-        public void setInfo(String info) {
-            this.info = info;
-        }
-
-        public ExceptionEnum getType() {
-            return type;
-        }
-
-        public void setType(ExceptionEnum type) {
-            this.type = type;
-        }
-
-        public String getRemark() {
-            return remark;
-        }
-
-        public void setRemark(String remark) {
-            this.remark = remark;
-        }
-
-        public Date getCreateTime() {
-            return createTime;
-        }
-
-        public void setCreateTime(Date createTime) {
-            this.createTime = createTime;
-        }
-    }
-
-    /**
-     * @Description: 考生日志bean
-     * @Param:
-     * @return:
-     * @Author: wangliang
-     * @Date: 2020/8/24
-     */
-    public class StudentLogBean implements Serializable {
-
-        @ApiModelProperty(value = "信息")
-        private String info;
-
-        @ApiModelProperty(value = "类别")
-        private ExamTypeEnum type;
-
-        @ApiModelProperty(value = "备注")
-        private String remark;
-
-        @ApiModelProperty(value = "创建时间")
-        private Date createTime;
-
-        @ApiModelProperty(value = "图片url")
-        private String photoUrl;
-
-        @ApiModelProperty(value = "视频url")
-        private String videoUrl;
-
-        public String getPhotoUrl() {
-            return photoUrl;
-        }
-
-        public void setPhotoUrl(String photoUrl) {
-            this.photoUrl = photoUrl;
-        }
-
-        public String getVideoUrl() {
-            return videoUrl;
-        }
-
-        public void setVideoUrl(String videoUrl) {
-            this.videoUrl = videoUrl;
-        }
-
-        public String getInfo() {
-            return info;
-        }
-
-        public void setInfo(String info) {
-            this.info = info;
-        }
-
-        public ExamTypeEnum getType() {
-            return type;
-        }
-
-        public void setType(ExamTypeEnum type) {
-            this.type = type;
-        }
-
-        public String getRemark() {
-            return remark;
-        }
-
-        public void setRemark(String remark) {
-            this.remark = remark;
-        }
-
-        public Date getCreateTime() {
-            return createTime;
-        }
-
-        public void setCreateTime(Date createTime) {
-            this.createTime = createTime;
-        }
-    }
 }

+ 44 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/backend/InvigilateListPatrolBean.java

@@ -71,6 +71,50 @@ public class InvigilateListPatrolBean implements Serializable {
     @ApiModelProperty(name = "虚拟考场名称")
     private String roomName;
 
+    @ApiModelProperty(name = "答题进度")
+    private Double progress;
+
+    @ApiModelProperty(name = "科目编码")
+    private String courseCode;
+
+    @ApiModelProperty(name = "科目名称")
+    private String courseName;
+
+    @ApiModelProperty(name = "剩余时间")
+    private String remainTime;
+
+    public Double getProgress() {
+        return progress;
+    }
+
+    public void setProgress(Double progress) {
+        this.progress = progress;
+    }
+
+    public String getCourseCode() {
+        return courseCode;
+    }
+
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public String getRemainTime() {
+        return remainTime;
+    }
+
+    public void setRemainTime(String remainTime) {
+        this.remainTime = remainTime;
+    }
+
     public Integer getSeq() {
         return seq;
     }

+ 11 - 14
themis-business/src/main/java/com/qmth/themis/business/cache/ExamRecordCacheUtil.java

@@ -1,20 +1,14 @@
 package com.qmth.themis.business.cache;
 
-import java.util.Date;
-import java.util.Objects;
-
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SystemConstant;
-import com.qmth.themis.business.enums.ExamRecordStatusEnum;
-import com.qmth.themis.business.enums.FinishTypeEnum;
-import com.qmth.themis.business.enums.MonitorCallStatusSourceEnum;
-import com.qmth.themis.business.enums.MonitorStatusSourceEnum;
-import com.qmth.themis.business.enums.MonitorVideoSourceEnum;
-import com.qmth.themis.business.enums.VerifyExceptionEnum;
-import com.qmth.themis.business.enums.WebsocketStatusEnum;
+import com.qmth.themis.business.enums.*;
 import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.RedisUtil;
 
+import java.util.Date;
+import java.util.Objects;
+
 /**
  * 考试记录缓存hash值操作
  *
@@ -206,7 +200,7 @@ public class ExamRecordCacheUtil {
     }
 
     public static void setMonitorCallStatus(Long recordId, String source, MonitorCallStatusSourceEnum callStatusSourceEnum) {
-        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_CALL_STATUS_ + source, callStatusSourceEnum.name());
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), SystemConstant.MONITOR_CALL_STATUS_ + source, callStatusSourceEnum);
     }
 
     public static WebsocketStatusEnum getClientWebsocketStatus(Long recordId) {
@@ -264,24 +258,27 @@ public class ExamRecordCacheUtil {
     public static Date getLastStartTime(Long recordId) {
         return (Date) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "lastStartTime");
     }
-    
+
     public static Date getStartTime(Long recordId) {
         return (Date) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "startTime");
     }
-    
+
     public static Date getEndTime(Long recordId) {
         return (Date) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "endTime");
     }
-    
+
     public static Integer getOpeningSeconds(Long recordId) {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "openingSeconds");
     }
+
     public static Integer getMinDurationSeconds(Long recordId) {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "minDurationSeconds");
     }
+
     public static Integer getMaxDurationSeconds(Long recordId) {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "maxDurationSeconds");
     }
+
     public static Integer getForceFinish(Long recordId) {
         return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "forceFinish");
     }

+ 4 - 9
themis-business/src/main/java/com/qmth/themis/business/dto/response/TEExamActivityDto.java

@@ -1,12 +1,5 @@
 package com.qmth.themis.business.dto.response;
 
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
-
 import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.cache.bean.ExamCourseCacheBean;
@@ -15,9 +8,11 @@ import com.qmth.themis.business.enums.EntryAuthenticationPolicyEnum;
 import com.qmth.themis.business.enums.ExamModeEnum;
 import com.qmth.themis.business.enums.HardwareTestEnum;
 import com.qmth.themis.business.enums.MonitorVideoSourceEnum;
-
 import io.swagger.annotations.ApiModelProperty;
 
+import java.io.Serializable;
+import java.util.*;
+
 /**
  * @Description: 考试场次dto
  * @Param:
@@ -212,7 +207,7 @@ public class TEExamActivityDto implements Serializable {
         this.inProcessLivenessJudgePolicy = ec.getInProcessLivenessJudgePolicy().name();
         this.startTime = examActivityCacheBean.getStartTime();
         this.finishTime = examActivityCacheBean.getFinishTime();
-        this.leftExamCount = ec.getExamCount()-examStudentCacheBean.getAlreadyExamCount();
+        this.leftExamCount = ec.getExamCount() - examStudentCacheBean.getAlreadyExamCount();
         this.mobilePhotoUpload = ec.getMobilePhotoUpload();
         this.examId = ec.getId();
     }

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

@@ -35,6 +35,17 @@ public class TIeWarningNotifyDto implements Serializable {
     @ApiModelProperty(name = "预警备注")
     private String remark;//预警备注
 
+    @ApiModelProperty(name = "考试记录id")
+    private Long examRecordId;//考试记录id
+
+    public Long getExamRecordId() {
+        return examRecordId;
+    }
+
+    public void setExamRecordId(Long examRecordId) {
+        this.examRecordId = examRecordId;
+    }
+
     public Long getExamId() {
         return examId;
     }

+ 136 - 178
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -1,56 +1,12 @@
 package com.qmth.themis.business.service.impl;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.time.LocalDateTime;
-import java.time.ZoneOffset;
-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.extension.service.impl.ServiceImpl;
-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.bean.exam.*;
 import com.qmth.themis.business.cache.ExamActivityRecordCacheUtil;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
-import com.qmth.themis.business.cache.bean.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.cache.bean.*;
 import com.qmth.themis.business.config.SystemConfig;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dao.TEExamMapper;
@@ -63,32 +19,32 @@ 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.TOeExamRecord;
-import com.qmth.themis.business.enums.EntryAuthenticationPolicyEnum;
-import com.qmth.themis.business.enums.ExamModeEnum;
-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.enums.*;
+import com.qmth.themis.business.service.*;
 import com.qmth.themis.business.util.OssUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.business.util.ServletUtil;
 import com.qmth.themis.business.util.TencentYunUtil;
 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.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.*;
 
 /**
  * @Description: 考试批次 服务实现类
@@ -129,7 +85,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 
     @Resource
     TencentYunUtil tencentYunUtil;
-    
+
     @Resource
     private TBTaskHistoryService tbTaskHistoryService;
 
@@ -163,10 +119,12 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
     public List<TEExamDto> getWaitingExam(Long studentId, Long examId, Long orgId) {
         List<TEExamDto> list = teExamMapper.getWaitingExam(studentId, examId, orgId);
         if (Objects.nonNull(list) && list.size() > 0) {
-        	ExamCacheBean examCache=getExamCacheBean(examId);
             list.forEach(s -> {
                 List<TEExamActivityDto> teExamActivityList = teExamActivityService.getWaitingExam(studentId, s.getId(), s.getExamActivityId(), s.getMode());
                 teExamActivityList.forEach(v -> {
+                    ExamCacheBean examCache = getExamCacheBean(v.getExamId());
+                    ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(v.getExamStudentId());
+                    v.setLeftExamCount(examCache.getExamCount() - examStudentCacheBean.getAlreadyExamCount());
                     if (Objects.nonNull(v.getInProcessLivenessFixedRangeStr())) {
                         String[] longs = v.getInProcessLivenessFixedRangeStr().trim().replaceAll(" ", "").split(",");
                         List inProcessLivenessFixedRange = new ArrayList();
@@ -203,8 +161,6 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
                     } else {
                         v.setMonitorVideoSource(null);
                     }
-                    ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(v.getExamStudentId());
-                    v.setLeftExamCount(examCache.getExamCount()-examStudentCacheBean.getAlreadyExamCount());
                 });
                 s.setActivities(teExamActivityList);
             });
@@ -227,32 +183,32 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         if (!studentId.equals(es.getStudentId())) {
             throw new BusinessException("考生Id和当前登录用户不一致");
         }
-        ExamCacheBean examCache=getExamCacheBean(es.getExamId());
+        ExamCacheBean examCache = getExamCacheBean(es.getExamId());
         TEStudentCacheDto teStudentCacheDto = (TEStudentCacheDto) redisUtil.getStudent(es.getStudentId());
         if (teStudentCacheDto.getUnFinishedRecordId() != null) {
             Long recordId = teStudentCacheDto.getUnFinishedRecordId();
-            if(examStudentId.equals(ExamRecordCacheUtil.getExamStudentId(recordId))) {//当前考生已存在候考的考试记录
-	            ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(ExamRecordCacheUtil.getPaperId(recordId));
-	            ExamCourseCacheBean ec = teExamCourseService.getExamCourseCacheBean(es.getExamId(), es.getCourseCode());
-	            ExamPrepareBean prepare = new ExamPrepareBean();
-	            prepare.setRecordId(recordId);
-	            prepare.setAudioPlayCount(ep.getAudioPlayCount());
-	            prepare.setHasAudio((ep.getHasAudio() == null || ep.getHasAudio().intValue() == 0 ? false : true));
-	            prepare.setObjectiveShuffle(
-	                    (ec.getObjectiveShuffle() == null || ec.getObjectiveShuffle().intValue() == 0 ? false : true));
-	            prepare.setOptionShuffle(
-	                    (ec.getOptionShuffle() == null || ec.getOptionShuffle().intValue() == 0 ? false : true));
-	            String paperurl = OssUtil.getUrlForPrivateBucket(systemConfig.getOssEnv(3), ep.getPaperPath());
-	            String structurl = OssUtil.getUrlForPrivateBucket(systemConfig.getOssEnv(3), ep.getStructPath());
-	            prepare.setPaperUrl(paperurl);
-	            prepare.setStructUrl(structurl);
-	            prepare.setMonitorKey(ExamRecordCacheUtil.getMonitorKey(recordId));
-	            prepare.setMonitorUserId("s_" + tbSession.getId());
-	            prepare.setMonitorUserSig(tencentYunUtil.getSign(prepare.getMonitorUserId(), SystemConstant.TENCENT_EXPIRE_TIME));
-	            return prepare;
+            if (examStudentId.equals(ExamRecordCacheUtil.getExamStudentId(recordId))) {//当前考生已存在候考的考试记录
+                ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(ExamRecordCacheUtil.getPaperId(recordId));
+                ExamCourseCacheBean ec = teExamCourseService.getExamCourseCacheBean(es.getExamId(), es.getCourseCode());
+                ExamPrepareBean prepare = new ExamPrepareBean();
+                prepare.setRecordId(recordId);
+                prepare.setAudioPlayCount(ep.getAudioPlayCount());
+                prepare.setHasAudio((ep.getHasAudio() == null || ep.getHasAudio().intValue() == 0 ? false : true));
+                prepare.setObjectiveShuffle(
+                        (ec.getObjectiveShuffle() == null || ec.getObjectiveShuffle().intValue() == 0 ? false : true));
+                prepare.setOptionShuffle(
+                        (ec.getOptionShuffle() == null || ec.getOptionShuffle().intValue() == 0 ? false : true));
+                String paperurl = OssUtil.getUrlForPrivateBucket(systemConfig.getOssEnv(3), ep.getPaperPath());
+                String structurl = OssUtil.getUrlForPrivateBucket(systemConfig.getOssEnv(3), ep.getStructPath());
+                prepare.setPaperUrl(paperurl);
+                prepare.setStructUrl(structurl);
+                prepare.setMonitorKey(ExamRecordCacheUtil.getMonitorKey(recordId));
+                prepare.setMonitorUserId("s_" + tbSession.getId());
+                prepare.setMonitorUserSig(tencentYunUtil.getSign(prepare.getMonitorUserId(), SystemConstant.TENCENT_EXPIRE_TIME));
+                return prepare;
             }
         }
-        if (examCache.getExamCount().intValue()<=es.getAlreadyExamCount().intValue()) {
+        if (examCache.getExamCount().intValue() <= es.getAlreadyExamCount().intValue()) {
             throw new BusinessException("没有剩余考试次数");
         }
         ExamCacheBean exam = getExamCacheBean(es.getExamId());
@@ -262,16 +218,16 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
             throw new BusinessException("未找到场次");
         }
         Date now = new Date();
-        if(ExamModeEnum.ANYTIME.equals(exam.getMode())) {
-    		Long start = ac.getStartTime().getTime() - (ac.getPrepareSeconds() * 1000);
-    		Long end = ac.getFinishTime().getTime();
-    		if (now.getTime() < start) {
-    			throw new BusinessException("没有到允许开考的时间");
-    		}
-    		if (now.getTime() > end) {
-    			throw new BusinessException("允许开考的时间已结束");
-    		}
-        }else {
+        if (ExamModeEnum.ANYTIME.equals(exam.getMode())) {
+            Long start = ac.getStartTime().getTime() - (ac.getPrepareSeconds() * 1000);
+            Long end = ac.getFinishTime().getTime();
+            if (now.getTime() < start) {
+                throw new BusinessException("没有到允许开考的时间");
+            }
+            if (now.getTime() > end) {
+                throw new BusinessException("允许开考的时间已结束");
+            }
+        } else {
             Long start = ac.getStartTime().getTime() - (ac.getPrepareSeconds() * 1000);
             Long end = ac.getStartTime().getTime() + (ac.getOpeningSeconds() * 1000);
             if (now.getTime() < start) {
@@ -281,7 +237,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
                 throw new BusinessException("允许开考的时间已结束");
             }
         }
-        
+
         ExamCourseCacheBean ec = teExamCourseService.getExamCourseCacheBean(es.getExamId(), es.getCourseCode());
         if (ec == null) {
             throw new BusinessException("未找到考试科目");
@@ -333,7 +289,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         prepare.setMonitorUserId("s_" + tbSession.getId());
         prepare.setMonitorUserSig(tencentYunUtil.getSign(prepare.getMonitorUserId(), SystemConstant.TENCENT_EXPIRE_TIME));
 
-        
+
         // 更新考生缓存
         redisUtil.set(RedisKeyHelper.examStudentCacheKey(examStudentId), es);
         //更新场次-考试记录缓存
@@ -390,24 +346,24 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
             throw new BusinessException("未找到场次");
         }
         Date now = new Date();
-        if(ExamModeEnum.ANYTIME.equals(exam.getMode())) {
-    		Long start = ac.getStartTime().getTime();
-    		Long end = ac.getFinishTime().getTime();
-    		if (now.getTime() < start) {
-    			throw new BusinessException("没有到允许开考的时间");
-    		}
-    		if (now.getTime() > end) {
-    			throw new BusinessException("允许开考的时间已结束");
-    		}
-        }else {
-	        Long start = ac.getStartTime().getTime();
-	        Long end = ac.getStartTime().getTime() + (ac.getOpeningSeconds() * 1000);
-	        if (now.getTime() < start) {
-	            throw new BusinessException("没有到允许开考的时间");
-	        }
-	        if (now.getTime() > end) {
-	            throw new BusinessException("允许开考的时间已结束");
-	        }
+        if (ExamModeEnum.ANYTIME.equals(exam.getMode())) {
+            Long start = ac.getStartTime().getTime();
+            Long end = ac.getFinishTime().getTime();
+            if (now.getTime() < start) {
+                throw new BusinessException("没有到允许开考的时间");
+            }
+            if (now.getTime() > end) {
+                throw new BusinessException("允许开考的时间已结束");
+            }
+        } else {
+            Long start = ac.getStartTime().getTime();
+            Long end = ac.getStartTime().getTime() + (ac.getOpeningSeconds() * 1000);
+            if (now.getTime() < start) {
+                throw new BusinessException("没有到允许开考的时间");
+            }
+            if (now.getTime() > end) {
+                throw new BusinessException("允许开考的时间已结束");
+            }
         }
         ExamRecordStatusEnum sta = ExamRecordCacheUtil.getStatus(recordId);
         if (ExamRecordStatusEnum.FINISHED.equals(sta) || ExamRecordStatusEnum.PERSISTED.equals(sta)) {
@@ -811,18 +767,18 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         }
 
         Map<String, Object> transMap = new HashMap<String, Object>();
-		transMap.put("recordId", recordId);
-		String level = "10s";
-		Integer time = SystemConstant.mqDelayLevel.get(level);
-		LocalDateTime dt = LocalDateTime.now();
-		dt = dt.plusSeconds(Long.parseLong(level.replace("s", "")));
-		Map<String, Object> propMap = new HashMap<String, Object>();
-		propMap.put("timeOut", time);
-		propMap.put("mqExecTime", dt.toInstant(ZoneOffset.of("+8")).toEpochMilli());
-		MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.EXAM_RECORD_PERSISTED.name(),
-				transMap, MqTagEnum.EXAM_RECORD_PERSISTED, recordId.toString(), propMap, recordId.toString());
-
-		mqDtoService.assembleSendAsyncDelayMsg(mqDto);
+        transMap.put("recordId", recordId);
+        String level = "10s";
+        Integer time = SystemConstant.mqDelayLevel.get(level);
+        LocalDateTime dt = LocalDateTime.now();
+        dt = dt.plusSeconds(Long.parseLong(level.replace("s", "")));
+        Map<String, Object> propMap = new HashMap<String, Object>();
+        propMap.put("timeOut", time);
+        propMap.put("mqExecTime", dt.toInstant(ZoneOffset.of("+8")).toEpochMilli());
+        MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.EXAM_RECORD_PERSISTED.name(),
+                transMap, MqTagEnum.EXAM_RECORD_PERSISTED, recordId.toString(), propMap, recordId.toString());
+
+        mqDtoService.assembleSendAsyncDelayMsg(mqDto);
     }
 
     @Cacheable(value = "exam", key = "#examId", unless = "#result == null")
@@ -979,62 +935,64 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         }
         return ret;
     }
-    
-    /**重新算分
+
+    /**
+     * 重新算分
+     *
      * @param examId
      * @param taskId
      */
     @Override
-    public void calculateScore(Long examId,Long taskId) {
-    	int timeOutSecond=60*5;
-    	String lockKey = SystemConstant.REDIS_LOCK_CALCULATE_SCORE_PREFIX + examId;
+    public void calculateScore(Long examId, Long taskId) {
+        int timeOutSecond = 60 * 5;
+        String lockKey = SystemConstant.REDIS_LOCK_CALCULATE_SCORE_PREFIX + examId;
         Boolean lock = redisUtil.lock(lockKey, timeOutSecond);
         if (!lock) {
             return;
         }
-        TBTaskHistory task=null;
-        Long recordId=null;
+        TBTaskHistory task = null;
+        Long recordId = null;
         try {
-	    	task=tbTaskHistoryService.getById(taskId);
-	    	task.setStatus(TaskStatusEnum.RUNNING);
-	    	tbTaskHistoryService.saveOrUpdate(task);
-    		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())) {
-	    					recordId=rc.getId();
-	    					toeExamRecordService.calculateScore(rc.getId());
-	    				}
-	    				redisUtil.expire(lockKey, timeOutSecond);
-	    			}
-	    			task.setProgress(getPercentage(index, total));
-	    			tbTaskHistoryService.saveOrUpdate(task);
-    			}
-    		}
-			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());
-		} finally {
+            task = tbTaskHistoryService.getById(taskId);
+            task.setStatus(TaskStatusEnum.RUNNING);
+            tbTaskHistoryService.saveOrUpdate(task);
+            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())) {
+                            recordId = rc.getId();
+                            toeExamRecordService.calculateScore(rc.getId());
+                        }
+                        redisUtil.expire(lockKey, timeOutSecond);
+                    }
+                    task.setProgress(getPercentage(index, total));
+                    tbTaskHistoryService.saveOrUpdate(task);
+                }
+            }
+            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());
+        } finally {
             redisUtil.releaseLock(lockKey);
         }
-    	tbTaskHistoryService.saveOrUpdate(task);
+        tbTaskHistoryService.saveOrUpdate(task);
     }
-    
+
     private Double getPercentage(Long a, Long b) {
         if (a == null) {
             a = 0L;

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

@@ -142,7 +142,6 @@
             tee.mobile_photo_upload as mobilePhotoUpload,
             teea.start_time as startTime,
             teea.finish_time as finishTime,
-            tees.left_exam_count as leftExamCount,
             tee.id as examId
         from
             t_e_exam_student tees

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

@@ -34,7 +34,8 @@
             tiiwi.`level`,
             tiiwi.id as warningId,
             tiiwi.remark,
-            tiiwi.exam_id as examId
+            tiiwi.exam_id as examId,
+            tiiwi.exam_record_id as examRecordId
         from
             t_ie_invigilate_warn_info tiiwi
         left join t_e_exam_student tees on

+ 8 - 5
themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml

@@ -178,12 +178,12 @@
         <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 != ''">,
-            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
+        <if test="paperDownload != null and paperDownload != ''">
             and t.paper_download = #{paperDownload}
         </if>
         ) t,
@@ -216,6 +216,9 @@
 		,(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
+		,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" />
 		) t
@@ -348,7 +351,7 @@
 		tees.name,
 		tees.course_code as courseCode,
 		tees.course_name as courseName,
-		tees.left_exam_count as leftExamCount,
+		(tee.exam_count - tees.already_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