Selaa lähdekoodia

待考列表优化

wangliang 1 vuosi sitten
vanhempi
commit
34812ca765

+ 6 - 1
themis-admin/src/main/java/com/qmth/themis/admin/api/TEExamController.java

@@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qmth.themis.business.annotation.ApiJsonObject;
 import com.qmth.themis.business.annotation.ApiJsonProperty;
 import com.qmth.themis.business.annotation.Logs;
-//import com.qmth.themis.business.annotation.RedisLimitAnnotation;
 import com.qmth.themis.business.cache.ExamingDataCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
@@ -225,9 +224,15 @@ public class TEExamController {
                 teExamActivityService.updateExamActivityCacheBean(teExamActivity.getId());
             }
             themisCacheService.updateTodayExamListCache(teExam.getId());
+            if (teExam.getEndTime().intValue() == 1 && teExam.getEndTime().longValue() > System.currentTimeMillis()) {
+                themisCacheService.updateExamListIdCache(teExam.getId());
+            }
             List<TEExamActivity> teExamActivityList = teExamActivityService.list(new QueryWrapper<TEExamActivity>().lambda().eq(TEExamActivity::getExamId, teExam.getId()).eq(TEExamActivity::getEnable, 1));
             for (TEExamActivity t : teExamActivityList) {
                 themisCacheService.updateTodayExamCache(t.getExamId().toString(), t.getId().toString());
+                if (t.getEnable().intValue() == 1 && t.getFinishTime().longValue() > System.currentTimeMillis()) {
+                    themisCacheService.updateExamListCache(t.getExamId().toString(), t.getId().toString());
+                }
             }
         } catch (Exception e) {
             log.error(SystemConstant.LOG_ERROR, e);

+ 2 - 0
themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java

@@ -217,6 +217,8 @@ public class SystemConstant {
     public static final String PROBLEM_CACHE = "problem:cache";
     public static final String TODAY_EXAM_MAP_CACHE = "today:exam:map:cache:";
     public static final String TODAY_EXAM_ID_LIST_CACHE = "today:exam:id:list:cache";
+    public static final String EXAM_LIST_MAP_CACHE = "exam:list:map:cache:";
+    public static final String EXAM_LIST_ID_CACHE = "exam:list:id:cache";
 
     public volatile static Searcher SEARCHER = null;
     public static final String ONLINE_WARN_INTERVAL = "online.warn.interval";

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

@@ -81,10 +81,9 @@ public interface TEExamActivityMapper extends BaseMapper<TEExamActivity> {
      *
      * @param studentId
      * @param examActivityIds
-     * @param mode
      * @return
      */
-    public List<TEExamActivityWaitDto> getWaitingExam(@Param("studentId") Long studentId, @Param("examActivityIds") Set<Long> examActivityIds, @Param("mode") String mode);
+    public List<TEExamActivityWaitDto> getWaitingExam(@Param("studentId") Long studentId, @Param("examActivityIds") Set<Long> examActivityIds);
 
     /**
      * 获取考试待考列表

+ 14 - 3
themis-business/src/main/java/com/qmth/themis/business/dto/response/TEExamWaitDto.java

@@ -23,7 +23,7 @@ public class TEExamWaitDto implements Serializable {
 
     @JsonSerialize(using = ToStringSerializer.class)
     @ApiModelProperty(name = "考试场次id")
-    private String examActivityId;//考试场次id
+    private Long examActivityId;//考试场次id
 
     @ApiModelProperty(name = "考试名称")
     private String name;//考试名称
@@ -34,6 +34,17 @@ public class TEExamWaitDto implements Serializable {
     @ApiModelProperty(name = "考试场次集合")
     private List<TEExamActivityWaitDto> activities;
 
+    public TEExamWaitDto() {
+
+    }
+
+    public TEExamWaitDto(Long id, Long examActivityId, String name, String code) {
+        this.id = id;
+        this.examActivityId = examActivityId;
+        this.name = name;
+        this.code = code;
+    }
+
     public String getCode() {
         return code;
     }
@@ -42,11 +53,11 @@ public class TEExamWaitDto implements Serializable {
         this.code = code;
     }
 
-    public String getExamActivityId() {
+    public Long getExamActivityId() {
         return examActivityId;
     }
 
-    public void setExamActivityId(String examActivityId) {
+    public void setExamActivityId(Long examActivityId) {
         this.examActivityId = examActivityId;
     }
 

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

@@ -79,10 +79,9 @@ public interface TEExamActivityService extends IService<TEExamActivity> {
      *
      * @param studentId
      * @param examActivityIds
-     * @param mode
      * @return
      */
-    public List<TEExamActivityWaitDto> getWaitingExam(Long studentId, Set<Long> examActivityIds, String mode);
+    public List<TEExamActivityWaitDto> getWaitingExam(Long studentId, Set<Long> examActivityIds);
 
     /**
      * 获取考试待考列表

+ 57 - 0
themis-business/src/main/java/com/qmth/themis/business/service/ThemisCacheService.java

@@ -1,5 +1,6 @@
 package com.qmth.themis.business.service;
 
+import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.AuthDto;
 import com.qmth.themis.business.dto.cache.TEStudentCacheDto;
 import com.qmth.themis.business.entity.*;
@@ -311,6 +312,62 @@ public interface ThemisCacheService {
      */
     public void setTodayExamCache();
 
+    /**
+     * 设置考试列表缓存
+     */
+    public void setExamListCache();
+
+    /**
+     * 获取考试列表缓存
+     *
+     * @param examId
+     * @return
+     */
+    public Map<String, List<Long>> getExamListCache(String examId);
+
+    /**
+     * 获取考试列表id缓存
+     *
+     * @return
+     */
+    public Set<Long> getExamIdListCache();
+
+    /**
+     * 更新考试列表id缓存
+     *
+     * @param examId
+     */
+    public void updateExamListIdCache(Long examId);
+
+    /**
+     * 更新考试列表id缓存
+     *
+     * @param examId
+     */
+    public void removeExamListIdCache(Long examId);
+
+    /**
+     * 更新考试列表缓存
+     *
+     * @param examId
+     * @param examActivityId
+     */
+    public void updateExamListCache(String examId, String examActivityId);
+
+    /**
+     * 删除考试列表缓存
+     *
+     * @return
+     */
+    public void removeExamListCache(String examId);
+
+    /**
+     * 删除考试列表缓存
+     *
+     * @return
+     */
+    public void removeExamListCache(String examId, String examActivityId);
+
     /**
      * 获取当天考试缓存
      *

+ 5 - 3
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamActivityServiceImpl.java

@@ -161,12 +161,11 @@ public class TEExamActivityServiceImpl extends ServiceImpl<TEExamActivityMapper,
      *
      * @param studentId
      * @param examActivityIds
-     * @param mode
      * @return
      */
     @Override
-    public List<TEExamActivityWaitDto> getWaitingExam(Long studentId, Set<Long> examActivityIds, String mode) {
-        return teExamActivityMapper.getWaitingExam(studentId, examActivityIds, mode);
+    public List<TEExamActivityWaitDto> getWaitingExam(Long studentId, Set<Long> examActivityIds) {
+        return teExamActivityMapper.getWaitingExam(studentId, examActivityIds);
     }
 
     /**
@@ -415,6 +414,9 @@ public class TEExamActivityServiceImpl extends ServiceImpl<TEExamActivityMapper,
 
             for (TEExamActivity ac : teExamActivityList) {
                 themisCacheService.updateTodayExamCache(ac.getExamId().toString(), ac.getId().toString());
+                if (ac.getEnable().intValue() == 1 && ac.getFinishTime().longValue() > System.currentTimeMillis()) {
+                    themisCacheService.updateExamListCache(ac.getExamId().toString(), ac.getId().toString());
+                }
                 teExamActivityService.updateExamActivityCacheBean(ac.getId());
             }
 

+ 19 - 41
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -41,6 +41,7 @@ import org.springframework.cache.annotation.CachePut;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
@@ -51,7 +52,6 @@ import java.math.BigDecimal;
 import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import java.util.stream.Collectors;
 
 /**
  * @Description: 考试批次 服务实现类
@@ -154,46 +154,24 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
      */
     @Override
     public List<TEExamWaitDto> getWaitingExam(Long studentId, Long examId, Long orgId) {
-        List<TEExamWaitDto> list = teExamMapper.getWaitingExam(studentId, examId, orgId);
-        if (Objects.nonNull(list) && list.size() > 0) {
-            Set<String> examActivityIdsTemp = new LinkedHashSet<>();
-            Map<Long, TEExamWaitDto> setMap = new LinkedHashMap<>();
-            for (TEExamWaitDto t : list) {
-                setMap.put(t.getId(), t);
-                if (t.getExamActivityId().indexOf(",") != -1) {
-                    examActivityIdsTemp.addAll(Arrays.asList(t.getExamActivityId().split(",")));
-                } else {
-                    examActivityIdsTemp.add(t.getExamActivityId());
-                }
-            }
-            Set<Long> examActivityIds = examActivityIdsTemp.stream().map(s -> Long.parseLong(s))
-                    .collect(Collectors.toSet());
-            List<TEExamActivityWaitDto> teExamActivityWaitList = teExamActivityService
-                    .getWaitingExam(studentId, examActivityIds, null);
-            Map<Long, Set<TEExamActivityWaitDto>> map = new HashMap<>();
-            teExamActivityWaitList.forEach(v -> {
-                Set<TEExamActivityWaitDto> teExamActivityWaitDtos = null;
-                if (Objects.isNull(map.get(v.getExamId()))) {
-                    teExamActivityWaitDtos = new HashSet<>();
-                } else {
-                    teExamActivityWaitDtos = map.get(v.getExamId());
-                }
-                teExamActivityWaitDtos.add(v);
-                map.put(v.getExamId(), teExamActivityWaitDtos);
-                ExamCacheBean examCache = getExamCacheBeanNative(v.getExamId());
-                ExamStudentCacheBean examStudentCacheBean = teExamStudentService
-                        .getExamStudentCacheBean(v.getExamStudentId());
-                v.setLeftExamCount(
-                        (examCache.getExamCount().intValue() - (examStudentCacheBean.getAlreadyExamCount().intValue())
-                                < 0 ?
-                                0 :
-                                examCache.getExamCount().intValue() - (examStudentCacheBean.getAlreadyExamCount()
-                                        .intValue())));
-            });
-            list.clear();
-            setMap.forEach((k, v) -> {
-                v.setActivities(new ArrayList<>(map.get(k)));
-                list.add(v);
+        List<TEExamWaitDto> list = new ArrayList<>();
+        Map<String, List<Long>> examActivityIdMap = themisCacheService.getExamListCache(examId.toString());
+        if (!CollectionUtils.isEmpty(examActivityIdMap)) {
+            examActivityIdMap.forEach((k, v) -> {
+                ExamCacheBean examCache = getExamCacheBeanNative(examId);
+                TEExamWaitDto teExamWaitDto = new TEExamWaitDto(examId, Long.parseLong(k), examCache.getName(), examCache.getCode());
+                List<TEExamActivityWaitDto> teExamActivityWaitList = teExamActivityService.getWaitingExam(studentId, new HashSet<>(v));
+                Map<Long, Set<TEExamActivityWaitDto>> map = new HashMap<>();
+                teExamActivityWaitList.forEach(i -> {
+                    Set<TEExamActivityWaitDto> teExamActivityWaitDtos = Objects.nonNull(map.get(examId)) ? map.get(examId) : new LinkedHashSet<>();
+                    teExamActivityWaitDtos.add(i);
+                    map.put(examId, teExamActivityWaitDtos);
+                    ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(i.getExamStudentId());
+                    Integer leftExamCount = examCache.getExamCount().intValue() - examStudentCacheBean.getAlreadyExamCount().intValue() < 0 ? 0 : examCache.getExamCount().intValue() - examStudentCacheBean.getAlreadyExamCount().intValue();
+                    i.setLeftExamCount(leftExamCount);
+                });
+                teExamWaitDto.setActivities(new ArrayList<>(map.get(k)));
+                list.add(teExamWaitDto);
             });
         }
         return list;

+ 98 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/ThemisCacheServiceImpl.java

@@ -644,6 +644,104 @@ public class ThemisCacheServiceImpl implements ThemisCacheService {
         }
     }
 
+    /**
+     * 设置考试列表缓存
+     */
+    @Override
+    public void setExamListCache() {
+        //查询考试场次结束时间大于当前时间的所有考试
+        List<TEExamActivity> teExamActivityList = teExamActivityService.list(new QueryWrapper<TEExamActivity>().lambda().gt(TEExamActivity::getFinishTime, System.currentTimeMillis()).eq(TEExamActivity::getEnable, 1));
+        if (!CollectionUtils.isEmpty(teExamActivityList)) {
+            LinkedMultiValueMap<Long, Long> examActivityMap = new LinkedMultiValueMap<>();
+            for (TEExamActivity t : teExamActivityList) {
+                ExamCacheBean examCacheBean = teExamService.getExamCacheBean(t.getExamId());
+                if (Objects.nonNull(examCacheBean.getEnable()) && examCacheBean.getEnable().intValue() == 1) {
+                    examActivityMap.add(t.getExamId(), t.getId());
+                }
+            }
+            examActivityMap.forEach((k, v) -> {
+                for (Long l : v) {
+                    redisUtil.set(SystemConstant.EXAM_LIST_MAP_CACHE + k, l.toString(), l);
+                    redisUtil.addSet(SystemConstant.EXAM_LIST_ID_CACHE, k);
+                }
+            });
+        }
+    }
+
+    /**
+     * 获取考试列表缓存
+     *
+     * @param examId
+     * @return
+     */
+    @Override
+    public Map<String, List<Long>> getExamListCache(String examId) {
+        return redisUtil.getHashEntries(SystemConstant.EXAM_LIST_MAP_CACHE + examId);
+    }
+
+    /**
+     * 获取考试列表id缓存
+     *
+     * @return
+     */
+    @Override
+    public Set<Long> getExamIdListCache() {
+        return redisUtil.getSet(SystemConstant.EXAM_LIST_ID_CACHE);
+    }
+
+    /**
+     * 更新考试列表id缓存
+     *
+     * @param examId
+     */
+    @Override
+    public void updateExamListIdCache(Long examId) {
+        redisUtil.addSet(SystemConstant.EXAM_LIST_ID_CACHE, examId);
+    }
+
+    /**
+     * 删除考试列表id缓存
+     *
+     * @param examId
+     */
+    @Override
+    public void removeExamListIdCache(Long examId) {
+        redisUtil.removeSet(SystemConstant.EXAM_LIST_ID_CACHE, examId);
+    }
+
+    /**
+     * 更新考试列表缓存
+     *
+     * @param examId
+     * @param examActivityId
+     */
+    @Override
+    public void updateExamListCache(String examId, String examActivityId) {
+        this.removeExamListCache(examId, examActivityId);
+        redisUtil.set(SystemConstant.EXAM_LIST_MAP_CACHE + examId, examActivityId, examActivityId);
+    }
+
+    /**
+     * 删除考试列表缓存
+     *
+     * @param examId
+     */
+    @Override
+    public void removeExamListCache(String examId) {
+        redisUtil.delete(SystemConstant.EXAM_LIST_MAP_CACHE + examId);
+    }
+
+    /**
+     * 删除考试列表缓存
+     *
+     * @param examId
+     * @param examActivityId
+     */
+    @Override
+    public void removeExamListCache(String examId, String examActivityId) {
+        redisUtil.delete(SystemConstant.EXAM_LIST_MAP_CACHE + examId, examActivityId);
+    }
+
     /**
      * 获取当天考试缓存
      *

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

@@ -130,12 +130,9 @@
         ,tees.id as examStudentId,
         tees.course_code as courseCode,
         tees.course_name as courseName
-        from
-        t_e_exam_student tees
-        left join t_e_exam tee on
-        tee.id = tees.exam_id
-        left join t_e_exam_activity teea on
-        teea.id = tees.exam_activity_id
+        from t_e_exam_student tees
+        left join t_e_exam tee on tee.id = tees.exam_id
+        left join t_e_exam_activity teea on teea.id = tees.exam_activity_id
         <where>1 = 1
             and teea.id in
             <foreach collection="examActivityIds" item="examActivityId" index="index" open="(" close=")" separator=",">
@@ -144,12 +141,7 @@
             <if test="studentId != null and studentId != ''">
                 and tees.student_id = #{studentId}
             </if>
-            and tee.enable = 1
-            and teea.enable = 1
             and tees.enable = 1
-            <!--<if test="mode != null and mode != '' and mode == 'TOGETHER'">
-                and teea.start_time <![CDATA[ >= ]]> date_sub(now(), interval IFNULL(teea.opening_seconds, tee.opening_seconds) second)
-            </if>-->
         </where>
     </select>
 

+ 5 - 1
themis-task/src/main/java/com/qmth/themis/task/enums/QuartzTaskEnum.java

@@ -29,7 +29,11 @@ public enum QuartzTaskEnum {
 
     EXAM_SUMMARY_JOB_NAME("考试统计"),
 
-    EXAM_SUMMARY_JOB_GROUP_NAME("考试统计 group");
+    EXAM_SUMMARY_JOB_GROUP_NAME("考试统计 group"),
+
+    EXAM_LIST_JOB_NAME("考试列表"),
+
+    EXAM_LIST_JOB_GROUP_NAME("考试列表 group");
 
 //    REPAIR_JOB_NAME("repair_job"),
 

+ 32 - 0
themis-task/src/main/java/com/qmth/themis/task/quartz/ExamListJob.java

@@ -0,0 +1,32 @@
+package com.qmth.themis.task.quartz;
+
+import com.qmth.themis.business.service.ThemisCacheService;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @Description: 考试列表
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2023/10/27
+ */
+@Component
+public class ExamListJob extends QuartzJobBean {
+    private final static Logger log = LoggerFactory.getLogger(ExamListJob.class);
+
+    @Resource
+    ThemisCacheService themisCacheService;
+
+    @Override
+    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
+        log.info("ExamListJob,context:{}", context);
+        themisCacheService.setExamListCache();
+    }
+}

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

@@ -178,20 +178,5 @@ public class MqActivityJob extends QuartzJobBean {
             }
             teExamService.saveOrUpdateBatch(teExamList);
         }
-        //修正考试状态
-        List<TOeExamRecord> tOeExamRecordList = tOeExamRecordService.updateExamStatus();
-        if (!CollectionUtils.isEmpty(tOeExamRecordList)) {
-            for (TOeExamRecord t : tOeExamRecordList) {
-                if ((System.currentTimeMillis() - t.getFinishTime().longValue()) / 1000 / 60 >= 30) {//超过30分钟则改状态
-                    try {
-                        ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(t.getExamStudentId());
-                        TEStudentCacheDto teStudent = themisCacheService.addStudentAccountCache(examStudentCacheBean.getStudentId());
-                        commonService.persisted(t.getId(), teStudent.getId());
-                    } catch (Exception e) {
-                        log.error(SystemConstant.LOG_ERROR, e);
-                    }
-                }
-            }
-        }
     }
 }

+ 9 - 4
themis-task/src/main/java/com/qmth/themis/task/start/StartRunning.java

@@ -11,10 +11,7 @@ import com.qmth.themis.mq.templete.impl.*;
 import com.qmth.themis.task.config.DictionaryConfig;
 import com.qmth.themis.task.enums.QuartzTaskEnum;
 import com.qmth.themis.task.listener.QuartzOrderlyImpl;
-import com.qmth.themis.task.quartz.ExamSummaryJob;
-import com.qmth.themis.task.quartz.MqActivityJob;
-import com.qmth.themis.task.quartz.MqJob;
-import com.qmth.themis.task.quartz.ObjectiveAnswerCacheLoadJob;
+import com.qmth.themis.task.quartz.*;
 import com.qmth.themis.task.service.QuartzService;
 import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
 import org.slf4j.Logger;
@@ -63,6 +60,7 @@ public class StartRunning implements CommandLineRunner {
         log.info("服务器启动时执行 start");
         log.info("增加mqjob start");
         themisCacheService.setTodayExamCache();
+        themisCacheService.setExamListCache();
 
         Map mqMap = new HashMap();
         mqMap.put(SystemConstant.NAME, MqJob.class.getName());
@@ -91,6 +89,13 @@ public class StartRunning implements CommandLineRunner {
         quartzService.addJob(ExamSummaryJob.class, QuartzTaskEnum.EXAM_SUMMARY_JOB_NAME.name(), QuartzTaskEnum.EXAM_SUMMARY_JOB_GROUP_NAME.name(), "0 0/1 * * * ?", examSummaryMap);
         log.info("增加考试信息统计job end");
 
+        log.info("增加考试列表job start");
+        Map examListMap = new HashMap();
+        examListMap.put(SystemConstant.NAME, ExamListJob.class.getName());
+        quartzService.deleteJob(QuartzTaskEnum.EXAM_LIST_JOB_NAME.name(), QuartzTaskEnum.EXAM_LIST_JOB_GROUP_NAME.name());
+        quartzService.addJob(ExamListJob.class, QuartzTaskEnum.EXAM_LIST_JOB_NAME.name(), QuartzTaskEnum.EXAM_LIST_JOB_GROUP_NAME.name(), "0 0 0/1 * * ?", examListMap);
+        log.info("增加考试列表job end");
+
 //        log.info("增加修复job start");
 //        Map repairMap = new HashMap();
 //        repairMap.put(SystemConstant.NAME, RepairJob.class.getName());