wangliang 2 rokov pred
rodič
commit
a18e4e3f48

+ 14 - 8
themis-admin/src/main/java/com/qmth/themis/admin/api/TEExamController.java

@@ -18,7 +18,6 @@ import com.qmth.themis.business.service.*;
 import com.qmth.themis.business.util.*;
 import com.qmth.themis.common.enums.ExceptionResultEnum;
 import com.qmth.themis.common.exception.BusinessException;
-import com.qmth.themis.common.util.GsonUtil;
 import com.qmth.themis.common.util.Result;
 import com.qmth.themis.common.util.ResultUtil;
 import io.swagger.annotations.*;
@@ -160,8 +159,8 @@ public class TEExamController {
             teExamDto.setMonitorStatus(Objects.nonNull(oldTeExam) ? oldTeExam.getMonitorStatus() : InvigilateMonitorStatusEnum.NOT_START);
             teExam = new TEExam(teExamDto);
             if (Objects.nonNull(oldTeExam) && !teExam.equals(oldTeExam)) {//不一样则日志记录
-                if (teExam.getEndTime().longValue() < oldTeExam.getEndTime().longValue()) {
-                    throw new BusinessException("修改的批次结束时间只能大于未修改前的批次结束时间");
+                if (teExam.getEndTime().longValue() < System.currentTimeMillis()) {
+                    throw new BusinessException("修改的批次结束时间只能大于当前时间");
                 }
                 if (Objects.nonNull(oldTeExam) && Objects.nonNull(teExam)
                         && oldTeExam.getForceFinish().intValue() != teExam.getForceFinish().intValue()
@@ -740,8 +739,17 @@ public class TEExamController {
                                   @ApiParam(value = "考试状态") @RequestParam(required = false) ExamRecordStatusEnum status) {
         List<TOeExamRecord> tOeExamRecordList = null;
         if (Objects.nonNull(batch) && batch) {
-            Optional.ofNullable(examId).orElseThrow(() -> new BusinessException("考试批次id不能为空"));
-            tOeExamRecordList = tOeExamRecordService.persistedAnswerBatch(examId, examActivityId, status);
+            if (repariEnum == RepariEnum.EXAM_STUDENT) {
+                List<TEExamStudent> teExamStudentList = teExamStudentService.findAlreadyExamCountZero(examId, examActivityId, examStudentId, examRecordId);
+                if (!CollectionUtils.isEmpty(teExamStudentList)) {
+                    for (TEExamStudent t : teExamStudentList) {
+                        teExamStudentService.updateExamStudentByCache(t.getId());
+                    }
+                }
+                return ResultUtil.ok(true);
+            } else {
+                tOeExamRecordList = tOeExamRecordService.persistedAnswerBatch(examId, examActivityId, status);
+            }
         } else {
             QueryWrapper<TOeExamRecord> tOeExamRecordQueryWrapper = new QueryWrapper<>();
             if (Objects.nonNull(examRecordId)) {
@@ -771,9 +779,7 @@ public class TEExamController {
                             teExamService.finish(examStudentCacheBean.getStudentId(), t.getId(), FinishTypeEnum.AUTO.name(), t.getDurationSeconds());
                             break;
                         case EXAM_STUDENT:
-                            ExamStudentCacheBean examStudentCache = teExamStudentService.getExamStudentCacheBean(t.getExamStudentId());
-                            TEExamStudent examStudent = GsonUtil.fromJson(GsonUtil.toJson(examStudentCache), TEExamStudent.class);
-                            teExamStudentService.saveOrUpdate(examStudent);
+                            teExamStudentService.updateExamStudentByCache(t.getExamStudentId());
                             break;
                         default:
                             break;

+ 11 - 0
themis-business/src/main/java/com/qmth/themis/business/dao/TEExamStudentMapper.java

@@ -118,4 +118,15 @@ public interface TEExamStudentMapper extends CustomBaseMapper<TEExamStudent> {
      * @return
      */
     public List<TEExamStudent> findExamStudentNeedMarkAll(@Param("examId") Long examId, @Param("examPaperIdSet") Set<Long> examPaperIdSet);
+
+    /**
+     * 获取考试次数为0的考生
+     *
+     * @param examId
+     * @param examActivityId
+     * @param id
+     * @param examRecordId
+     * @return
+     */
+    public List<TEExamStudent> findAlreadyExamCountZero(@Param("examId") Long examId, @Param("examActivityId") Long examActivityId, @Param("id") Long id, @Param("examRecordId") Long examRecordId);
 }

+ 18 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TEExamStudentService.java

@@ -102,4 +102,22 @@ public interface TEExamStudentService extends IService<TEExamStudent> {
      * @return
      */
     public List<TEExamStudent> findExamStudentNeedMarkAll(Long examId, Set<Long> examPaperIdSet);
+
+    /**
+     * 更新学生缓存
+     *
+     * @param examStudentId
+     */
+    public void updateExamStudentByCache(Long examStudentId);
+
+    /**
+     * 获取考试次数为0的考生
+     *
+     * @param examId
+     * @param examActivityId
+     * @param id
+     * @param examRecordId
+     * @return
+     */
+    public List<TEExamStudent> findAlreadyExamCountZero(Long examId, Long examActivityId, Long id, Long examRecordId);
 }

+ 6 - 4
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamActivityServiceImpl.java

@@ -1,6 +1,5 @@
 package com.qmth.themis.business.service.impl;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
@@ -15,7 +14,10 @@ import com.qmth.themis.business.dto.response.MonitorStreamDto;
 import com.qmth.themis.business.dto.response.TEExamActivityDto;
 import com.qmth.themis.business.dto.response.TEExamActivityQueryDto;
 import com.qmth.themis.business.dto.response.TEExamActivityWaitDto;
-import com.qmth.themis.business.entity.*;
+import com.qmth.themis.business.entity.TBUser;
+import com.qmth.themis.business.entity.TEExam;
+import com.qmth.themis.business.entity.TEExamActivity;
+import com.qmth.themis.business.entity.TSLog;
 import com.qmth.themis.business.enums.*;
 import com.qmth.themis.business.service.*;
 import com.qmth.themis.business.util.*;
@@ -378,8 +380,8 @@ public class TEExamActivityServiceImpl extends ServiceImpl<TEExamActivityMapper,
                             if (Objects.nonNull(teExamActivityDb)) {
                                 s.setCode(teExamActivityDb.getCode());
                                 if (!s.equals(teExamActivityDb)) {//不一样则日志记录
-                                    if (s.getFinishTime().longValue() < teExamActivityDb.getFinishTime().longValue()) {
-                                        throw new BusinessException("修改的场次结束时间只能大于未修改前的场次结束时间");
+                                    if (s.getFinishTime().longValue() < System.currentTimeMillis()) {
+                                        throw new BusinessException("修改的场次结束时间只能大于当前时间");
                                     }
                                     if (Objects.nonNull(teExam.getForceFinish()) && teExam.getForceFinish().intValue() == 1
                                             && s.getFinishTime().longValue() != teExamActivityDb.getFinishTime().longValue()) {

+ 34 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamStudentServiceImpl.java

@@ -2,6 +2,7 @@ package com.qmth.themis.business.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dao.TEExamStudentMapper;
@@ -11,6 +12,8 @@ import com.qmth.themis.business.dto.response.RoomCodeQueryDto;
 import com.qmth.themis.business.dto.response.TEExamStudentDto;
 import com.qmth.themis.business.entity.TEExamStudent;
 import com.qmth.themis.business.service.TEExamStudentService;
+import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.util.GsonUtil;
 import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.cache.annotation.CachePut;
 import org.springframework.cache.annotation.Cacheable;
@@ -37,6 +40,9 @@ public class TEExamStudentServiceImpl extends ServiceImpl<TEExamStudentMapper, T
     @Resource
     TEExamStudentMapper teExamStudentMapper;
 
+    @Resource
+    RedisUtil redisUtil;
+
     /**
      * 查询考生信息
      *
@@ -197,4 +203,32 @@ public class TEExamStudentServiceImpl extends ServiceImpl<TEExamStudentMapper, T
     public List<TEExamStudent> findExamStudentNeedMarkAll(Long examId, Set<Long> examPaperIdSet) {
         return teExamStudentMapper.findExamStudentNeedMarkAll(examId, examPaperIdSet);
     }
+
+    /**
+     * 更新学生缓存
+     *
+     * @param examStudentId
+     */
+    @Override
+    public void updateExamStudentByCache(Long examStudentId) {
+        ExamStudentCacheBean examStudentCache = (ExamStudentCacheBean) redisUtil.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+        if (Objects.nonNull(examStudentCache)) {
+            TEExamStudent examStudent = GsonUtil.fromJson(GsonUtil.toJson(examStudentCache), TEExamStudent.class);
+            this.saveOrUpdate(examStudent);
+        }
+    }
+
+    /**
+     * 获取考试次数为0的考生
+     *
+     * @param examId
+     * @param examActivityId
+     * @param id
+     * @param examRecordId
+     * @return
+     */
+    @Override
+    public List<TEExamStudent> findAlreadyExamCountZero(Long examId, Long examActivityId, Long id, Long examRecordId) {
+        return teExamStudentMapper.findAlreadyExamCountZero(examId, examActivityId, id, examRecordId);
+    }
 }

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

@@ -19,6 +19,7 @@ import com.qmth.themis.business.dao.TOeExamRecordMapper;
 import com.qmth.themis.business.dto.MqDto;
 import com.qmth.themis.business.dto.response.MarkResultDto;
 import com.qmth.themis.business.dto.response.TEStudentMonitorRecordDto;
+import com.qmth.themis.business.entity.TEExamStudent;
 import com.qmth.themis.business.entity.TOeExamAnswer;
 import com.qmth.themis.business.entity.TOeExamRecord;
 import com.qmth.themis.business.entity.TSyncExamStudentScore;
@@ -29,6 +30,7 @@ import com.qmth.themis.common.contanst.Constants;
 import com.qmth.themis.common.enums.ExceptionResultEnum;
 import com.qmth.themis.common.exception.BusinessException;
 import com.qmth.themis.common.util.FileUtil;
+import com.qmth.themis.common.util.GsonUtil;
 import com.qmth.themis.common.util.IpUtil;
 import com.qmth.themis.common.util.SimpleBeanUtil;
 import org.apache.commons.lang3.StringUtils;
@@ -430,19 +432,18 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
             Map<String, ExamStudentAnswerCacheBean> answerMap = redisUtil
                     .getHashEntries(RedisKeyHelper.examAnswerKey(recordId));
             if (!CollectionUtils.isEmpty(answerMap)) {
+                List<TOeExamAnswer> tOeExamAnswerList = new ArrayList<>(answerMap.size());
                 for (ExamStudentAnswerCacheBean answerCache : answerMap.values()) {
                     TOeExamAnswer answer = new TOeExamAnswer();
                     BeanUtils.copyProperties(answerCache, answer);
                     answer.setId(uidUtil.getId());
                     answer.setExamRecordId(recordId);
-                    examAnswerService.saveOrUpdate(answer);
+                    tOeExamAnswerList.add(answer);
                 }
+                examAnswerService.saveOrUpdateBatch(tOeExamAnswerList);
             }
-            //            //更新考生信息
-            //            ExamStudentCacheBean examStudentCache = examStudentService.getExamStudentCacheBean(er.getExamStudentId());
-            //            TEExamStudent examStudent = new TEExamStudent();
-            //            BeanUtils.copyProperties(examStudentCache, examStudent);
-            //            examStudentService.saveOrUpdate(examStudent);
+            //更新考生信息
+            teExamStudentService.updateExamStudentByCache(er.getExamStudentId());
             //上传个人试卷结构
             if (struct != null) {
                 ossUtil.upload(false, structFilePath, struct.getContent());
@@ -1512,13 +1513,15 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         Map<String, ExamStudentAnswerCacheBean> answerMap = redisUtil
                 .getHashEntries(RedisKeyHelper.examAnswerKey(recordId));
         if (!CollectionUtils.isEmpty(answerMap)) {
+            List<TOeExamAnswer> tOeExamAnswerList = new ArrayList<>(answerMap.size());
             for (ExamStudentAnswerCacheBean answerCache : answerMap.values()) {
                 TOeExamAnswer answer = new TOeExamAnswer();
                 BeanUtils.copyProperties(answerCache, answer);
                 answer.setId(uidUtil.getId());
                 answer.setExamRecordId(recordId);
-                examAnswerService.saveOrUpdate(answer);
+                tOeExamAnswerList.add(answer);
             }
+            examAnswerService.saveOrUpdateBatch(tOeExamAnswerList);
         }
     }
 

+ 23 - 0
themis-business/src/main/resources/mapper/TEExamStudentMapper.xml

@@ -501,4 +501,27 @@
             <!--limit 510-->
         </where>
     </select>
+
+    <select id="findAlreadyExamCountZero" resultType="com.qmth.themis.business.entity.TEExamStudent">
+        select tees.* from t_e_exam_student tees
+            join t_oe_exam_record toer on toer.exam_student_id = tees.id
+        <where>
+            tees.already_exam_count = 0
+          and toer.first_start_time is not null
+          and toer.finish_time is not null
+          and toer.objective_score <![CDATA[ > ]]> 0
+            <if test="examId != null and examId != ''">
+                and tees.exam_id = #{examId}
+            </if>
+            <if test="examActivityId != null and examActivityId != ''">
+                and tees.exam_activity_id = #{examActivityId}
+            </if>
+            <if test="id != null and id != ''">
+                and tees.id = #{id}
+            </if>
+            <if test="examRecordId != null and examRecordId != ''">
+                and toer.id = #{examRecordId}
+            </if>
+        </where>
+    </select>
 </mapper>

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

@@ -1829,6 +1829,8 @@
                 </if>
               and toer.objective_score > 0
               and toea.id is null
+              and toer.first_start_time is not null
+              and toer.finish_time is not null
             </where>
             group by toer.id
             having count(toea.id) = 0

+ 25 - 0
themis-task/src/main/java/com/qmth/themis/task/quartz/MqActivityJob.java

@@ -5,6 +5,7 @@ import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.entity.TEExam;
 import com.qmth.themis.business.entity.TEExamActivity;
+import com.qmth.themis.business.entity.TEExamStudent;
 import com.qmth.themis.business.entity.TOeExamRecord;
 import com.qmth.themis.business.enums.ExamRecordStatusEnum;
 import com.qmth.themis.business.enums.FinishTypeEnum;
@@ -130,5 +131,29 @@ public class MqActivityJob extends QuartzJobBean {
             }
             teExamService.saveOrUpdateBatch(teExamList);
         }
+
+        //答案补救
+        List<TOeExamRecord> tOeExamRecordList = tOeExamRecordService.persistedAnswerBatch(null, null, null);
+        if (!CollectionUtils.isEmpty(tOeExamRecordList)) {
+            for (TOeExamRecord t : tOeExamRecordList) {
+                try {
+                    tOeExamRecordService.saveDataByCachePersistedAnswer(t.getId());
+                } catch (Exception e) {
+                    log.error(SystemConstant.LOG_ERROR, e);
+                }
+            }
+        }
+
+        //更新考生缓存
+        List<TEExamStudent> teExamStudentList = teExamStudentService.findAlreadyExamCountZero(null, null, null, null);
+        if (!CollectionUtils.isEmpty(teExamStudentList)) {
+            for (TEExamStudent t : teExamStudentList) {
+                try {
+                    teExamStudentService.updateExamStudentByCache(t.getId());
+                } catch (Exception e) {
+                    log.error(SystemConstant.LOG_ERROR, e);
+                }
+            }
+        }
     }
 }