浏览代码

Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	themis-task/src/main/java/com/qmth/themis/task/quartz/ExamActivityJob.java
wangliang 4 年之前
父节点
当前提交
862fde4005

+ 67 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/exam/ExamResultBean.java

@@ -0,0 +1,67 @@
+package com.qmth.themis.business.bean.exam;
+
+import com.qmth.themis.business.enums.FinishTypeEnum;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("交卷结果返回信息")
+public class ExamResultBean {
+
+	@ApiModelProperty("finishTime")
+	private Long finishTime;
+
+	@ApiModelProperty("交卷后状态")
+	private FinishTypeEnum finishType;
+
+	@ApiModelProperty("客观分")
+	private Double objectiveScore;
+	
+	@ApiModelProperty("考试时长(秒)")
+	private Integer durationSeconds;
+
+	@ApiModelProperty("审核结果")
+	private String reviewResult;
+
+	public Long getFinishTime() {
+		return finishTime;
+	}
+
+	public void setFinishTime(Long finishTime) {
+		this.finishTime = finishTime;
+	}
+
+
+	public FinishTypeEnum getFinishType() {
+		return finishType;
+	}
+
+	public void setFinishType(FinishTypeEnum finishType) {
+		this.finishType = finishType;
+	}
+
+	public Integer getDurationSeconds() {
+		return durationSeconds;
+	}
+
+	public void setDurationSeconds(Integer durationSeconds) {
+		this.durationSeconds = durationSeconds;
+	}
+
+	public Double getObjectiveScore() {
+		return objectiveScore;
+	}
+
+	public void setObjectiveScore(Double objectiveScore) {
+		this.objectiveScore = objectiveScore;
+	}
+
+	public String getReviewResult() {
+		return reviewResult;
+	}
+
+	public void setReviewResult(String reviewResult) {
+		this.reviewResult = reviewResult;
+	}
+
+}

+ 33 - 9
themis-business/src/main/java/com/qmth/themis/business/cache/ExamRecordCacheUtil.java

@@ -4,6 +4,7 @@ import java.util.Date;
 
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.enums.ExamRecordStatusEnum;
+import com.qmth.themis.business.enums.FinishTypeEnum;
 import com.qmth.themis.business.util.RedisUtil;
 
 /**
@@ -27,26 +28,49 @@ public class ExamRecordCacheUtil {
 	public static Long getPaperId(Long recordId) {
 		return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "paperId");
 	}
-	public static void setFirstStartTime(Long recordId,Date date) {
-		redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), "firstStartTime",date);
+
+	public static void setFirstStartTime(Long recordId, Date date) {
+		redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), "firstStartTime", date);
 	}
-	public static void setStatus(Long recordId,ExamRecordStatusEnum status) {
-		redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), "status",status);
+
+	public static void setStatus(Long recordId, ExamRecordStatusEnum status) {
+		redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), "status", status);
 	}
-	
+
 	public static Integer getDurationSeconds(Long recordId) {
 		return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "surationSeconds");
 	}
-	
+
 	public static Double getObjectiveScore(Long recordId) {
 		return (Double) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "objectiveScore");
 	}
-	
+
 	public static Long getExamId(Long recordId) {
 		return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "examId");
 	}
+
+	public static void setObjectiveScore(Long recordId, Double objectiveScore) {
+		redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), "objectiveScore", objectiveScore);
+	}
+
+	public static void setFinishTime(Long recordId, Date finishTime) {
+		redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), "finishTime", finishTime);
+	}
+
+	public static Long getFinishTime(Long recordId) {
+		return (Long) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "finishTime");
+	}
+
+	public static void setDurationSeconds(Long recordId, Integer durationSeconds) {
+		redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), "durationSeconds", durationSeconds);
+	}
+
+	public static void setFinishType(Long recordId, FinishTypeEnum finishType) {
+		redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), "finishType", finishType);
+	}
 	
-	public static void setObjectiveScore(Long recordId,Double objectiveScore) {
-		redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), "objectiveScore",objectiveScore);
+	public static FinishTypeEnum getFinishType(Long recordId) {
+		return (FinishTypeEnum) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "finishType");
 	}
+
 }

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

@@ -15,7 +15,7 @@ public enum FinishTypeEnum {
 
     breach("违纪交卷"),
 
-    INTERRUPT("监考强制");
+    interrupt("监考强制");
 
     private String code;
 

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

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 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.cache.bean.ExamCacheBean;
@@ -129,4 +130,11 @@ public interface TEExamService extends IService<TEExam> {
 	public ExamFinishBean finish(Long studentId, Long recordId, String type, Integer durationSeconds);
 
 	ExamCacheBean getExamCacheBean(Long examId);
+
+	/**查询交卷结果
+	 * @param id
+	 * @param recordId
+	 * @return
+	 */
+	public ExamResultBean result(Long studentId, Long recordId);
 }

+ 39 - 13
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -27,6 +27,7 @@ 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.cache.ExamRecordCacheUtil;
@@ -42,6 +43,7 @@ import com.qmth.themis.business.config.SystemConfig;
 import com.qmth.themis.business.dao.TEExamMapper;
 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;
@@ -304,7 +306,6 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 		if (studentId.equals(es.getStudentId())) {
 			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
 		}
-		
 
 		ExamStudentPaperStructCacheBean struct = new ExamStudentPaperStructCacheBean();
 		struct.setContent(content);
@@ -331,7 +332,6 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 		if (studentId.equals(es.getStudentId())) {
 			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
 		}
-		
 
 		ExamStudentAnswerCacheBean answerCache = (ExamStudentAnswerCacheBean) redisUtil.get(
 				RedisKeyHelper.examAnswerKey(recordId),
@@ -352,16 +352,15 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 			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) {
@@ -379,7 +378,6 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 		if (studentId.equals(es.getStudentId())) {
 			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
 		}
-		
 
 		// 音频剩余播放次数缓存
 		redisUtil.set(RedisKeyHelper.audioLeftPlayCountKey(recordId), key, count);
@@ -403,7 +401,6 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 		if (studentId.equals(es.getStudentId())) {
 			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
 		}
-		
 
 		String filePath = "upload/" + sdf.format(new Date()) + "/" + uuid() + ".json";
 		InputStream in = null;
@@ -452,7 +449,6 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 		if (studentId.equals(es.getStudentId())) {
 			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
 		}
-		
 
 		Long paperId = ExamRecordCacheUtil.getPaperId(recordId);
 		ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(paperId);
@@ -539,20 +535,24 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 		if (studentId.equals(es.getStudentId())) {
 			throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
 		}
-		
 
+		Date now = new Date();
 		ExamFinishBean ret = new ExamFinishBean();
-		ret.setFinishTime(new Date().getTime());
+		ret.setFinishTime(now.getTime());
 		ret.setObjectiveScore(ExamRecordCacheUtil.getObjectiveScore(recordId));
 		// TODO
 		ret.setReviewResult("");
-		return null;
+		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;
+		ExamCacheBean ret = null;
 		TEExam exam = getById(examId);
 		if (exam == null) {
 			return ret;
@@ -561,4 +561,30 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 		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;
+	}
 }

+ 18 - 0
themis-exam/src/main/java/com/qmth/themis/exam/api/TEExamController.java

@@ -16,6 +16,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 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.constant.SystemConstant;
@@ -235,4 +236,21 @@ public class TEExamController {
         MqDto mqDto = new MqDto(MqTopicEnum.normal.getCode(), MqTagEnum.calculateObjectiveScore.name(), transMap, MqEnum.EXAM, null, null);
         mqDtoService.assembleSendOneWayMsg(mqDto);
 	}
+	
+	@ApiOperation(value = "查询交卷结果")
+	@RequestMapping(value = "/result", method = RequestMethod.POST)
+	@ApiResponses({ @ApiResponse(code = 200, message = "试卷信息") })
+	public ExamResultBean result(@ApiParam(value = "考试记录ID", required = true) @RequestParam Long recordId) {
+		TEStudent teStudent = (TEStudent) ServletUtil.getRequestStudentAccount();
+		String lockKey = SystemConstant.REDIS_LOCK_STUDENT_PREFIX + teStudent.getId();
+		Boolean lock = redisUtil.lock(lockKey, SystemConstant.REDIS_CACHE_TIME_OUT);
+		if (!lock) {
+			throw new BusinessException(ExceptionResultEnum.REQUEST_AWAIT);
+		}
+		try {
+			return teExamService.result(teStudent.getId(), recordId);
+		} finally {
+			redisUtil.releaseLock(lockKey);
+		}
+	}
 }