|
@@ -14,7 +14,6 @@ import java.util.UUID;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
|
-import com.qmth.themis.business.enums.ExamRecordStatusEnum;
|
|
|
import org.apache.commons.codec.digest.DigestUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.stereotype.Service;
|
|
@@ -24,20 +23,22 @@ 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.ExamResumeBean;
|
|
|
import com.qmth.themis.business.bean.exam.ExamStartBean;
|
|
|
+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.ExamCourseCacheBean;
|
|
|
import com.qmth.themis.business.cache.bean.ExamPaperCacheBean;
|
|
|
-import com.qmth.themis.business.cache.bean.ExamRecordCacheBean;
|
|
|
import com.qmth.themis.business.cache.bean.ExamStudentAnswerCacheBean;
|
|
|
import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
|
|
|
import com.qmth.themis.business.cache.bean.ExamStudentPaperStructCacheBean;
|
|
|
import com.qmth.themis.business.config.SystemConfig;
|
|
|
import com.qmth.themis.business.dao.TEExamMapper;
|
|
|
import com.qmth.themis.business.entity.TEExam;
|
|
|
+import com.qmth.themis.business.enums.ExamRecordStatusEnum;
|
|
|
import com.qmth.themis.business.service.TEExamActivityService;
|
|
|
import com.qmth.themis.business.service.TEExamCourseService;
|
|
|
import com.qmth.themis.business.service.TEExamPaperService;
|
|
@@ -234,22 +235,24 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- @Transactional
|
|
|
@Override
|
|
|
public ExamStartBean start(Long studentId, Long recordId) {
|
|
|
ExamStartBean ret = null;
|
|
|
- ExamRecordCacheBean er = (ExamRecordCacheBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId));
|
|
|
- if (er == null) {
|
|
|
+
|
|
|
+ // 校验当前登录用户和参数一致性
|
|
|
+ if (ExamRecordCacheUtil.getId(recordId) == null) {
|
|
|
throw new BusinessException("未找到考试记录");
|
|
|
}
|
|
|
+ Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
|
|
|
ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
|
|
|
- .get(RedisKeyHelper.examStudentCacheKey(er.getExamStudentId()));
|
|
|
+ .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) {
|
|
@@ -265,11 +268,8 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
throw new BusinessException("允许开考的时间已结束");
|
|
|
}
|
|
|
|
|
|
- // 修改考试记录数据
|
|
|
- er.setFirstStartTime(new Date());
|
|
|
- er.setStatus(ExamRecordStatusEnum.break_off);
|
|
|
-
|
|
|
- ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(er.getPaperId());
|
|
|
+ Long paperId = ExamRecordCacheUtil.getPaperId(recordId);
|
|
|
+ ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(paperId);
|
|
|
if (ep == null) {
|
|
|
throw new BusinessException("未找到试卷");
|
|
|
}
|
|
@@ -279,50 +279,57 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
ret.setPaperDecryptVector(ep.getDecryptVector());
|
|
|
|
|
|
// 更新考试记录缓存
|
|
|
- redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), er);
|
|
|
+ ExamRecordCacheUtil.setFirstStartTime(recordId, new Date());
|
|
|
+ ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.first_prepare);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- @Transactional
|
|
|
@Override
|
|
|
public Long studentPaperStruct(Long studentId, Long recordId, String content) {
|
|
|
- ExamRecordCacheBean er = (ExamRecordCacheBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId));
|
|
|
- if (er == null) {
|
|
|
+
|
|
|
+ // 校验当前登录用户和参数一致性
|
|
|
+ if (ExamRecordCacheUtil.getId(recordId) == null) {
|
|
|
throw new BusinessException("未找到考试记录");
|
|
|
}
|
|
|
+ Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
|
|
|
ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
|
|
|
- .get(RedisKeyHelper.examStudentCacheKey(er.getExamStudentId()));
|
|
|
+ .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());
|
|
|
+ struct.setTime(new Date().getTime());
|
|
|
// 更新考生试卷结构
|
|
|
redisUtil.set(RedisKeyHelper.studentPaperStructKey(recordId), struct);
|
|
|
return struct.getTime();
|
|
|
}
|
|
|
|
|
|
- @Transactional
|
|
|
@Override
|
|
|
public Long answerSubmit(Long studentId, Long recordId, Integer mainNumber, Integer subNumber, Integer subIndex,
|
|
|
String answer, Long version, Integer durationSeconds) {
|
|
|
- ExamRecordCacheBean er = (ExamRecordCacheBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId));
|
|
|
- if (er == null) {
|
|
|
+
|
|
|
+ // 校验当前登录用户和参数一致性
|
|
|
+ if (ExamRecordCacheUtil.getId(recordId) == null) {
|
|
|
throw new BusinessException("未找到考试记录");
|
|
|
}
|
|
|
+ Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
|
|
|
ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
|
|
|
- .get(RedisKeyHelper.examStudentCacheKey(er.getExamStudentId()));
|
|
|
+ .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));
|
|
@@ -348,21 +355,24 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
return version;
|
|
|
}
|
|
|
|
|
|
- @Transactional
|
|
|
@Override
|
|
|
public Integer audioLeftPlayCountSubmit(Long studentId, Long recordId, String key, Integer count) {
|
|
|
- ExamRecordCacheBean er = (ExamRecordCacheBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId));
|
|
|
- if (er == null) {
|
|
|
+
|
|
|
+ // 校验当前登录用户和参数一致性
|
|
|
+ if (ExamRecordCacheUtil.getId(recordId) == null) {
|
|
|
throw new BusinessException("未找到考试记录");
|
|
|
}
|
|
|
+ Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
|
|
|
ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
|
|
|
- .get(RedisKeyHelper.examStudentCacheKey(er.getExamStudentId()));
|
|
|
+ .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);
|
|
|
|
|
@@ -371,31 +381,35 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
|
|
|
@Override
|
|
|
public ExamFileUploadBean fileUpload(Long studentId, Long recordId, MultipartFile file, String suffix, String md5) {
|
|
|
- ExamRecordCacheBean er = (ExamRecordCacheBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId));
|
|
|
- if (er == null) {
|
|
|
+
|
|
|
+ // 校验当前登录用户和参数一致性
|
|
|
+ if (ExamRecordCacheUtil.getId(recordId) == null) {
|
|
|
throw new BusinessException("未找到考试记录");
|
|
|
}
|
|
|
+ Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
|
|
|
ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
|
|
|
- .get(RedisKeyHelper.examStudentCacheKey(er.getExamStudentId()));
|
|
|
+ .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)) {
|
|
|
+ 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();
|
|
|
+ String url = systemConfig.getProperty("aliyun.oss.url") + "/" + filePath;
|
|
|
+ ExamFileUploadBean ret = new ExamFileUploadBean();
|
|
|
ret.setUrl(url);
|
|
|
- ret.setUploadTime(System.currentTimeMillis());
|
|
|
+ ret.setUploadTime(new Date().getTime());
|
|
|
return ret;
|
|
|
} catch (IOException e) {
|
|
|
throw new BusinessException("文件读取出错");
|
|
@@ -416,49 +430,57 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
@SuppressWarnings("unchecked")
|
|
|
@Override
|
|
|
public ExamResumeBean resume(Long studentId, Long recordId) {
|
|
|
- ExamRecordCacheBean er = (ExamRecordCacheBean) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId));
|
|
|
- if (er == null) {
|
|
|
+
|
|
|
+ // 校验当前登录用户和参数一致性
|
|
|
+ if (ExamRecordCacheUtil.getId(recordId) == null) {
|
|
|
throw new BusinessException("未找到考试记录");
|
|
|
}
|
|
|
+ Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
|
|
|
ExamStudentCacheBean es = (ExamStudentCacheBean) redisUtil
|
|
|
- .get(RedisKeyHelper.examStudentCacheKey(er.getExamStudentId()));
|
|
|
+ .get(RedisKeyHelper.examStudentCacheKey(examStudentId));
|
|
|
if (es == null) {
|
|
|
throw new BusinessException("未找到考生");
|
|
|
}
|
|
|
if (studentId.equals(es.getStudentId())) {
|
|
|
throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
|
|
|
}
|
|
|
- ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(er.getPaperId());
|
|
|
+
|
|
|
+
|
|
|
+ Long paperId = ExamRecordCacheUtil.getPaperId(recordId);
|
|
|
+ ExamPaperCacheBean ep = teExamPaperService.getExamPaperCacheBean(paperId);
|
|
|
if (ep == null) {
|
|
|
throw new BusinessException("未找到试卷");
|
|
|
}
|
|
|
-
|
|
|
- ExamResumeBean ret=new ExamResumeBean();
|
|
|
- ret.setDurationSeconds(er.getDurationSeconds());
|
|
|
+
|
|
|
+ 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.setHasAudio((ep.getHasAudio() != null && ep.getHasAudio().intValue() == 1 ? true : false));
|
|
|
ret.setAudioPlayCount(ep.getAudioPlayCount());
|
|
|
- //TODO 9527
|
|
|
+ // TODO 9527
|
|
|
ret.setMonitorKey(recordId.toString());
|
|
|
-
|
|
|
- ExamStudentPaperStructCacheBean struct=(ExamStudentPaperStructCacheBean)redisUtil.get(RedisKeyHelper.studentPaperStructKey(recordId));
|
|
|
- if(struct!=null) {
|
|
|
+
|
|
|
+ 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) {
|
|
|
+ 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) {
|
|
|
+ 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) {
|
|
|
+
|
|
|
+ // 作答排序
|
|
|
+ private List<ExamStudentAnswerCacheBean> sortAnswers(Map<String, ExamStudentAnswerCacheBean> answers) {
|
|
|
List<ExamStudentAnswerCacheBean> ret = new ArrayList<ExamStudentAnswerCacheBean>(answers.values());
|
|
|
Collections.sort(ret, new Comparator<ExamStudentAnswerCacheBean>() {
|
|
|
|
|
@@ -474,9 +496,9 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
} else if (o1.getSubNumber() < o2.getSubNumber()) {
|
|
|
return -1;
|
|
|
} else {
|
|
|
- if (o1.getSubIndex()==null || o2.getSubIndex()==null) {
|
|
|
+ if (o1.getSubIndex() == null || o2.getSubIndex() == null) {
|
|
|
return 0;
|
|
|
- }else {
|
|
|
+ } else {
|
|
|
if (o1.getSubIndex() > o2.getSubIndex()) {
|
|
|
return 1;
|
|
|
} else if (o1.getSubIndex() < o2.getSubIndex()) {
|
|
@@ -492,4 +514,30 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
});
|
|
|
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和当前登录用户不一致");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ ExamFinishBean ret = new ExamFinishBean();
|
|
|
+ ret.setFinishTime(new Date().getTime());
|
|
|
+ ret.setObjectiveScore(ExamRecordCacheUtil.getObjectiveScore(recordId));
|
|
|
+ // TODO
|
|
|
+ ret.setReviewResult("");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
}
|