haogh 1 жил өмнө
parent
commit
e7fdb79e3f

+ 5 - 0
src/main/java/com/qmth/exam/reserve/cache/CacheConstants.java

@@ -25,4 +25,9 @@ public interface CacheConstants {
      */
     String CACHE_STUDENT_LOGIN = "S_";
 
+    /**
+     * 自动排考前缀:{yyyyMMdd}
+     */
+    String LOCK_ARRANGE_EXAM = "LOCK:ARRANGE:EXAM:";
+
 }

+ 8 - 3
src/main/java/com/qmth/exam/reserve/cache/RedisClient.java

@@ -1,13 +1,14 @@
 package com.qmth.exam.reserve.cache;
 
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Resource;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
-import javax.annotation.Resource;
-import java.util.concurrent.TimeUnit;
-
 @Component
 public class RedisClient {
 
@@ -49,4 +50,8 @@ public class RedisClient {
         return redisTemplate.hasKey(key);
     }
 
+    public boolean tryLock(String key, Object value, long timeout, TimeUnit timeUnit) {
+        return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, timeUnit).booleanValue();
+    }
+
 }

+ 9 - 5
src/main/java/com/qmth/exam/reserve/controller/admin/StudentApplyController.java

@@ -119,10 +119,10 @@ public class StudentApplyController extends BaseController {
         if (taskId == null) {
             throw new StatusException("请选择预约任务");
         }
-        // LoginUser user = this.curLoginUser();
-        // if (!Role.ADMIN.equals(user.getRole())) {
-        // throw new StatusException("没有权限");
-        // }
+        LoginUser user = this.curLoginUser();
+        if (!Role.ADMIN.equals(user.getRole())) {
+            throw new StatusException("没有权限");
+        }
         studentApplyService.autoAssign(taskId);
     }
 
@@ -135,7 +135,11 @@ public class StudentApplyController extends BaseController {
     @ApiOperation(value = "自动排考")
     @PostMapping(value = "/std/auto/layout")
     public void autoLayout(@ApiParam("教学点ID") @RequestParam Long teachingId) {
-        // TODO 自动将各教学点下待考试的考生分配考场和座位号,并生成准考证号码
+        /*
+         * LoginUser user = this.curLoginUser(); if (!Role.ADMIN.equals(user.getRole()))
+         * { throw new StatusException("没有权限"); }
+         */
+        studentApplyService.autoLayout(teachingId);
     }
 
 }

+ 7 - 3
src/main/java/com/qmth/exam/reserve/dao/StudentApplyDao.java

@@ -1,5 +1,9 @@
 package com.qmth.exam.reserve.dao;
 
+import java.util.List;
+
+import org.apache.ibatis.annotations.Param;
+
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -8,9 +12,6 @@ import com.qmth.exam.reserve.bean.apply.TicketInfo;
 import com.qmth.exam.reserve.bean.stdapply.StudentApplyReq;
 import com.qmth.exam.reserve.bean.stdapply.StudentApplyVO;
 import com.qmth.exam.reserve.entity.StudentApplyEntity;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
 
 public interface StudentApplyDao extends BaseMapper<StudentApplyEntity> {
 
@@ -22,4 +23,7 @@ public interface StudentApplyDao extends BaseMapper<StudentApplyEntity> {
 
     TicketInfo getStudentApplyTicket(@Param("applyId") Long applyId);
 
+    List<StudentApplyEntity> listTimePeriod(@Param(value = "timePeriodIds") List<Long> timePeriodIds,
+            @Param(value = "cancel") Boolean cancel);
+
 }

+ 36 - 0
src/main/java/com/qmth/exam/reserve/enums/DateField.java

@@ -0,0 +1,36 @@
+package com.qmth.exam.reserve.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum DateField {
+
+    YEAR(1, "年份"),
+
+    MONTH(2, "月份"),
+
+    WEEK(3, "星期"),
+
+    DAY(5, "日期"),
+
+    HOUR(11, "小时"),
+
+    MINUTE(12, "分钟"),
+
+    SECOND(13, "秒");
+
+    private int value;
+    private String name;
+
+    public static DateField getByName(String name) {
+        for (DateField r : DateField.values()) {
+            if (r.getName().equals(name)) {
+                return r;
+            }
+        }
+        return null;
+    }
+
+}

+ 20 - 0
src/main/java/com/qmth/exam/reserve/job/AutoArrangeExamJob.java

@@ -0,0 +1,20 @@
+package com.qmth.exam.reserve.job;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import com.qmth.exam.reserve.service.StudentApplyService;
+
+@Service
+public class AutoArrangeExamJob {
+
+    @Autowired
+    private StudentApplyService studentApplyService;
+
+    // 0 0/1 * * * ?
+    @Scheduled(cron = "0 * 12 * * ?")
+    public void autoArrangeExam() {
+        studentApplyService.autoLayout(null);
+    }
+}

+ 2 - 0
src/main/java/com/qmth/exam/reserve/service/StudentApplyService.java

@@ -21,4 +21,6 @@ public interface StudentApplyService extends IService<StudentApplyEntity> {
 
     void autoAssign(Long taskId);
 
+    void autoLayout(Long teachingId);
+
 }

+ 190 - 39
src/main/java/com/qmth/exam/reserve/service/impl/StudentApplyServiceImpl.java

@@ -3,13 +3,19 @@ package com.qmth.exam.reserve.service.impl;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -18,7 +24,6 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.boot.core.collection.PageResult;
@@ -31,17 +36,22 @@ import com.qmth.exam.reserve.bean.stdapply.AgentAndTimeVO;
 import com.qmth.exam.reserve.bean.stdapply.StudentApplyReq;
 import com.qmth.exam.reserve.bean.stdapply.StudentApplyVO;
 import com.qmth.exam.reserve.bean.stdapply.StudentImportVO;
+import com.qmth.exam.reserve.cache.CacheConstants;
+import com.qmth.exam.reserve.cache.RedisClient;
 import com.qmth.exam.reserve.dao.StudentApplyDao;
 import com.qmth.exam.reserve.entity.ApplyTaskEntity;
 import com.qmth.exam.reserve.entity.CategoryEntity;
+import com.qmth.exam.reserve.entity.ExamRoomEntity;
 import com.qmth.exam.reserve.entity.ExamSiteEntity;
 import com.qmth.exam.reserve.entity.StudentApplyEntity;
 import com.qmth.exam.reserve.entity.StudentEntity;
 import com.qmth.exam.reserve.entity.TimePeriodEntity;
 import com.qmth.exam.reserve.enums.CategoryLevel;
+import com.qmth.exam.reserve.enums.DateField;
 import com.qmth.exam.reserve.enums.EventType;
 import com.qmth.exam.reserve.service.ApplyTaskService;
 import com.qmth.exam.reserve.service.CategoryService;
+import com.qmth.exam.reserve.service.ExamRoomService;
 import com.qmth.exam.reserve.service.ExamSiteService;
 import com.qmth.exam.reserve.service.OperateLogService;
 import com.qmth.exam.reserve.service.StudentApplyService;
@@ -55,9 +65,13 @@ import com.qmth.exam.reserve.util.PageUtil;
 public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, StudentApplyEntity>
         implements StudentApplyService {
 
+    private final static Logger log = LoggerFactory.getLogger(StudentApplyServiceImpl.class);
+
     private static final String[] EXCEL_HEADER = new String[] { "学号", "姓名", "证件号", "所属教学点", "预约考点1", "预约时段1", "预约考点2",
             "预约时段2", "预约考点3", "预约时段3", "预约考点4", "预约时段4" };
 
+    private final long TIMEOUT = 60;
+
     @Autowired
     private TimePeriodService timePeriodService;
 
@@ -76,6 +90,12 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
     @Autowired
     private OperateLogService operateLogService;
 
+    @Autowired
+    private RedisClient redisClient;
+
+    @Autowired
+    private ExamRoomService examRoomService;
+
     @Override
     public PageResult<StudentApplyVO> page(StudentApplyReq req) {
         IPage<StudentApplyVO> iPage = this.baseMapper
@@ -93,11 +113,9 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
         TimePeriodEntity timePeroid = timePeriodService.getById(studentApply.getTimePeriodId());
         if (timePeroid == null)
             throw new StatusException("考试时段不存在,请检查考试时段数据!");
-        LambdaQueryWrapper<ApplyTaskEntity> wrapper = new LambdaQueryWrapper<ApplyTaskEntity>()
-                .eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
-        ApplyTaskEntity task = applyTaskService.getOne(wrapper);
+        ApplyTaskEntity task = getApplyTask();
         Date applyDate = DateUtil.parse(DateUtil.getShortDateByLongTime(timePeroid.getStartTime()), "yyyy-MM-dd");
-        Date canCancelDay = DateUtil.addValues(applyDate, 5, -task.getAllowApplyCancelDays());
+        Date canCancelDay = DateUtil.addValues(applyDate, DateField.DAY.getValue(), -task.getAllowApplyCancelDays());
         if (new Date().after(canCancelDay))
             throw new StatusException("可取消时间已过,无法取消!");
         studentApply.setCancel(Boolean.TRUE);
@@ -308,9 +326,7 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
     }
 
     private void checkInOpenTime() {
-        LambdaQueryWrapper<ApplyTaskEntity> wrapper = new LambdaQueryWrapper<ApplyTaskEntity>()
-                .eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
-        ApplyTaskEntity task = applyTaskService.getOne(wrapper);
+        ApplyTaskEntity task = getApplyTask();
         Date start = DateUtil.parse(DateUtil.getLongDateByLongTime(task.getOpenApplyStartTime()), null);
         Date end = DateUtil.parse(DateUtil.getLongDateByLongTime(task.getOpenApplyEndTime()), null);
         if (!DateUtil.isBetwwen(start, end)) {
@@ -318,6 +334,12 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
         }
     }
 
+    private ApplyTaskEntity getApplyTask() {
+        LambdaQueryWrapper<ApplyTaskEntity> wrapper = new LambdaQueryWrapper<ApplyTaskEntity>()
+                .eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
+        return applyTaskService.getOne(wrapper);
+    }
+
     private void saveStdApply(Long userId, StudentImportVO vo) {
         List<AgentAndTimeVO> agentTimeList = vo.getAgentTimeList();
         LambdaQueryWrapper<StudentApplyEntity> lm = new LambdaQueryWrapper<>();
@@ -415,38 +437,45 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
     @Transactional
     @Override
     public void autoAssign(Long taskId) {
-        // checkAfterOpenTime();
-        // 1、未完成预约的考生
-        LambdaQueryWrapper<StudentEntity> lm = new LambdaQueryWrapper<>();
-        lm.eq(StudentEntity::getApplyFinished, Boolean.FALSE);
-        List<StudentEntity> studentList = studentService.list(lm);
-        Map<Long, List<StudentEntity>> map = studentList.stream()
-                .collect(Collectors.groupingBy(StudentEntity::getCategoryId));
-        // 2、考位是否充足
-        List<TimePeriodEntity> timeList = listTimePeroid(taskId);
-        checkTeachingCapacity(map, timeList, taskId);
-        // 3、按照教学点安排考位。规则:不能和已预约的时间上有冲突
-        for (Long key : map.keySet()) {
-            List<ExamSiteEntity> siteList = listExamSite(key);
-
-            List<StudentEntity> teachingStudentList = map.get(key);
-            for (TimePeriodEntity time : timeList) {
-                for (ExamSiteEntity site : siteList) {
-                    // 该时段已预约的考生
-                    Integer haveApplyNum = getHaveApplyNum(site.getId(), time.getId());
-                    // 剩余的考位
-                    Integer remainNum = site.getCapacity() - haveApplyNum;
-                    assignStdApply(site.getId(), time.getId(), teachingStudentList, remainNum);
+        checkAfterOpenTime();
+        try {
+            // 1、未完成预约的考生
+            LambdaQueryWrapper<StudentEntity> lm = new LambdaQueryWrapper<>();
+            lm.eq(StudentEntity::getApplyFinished, Boolean.FALSE);
+            List<StudentEntity> studentList = studentService.list(lm);
+            Map<Long, List<StudentEntity>> map = studentList.stream()
+                    .collect(Collectors.groupingBy(StudentEntity::getCategoryId));
+            // 2、考位是否充足
+            List<TimePeriodEntity> timeList = listTimePeroid(taskId);
+            checkTeachingCapacity(map, timeList, taskId);
+            // 3、按照教学点安排考位。规则:不能和已预约的时间上有冲突
+            for (Long key : map.keySet()) {
+                List<ExamSiteEntity> siteList = listExamSite(key);
+                List<StudentEntity> teachingStudentList = map.get(key);
+                for (TimePeriodEntity time : timeList) {
+                    for (ExamSiteEntity site : siteList) {
+                        // 该时段已预约的考生
+                        Integer haveApplyNum = getHaveApplyNum(site.getId(), time.getId());
+                        // 剩余的考位
+                        Integer remainNum = site.getCapacity() - haveApplyNum;
+                        assignStudentApply(site.getId(), time.getId(), teachingStudentList, remainNum);
+                    }
                 }
+                // 4、判断是否还有剩余考生未完成预约,提醒考位不够
+                if (teachingStudentList.size() > 0)
+                    throw new StatusException("【" + categoryService.getById(key).getName() + "】教学点考位不足");
             }
-            // 4、判断是否还有剩余考生未完成预约,提醒考位不够
-            if (teachingStudentList.size() > 0)
-                throw new StatusException("【" + categoryService.getById(key).getName() + "】教学点考位不足");
+        } catch (Exception e) {
+            log.error(e.getMessage());
+            throw new StatusException(e.getMessage());
+        } finally {
+
         }
 
     }
 
-    private void assignStdApply(Long siteId, Long timeId, List<StudentEntity> teachingStudentList, Integer remainNum) {
+    private void assignStudentApply(Long siteId, Long timeId, List<StudentEntity> teachingStudentList,
+            Integer remainNum) {
         int num = 0;
         for (Iterator<StudentEntity> iterator = teachingStudentList.iterator(); iterator.hasNext();) {
             StudentEntity student = iterator.next();
@@ -493,9 +522,7 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
     }
 
     private void checkAfterOpenTime() {
-        LambdaQueryWrapper<ApplyTaskEntity> wrapper = new LambdaQueryWrapper<ApplyTaskEntity>()
-                .eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
-        ApplyTaskEntity task = applyTaskService.getOne(wrapper);
+        ApplyTaskEntity task = getApplyTask();
         Date openEndTime = DateUtil.parse(DateUtil.getLongDateByLongTime(task.getOpenApplyEndTime()), null);
         Date selfStartTime = DateUtil.parse(DateUtil.getLongDateByLongTime(task.getSelfApplyStartTime()), null);
         if (!DateUtil.isBetwwen(openEndTime, selfStartTime)) {
@@ -511,8 +538,8 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
             Integer total = siteList.stream().collect(Collectors.summingInt(ExamSiteEntity::getCapacity))
                     * timeList.size();
             // 已经预约的数量
-            Integer haveApplyNum = this.getBaseMapper()
-                    .getHaveApplyCount(siteList.stream().map(site -> site.getId()).collect(Collectors.toList()));
+            Integer haveApplyNum = this.getBaseMapper().getHaveApplyCount(
+                    siteList.stream().map(site -> site.getId()).collect(Collectors.toList()), Boolean.FALSE);
             // 未预约的数量
             Integer noApplyNum = getNoApplyNum(map.get(key));
             if (noApplyNum > total - haveApplyNum) {
@@ -560,4 +587,128 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
         return examSiteService.list(wrapper);
     }
 
+    @Override
+    public void autoLayout(Long teachingId) {
+        ApplyTaskEntity applyTask = getApplyTask();
+        if (applyTask == null) {
+            log.info("没有开启的预约任务");
+            return;
+        }
+        boolean isSuccess = redisClient.tryLock(
+                CacheConstants.LOCK_ARRANGE_EXAM + DateUtil.formatShortDateString(new Date()), UUID.randomUUID(),
+                TIMEOUT, TimeUnit.MINUTES);
+        try {
+            if (isSuccess) {
+                // 1.根据当前日期,查询不能取消的时段
+                List<TimePeriodEntity> timePeriodList = listTimePeroid(applyTask.getId());
+                List<TimePeriodEntity> noCancelTimePeroidList = listNoCancelApplyTimePeroid(timePeriodList,
+                        applyTask.getAllowApplyCancelDays());
+                if (noCancelTimePeroidList.isEmpty()) {
+                    log.info("当前时间,没有取消的时段。");
+                    return;
+                }
+                // 2.查询考试日期的待排考的考生
+                List<StudentApplyEntity> toBeLayoutStudentList = this.baseMapper.listTimePeriod(
+                        noCancelTimePeroidList.stream().map(item -> item.getId()).collect(Collectors.toList()),
+                        Boolean.FALSE);
+                // 3.开始排考
+                Map<Long, List<StudentApplyEntity>> toBeLayoutStudentMap = toBeLayoutStudentList.stream()
+                        .collect(Collectors.groupingBy(StudentApplyEntity::getExamSiteId));
+                for (Long examSiteId : toBeLayoutStudentMap.keySet()) {
+                    Map<Long, List<StudentApplyEntity>> timeLayoutStudentMap = toBeLayoutStudentMap.get(examSiteId)
+                            .stream().collect(Collectors.groupingBy(StudentApplyEntity::getTimePeriodId));
+                    List<ExamRoomEntity> roomList = listExamRoom(examSiteId);
+                    if (roomList.isEmpty()) {
+                        throw new StatusException(examSiteId + ":未设置考场");
+                    }
+                    ExamSiteEntity examSite = examSiteService.getById(examSiteId);
+                    layoutStudentByTimePeriod(applyTask.getId(), examSite, roomList, timeLayoutStudentMap);
+                }
+            }
+        } catch (StatusException e) {
+            log.error(e.getMessage());
+            e.printStackTrace();
+        } finally {
+            redisClient.delete(CacheConstants.LOCK_ARRANGE_EXAM + DateUtil.formatShortDateString(new Date()));
+        }
+    }
+
+    private void layoutStudentByTimePeriod(Long taskId, ExamSiteEntity examSite, List<ExamRoomEntity> roomList,
+            Map<Long, List<StudentApplyEntity>> timeLayoutStudentMap) {
+        for (Long timePeriodId : timeLayoutStudentMap.keySet()) {
+            List<StudentApplyEntity> studentApplyList = timeLayoutStudentMap.get(timePeriodId);
+            layoutStudentToRoom(taskId, examSite, roomList, studentApplyList, timePeriodService.getById(timePeriodId));
+        }
+    }
+
+    private void layoutStudentToRoom(Long taskId, ExamSiteEntity examSite, List<ExamRoomEntity> roomList,
+            List<StudentApplyEntity> studentApplyList, TimePeriodEntity timePeriod) {
+        Integer timePeriodOrder = getTimePeriodOrder(taskId, timePeriod);
+        for (ExamRoomEntity room : roomList) {
+            Integer num = 0;
+            for (Iterator<StudentApplyEntity> iterator = studentApplyList.iterator(); iterator.hasNext();) {
+                StudentApplyEntity student = iterator.next();
+                if (num >= room.getCapacity())
+                    break;
+                String seatNumber = StringUtils.leftPad(String.valueOf(++num), 3, '0');
+                student.setExamRoomId(room.getId());
+                student.setSeatNumber(seatNumber);
+                student.setTicketNumber(
+                        generateTicketNumber(timePeriodOrder, examSite.getCode(), room.getCode(), seatNumber));
+                this.baseMapper.updateById(student);
+                iterator.remove();
+            }
+        }
+    }
+
+    private Integer getTimePeriodOrder(Long taskId, TimePeriodEntity timePeriod) {
+        List<TimePeriodEntity> timeList = listTimePeroid(taskId);
+        List<TimePeriodEntity> sameDayTimeList = listSameDayTimePeroid(timeList, timePeriod.getStartTime());
+        for (int i = 0; i < sameDayTimeList.size(); i++) {
+            TimePeriodEntity time = sameDayTimeList.get(i);
+            if (time.getStartTime().equals(timePeriod.getStartTime()))
+                return i + 1;
+        }
+        return 0;
+    }
+
+    private List<TimePeriodEntity> listSameDayTimePeroid(List<TimePeriodEntity> timeList, Long startTime) {
+        String day = DateUtil.getShortDateWithoutSplitByLongTime(startTime);
+        List<TimePeriodEntity> resultList = new ArrayList<>();
+        for (TimePeriodEntity time : timeList) {
+            if (DateUtil.getShortDateWithoutSplitByLongTime(startTime).equals(day))
+                resultList.add(time);
+        }
+        return resultList.stream().sorted(Comparator.comparing(TimePeriodEntity::getStartTime))
+                .collect(Collectors.toList());
+    }
+
+    private String generateTicketNumber(Integer timePeriodOrder, String examSiteCode, String roomCode,
+            String seatNumber) {
+        return DateUtil.formatShortDateString(new Date()) + timePeriodOrder + examSiteCode + roomCode + seatNumber;
+    }
+
+    public List<ExamRoomEntity> listExamRoom(Long examSiteId) {
+        LambdaQueryWrapper<ExamRoomEntity> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(ExamRoomEntity::getExamSiteId, examSiteId);
+        wrapper.orderByAsc(ExamRoomEntity::getCode);
+        return examRoomService.list(wrapper);
+    }
+
+    private List<TimePeriodEntity> listNoCancelApplyTimePeroid(List<TimePeriodEntity> list,
+            Integer allowApplyCancelDays) {
+        String noCancelDate = getNoCancelApplyDate(allowApplyCancelDays);
+        List<TimePeriodEntity> noCancelTimePeroidList = new ArrayList<>();
+        for (TimePeriodEntity time : list) {
+            if (DateUtil.getShortDateWithoutSplitByLongTime(time.getStartTime()).equals(noCancelDate))
+                noCancelTimePeroidList.add(time);
+        }
+        return noCancelTimePeroidList;
+
+    }
+
+    private String getNoCancelApplyDate(Integer allowApplyCancelDays) {
+        return DateUtil.formatShortDateString(DateUtil.addValues(DateField.DAY.getValue(), allowApplyCancelDays));
+    }
+
 }

+ 20 - 1
src/main/java/com/qmth/exam/reserve/util/DateUtil.java

@@ -56,6 +56,12 @@ public class DateUtil {
         return simpleDateFormat.format(date);
     }
 
+    public static String getShortDateWithoutSplitByLongTime(Long time) {
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(ShortDateStringWithoutSplit);
+        Date date = new Date(time);
+        return simpleDateFormat.format(date);
+    }
+
     public static Long getLongTimeByDate(String dateStr) {
         SimpleDateFormat sdf = new SimpleDateFormat(LongDateString);
         try {
@@ -81,7 +87,8 @@ public class DateUtil {
     }
 
     public static void main(String[] args) {
-        parse("2024-10-01 10:00:00", null);
+        String result = formatShortDateString(new Date());
+        System.out.println(result);
     }
 
     public static Date addValues(int filed, int value) {
@@ -105,6 +112,18 @@ public class DateUtil {
         return null;
     }
 
+    public static String formatShortString(Date date, String pattern) {
+        try {
+            return getFormatter(pattern).format(date);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static String formatShortDateString(Date date) {
+        return formatShortString(date, ShortDateStringWithoutSplit);
+    }
+
     public static Date parse(String source, String pattern) {
         if (StringUtils.isEmpty(pattern))
             pattern = LongDateString;

+ 8 - 0
src/main/resources/mapper/StudentApplyMapper.xml

@@ -90,5 +90,13 @@
                  left join t_exam_room ec on ec.id = sa.exam_room_id
         where sa.id = #{applyId}
     </select>
+    
+    <select id="listTimePeriod" resultType="com.qmth.exam.reserve.entity.StudentApplyEntity">
+		select sa.* from t_student_apply sa,t_student s where sa.student_id=s.id and  sa.cancel=#{cancel} and sa.time_period_id in
+		<foreach collection="timePeriodIds" item="item" index="index" separator="," open="(" close=")">
+			#{item}
+		</foreach>
+		 order by s.student_code
+	</select>
 
 </mapper>