Ver código fonte

异常修改

wangliang 4 anos atrás
pai
commit
0185fd2248
18 arquivos alterados com 1446 adições e 775 exclusões
  1. 2 1
      themis-business/src/main/java/com/qmth/themis/business/dao/TEExamActivityMapper.java
  2. 2 1
      themis-business/src/main/java/com/qmth/themis/business/dao/TEExamMapper.java
  3. 2 1
      themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamRecordMapper.java
  4. 267 0
      themis-business/src/main/java/com/qmth/themis/business/dto/response/TEExamActivityDto.java
  5. 96 0
      themis-business/src/main/java/com/qmth/themis/business/dto/response/TEExamDto.java
  6. 321 0
      themis-business/src/main/java/com/qmth/themis/business/dto/response/TEExamUnFinishDto.java
  7. 2 1
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamActivityService.java
  8. 2 1
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamService.java
  9. 1 0
      themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java
  10. 2 1
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamActivityServiceImpl.java
  11. 541 565
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java
  12. 195 195
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java
  13. 1 1
      themis-business/src/main/resources/mapper/TEExamActivityMapper.xml
  14. 1 1
      themis-business/src/main/resources/mapper/TEExamMapper.xml
  15. 1 1
      themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml
  16. 6 4
      themis-exam/src/main/java/com/qmth/themis/exam/api/TEStudentController.java
  17. 1 1
      themis-exam/src/main/java/com/qmth/themis/exam/start/StartRunning.java
  18. 3 1
      themis-mq/src/main/java/com/qmth/themis/mq/enums/MqGroupEnum.java

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

@@ -2,6 +2,7 @@ package com.qmth.themis.business.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qmth.themis.business.dto.response.TEExamActivityDto;
 import com.qmth.themis.business.entity.TEExamActivity;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -79,5 +80,5 @@ public interface TEExamActivityMapper extends BaseMapper<TEExamActivity> {
      * @param examActivityId
      * @return
      */
-    public List<Map> getWaitingExam(@Param("studentId") Long studentId, @Param("examId") Long examId, @Param("examActivityId") Long examActivityId);
+    public List<TEExamActivityDto> getWaitingExam(@Param("studentId") Long studentId, @Param("examId") Long examId, @Param("examActivityId") Long examActivityId);
 }

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

@@ -2,6 +2,7 @@ package com.qmth.themis.business.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qmth.themis.business.dto.response.TEExamDto;
 import com.qmth.themis.business.entity.TEExam;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -40,7 +41,7 @@ public interface TEExamMapper extends BaseMapper<TEExam> {
      * @param orgId
      * @return
      */
-    public List<Map> getWaitingExam(@Param("studentId") Long studentId, @Param("examId") Long examId, @Param("orgId") Long orgId);
+    public List<TEExamDto> getWaitingExam(@Param("studentId") Long studentId, @Param("examId") Long examId, @Param("orgId") Long orgId);
 
     /**
      * 获取考试待考列表

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

@@ -1,6 +1,7 @@
 package com.qmth.themis.business.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.themis.business.dto.response.TEExamUnFinishDto;
 import com.qmth.themis.business.entity.TOeExamRecord;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -26,5 +27,5 @@ public interface TOeExamRecordMapper extends BaseMapper<TOeExamRecord> {
      * @param orgId
      * @return
      */
-    public Map getUnFinishExam(@Param("studentId") Long studentId, @Param("examId") Long examId, @Param("orgId") Long orgId);
+    public TEExamUnFinishDto getUnFinishExam(@Param("studentId") Long studentId, @Param("examId") Long examId, @Param("orgId") Long orgId);
 }

+ 267 - 0
themis-business/src/main/java/com/qmth/themis/business/dto/response/TEExamActivityDto.java

@@ -0,0 +1,267 @@
+package com.qmth.themis.business.dto.response;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description: 考试场次dto
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/8/3
+ */
+public class TEExamActivityDto implements Serializable {
+
+    private Long id;//考试id
+    private String code;//考试场次代码
+    private Long examStudentId;//考生id
+    private String courseCode;//科目代码
+    private String courseName;//科目名称
+    private Long openingSeconds;//允许开考开放时长(分钟),相当于迟到时间
+    private Long activityOpeningSeconds;//允许开考开放时长(分钟),相当于迟到时间
+    private Long prepareSeconds;//提前多长时间开始候考(分钟)
+    private Long activityPrepareSeconds;//提前多长时间开始候考(分钟)
+    private Long minDurationSeconds;//最短考试时长,相当于考试冻结时间(分钟)
+    private Long maxDurationSeconds;//最大考试时长
+    private Long activityMaxDurationSeconds;//最大考试时长
+    private Integer examCount;//允许考试次数
+    private Integer fouceFinish;//是否在结束时间集中强制收卷,0:不强制,1:强制
+    private String entryAuthenticationPolicy;//开考身份验证策略,off:关闭,face_verify_optional:非强制人脸验证,face_verify_force:强制人脸验证,liveness:活体验证
+    private Integer inProcessFaceVerify;//考试过程中人脸检测是否开启,0:不开启,1:开启
+    private Integer inProcessFaceStrangerIgnore;//考试过程中人脸检测是否忽略陌生人 ,0:不忽略,1:忽略
+    private Integer inProcessLivenessVerify;//考试过程中是否启用活体检测 ,0:不启用,1:启用
+    private String inProcessLivenessFixedRange;//考试过程中活体检测间隔时间
+    private String inProcessLivenessJudgePolicy;//考试过程中活体检测结果判定规则,any:任意一次通过,all:全部都要通过,more:通过次数大于失败次数
+    private Integer inProcessLivenessRetryCount;//考试过程中活体检测重试次数
+    private Integer clientVideoPush;//是否开启/强制客户端视频监控,0:不开启,1:开启,2:强制开启
+    private Integer wxappVideoPush;//是否开启/强制微信小程序监控,0:不开启,1:开启,2:强制开启
+    private Integer cameraPhotoUpload;//是否允许使用摄像头拍照答题,0:不允许,1:允许
+    private Integer wxappPhotoUpload;//是否允许使用微信拍照答题,0:不允许,1:允许
+    private Integer wxappVideoRecord;//是否开启微信小程序视频转录,0:不开启,1:开启
+    private Date startTime;//考场开始时间
+    private Date finishTime;//考场结束时间
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public Long getExamStudentId() {
+        return examStudentId;
+    }
+
+    public void setExamStudentId(Long examStudentId) {
+        this.examStudentId = examStudentId;
+    }
+
+    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 Long getOpeningSeconds() {
+        return openingSeconds;
+    }
+
+    public void setOpeningSeconds(Long openingSeconds) {
+        this.openingSeconds = openingSeconds;
+    }
+
+    public Long getActivityOpeningSeconds() {
+        return activityOpeningSeconds;
+    }
+
+    public void setActivityOpeningSeconds(Long activityOpeningSeconds) {
+        this.activityOpeningSeconds = activityOpeningSeconds;
+    }
+
+    public Long getPrepareSeconds() {
+        return prepareSeconds;
+    }
+
+    public void setPrepareSeconds(Long prepareSeconds) {
+        this.prepareSeconds = prepareSeconds;
+    }
+
+    public Long getActivityPrepareSeconds() {
+        return activityPrepareSeconds;
+    }
+
+    public void setActivityPrepareSeconds(Long activityPrepareSeconds) {
+        this.activityPrepareSeconds = activityPrepareSeconds;
+    }
+
+    public Long getMinDurationSeconds() {
+        return minDurationSeconds;
+    }
+
+    public void setMinDurationSeconds(Long minDurationSeconds) {
+        this.minDurationSeconds = minDurationSeconds;
+    }
+
+    public Long getMaxDurationSeconds() {
+        return maxDurationSeconds;
+    }
+
+    public void setMaxDurationSeconds(Long maxDurationSeconds) {
+        this.maxDurationSeconds = maxDurationSeconds;
+    }
+
+    public Long getActivityMaxDurationSeconds() {
+        return activityMaxDurationSeconds;
+    }
+
+    public void setActivityMaxDurationSeconds(Long activityMaxDurationSeconds) {
+        this.activityMaxDurationSeconds = activityMaxDurationSeconds;
+    }
+
+    public Integer getExamCount() {
+        return examCount;
+    }
+
+    public void setExamCount(Integer examCount) {
+        this.examCount = examCount;
+    }
+
+    public Integer getFouceFinish() {
+        return fouceFinish;
+    }
+
+    public void setFouceFinish(Integer fouceFinish) {
+        this.fouceFinish = fouceFinish;
+    }
+
+    public String getEntryAuthenticationPolicy() {
+        return entryAuthenticationPolicy;
+    }
+
+    public void setEntryAuthenticationPolicy(String entryAuthenticationPolicy) {
+        this.entryAuthenticationPolicy = entryAuthenticationPolicy;
+    }
+
+    public Integer getInProcessFaceVerify() {
+        return inProcessFaceVerify;
+    }
+
+    public void setInProcessFaceVerify(Integer inProcessFaceVerify) {
+        this.inProcessFaceVerify = inProcessFaceVerify;
+    }
+
+    public Integer getInProcessFaceStrangerIgnore() {
+        return inProcessFaceStrangerIgnore;
+    }
+
+    public void setInProcessFaceStrangerIgnore(Integer inProcessFaceStrangerIgnore) {
+        this.inProcessFaceStrangerIgnore = inProcessFaceStrangerIgnore;
+    }
+
+    public Integer getInProcessLivenessVerify() {
+        return inProcessLivenessVerify;
+    }
+
+    public void setInProcessLivenessVerify(Integer inProcessLivenessVerify) {
+        this.inProcessLivenessVerify = inProcessLivenessVerify;
+    }
+
+    public String getInProcessLivenessFixedRange() {
+        return inProcessLivenessFixedRange;
+    }
+
+    public void setInProcessLivenessFixedRange(String inProcessLivenessFixedRange) {
+        this.inProcessLivenessFixedRange = inProcessLivenessFixedRange;
+    }
+
+    public String getInProcessLivenessJudgePolicy() {
+        return inProcessLivenessJudgePolicy;
+    }
+
+    public void setInProcessLivenessJudgePolicy(String inProcessLivenessJudgePolicy) {
+        this.inProcessLivenessJudgePolicy = inProcessLivenessJudgePolicy;
+    }
+
+    public Integer getInProcessLivenessRetryCount() {
+        return inProcessLivenessRetryCount;
+    }
+
+    public void setInProcessLivenessRetryCount(Integer inProcessLivenessRetryCount) {
+        this.inProcessLivenessRetryCount = inProcessLivenessRetryCount;
+    }
+
+    public Integer getClientVideoPush() {
+        return clientVideoPush;
+    }
+
+    public void setClientVideoPush(Integer clientVideoPush) {
+        this.clientVideoPush = clientVideoPush;
+    }
+
+    public Integer getWxappVideoPush() {
+        return wxappVideoPush;
+    }
+
+    public void setWxappVideoPush(Integer wxappVideoPush) {
+        this.wxappVideoPush = wxappVideoPush;
+    }
+
+    public Integer getCameraPhotoUpload() {
+        return cameraPhotoUpload;
+    }
+
+    public void setCameraPhotoUpload(Integer cameraPhotoUpload) {
+        this.cameraPhotoUpload = cameraPhotoUpload;
+    }
+
+    public Integer getWxappPhotoUpload() {
+        return wxappPhotoUpload;
+    }
+
+    public void setWxappPhotoUpload(Integer wxappPhotoUpload) {
+        this.wxappPhotoUpload = wxappPhotoUpload;
+    }
+
+    public Integer getWxappVideoRecord() {
+        return wxappVideoRecord;
+    }
+
+    public void setWxappVideoRecord(Integer wxappVideoRecord) {
+        this.wxappVideoRecord = wxappVideoRecord;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getFinishTime() {
+        return finishTime;
+    }
+
+    public void setFinishTime(Date finishTime) {
+        this.finishTime = finishTime;
+    }
+}

+ 96 - 0
themis-business/src/main/java/com/qmth/themis/business/dto/response/TEExamDto.java

@@ -0,0 +1,96 @@
+package com.qmth.themis.business.dto.response;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @Description: 考试dto
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/8/3
+ */
+public class TEExamDto implements Serializable {
+
+    private Long id;//考试id
+    private Long examActivityId;//考试场次id
+    private String name;//考试名称
+    private String mode;//考试模式
+    private String preNotice;//考前须知
+    private Integer preNoticeStaySeconds;//考试须知阅读时长(秒)
+    private String postNotice;//考后说明,针对一个场次进行设置
+    private Integer reallyTime;
+    private Map<String,Object> activities;
+
+    public Map<String, Object> getActivities() {
+        return activities;
+    }
+
+    public void setActivities(Map<String, Object> activities) {
+        this.activities = activities;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getExamActivityId() {
+        return examActivityId;
+    }
+
+    public void setExamActivityId(Long examActivityId) {
+        this.examActivityId = examActivityId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getMode() {
+        return mode;
+    }
+
+    public void setMode(String mode) {
+        this.mode = mode;
+    }
+
+    public String getPreNotice() {
+        return preNotice;
+    }
+
+    public void setPreNotice(String preNotice) {
+        this.preNotice = preNotice;
+    }
+
+    public Integer getPreNoticeStaySeconds() {
+        return preNoticeStaySeconds;
+    }
+
+    public void setPreNoticeStaySeconds(Integer preNoticeStaySeconds) {
+        this.preNoticeStaySeconds = preNoticeStaySeconds;
+    }
+
+    public String getPostNotice() {
+        return postNotice;
+    }
+
+    public void setPostNotice(String postNotice) {
+        this.postNotice = postNotice;
+    }
+
+    public Integer getReallyTime() {
+        return reallyTime;
+    }
+
+    public void setReallyTime(Integer reallyTime) {
+        this.reallyTime = reallyTime;
+    }
+}

+ 321 - 0
themis-business/src/main/java/com/qmth/themis/business/dto/response/TEExamUnFinishDto.java

@@ -0,0 +1,321 @@
+package com.qmth.themis.business.dto.response;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description: 未完成的考试记录
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/8/3
+ */
+public class TEExamUnFinishDto implements Serializable {
+
+    private Long id;//考试id
+    private Long examActivityId;//考试场次id
+    private Long recordId;//考试记录id
+    private Long examStudentId;//考生id
+    private String name;//考试名称
+    private String mode;//考试模式
+    private String preNotice;//考前须知
+    private Integer preNoticeStaySeconds;//考试须知阅读时长(秒)
+    private String postNotice;//考后说明,针对一个场次进行设置
+    private String examCode;//考试代码
+    private String examActivityCode;//考试场次代码
+    private Date examStartTime;//考试开始时间
+    private Date examEndTime;//考试结束时间
+    private Date examActivityStartTime;//考场开始时间
+    private Date examActivityFinishTime;//考场结束时间
+    private String courseCode;//科目代码
+    private String courseName;//科目名称
+    private Long prepareSeconds;//提前多长时间开始候考(分钟)
+    private Long minDurationSeconds;//最短考试时长,相当于考试冻结时间(分钟)
+    private Long maxDurationSeconds;//最大考试时长
+    private Integer examCount;//允许考试次数
+    private Integer fouceFinish;//是否在结束时间集中强制收卷,0:不强制,1:强制
+    private String entryAuthenticationPolicy;//开考身份验证策略,off:关闭,face_verify_optional:非强制人脸验证,face_verify_force:强制人脸验证,liveness:活体验证
+    private Integer inProcessFaceVerify;//考试过程中人脸检测是否开启,0:不开启,1:开启
+    private Integer inProcessFaceStrangerIgnore;//考试过程中人脸检测是否忽略陌生人 ,0:不忽略,1:忽略
+    private Integer inProcessLivenessVerify;//考试过程中是否启用活体检测 ,0:不启用,1:启用
+    private String inProcessLivenessFixedRange;//考试过程中活体检测间隔时间
+    private String inProcessLivenessJudgePolicy;//考试过程中活体检测结果判定规则,any:任意一次通过,all:全部都要通过,more:通过次数大于失败次数
+    private Integer inProcessLivenessRetryCount;//考试过程中活体检测重试次数
+    private Integer clientVideoPush;//是否开启/强制客户端视频监控,0:不开启,1:开启,2:强制开启
+    private Integer wxappVideoPush;//是否开启/强制微信小程序监控,0:不开启,1:开启,2:强制开启
+    private Integer cameraPhotoUpload;//是否允许使用摄像头拍照答题,0:不允许,1:允许
+    private Integer wxappPhotoUpload;//是否允许使用微信拍照答题,0:不允许,1:允许
+    private Integer wxappVideoRecord;//是否开启微信小程序视频转录,0:不开启,1:开启
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getExamActivityId() {
+        return examActivityId;
+    }
+
+    public void setExamActivityId(Long examActivityId) {
+        this.examActivityId = examActivityId;
+    }
+
+    public Long getRecordId() {
+        return recordId;
+    }
+
+    public void setRecordId(Long recordId) {
+        this.recordId = recordId;
+    }
+
+    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 getMode() {
+        return mode;
+    }
+
+    public void setMode(String mode) {
+        this.mode = mode;
+    }
+
+    public String getPreNotice() {
+        return preNotice;
+    }
+
+    public void setPreNotice(String preNotice) {
+        this.preNotice = preNotice;
+    }
+
+    public Integer getPreNoticeStaySeconds() {
+        return preNoticeStaySeconds;
+    }
+
+    public void setPreNoticeStaySeconds(Integer preNoticeStaySeconds) {
+        this.preNoticeStaySeconds = preNoticeStaySeconds;
+    }
+
+    public String getPostNotice() {
+        return postNotice;
+    }
+
+    public void setPostNotice(String postNotice) {
+        this.postNotice = postNotice;
+    }
+
+    public String getExamCode() {
+        return examCode;
+    }
+
+    public void setExamCode(String examCode) {
+        this.examCode = examCode;
+    }
+
+    public String getExamActivityCode() {
+        return examActivityCode;
+    }
+
+    public void setExamActivityCode(String examActivityCode) {
+        this.examActivityCode = examActivityCode;
+    }
+
+    public Date getExamStartTime() {
+        return examStartTime;
+    }
+
+    public void setExamStartTime(Date examStartTime) {
+        this.examStartTime = examStartTime;
+    }
+
+    public Date getExamEndTime() {
+        return examEndTime;
+    }
+
+    public void setExamEndTime(Date examEndTime) {
+        this.examEndTime = examEndTime;
+    }
+
+    public Date getExamActivityStartTime() {
+        return examActivityStartTime;
+    }
+
+    public void setExamActivityStartTime(Date examActivityStartTime) {
+        this.examActivityStartTime = examActivityStartTime;
+    }
+
+    public Date getExamActivityFinishTime() {
+        return examActivityFinishTime;
+    }
+
+    public void setExamActivityFinishTime(Date examActivityFinishTime) {
+        this.examActivityFinishTime = examActivityFinishTime;
+    }
+
+    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 Long getPrepareSeconds() {
+        return prepareSeconds;
+    }
+
+    public void setPrepareSeconds(Long prepareSeconds) {
+        this.prepareSeconds = prepareSeconds;
+    }
+
+    public Long getMinDurationSeconds() {
+        return minDurationSeconds;
+    }
+
+    public void setMinDurationSeconds(Long minDurationSeconds) {
+        this.minDurationSeconds = minDurationSeconds;
+    }
+
+    public Long getMaxDurationSeconds() {
+        return maxDurationSeconds;
+    }
+
+    public void setMaxDurationSeconds(Long maxDurationSeconds) {
+        this.maxDurationSeconds = maxDurationSeconds;
+    }
+
+    public Integer getExamCount() {
+        return examCount;
+    }
+
+    public void setExamCount(Integer examCount) {
+        this.examCount = examCount;
+    }
+
+    public Integer getFouceFinish() {
+        return fouceFinish;
+    }
+
+    public void setFouceFinish(Integer fouceFinish) {
+        this.fouceFinish = fouceFinish;
+    }
+
+    public String getEntryAuthenticationPolicy() {
+        return entryAuthenticationPolicy;
+    }
+
+    public void setEntryAuthenticationPolicy(String entryAuthenticationPolicy) {
+        this.entryAuthenticationPolicy = entryAuthenticationPolicy;
+    }
+
+    public Integer getInProcessFaceVerify() {
+        return inProcessFaceVerify;
+    }
+
+    public void setInProcessFaceVerify(Integer inProcessFaceVerify) {
+        this.inProcessFaceVerify = inProcessFaceVerify;
+    }
+
+    public Integer getInProcessFaceStrangerIgnore() {
+        return inProcessFaceStrangerIgnore;
+    }
+
+    public void setInProcessFaceStrangerIgnore(Integer inProcessFaceStrangerIgnore) {
+        this.inProcessFaceStrangerIgnore = inProcessFaceStrangerIgnore;
+    }
+
+    public Integer getInProcessLivenessVerify() {
+        return inProcessLivenessVerify;
+    }
+
+    public void setInProcessLivenessVerify(Integer inProcessLivenessVerify) {
+        this.inProcessLivenessVerify = inProcessLivenessVerify;
+    }
+
+    public String getInProcessLivenessFixedRange() {
+        return inProcessLivenessFixedRange;
+    }
+
+    public void setInProcessLivenessFixedRange(String inProcessLivenessFixedRange) {
+        this.inProcessLivenessFixedRange = inProcessLivenessFixedRange;
+    }
+
+    public String getInProcessLivenessJudgePolicy() {
+        return inProcessLivenessJudgePolicy;
+    }
+
+    public void setInProcessLivenessJudgePolicy(String inProcessLivenessJudgePolicy) {
+        this.inProcessLivenessJudgePolicy = inProcessLivenessJudgePolicy;
+    }
+
+    public Integer getInProcessLivenessRetryCount() {
+        return inProcessLivenessRetryCount;
+    }
+
+    public void setInProcessLivenessRetryCount(Integer inProcessLivenessRetryCount) {
+        this.inProcessLivenessRetryCount = inProcessLivenessRetryCount;
+    }
+
+    public Integer getClientVideoPush() {
+        return clientVideoPush;
+    }
+
+    public void setClientVideoPush(Integer clientVideoPush) {
+        this.clientVideoPush = clientVideoPush;
+    }
+
+    public Integer getWxappVideoPush() {
+        return wxappVideoPush;
+    }
+
+    public void setWxappVideoPush(Integer wxappVideoPush) {
+        this.wxappVideoPush = wxappVideoPush;
+    }
+
+    public Integer getCameraPhotoUpload() {
+        return cameraPhotoUpload;
+    }
+
+    public void setCameraPhotoUpload(Integer cameraPhotoUpload) {
+        this.cameraPhotoUpload = cameraPhotoUpload;
+    }
+
+    public Integer getWxappPhotoUpload() {
+        return wxappPhotoUpload;
+    }
+
+    public void setWxappPhotoUpload(Integer wxappPhotoUpload) {
+        this.wxappPhotoUpload = wxappPhotoUpload;
+    }
+
+    public Integer getWxappVideoRecord() {
+        return wxappVideoRecord;
+    }
+
+    public void setWxappVideoRecord(Integer wxappVideoRecord) {
+        this.wxappVideoRecord = wxappVideoRecord;
+    }
+}

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

@@ -3,6 +3,7 @@ package com.qmth.themis.business.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
+import com.qmth.themis.business.dto.response.TEExamActivityDto;
 import com.qmth.themis.business.entity.TEExamActivity;
 
 import java.util.List;
@@ -77,7 +78,7 @@ public interface TEExamActivityService extends IService<TEExamActivity> {
      * @param examActivityId
      * @return
      */
-    public List<Map> getWaitingExam(Long studentId, Long examId,Long examActivityId);
+    public List<TEExamActivityDto> getWaitingExam(Long studentId, Long examId, Long examActivityId);
 
 	/**获取场次缓存
 	 * @param examActivityId

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

@@ -3,6 +3,7 @@ package com.qmth.themis.business.service;
 import java.util.List;
 import java.util.Map;
 
+import com.qmth.themis.business.dto.response.TEExamDto;
 import org.springframework.web.multipart.MultipartFile;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -46,7 +47,7 @@ public interface TEExamService extends IService<TEExam> {
      * @param orgId
      * @return
      */
-    public List<Map> getWaitingExam(Long studentId, Long examId, Long orgId);
+    public List<TEExamDto> getWaitingExam(Long studentId, Long examId, Long orgId);
 
     /**
      * 获取考试待考列表

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

@@ -1,6 +1,7 @@
 package com.qmth.themis.business.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.themis.business.dto.response.TEExamUnFinishDto;
 import com.qmth.themis.business.entity.TOeExamRecord;
 
 import java.util.Map;

+ 2 - 1
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamActivityServiceImpl.java

@@ -5,6 +5,7 @@ import java.util.Map;
 
 import javax.annotation.Resource;
 
+import com.qmth.themis.business.dto.response.TEExamActivityDto;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 
@@ -107,7 +108,7 @@ public class TEExamActivityServiceImpl extends ServiceImpl<TEExamActivityMapper,
      * @return
      */
     @Override
-    public List<Map> getWaitingExam(Long studentId, Long examId, Long examActivityId) {
+    public List<TEExamActivityDto> getWaitingExam(Long studentId, Long examId, Long examActivityId) {
         return teExamActivityMapper.getWaitingExam(studentId, examId, examActivityId);
     }
     

+ 541 - 565
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -1,58 +1,35 @@
 package com.qmth.themis.business.service.impl;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-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.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.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.*;
 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.dao.TEExamMapper;
+import com.qmth.themis.business.dto.response.TEExamActivityDto;
+import com.qmth.themis.business.dto.response.TEExamDto;
 import com.qmth.themis.business.entity.TEExam;
 import com.qmth.themis.business.enums.ExamRecordStatusEnum;
 import com.qmth.themis.business.enums.FinishTypeEnum;
-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.service.*;
 import com.qmth.themis.business.util.OssUtil;
 import com.qmth.themis.business.util.RedisUtil;
 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.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: 考试批次 服务实现类
@@ -63,528 +40,527 @@ import com.qmth.themis.common.exception.BusinessException;
  */
 @Service
 public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> implements TEExamService {
-	private SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
-	@Resource
-	TEExamMapper teExamMapper;
-
-	@Resource
-	TEExamActivityService teExamActivityService;
-
-	@Resource
-	TEExamStudentService teExamStudentService;
-
-	@Resource
-	TEExamCourseService teExamCourseService;
-
-	@Resource
-	TEExamPaperService teExamPaperService;
-
-	@Resource
-	TOeExamRecordService toeExamRecordService;
-
-	@Resource
-	RedisUtil redisUtil;
-
-	@Resource
-	SystemConfig systemConfig;
-
-	/**
-	 * 查询考试批次
-	 *
-	 * @param iPage
-	 * @param id
-	 * @param code
-	 * @param name
-	 * @param mode
-	 * @param enable
-	 * @return
-	 */
-	@Override
-	public IPage<TEExam> examQuery(IPage<Map> iPage, Long id, String code, String name, Integer mode, Integer enable) {
-		return teExamMapper.examQuery(iPage, id, code, name, mode, enable);
-	}
-
-	/**
-	 * 获取考试待考列表
-	 *
-	 * @param studentId
-	 * @param examId
-	 * @param orgId
-	 * @return
-	 */
-	@Override
-	public List<Map> getWaitingExam(Long studentId, Long examId, Long orgId) {
-		List<Map> list = teExamMapper.getWaitingExam(studentId, examId, orgId);
-		if (Objects.nonNull(list) && list.size() > 0) {
-			for (int i = 0; i < list.size(); i++) {
-				Map m = list.get(i);
-				List<Map> teExamActivityList = teExamActivityService.getWaitingExam(studentId,
-						Long.parseLong(String.valueOf(m.get("id"))),
-						Long.parseLong(String.valueOf(m.get("examActivityId"))));
-				m.put("activities", teExamActivityList);
-			}
-		}
-		return list;
-	}
-
-	/**
-	 * 获取考试待考列表
-	 *
-	 * @return
-	 */
-	@Override
-	public List<Map> getWaitingExamForJob() {
-		return teExamMapper.getWaitingExamForJob();
-	}
-
-	@Transactional
-	@Override
-	public ExamPrepareBean prepare(Long studentId, Long examStudentId) {
-		ExamPrepareBean ret = null;
-		ExamStudentCacheBean es = null;
-		es = (ExamStudentCacheBean) redisUtil.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
-		if (es == null) {
-			es = teExamStudentService.getExamStudnetCacheBean(examStudentId);
-		}
-		if (es == null) {
-			throw new BusinessException("未找到考试");
-		}
-
-		if (studentId.equals(es.getStudentId())) {
-			throw new BusinessException("考生Id和当前登录用户不一致");
-		}
-		if (es.getLeftExamCount() == 0) {
-			throw new BusinessException("没有剩余考试次数");
-		}
-		Long activityId = es.getExamActivityId();
-		ExamActivityCacheBean ac = teExamActivityService.getExamActivityCacheBean(activityId);
-		if (ac == null) {
-			throw new BusinessException("未找到场次");
-		}
-		Date now = new Date();
-		Long start = ac.getStartTime().getTime() - (ac.getPrepareSeconds() * 1000);
-		Long end = ac.getStartTime().getTime() + (ac.getOpeningSeconds() * 1000);
-		if (now.getTime() < start) {
-			throw new BusinessException("没有到允许开考的时间");
-		}
-		if (now.getTime() > end) {
-			throw new BusinessException("允许开考的时间已结束");
-		}
-		ExamCourseCacheBean ec = teExamCourseService.getExamCourseCacheBean(es.getExamId(), es.getCourseCode());
-		if (ec == null) {
-			throw new BusinessException("未找到考试科目");
-		}
-		if (ec.getPaperIds() == null) {
-			throw new BusinessException("考试科目未绑定试卷");
-		}
-		if (ec.getHasAnswer() == null || ec.getHasAnswer().intValue() == 0) {
-			throw new BusinessException("考试科目答案未补全");
-		}
-		// 根据权重选中试卷
-		Long paperId = ec.getPaperIds().get(getPaperByWeight(ec.getPaperWeight()));
-		ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(paperId);
-		if (ep == null) {
-			throw new BusinessException("未找到试卷:" + paperId);
-		}
-		if (StringUtils.isBlank(ep.getAnswerPath())) {
-			throw new BusinessException("试卷答案未上传:" + paperId);
-		}
-
-		// 写入次数
-		Integer serialNumber = es.getCurrentSerialNumber();
-		if (serialNumber == null) {
-			serialNumber = 0;
-		}
-		es.setCurrentSerialNumber(serialNumber + 1);
-
-		Long recordId = toeExamRecordService.saveByPrepare(es.getExamId(), es.getExamActivityId(), examStudentId,
-				paperId, es.getCurrentSerialNumber());
-
-		Integer leftExamCount = es.getLeftExamCount();
-		es.setLeftExamCount(leftExamCount - 1);
-
-		es.setCurrentRecordId(recordId);
-
-		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);
-
-		// 更新考生缓存
-		redisUtil.set(RedisKeyHelper.examStudentCacheKey(examStudentId), es);
-
-		return ret;
-	}
-
-	/**
-	 * 根据设定几率取出一套试卷
-	 */
-	private int getPaperByWeight(List<Double> paperWeight) {
-		// 从1开始
-		double r = Math.random();
-		for (int i = 0; i < paperWeight.size(); i++) {
-			r -= paperWeight.get(i);
-			if (r <= 0.0d) {
-				return i;// 选中
-			}
-		}
-
-		return -1;
-	}
-
-	@Override
-	public ExamStartBean start(Long studentId, Long recordId) {
-		ExamStartBean ret = null;
-
-		// 校验当前登录用户和参数一致性
-		if (ExamRecordCacheUtil.getId(recordId) == null) {
-			throw new BusinessException("未找到考试记录");
-		}
-		Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-		ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
-				.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
-		if (es == null) {
-			throw new BusinessException("未找到考生");
-		}
-		if (studentId.equals(es.getStudentId())) {
-			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
-		}
-
-		Long activityId = es.getExamActivityId();
-		ExamActivityCacheBean ac = teExamActivityService.getExamActivityCacheBean(activityId);
-		if (ac == null) {
-			throw new BusinessException("未找到场次");
-		}
-		Date now = new Date();
-		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("允许开考的时间已结束");
-		}
-
-		Long paperId = ExamRecordCacheUtil.getPaperId(recordId);
-		ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(paperId);
-		if (ep == null) {
-			throw new BusinessException("未找到试卷");
-		}
-
-		ret = new ExamStartBean();
-		ret.setPaperDecryptSecret(ep.getDecryptSecret());
-		ret.setPaperDecryptVector(ep.getDecryptVector());
-
-		// 更新考试记录缓存
-		ExamRecordCacheUtil.setFirstStartTime(recordId, new Date());
-		ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.FIRST_PREPARE);
-
-		return ret;
-	}
-
-	@Override
-	public Long studentPaperStruct(Long studentId, Long recordId, String content) {
-
-		// 校验当前登录用户和参数一致性
-		if (ExamRecordCacheUtil.getId(recordId) == null) {
-			throw new BusinessException("未找到考试记录");
-		}
-		Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-		ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
-				.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
-		if (es == null) {
-			throw new BusinessException("未找到考生");
-		}
-		if (studentId.equals(es.getStudentId())) {
-			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
-		}
-
-		ExamStudentPaperStructCacheBean struct = new ExamStudentPaperStructCacheBean();
-		struct.setContent(content);
-		struct.setTime(new Date().getTime());
-		// 更新考生试卷结构
-		redisUtil.set(RedisKeyHelper.studentPaperStructKey(recordId), struct);
-		return struct.getTime();
-	}
-
-	@Override
-	public Long answerSubmit(Long studentId, Long recordId, Integer mainNumber, Integer subNumber, Integer subIndex,
-			String answer, Long version, Integer durationSeconds) {
-
-		// 校验当前登录用户和参数一致性
-		if (ExamRecordCacheUtil.getId(recordId) == null) {
-			throw new BusinessException("未找到考试记录");
-		}
-		Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-		ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
-				.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
-		if (es == null) {
-			throw new BusinessException("未找到考生");
-		}
-		if (studentId.equals(es.getStudentId())) {
-			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
-		}
-
-		ExamStudentAnswerCacheBean answerCache = (ExamStudentAnswerCacheBean) redisUtil.get(
-				RedisKeyHelper.examAnswerKey(recordId),
-				RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex));
-		if (answerCache == null) {
-			answerCache = new ExamStudentAnswerCacheBean();
-			answerCache.setMainNumber(mainNumber);
-			answerCache.setSubNumber(subNumber);
-			answerCache.setSubIndex(subIndex);
-			answerCache.setContent(answer);
-			answerCache.setVersion(version);
-			answerCache.setDuration(durationSeconds);
-		} else {
-			if (version.longValue() < answerCache.getVersion().longValue()) {
-				throw new BusinessException("版本时间戳过期");
-			}
-			answerCache.setContent(answer);
-			answerCache.setVersion(version);
-			answerCache.setDuration(durationSeconds);
-		}
-		// 每次提交,清空得分
-		answerCache.setScore(null);
-		// 更新考生作答
-		redisUtil.set(RedisKeyHelper.examAnswerKey(recordId),
-				RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex), answerCache);
-		// 重置考试记录客观题得分
-		ExamRecordCacheUtil.setObjectiveScore(recordId, null);
-		return version;
-	}
-
-	@Override
-	public Integer audioLeftPlayCountSubmit(Long studentId, Long recordId, String key, Integer count) {
-
-		// 校验当前登录用户和参数一致性
-		if (ExamRecordCacheUtil.getId(recordId) == null) {
-			throw new BusinessException("未找到考试记录");
-		}
-		Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-		ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
-				.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
-		if (es == null) {
-			throw new BusinessException("未找到考生");
-		}
-		if (studentId.equals(es.getStudentId())) {
-			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
-		}
-
-		// 音频剩余播放次数缓存
-		redisUtil.set(RedisKeyHelper.audioLeftPlayCountKey(recordId), key, count);
-
-		return count;
-	}
-
-	@Override
-	public ExamFileUploadBean fileUpload(Long studentId, Long recordId, MultipartFile file, String suffix, String md5) {
-
-		// 校验当前登录用户和参数一致性
-		if (ExamRecordCacheUtil.getId(recordId) == null) {
-			throw new BusinessException("未找到考试记录");
-		}
-		Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-		ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
-				.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
-		if (es == null) {
-			throw new BusinessException("未找到考生");
-		}
-		if (studentId.equals(es.getStudentId())) {
-			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
-		}
-
-		String filePath = "upload/" + sdf.format(new Date()) + "/" + uuid() + ".json";
-		InputStream in = null;
-		try {
-			String fileMd5 = DigestUtils.md5Hex(file.getBytes());
-			if (!md5.equals(fileMd5)) {
-				throw new BusinessException("文件md5不一致");
-			}
-			in = file.getInputStream();
-			OssUtil.ossUploadStream(systemConfig.getOssEnv(3), filePath, in);
-			String url = systemConfig.getProperty("aliyun.oss.url") + "/" + filePath;
-			ExamFileUploadBean ret = new ExamFileUploadBean();
-			ret.setUrl(url);
-			ret.setUploadTime(new Date().getTime());
-			return ret;
-		} catch (IOException e) {
-			throw new BusinessException("文件读取出错");
-		} finally {
-			if (in != null) {
-				try {
-					in.close();
-				} catch (IOException e) {
-				}
-			}
-		}
-	}
-
-	private String uuid() {
-		return UUID.randomUUID().toString().replaceAll("-", "");
-	}
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public ExamResumeBean resume(Long studentId, Long recordId) {
-
-		// 校验当前登录用户和参数一致性
-		if (ExamRecordCacheUtil.getId(recordId) == null) {
-			throw new BusinessException("未找到考试记录");
-		}
-		Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-		ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
-				.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
-		if (es == null) {
-			throw new BusinessException("未找到考生");
-		}
-		if (studentId.equals(es.getStudentId())) {
-			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
-		}
-
-		Long paperId = ExamRecordCacheUtil.getPaperId(recordId);
-		ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(paperId);
-		if (ep == null) {
-			throw new BusinessException("未找到试卷");
-		}
-
-		ExamResumeBean ret = new ExamResumeBean();
-		ret.setDurationSeconds(ExamRecordCacheUtil.getDurationSeconds(recordId));
-		ret.setPaperUrl(OssUtil.getUrlForPrivateBucket(systemConfig.getOssEnv(3), ep.getPaperPath()));
-		ret.setStructUrl(OssUtil.getUrlForPrivateBucket(systemConfig.getOssEnv(3), ep.getStructPath()));
-		ret.setHasAudio((ep.getHasAudio() != null && ep.getHasAudio().intValue() == 1 ? true : false));
-		ret.setAudioPlayCount(ep.getAudioPlayCount());
-		// TODO 9527
-		ret.setMonitorKey(recordId.toString());
-
-		ExamStudentPaperStructCacheBean struct = (ExamStudentPaperStructCacheBean) redisUtil
-				.get(RedisKeyHelper.studentPaperStructKey(recordId));
-		if (struct != null) {
-			ret.setStudentPaperStruct(struct.getContent());
-		}
-		Map<String, ExamStudentAnswerCacheBean> answers = redisUtil
-				.getHashEntries(RedisKeyHelper.examAnswerKey(recordId));
-		if (answers != null && answers.size() > 0) {
-			ret.setAnswerList(sortAnswers(answers));
-		}
-		Map<String, Integer> audioLeftPlayCounts = redisUtil
-				.getHashEntries(RedisKeyHelper.audioLeftPlayCountKey(recordId));
-		if (audioLeftPlayCounts != null && audioLeftPlayCounts.size() > 0) {
-			ret.setAudioLeftPlayCount(audioLeftPlayCounts);
-		}
-		return ret;
-	}
-
-	// 作答排序
-	private List<ExamStudentAnswerCacheBean> sortAnswers(Map<String, ExamStudentAnswerCacheBean> answers) {
-		List<ExamStudentAnswerCacheBean> ret = new ArrayList<ExamStudentAnswerCacheBean>(answers.values());
-		Collections.sort(ret, new Comparator<ExamStudentAnswerCacheBean>() {
-
-			@Override
-			public int compare(ExamStudentAnswerCacheBean o1, ExamStudentAnswerCacheBean o2) {
-				if (o1.getMainNumber() > o2.getMainNumber()) {
-					return 1;
-				} else if (o1.getMainNumber() < o2.getMainNumber()) {
-					return -1;
-				} else {
-					if (o1.getSubNumber() > o2.getSubNumber()) {
-						return 1;
-					} else if (o1.getSubNumber() < o2.getSubNumber()) {
-						return -1;
-					} else {
-						if (o1.getSubIndex() == null || o2.getSubIndex() == null) {
-							return 0;
-						} else {
-							if (o1.getSubIndex() > o2.getSubIndex()) {
-								return 1;
-							} else if (o1.getSubIndex() < o2.getSubIndex()) {
-								return -1;
-							} else {
-								return 0;
-							}
-						}
-					}
-				}
-			}
-
-		});
-		return ret;
-	}
-
-	@Override
-	public ExamFinishBean finish(Long studentId, Long recordId, String type, Integer durationSeconds) {
-
-		// 校验当前登录用户和参数一致性
-		if (ExamRecordCacheUtil.getId(recordId) == null) {
-			throw new BusinessException("未找到考试记录");
-		}
-		Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-		ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
-				.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
-		if (es == null) {
-			throw new BusinessException("未找到考生");
-		}
-		if (studentId.equals(es.getStudentId())) {
-			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
-		}
-
-		Date now = new Date();
-		ExamFinishBean ret = new ExamFinishBean();
-		ret.setFinishTime(now.getTime());
-		ret.setObjectiveScore(ExamRecordCacheUtil.getObjectiveScore(recordId));
-		// TODO
-		ret.setReviewResult("");
-		ExamRecordCacheUtil.setFinishTime(recordId, now);
-		ExamRecordCacheUtil.setDurationSeconds(recordId, durationSeconds);
-		ExamRecordCacheUtil.setFinishType(recordId, FinishTypeEnum.valueOf(type.toLowerCase()));
-		ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.FINISHED);
-		return ret;
-	}
-
-	@Cacheable(value = "exam", key = "#examId", unless = "#result == null")
-	@Override
-	public ExamCacheBean getExamCacheBean(Long examId) {
-		ExamCacheBean ret = null;
-		TEExam exam = getById(examId);
-		if (exam == null) {
-			return ret;
-		}
-		ret = new ExamCacheBean();
-		BeanUtils.copyProperties(exam, ret);
-		return ret;
-	}
-
-	@Override
-	public ExamResultBean result(Long studentId, Long recordId) {
-		// 校验当前登录用户和参数一致性
-		if (ExamRecordCacheUtil.getId(recordId) == null) {
-			throw new BusinessException("未找到考试记录");
-		}
-		Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-		ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
-				.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
-		if (es == null) {
-			throw new BusinessException("未找到考生");
-		}
-		if (studentId.equals(es.getStudentId())) {
-			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
-		}
-		
-		ExamResultBean ret=new ExamResultBean();
-		ret.setDurationSeconds(ExamRecordCacheUtil.getDurationSeconds(recordId));
-		ret.setFinishTime(ExamRecordCacheUtil.getFinishTime(recordId));
-		ret.setFinishType(ExamRecordCacheUtil.getFinishType(recordId));
-		ret.setObjectiveScore(ExamRecordCacheUtil.getObjectiveScore(recordId));
-		//TODO
-		ret.setReviewResult("");
-		return ret;
-	}
+    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
+    @Resource
+    TEExamMapper teExamMapper;
+
+    @Resource
+    TEExamActivityService teExamActivityService;
+
+    @Resource
+    TEExamStudentService teExamStudentService;
+
+    @Resource
+    TEExamCourseService teExamCourseService;
+
+    @Resource
+    TEExamPaperService teExamPaperService;
+
+    @Resource
+    TOeExamRecordService toeExamRecordService;
+
+    @Resource
+    RedisUtil redisUtil;
+
+    @Resource
+    SystemConfig systemConfig;
+
+    /**
+     * 查询考试批次
+     *
+     * @param iPage
+     * @param id
+     * @param code
+     * @param name
+     * @param mode
+     * @param enable
+     * @return
+     */
+    @Override
+    public IPage<TEExam> examQuery(IPage<Map> iPage, Long id, String code, String name, Integer mode, Integer enable) {
+        return teExamMapper.examQuery(iPage, id, code, name, mode, enable);
+    }
+
+    /**
+     * 获取考试待考列表
+     *
+     * @param studentId
+     * @param examId
+     * @param orgId
+     * @return
+     */
+    @Override
+    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) {
+            list.forEach(s -> {
+                List<TEExamActivityDto> teExamActivityList = teExamActivityService.getWaitingExam(studentId, s.getId(), s.getExamActivityId());
+                Map<String, Object> map = new HashMap();
+                map.put("activities", teExamActivityList);
+                s.setActivities(map);
+            });
+        }
+        return list;
+    }
+
+    /**
+     * 获取考试待考列表
+     *
+     * @return
+     */
+    @Override
+    public List<Map> getWaitingExamForJob() {
+        return teExamMapper.getWaitingExamForJob();
+    }
+
+    @Transactional
+    @Override
+    public ExamPrepareBean prepare(Long studentId, Long examStudentId) {
+        ExamPrepareBean ret = null;
+        ExamStudentCacheBean es = null;
+        es = (ExamStudentCacheBean) redisUtil.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+        if (es == null) {
+            es = teExamStudentService.getExamStudnetCacheBean(examStudentId);
+        }
+        if (es == null) {
+            throw new BusinessException("未找到考试");
+        }
+
+        if (studentId.equals(es.getStudentId())) {
+            throw new BusinessException("考生Id和当前登录用户不一致");
+        }
+        if (es.getLeftExamCount() == 0) {
+            throw new BusinessException("没有剩余考试次数");
+        }
+        Long activityId = es.getExamActivityId();
+        ExamActivityCacheBean ac = teExamActivityService.getExamActivityCacheBean(activityId);
+        if (ac == null) {
+            throw new BusinessException("未找到场次");
+        }
+        Date now = new Date();
+        Long start = ac.getStartTime().getTime() - (ac.getPrepareSeconds() * 1000);
+        Long end = ac.getStartTime().getTime() + (ac.getOpeningSeconds() * 1000);
+        if (now.getTime() < start) {
+            throw new BusinessException("没有到允许开考的时间");
+        }
+        if (now.getTime() > end) {
+            throw new BusinessException("允许开考的时间已结束");
+        }
+        ExamCourseCacheBean ec = teExamCourseService.getExamCourseCacheBean(es.getExamId(), es.getCourseCode());
+        if (ec == null) {
+            throw new BusinessException("未找到考试科目");
+        }
+        if (ec.getPaperIds() == null) {
+            throw new BusinessException("考试科目未绑定试卷");
+        }
+        if (ec.getHasAnswer() == null || ec.getHasAnswer().intValue() == 0) {
+            throw new BusinessException("考试科目答案未补全");
+        }
+        // 根据权重选中试卷
+        Long paperId = ec.getPaperIds().get(getPaperByWeight(ec.getPaperWeight()));
+        ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(paperId);
+        if (ep == null) {
+            throw new BusinessException("未找到试卷:" + paperId);
+        }
+        if (StringUtils.isBlank(ep.getAnswerPath())) {
+            throw new BusinessException("试卷答案未上传:" + paperId);
+        }
+
+        // 写入次数
+        Integer serialNumber = es.getCurrentSerialNumber();
+        if (serialNumber == null) {
+            serialNumber = 0;
+        }
+        es.setCurrentSerialNumber(serialNumber + 1);
+
+        Long recordId = toeExamRecordService.saveByPrepare(es.getExamId(), es.getExamActivityId(), examStudentId,
+                paperId, es.getCurrentSerialNumber());
+
+        Integer leftExamCount = es.getLeftExamCount();
+        es.setLeftExamCount(leftExamCount - 1);
+
+        es.setCurrentRecordId(recordId);
+
+        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);
+
+        // 更新考生缓存
+        redisUtil.set(RedisKeyHelper.examStudentCacheKey(examStudentId), es);
+
+        return ret;
+    }
+
+    /**
+     * 根据设定几率取出一套试卷
+     */
+    private int getPaperByWeight(List<Double> paperWeight) {
+        // 从1开始
+        double r = Math.random();
+        for (int i = 0; i < paperWeight.size(); i++) {
+            r -= paperWeight.get(i);
+            if (r <= 0.0d) {
+                return i;// 选中
+            }
+        }
+
+        return -1;
+    }
+
+    @Override
+    public ExamStartBean start(Long studentId, Long recordId) {
+        ExamStartBean ret = null;
+
+        // 校验当前登录用户和参数一致性
+        if (ExamRecordCacheUtil.getId(recordId) == null) {
+            throw new BusinessException("未找到考试记录");
+        }
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
+                .get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+        if (es == null) {
+            throw new BusinessException("未找到考生");
+        }
+        if (studentId.equals(es.getStudentId())) {
+            throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
+        }
+
+        Long activityId = es.getExamActivityId();
+        ExamActivityCacheBean ac = teExamActivityService.getExamActivityCacheBean(activityId);
+        if (ac == null) {
+            throw new BusinessException("未找到场次");
+        }
+        Date now = new Date();
+        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("允许开考的时间已结束");
+        }
+
+        Long paperId = ExamRecordCacheUtil.getPaperId(recordId);
+        ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(paperId);
+        if (ep == null) {
+            throw new BusinessException("未找到试卷");
+        }
+
+        ret = new ExamStartBean();
+        ret.setPaperDecryptSecret(ep.getDecryptSecret());
+        ret.setPaperDecryptVector(ep.getDecryptVector());
+
+        // 更新考试记录缓存
+        ExamRecordCacheUtil.setFirstStartTime(recordId, new Date());
+        ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.FIRST_PREPARE);
+
+        return ret;
+    }
+
+    @Override
+    public Long studentPaperStruct(Long studentId, Long recordId, String content) {
+
+        // 校验当前登录用户和参数一致性
+        if (ExamRecordCacheUtil.getId(recordId) == null) {
+            throw new BusinessException("未找到考试记录");
+        }
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
+                .get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+        if (es == null) {
+            throw new BusinessException("未找到考生");
+        }
+        if (studentId.equals(es.getStudentId())) {
+            throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
+        }
+
+        ExamStudentPaperStructCacheBean struct = new ExamStudentPaperStructCacheBean();
+        struct.setContent(content);
+        struct.setTime(System.currentTimeMillis());
+        // 更新考生试卷结构
+        redisUtil.set(RedisKeyHelper.studentPaperStructKey(recordId), struct);
+        return struct.getTime();
+    }
+
+    @Override
+    public Long answerSubmit(Long studentId, Long recordId, Integer mainNumber, Integer subNumber, Integer subIndex,
+                             String answer, Long version, Integer durationSeconds) {
+
+        // 校验当前登录用户和参数一致性
+        if (ExamRecordCacheUtil.getId(recordId) == null) {
+            throw new BusinessException("未找到考试记录");
+        }
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
+                .get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+        if (es == null) {
+            throw new BusinessException("未找到考生");
+        }
+        if (studentId.equals(es.getStudentId())) {
+            throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
+        }
+
+        ExamStudentAnswerCacheBean answerCache = (ExamStudentAnswerCacheBean) redisUtil.get(
+                RedisKeyHelper.examAnswerKey(recordId),
+                RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex));
+        if (answerCache == null) {
+            answerCache = new ExamStudentAnswerCacheBean();
+            answerCache.setMainNumber(mainNumber);
+            answerCache.setSubNumber(subNumber);
+            answerCache.setSubIndex(subIndex);
+            answerCache.setContent(answer);
+            answerCache.setVersion(version);
+            answerCache.setDuration(durationSeconds);
+        } else {
+            if (version.longValue() < answerCache.getVersion().longValue()) {
+                throw new BusinessException("版本时间戳过期");
+            }
+            answerCache.setContent(answer);
+            answerCache.setVersion(version);
+            answerCache.setDuration(durationSeconds);
+        }
+        // 每次提交,清空得分
+        answerCache.setScore(null);
+        // 更新考生作答
+        redisUtil.set(RedisKeyHelper.examAnswerKey(recordId),
+                RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex), answerCache);
+        // 重置考试记录客观题得分
+        ExamRecordCacheUtil.setObjectiveScore(recordId, null);
+        return version;
+    }
+
+    @Override
+    public Integer audioLeftPlayCountSubmit(Long studentId, Long recordId, String key, Integer count) {
+
+        // 校验当前登录用户和参数一致性
+        if (ExamRecordCacheUtil.getId(recordId) == null) {
+            throw new BusinessException("未找到考试记录");
+        }
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
+                .get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+        if (es == null) {
+            throw new BusinessException("未找到考生");
+        }
+        if (studentId.equals(es.getStudentId())) {
+            throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
+        }
+
+        // 音频剩余播放次数缓存
+        redisUtil.set(RedisKeyHelper.audioLeftPlayCountKey(recordId), key, count);
+
+        return count;
+    }
+
+    @Override
+    public ExamFileUploadBean fileUpload(Long studentId, Long recordId, MultipartFile file, String suffix, String md5) {
+
+        // 校验当前登录用户和参数一致性
+        if (ExamRecordCacheUtil.getId(recordId) == null) {
+            throw new BusinessException("未找到考试记录");
+        }
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
+                .get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+        if (es == null) {
+            throw new BusinessException("未找到考生");
+        }
+        if (studentId.equals(es.getStudentId())) {
+            throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
+        }
+
+        String filePath = "upload/" + sdf.format(new Date()) + "/" + uuid() + ".json";
+        InputStream in = null;
+        try {
+            String fileMd5 = DigestUtils.md5Hex(file.getBytes());
+            if (!md5.equals(fileMd5)) {
+                throw new BusinessException("文件md5不一致");
+            }
+            in = file.getInputStream();
+            OssUtil.ossUploadStream(systemConfig.getOssEnv(3), filePath, in);
+            String url = systemConfig.getProperty("aliyun.oss.url") + "/" + filePath;
+            ExamFileUploadBean ret = new ExamFileUploadBean();
+            ret.setUrl(url);
+            ret.setUploadTime(System.currentTimeMillis());
+            return ret;
+        } catch (IOException e) {
+            throw new BusinessException("文件读取出错");
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+    }
+
+    private String uuid() {
+        return UUID.randomUUID().toString().replaceAll("-", "");
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public ExamResumeBean resume(Long studentId, Long recordId) {
+
+        // 校验当前登录用户和参数一致性
+        if (ExamRecordCacheUtil.getId(recordId) == null) {
+            throw new BusinessException("未找到考试记录");
+        }
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
+                .get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+        if (es == null) {
+            throw new BusinessException("未找到考生");
+        }
+        if (studentId.equals(es.getStudentId())) {
+            throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
+        }
+
+        Long paperId = ExamRecordCacheUtil.getPaperId(recordId);
+        ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(paperId);
+        if (ep == null) {
+            throw new BusinessException("未找到试卷");
+        }
+
+        ExamResumeBean ret = new ExamResumeBean();
+        ret.setDurationSeconds(ExamRecordCacheUtil.getDurationSeconds(recordId));
+        ret.setPaperUrl(OssUtil.getUrlForPrivateBucket(systemConfig.getOssEnv(3), ep.getPaperPath()));
+        ret.setStructUrl(OssUtil.getUrlForPrivateBucket(systemConfig.getOssEnv(3), ep.getStructPath()));
+        ret.setHasAudio((ep.getHasAudio() != null && ep.getHasAudio().intValue() == 1 ? true : false));
+        ret.setAudioPlayCount(ep.getAudioPlayCount());
+        // TODO 9527
+        ret.setMonitorKey(recordId.toString());
+
+        ExamStudentPaperStructCacheBean struct = (ExamStudentPaperStructCacheBean) redisUtil
+                .get(RedisKeyHelper.studentPaperStructKey(recordId));
+        if (struct != null) {
+            ret.setStudentPaperStruct(struct.getContent());
+        }
+        Map<String, ExamStudentAnswerCacheBean> answers = redisUtil
+                .getHashEntries(RedisKeyHelper.examAnswerKey(recordId));
+        if (answers != null && answers.size() > 0) {
+            ret.setAnswerList(sortAnswers(answers));
+        }
+        Map<String, Integer> audioLeftPlayCounts = redisUtil
+                .getHashEntries(RedisKeyHelper.audioLeftPlayCountKey(recordId));
+        if (audioLeftPlayCounts != null && audioLeftPlayCounts.size() > 0) {
+            ret.setAudioLeftPlayCount(audioLeftPlayCounts);
+        }
+        return ret;
+    }
+
+    // 作答排序
+    private List<ExamStudentAnswerCacheBean> sortAnswers(Map<String, ExamStudentAnswerCacheBean> answers) {
+        List<ExamStudentAnswerCacheBean> ret = new ArrayList<ExamStudentAnswerCacheBean>(answers.values());
+        Collections.sort(ret, new Comparator<ExamStudentAnswerCacheBean>() {
+
+            @Override
+            public int compare(ExamStudentAnswerCacheBean o1, ExamStudentAnswerCacheBean o2) {
+                if (o1.getMainNumber() > o2.getMainNumber()) {
+                    return 1;
+                } else if (o1.getMainNumber() < o2.getMainNumber()) {
+                    return -1;
+                } else {
+                    if (o1.getSubNumber() > o2.getSubNumber()) {
+                        return 1;
+                    } else if (o1.getSubNumber() < o2.getSubNumber()) {
+                        return -1;
+                    } else {
+                        if (o1.getSubIndex() == null || o2.getSubIndex() == null) {
+                            return 0;
+                        } else {
+                            if (o1.getSubIndex() > o2.getSubIndex()) {
+                                return 1;
+                            } else if (o1.getSubIndex() < o2.getSubIndex()) {
+                                return -1;
+                            } else {
+                                return 0;
+                            }
+                        }
+                    }
+                }
+            }
+
+        });
+        return ret;
+    }
+
+    @Override
+    public ExamFinishBean finish(Long studentId, Long recordId, String type, Integer durationSeconds) {
+
+        // 校验当前登录用户和参数一致性
+        if (ExamRecordCacheUtil.getId(recordId) == null) {
+            throw new BusinessException("未找到考试记录");
+        }
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
+                .get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+        if (es == null) {
+            throw new BusinessException("未找到考生");
+        }
+        if (studentId.equals(es.getStudentId())) {
+            throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
+        }
+
+        Date now = new Date();
+        ExamFinishBean ret = new ExamFinishBean();
+        ret.setFinishTime(now.getTime());
+        ret.setObjectiveScore(ExamRecordCacheUtil.getObjectiveScore(recordId));
+        // TODO
+        ret.setReviewResult("");
+        ExamRecordCacheUtil.setFinishTime(recordId, now);
+        ExamRecordCacheUtil.setDurationSeconds(recordId, durationSeconds);
+        ExamRecordCacheUtil.setFinishType(recordId, FinishTypeEnum.valueOf(type.toLowerCase()));
+        ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.FINISHED);
+        return ret;
+    }
+
+    @Cacheable(value = "exam", key = "#examId", unless = "#result == null")
+    @Override
+    public ExamCacheBean getExamCacheBean(Long examId) {
+        ExamCacheBean ret = null;
+        TEExam exam = getById(examId);
+        if (exam == null) {
+            return ret;
+        }
+        ret = new ExamCacheBean();
+        BeanUtils.copyProperties(exam, ret);
+        return ret;
+    }
+
+    @Override
+    public ExamResultBean result(Long studentId, Long recordId) {
+        // 校验当前登录用户和参数一致性
+        if (ExamRecordCacheUtil.getId(recordId) == null) {
+            throw new BusinessException("未找到考试记录");
+        }
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
+                .get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+        if (es == null) {
+            throw new BusinessException("未找到考生");
+        }
+        if (studentId.equals(es.getStudentId())) {
+            throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
+        }
+
+        ExamResultBean ret = new ExamResultBean();
+        ret.setDurationSeconds(ExamRecordCacheUtil.getDurationSeconds(recordId));
+        ret.setFinishTime(ExamRecordCacheUtil.getFinishTime(recordId));
+        ret.setFinishType(ExamRecordCacheUtil.getFinishType(recordId));
+        ret.setObjectiveScore(ExamRecordCacheUtil.getObjectiveScore(recordId));
+        //TODO
+        ret.setReviewResult("");
+        return ret;
+    }
 }

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

@@ -1,18 +1,8 @@
 package com.qmth.themis.business.service.impl;
 
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-
-import javax.annotation.Resource;
-
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
 import com.alibaba.fastjson.JSONArray;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.gson.Gson;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
@@ -20,6 +10,7 @@ import com.qmth.themis.business.cache.bean.ExamStudentAnswerCacheBean;
 import com.qmth.themis.business.cache.bean.ObjectiveAnswerCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dao.TOeExamRecordMapper;
+import com.qmth.themis.business.dto.response.TEExamUnFinishDto;
 import com.qmth.themis.business.entity.TOeExamRecord;
 import com.qmth.themis.business.enums.ExamRecordStatusEnum;
 import com.qmth.themis.business.enums.ObjectiveScorePolicyEnum;
@@ -29,6 +20,15 @@ import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.common.contanst.Constants;
 import com.qmth.themis.common.util.SimpleBeanUtil;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
 
 /**
  * @Description: 考试记录 服务实现类
@@ -45,13 +45,13 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
 
     @Resource
     RedisUtil redisUtil;
-    
-	@Resource
-	TEExamPaperService examPaperService;
 
-	@Resource
-	TEExamService examService;
-    
+    @Resource
+    TEExamPaperService examPaperService;
+
+    @Resource
+    TEExamService examService;
+
     /**
      * 获取考试未完列表
      *
@@ -62,202 +62,202 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
      */
     @Override
     public Map getUnFinishExam(Long studentId, Long examId, Long orgId) {
-        Map unFinishExam = tOeExamRecordMapper.getUnFinishExam(studentId, examId, orgId);
-        if (Objects.nonNull(unFinishExam)) {
+        TEExamUnFinishDto teExamUnFinishDto = tOeExamRecordMapper.getUnFinishExam(studentId, examId, orgId);
+        if (Objects.nonNull(teExamUnFinishDto)) {
             Map finalMap = new HashMap();
             Map<String, Object> waitingMap = new HashMap();
-            waitingMap.put("id", unFinishExam.get("id"));
-            waitingMap.put("examActivityId", unFinishExam.get("examActivityId"));
-            waitingMap.put("name", unFinishExam.get("name"));
-            waitingMap.put("mode", unFinishExam.get("mode"));
-            waitingMap.put("preNotice", unFinishExam.get("preNotice"));
-            waitingMap.put("preNoticeStaySeconds", unFinishExam.get("preNoticeStaySeconds"));
-            waitingMap.put("postNotice", unFinishExam.get("postNotice"));
+            waitingMap.put("id", teExamUnFinishDto.getId());
+            waitingMap.put("examActivityId", teExamUnFinishDto.getExamActivityId());
+            waitingMap.put("name", teExamUnFinishDto.getName());
+            waitingMap.put("mode", teExamUnFinishDto.getMode());
+            waitingMap.put("preNotice", teExamUnFinishDto.getPreNotice());
+            waitingMap.put("preNoticeStaySeconds", teExamUnFinishDto.getPreNoticeStaySeconds());
+            waitingMap.put("postNotice", teExamUnFinishDto.getPostNotice());
             finalMap.put("waiting", waitingMap);
 
             Map<String, Object> activityMap = new HashMap();
-            activityMap.put("recordId", unFinishExam.get("recordId"));
-            activityMap.put("minDurationSeconds", unFinishExam.get("minDurationSeconds"));
-            activityMap.put("clientVideoPush", unFinishExam.get("clientVideoPush"));
-            activityMap.put("cameraPhotoUpload", unFinishExam.get("cameraPhotoUpload"));
-            activityMap.put("courseCode", unFinishExam.get("courseCode"));
-            activityMap.put("wxappPhotoUpload", unFinishExam.get("wxappPhotoUpload"));
-            activityMap.put("inProcessLivenessRetryCount", unFinishExam.get("inProcessLivenessRetryCount"));
-            activityMap.put("examStudentId", unFinishExam.get("examStudentId"));
-            activityMap.put("inProcessLivenessVerify", unFinishExam.get("inProcessLivenessVerify"));
-            activityMap.put("inProcessFaceStrangerIgnore", unFinishExam.get("inProcessFaceStrangerIgnore"));
-            activityMap.put("wxappVideoRecord", unFinishExam.get("wxappVideoRecord"));
-            activityMap.put("inProcessFaceVerify", unFinishExam.get("inProcessFaceVerify"));
-            activityMap.put("courseName", unFinishExam.get("courseName"));
-            activityMap.put("wxappVideoPush", unFinishExam.get("wxappVideoPush"));
-            activityMap.put("inProcessLivenessFixedRange", unFinishExam.get("inProcessLivenessFixedRange"));
-            activityMap.put("prepareSeconds", unFinishExam.get("prepareSeconds"));
-            activityMap.put("fouceFinish", unFinishExam.get("fouceFinish"));
-            activityMap.put("entryAuthenticationPolicy", unFinishExam.get("entryAuthenticationPolicy"));
-            activityMap.put("maxDurationSeconds", unFinishExam.get("maxDurationSeconds"));
-            activityMap.put("examCount", unFinishExam.get("examCount"));
-            activityMap.put("inProcessLivenessJudgePolicy", unFinishExam.get("inProcessLivenessJudgePolicy"));
-            activityMap.put("id", unFinishExam.get("examActivityId"));
+            activityMap.put("recordId", teExamUnFinishDto.getRecordId());
+            activityMap.put("minDurationSeconds", teExamUnFinishDto.getMinDurationSeconds());
+            activityMap.put("clientVideoPush", teExamUnFinishDto.getClientVideoPush());
+            activityMap.put("cameraPhotoUpload", teExamUnFinishDto.getCameraPhotoUpload());
+            activityMap.put("courseCode", teExamUnFinishDto.getCourseCode());
+            activityMap.put("wxappPhotoUpload", teExamUnFinishDto.getWxappPhotoUpload());
+            activityMap.put("inProcessLivenessRetryCount", teExamUnFinishDto.getInProcessLivenessRetryCount());
+            activityMap.put("examStudentId", teExamUnFinishDto.getExamStudentId());
+            activityMap.put("inProcessLivenessVerify", teExamUnFinishDto.getInProcessLivenessVerify());
+            activityMap.put("inProcessFaceStrangerIgnore", teExamUnFinishDto.getInProcessFaceStrangerIgnore());
+            activityMap.put("wxappVideoRecord", teExamUnFinishDto.getWxappVideoRecord());
+            activityMap.put("inProcessFaceVerify", teExamUnFinishDto.getInProcessFaceVerify());
+            activityMap.put("courseName", teExamUnFinishDto.getCourseName());
+            activityMap.put("wxappVideoPush", teExamUnFinishDto.getWxappVideoPush());
+            activityMap.put("inProcessLivenessFixedRange", teExamUnFinishDto.getInProcessLivenessFixedRange());
+            activityMap.put("prepareSeconds", teExamUnFinishDto.getPrepareSeconds());
+            activityMap.put("fouceFinish", teExamUnFinishDto.getFouceFinish());
+            activityMap.put("entryAuthenticationPolicy", teExamUnFinishDto.getEntryAuthenticationPolicy());
+            activityMap.put("maxDurationSeconds", teExamUnFinishDto.getMaxDurationSeconds());
+            activityMap.put("examCount", teExamUnFinishDto.getExamCount());
+            activityMap.put("inProcessLivenessJudgePolicy", teExamUnFinishDto.getInProcessLivenessJudgePolicy());
+            activityMap.put("id", teExamUnFinishDto.getExamActivityId());
 
             finalMap.put("activity", activityMap);
             return finalMap;
         } else {
-            return unFinishExam;
+            return null;
         }
     }
 
     @Transactional
-	@Override
-	public Long saveByPrepare(Long examId, Long examActivityId, Long examStudentId, Long paperId,
-			Integer serialNumber) {
-		TOeExamRecord er = new TOeExamRecord();
-		er.setId(Constants.idGen.next());
-		er.setExamId(examId);
-		er.setExamActivityId(examActivityId);
-		er.setExamStudentId(examStudentId);
-		er.setPaperId(paperId);
-		er.setSerialNumber(serialNumber);
-		er.setFirstPrepareTime(new Date());
-		er.setStatus(ExamRecordStatusEnum.FIRST_PREPARE);
-		redisUtil.set(RedisKeyHelper.examRecordCacheKey(er.getId()), SimpleBeanUtil.objectToMap(er));
-		return er.getId();
-	}
+    @Override
+    public Long saveByPrepare(Long examId, Long examActivityId, Long examStudentId, Long paperId,
+                              Integer serialNumber) {
+        TOeExamRecord er = new TOeExamRecord();
+        er.setId(Constants.idGen.next());
+        er.setExamId(examId);
+        er.setExamActivityId(examActivityId);
+        er.setExamStudentId(examStudentId);
+        er.setPaperId(paperId);
+        er.setSerialNumber(serialNumber);
+        er.setFirstPrepareTime(new Date());
+        er.setStatus(ExamRecordStatusEnum.FIRST_PREPARE);
+        redisUtil.set(RedisKeyHelper.examRecordCacheKey(er.getId()), SimpleBeanUtil.objectToMap(er));
+        return er.getId();
+    }
 
-	/**
-	 *计算客观分
-	 */
-	@Override
-	public void calculateObjectiveScore(Map<String, Object> param) {
-		Long recordId = (Long) param.get("recordId");
-		Integer mainNumber = (Integer) param.get("mainNumber");
-		Integer subNumber = (Integer) param.get("subNumber");
-		Integer subIndex = (Integer) param.get("subIndex");
-		Long paperId = ExamRecordCacheUtil.getPaperId(recordId);
-		Map<String, ObjectiveAnswerCacheBean> map = examPaperService.getObjectiveAnswerCacheBean(paperId);
-		if (map == null || map.size() == 0) {
-			log.error("no ObjectiveAnswerCacheBean for calculateObjectiveScore");
-			return;
-		}
-		String key = RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex);
-		ObjectiveAnswerCacheBean cb = map.get(key);
-		if(cb==null) {
-			return;
-		}
-		ExamStudentAnswerCacheBean answer = (ExamStudentAnswerCacheBean) redisUtil.get(
-				RedisKeyHelper.examAnswerKey(recordId),
-				RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex));
-		if (answer == null) {
-			log.error("no ExamStudentAnswerCacheBean for calculateObjectiveScore");
-			return;
-		}
+    /**
+     * 计算客观分
+     */
+    @Override
+    public void calculateObjectiveScore(Map<String, Object> param) {
+        Long recordId = (Long) param.get("recordId");
+        Integer mainNumber = (Integer) param.get("mainNumber");
+        Integer subNumber = (Integer) param.get("subNumber");
+        Integer subIndex = (Integer) param.get("subIndex");
+        Long paperId = ExamRecordCacheUtil.getPaperId(recordId);
+        Map<String, ObjectiveAnswerCacheBean> map = examPaperService.getObjectiveAnswerCacheBean(paperId);
+        if (map == null || map.size() == 0) {
+            log.error("no ObjectiveAnswerCacheBean for calculateObjectiveScore");
+            return;
+        }
+        String key = RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex);
+        ObjectiveAnswerCacheBean cb = map.get(key);
+        if (cb == null) {
+            return;
+        }
+        ExamStudentAnswerCacheBean answer = (ExamStudentAnswerCacheBean) redisUtil.get(
+                RedisKeyHelper.examAnswerKey(recordId),
+                RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex));
+        if (answer == null) {
+            log.error("no ExamStudentAnswerCacheBean for calculateObjectiveScore");
+            return;
+        }
 
-		if (cb.getStructType().intValue() == 1) {
-			if (checkSingleChoice(answer.getContent(), cb.getChoiceAnswer())) {
-				answer.setScore(cb.getScore());
-			} else {
-				answer.setScore(0.0);
-			}
-		}
-		if (cb.getStructType().intValue() == 2) {
-			ExamCacheBean ec = examService.getExamCacheBean(ExamRecordCacheUtil.getExamId(recordId));
-			int r = checkMultipleChoice(answer.getContent(), cb.getChoiceAnswer());
-			if (ec.getObjectiveScorePolicy().equals(ObjectiveScorePolicyEnum.EQUAL)) {// 全对给分
-				if (r == 1) {
-					answer.setScore(cb.getScore());
-				} else {
-					answer.setScore(0.0);
-				}
-			}
-			if (ec.getObjectiveScorePolicy().equals(ObjectiveScorePolicyEnum.PARTIAL)) {// 漏选半分
-				if (r == 1) {
-					answer.setScore(cb.getScore());
-				} else if (r == 0) {
-					BigDecimal b = new BigDecimal(cb.getScore()).divide(new BigDecimal("2"), 1, BigDecimal.ROUND_UP);
-					answer.setScore(b.doubleValue());
-				} else {
-					answer.setScore(0.0);
-				}
-			}
-		}
-		if (cb.getStructType().intValue() == 3) {
-			if (Boolean.parseBoolean(answer.getContent())==cb.getBoolAnswer().booleanValue()) {
-				answer.setScore(cb.getScore());
-			} else {
-				answer.setScore(0.0);
-			}
-		}
+        if (cb.getStructType().intValue() == 1) {
+            if (checkSingleChoice(answer.getContent(), cb.getChoiceAnswer())) {
+                answer.setScore(cb.getScore());
+            } else {
+                answer.setScore(0.0);
+            }
+        }
+        if (cb.getStructType().intValue() == 2) {
+            ExamCacheBean ec = examService.getExamCacheBean(ExamRecordCacheUtil.getExamId(recordId));
+            int r = checkMultipleChoice(answer.getContent(), cb.getChoiceAnswer());
+            if (ec.getObjectiveScorePolicy().equals(ObjectiveScorePolicyEnum.EQUAL)) {// 全对给分
+                if (r == 1) {
+                    answer.setScore(cb.getScore());
+                } else {
+                    answer.setScore(0.0);
+                }
+            }
+            if (ec.getObjectiveScorePolicy().equals(ObjectiveScorePolicyEnum.PARTIAL)) {// 漏选半分
+                if (r == 1) {
+                    answer.setScore(cb.getScore());
+                } else if (r == 0) {
+                    BigDecimal b = new BigDecimal(cb.getScore()).divide(new BigDecimal("2"), 1, BigDecimal.ROUND_UP);
+                    answer.setScore(b.doubleValue());
+                } else {
+                    answer.setScore(0.0);
+                }
+            }
+        }
+        if (cb.getStructType().intValue() == 3) {
+            if (Boolean.parseBoolean(answer.getContent()) == cb.getBoolAnswer().booleanValue()) {
+                answer.setScore(cb.getScore());
+            } else {
+                answer.setScore(0.0);
+            }
+        }
 
-		answer.setObjective(true);
-		// 更新分数
-		redisUtil.set(RedisKeyHelper.examAnswerKey(recordId),
-				RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex), answer);
+        answer.setObjective(true);
+        // 更新分数
+        redisUtil.set(RedisKeyHelper.examAnswerKey(recordId),
+                RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex), answer);
 
-		// 计算客观分总分
-		calculateTotalObjectiveScore(recordId, map);
-	}
+        // 计算客观分总分
+        calculateTotalObjectiveScore(recordId, map);
+    }
 
-	@SuppressWarnings("unchecked")
-	private void calculateTotalObjectiveScore(Long recordId, Map<String, ObjectiveAnswerCacheBean> map) {
-		String lockKey = SystemConstant.REDIS_LOCK_TOTAL_OBJECTIVE_SCORE_PREFIX + recordId;
-		try {
-			Boolean lock = redisUtil.lock(lockKey, SystemConstant.REDIS_CACHE_TIME_OUT);
-			if (lock) {
-				Map<String,ExamStudentAnswerCacheBean> as=redisUtil.getHashEntries(RedisKeyHelper.examAnswerKey(recordId));
-				if(as!=null&&as.size()>0) {
-					Double total=0.0;
-					for(ExamStudentAnswerCacheBean sa:as.values()) {
-						if(sa.getObjective()!=null&&sa.getObjective()) {//是客观题
-							if(sa.getScore()!=null) {//有分值
-								total=total+sa.getScore();
-							}else {
-								total=null;
-								break;
-							}
-						}
-					}
-					if(total!=null) {
-						ExamRecordCacheUtil.setObjectiveScore(recordId, total);
-					}
-				}
-			}
-		} finally {
-			redisUtil.releaseLock(lockKey);
-		}
-	}
+    @SuppressWarnings("unchecked")
+    private void calculateTotalObjectiveScore(Long recordId, Map<String, ObjectiveAnswerCacheBean> map) {
+        String lockKey = SystemConstant.REDIS_LOCK_TOTAL_OBJECTIVE_SCORE_PREFIX + recordId;
+        try {
+            Boolean lock = redisUtil.lock(lockKey, SystemConstant.REDIS_CACHE_TIME_OUT);
+            if (lock) {
+                Map<String, ExamStudentAnswerCacheBean> as = redisUtil.getHashEntries(RedisKeyHelper.examAnswerKey(recordId));
+                if (as != null && as.size() > 0) {
+                    Double total = 0.0;
+                    for (ExamStudentAnswerCacheBean sa : as.values()) {
+                        if (sa.getObjective() != null && sa.getObjective()) {//是客观题
+                            if (sa.getScore() != null) {//有分值
+                                total = total + sa.getScore();
+                            } else {
+                                total = null;
+                                break;
+                            }
+                        }
+                    }
+                    if (total != null) {
+                        ExamRecordCacheUtil.setObjectiveScore(recordId, total);
+                    }
+                }
+            }
+        } finally {
+            redisUtil.releaseLock(lockKey);
+        }
+    }
 
-	private boolean checkSingleChoice(String answer, JSONArray ar) {
-		int a = Integer.parseInt(answer);
-		for (int i = 0; i < ar.size(); i++) {
-			if (a == ar.getIntValue(i)) {
-				return true;
-			}
-		}
-		return false;
-	}
+    private boolean checkSingleChoice(String answer, JSONArray ar) {
+        int a = Integer.parseInt(answer);
+        for (int i = 0; i < ar.size(); i++) {
+            if (a == ar.getIntValue(i)) {
+                return true;
+            }
+        }
+        return false;
+    }
 
-	/**
-	 * @param answer
-	 * @param ar
-	 * @return -1 有错选项,0-无措选项 未答全 1-全对
-	 */
-	private int checkMultipleChoice(String answer, JSONArray ar) {
-		int yes = 0;
-		int no = 0;
-		String[] ss = answer.split(",");
-		for (String an : ss) {
-			if (checkSingleChoice(an, ar)) {
-				yes++;
-				continue;
-			} else {
-				no++;
-			}
-		}
-		if (yes == ar.size()) {
-			return 1;
-		}
-		if (yes != 0 && no == 0) {
-			return 0;
-		}
-		return -1;
-	}
+    /**
+     * @param answer
+     * @param ar
+     * @return -1 有错选项,0-无措选项 未答全 1-全对
+     */
+    private int checkMultipleChoice(String answer, JSONArray ar) {
+        int yes = 0;
+        int no = 0;
+        String[] ss = answer.split(",");
+        for (String an : ss) {
+            if (checkSingleChoice(an, ar)) {
+                yes++;
+                continue;
+            } else {
+                no++;
+            }
+        }
+        if (yes == ar.size()) {
+            return 1;
+        }
+        if (yes != 0 && no == 0) {
+            return 0;
+        }
+        return -1;
+    }
 }

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

@@ -78,7 +78,7 @@
         </where>
     </select>
 
-    <select id="getWaitingExam" resultType="java.util.Map">
+    <select id="getWaitingExam" resultType="com.qmth.themis.business.dto.response.TEExamActivityDto">
          select
             teea.id,
             teea.code,

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

@@ -23,7 +23,7 @@
         </where>
     </select>
 
-    <select id="getWaitingExam" resultType="java.util.Map">
+    <select id="getWaitingExam" resultType="com.qmth.themis.business.dto.response.TEExamDto">
         select
         t.*
         from

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

@@ -2,7 +2,7 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.themis.business.dao.TOeExamRecordMapper">
 
-    <select id="getUnFinishExam" resultType="java.util.Map">
+    <select id="getUnFinishExam" resultType="com.qmth.themis.business.dto.response.TEExamUnFinishDto">
         select
             tee.id,
             teea.id as examActivityId,

+ 6 - 4
themis-exam/src/main/java/com/qmth/themis/exam/api/TEStudentController.java

@@ -5,6 +5,8 @@ import com.qmth.themis.business.annotation.ApiJsonObject;
 import com.qmth.themis.business.annotation.ApiJsonProperty;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.AuthDto;
+import com.qmth.themis.business.dto.response.TEExamDto;
+import com.qmth.themis.business.dto.response.TEExamUnFinishDto;
 import com.qmth.themis.business.entity.TBSession;
 import com.qmth.themis.business.entity.TEConfig;
 import com.qmth.themis.business.entity.TEStudent;
@@ -166,14 +168,14 @@ public class TEStudentController {
         String test = SignatureInfo.build(SignatureType.TOKEN, sessionId, token);
         Map<String, Object> map = new HashMap<>();
         //获取未完/待考列表
-        Map unFinishExam = tOeExamRecordService.getUnFinishExam(teStudent.getId(), examId, orgId);
-        if (Objects.isNull(unFinishExam)) {
-            List<Map> list = teExamService.getWaitingExam(teStudent.getId(), examId, orgId);
+        Map TEExamUnFinishDto = tOeExamRecordService.getUnFinishExam(teStudent.getId(), examId, orgId);
+        if (Objects.isNull(TEExamUnFinishDto)) {
+            List<TEExamDto> list = teExamService.getWaitingExam(teStudent.getId(), examId, orgId);
             if (Objects.nonNull(list) && list.size() > 0) {
                 map.put("waiting", list);
             }
         } else {
-            map.put("unFinished", unFinishExam);
+            map.put("unFinished", TEExamUnFinishDto);
         }
         //获取全局考试配置
         TEConfig teConfig = teConfigService.getGlobalConfig();

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

@@ -88,7 +88,7 @@ public class StartRunning implements CommandLineRunner {
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.normalGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.calculateObjectiveScore.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(CalculateObjectiveScoreConcurrentlyImpl.class));
         
         //人脸验证保存
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.normalGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.faceVerifySave.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(FaceVerifyConcurrentlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.faceVerifySaveGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.faceVerifySave.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(FaceVerifyConcurrentlyImpl.class));
         
         
         SystemConstant.initTempFiles();

+ 3 - 1
themis-mq/src/main/java/com/qmth/themis/mq/enums/MqGroupEnum.java

@@ -87,7 +87,9 @@ public enum MqGroupEnum {
     /**
      * 通用分组
      */
-    normalGroup("themis-group-exam-normal");
+    normalGroup("themis-group-exam-normal"),
+
+    faceVerifySaveGroup("themis-group-exam-faceVerifySave");
 
     private MqGroupEnum(String code) {
         this.code = code;