TimePeriodExamRoomServiceImpl.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. package com.qmth.exam.reserve.service.impl;
  2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  3. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  4. import com.qmth.boot.core.concurrent.service.ConcurrentService;
  5. import com.qmth.boot.core.exception.StatusException;
  6. import com.qmth.exam.reserve.bean.applytask.CurrentApplyTaskVO;
  7. import com.qmth.exam.reserve.bean.examsite.ExamSiteCacheBean;
  8. import com.qmth.exam.reserve.bean.login.LoginUser;
  9. import com.qmth.exam.reserve.bean.org.OrgInfo;
  10. import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteBean;
  11. import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteInfo;
  12. import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteReq;
  13. import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteVo;
  14. import com.qmth.exam.reserve.cache.CacheConstants;
  15. import com.qmth.exam.reserve.cache.impl.ApplyTaskCacheService;
  16. import com.qmth.exam.reserve.cache.impl.ExamSiteCacheService;
  17. import com.qmth.exam.reserve.cache.impl.OrgCacheService;
  18. import com.qmth.exam.reserve.dao.TimePeriodExamRoomDao;
  19. import com.qmth.exam.reserve.entity.ExamRoomEntity;
  20. import com.qmth.exam.reserve.entity.TimePeriodEntity;
  21. import com.qmth.exam.reserve.entity.TimePeriodExamRoomEntity;
  22. import com.qmth.exam.reserve.enums.Role;
  23. import com.qmth.exam.reserve.service.*;
  24. import com.qmth.exam.reserve.util.DateUtil;
  25. import com.qmth.exam.reserve.util.UnionUtil;
  26. import org.apache.commons.collections4.CollectionUtils;
  27. import org.apache.commons.lang3.StringUtils;
  28. import org.redisson.api.RLock;
  29. import org.slf4j.Logger;
  30. import org.slf4j.LoggerFactory;
  31. import org.springframework.beans.BeanUtils;
  32. import org.springframework.beans.factory.annotation.Autowired;
  33. import org.springframework.stereotype.Service;
  34. import org.springframework.transaction.annotation.Transactional;
  35. import org.springframework.transaction.support.TransactionSynchronization;
  36. import org.springframework.transaction.support.TransactionSynchronizationManager;
  37. import java.util.*;
  38. import java.util.stream.Collectors;
  39. @Service
  40. public class TimePeriodExamRoomServiceImpl extends ServiceImpl<TimePeriodExamRoomDao, TimePeriodExamRoomEntity> implements TimePeriodExamRoomService {
  41. private static final Logger log = LoggerFactory.getLogger(TimePeriodExamRoomServiceImpl.class);
  42. @Autowired
  43. private ApplyTaskCacheService applyTaskCacheService;
  44. @Autowired
  45. private OrgCacheService orgCacheService;
  46. @Autowired
  47. private TimePeriodService timePeriodService;
  48. @Autowired
  49. private ExamSiteCacheService examSiteCacheService;
  50. @Autowired
  51. private ExamRoomService examRoomService;
  52. @Autowired
  53. private ConcurrentService concurrentService;
  54. @Autowired
  55. private ExamSiteService examSiteService;
  56. @Autowired
  57. private TimePeriodExamRoomService timePeriodExamRoomService;
  58. @Autowired
  59. private StudentApplyService studentApplyService;
  60. @Override
  61. public List<TimePeriodExamSiteVo> ListDetail(LoginUser loginUser, Long examRoomId) {
  62. //获取当前机构
  63. OrgInfo org = orgCacheService.currentOrg();
  64. if (org == null) {
  65. log.warn("[考场排班设置列表]未找到当前机构");
  66. return Collections.emptyList();
  67. }
  68. //判断考场是否存在
  69. ExamRoomEntity examRoom = examRoomService.getById(examRoomId);
  70. if (examRoom == null) {
  71. log.warn("[考场排班设置列表]未找到考场:{}", examRoomId);
  72. return Collections.emptyList();
  73. }
  74. //教学点管理员权限限制
  75. ExamSiteCacheBean examSite = examSiteCacheService.getExamSiteById(examRoom.getExamSiteId());
  76. if (examSite == null) {
  77. log.warn("[考场排班设置列表]考场:{}未找到所属考点", examRoomId);
  78. return Collections.emptyList();
  79. }
  80. if (loginUser.getRole().equals(Role.TEACHING) && !loginUser.getCategoryId().equals(examSite.getCategoryId())) {
  81. return Collections.emptyList();
  82. }
  83. //获取当前任务
  84. CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(org.getOrgId());
  85. if (curApplyTask == null) {
  86. log.warn("[考场排班设置列表]机构:{},当前未有启用的任务", org.getOrgId());
  87. return Collections.emptyList();
  88. }
  89. // 所有的预约日期
  90. List<String> dateList = timePeriodService.listTimePeriodDate(curApplyTask.getTaskId());
  91. if (CollectionUtils.isEmpty(dateList)) {
  92. log.warn("[考场排班设置列表]当前任务:{}未设置预约日期", curApplyTask.getTaskId());
  93. return Collections.emptyList();
  94. }
  95. //教学点管理员设置的所有的考点时段
  96. List<TimePeriodExamSiteBean> timePeriodExamRoomList = timePeriodService.listTimePeriodByExamRoomId(curApplyTask.getTaskId(), examRoomId);
  97. //学校管理员设置的所有预约时段
  98. List<TimePeriodExamSiteBean> timePeriodList = timePeriodService.listTimePeriodByTask(curApplyTask.getTaskId());
  99. List<TimePeriodExamSiteBean> resultList;
  100. if (CollectionUtils.isEmpty(timePeriodExamRoomList)) {
  101. resultList = timePeriodList;
  102. } else {
  103. //取并集
  104. resultList = UnionUtil.unionByAttribute(timePeriodExamRoomList, timePeriodList, TimePeriodExamSiteBean::getTimePeriodId);
  105. }
  106. //按日期封装
  107. List<TimePeriodExamSiteVo> list = new ArrayList<>();
  108. for (String date : dateList) {
  109. TimePeriodExamSiteVo timePeriodVo = new TimePeriodExamSiteVo();
  110. timePeriodVo.setDateStr(getDateStr(date));
  111. timePeriodVo.setTimePeriodList(filterTimePeriod(date, resultList, curApplyTask.getAllowApplyCancelDays()));
  112. list.add(timePeriodVo);
  113. }
  114. return list;
  115. }
  116. private String getDateStr(String date) {
  117. if (StringUtils.isEmpty(date)) {
  118. return "";
  119. }
  120. String[] dateArr = date.split("-");
  121. if (dateArr.length != 3) {
  122. return "";
  123. }
  124. return dateArr[1] + "月" + dateArr[2] + "日";
  125. }
  126. private List<TimePeriodExamSiteInfo> filterTimePeriod(String date, List<TimePeriodExamSiteBean> timePeriodList, Integer canCancelDay) {
  127. // 参数校验
  128. if (timePeriodList == null || date == null || canCancelDay == null || canCancelDay < 0) {
  129. return new ArrayList<>();
  130. }
  131. List<TimePeriodExamSiteInfo> resultList = new ArrayList<>();
  132. // 过滤符合条件的时间段
  133. List<TimePeriodExamSiteBean> filteredTimePeriodList = timePeriodList.stream()
  134. .filter(item -> DateUtil.getShortDateByLongTime(item.getStartTime()).equals(date))
  135. .sorted(Comparator.comparing(TimePeriodExamSiteBean::getStartTime))
  136. .collect(Collectors.toList());
  137. // 计算可取消时间范围
  138. Long longToday = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(new Date()) + " 00:00:00");
  139. Date today = new Date(longToday);
  140. Date otherDay = DateUtil.addValues(today, Calendar.DAY_OF_MONTH, canCancelDay);
  141. long longOtherDay = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(otherDay) + " 23:59:59");
  142. // 当前时间
  143. long now = System.currentTimeMillis();
  144. for (TimePeriodExamSiteBean time : filteredTimePeriodList) {
  145. // 检查时间是否有效
  146. if (time.getStartTime() == null || time.getEndTime() == null) {
  147. continue; // 跳过无效时间段
  148. }
  149. TimePeriodExamSiteInfo bean = new TimePeriodExamSiteInfo();
  150. bean.setId(time.getId());
  151. bean.setTimePeriodId(time.getTimePeriodId());
  152. bean.setEnable(time.getEnable());
  153. bean.setTimePeriodStr(DateUtil.getStartToEndTime(time.getStartTime(), time.getEndTime()));
  154. // 判断是否可编辑
  155. boolean isEditable = isTimeEditable(now, time.getEndTime(), longOtherDay, time.getStartTime());
  156. bean.setEditable(isEditable);
  157. resultList.add(bean);
  158. }
  159. return resultList;
  160. }
  161. private boolean isTimeEditable(long now, long endTime, long longOtherDay, long startTime) {
  162. return !(endTime < now || startTime < longOtherDay);
  163. }
  164. @Transactional(rollbackFor = Exception.class)
  165. @Override
  166. public void save(Long userId, Long examRoomId, List<TimePeriodExamSiteReq> timePeriodExamRoomList) {
  167. if (concurrentService.isLocked(CacheConstants.LOCK_AUTO_APPLY)) {
  168. log.warn("[考场排班保存]系统自动预约中,不允许操作考场排班!lockKey:{}", CacheConstants.LOCK_AUTO_APPLY);
  169. throw new StatusException("系统正在自动预约中,不允许修改");
  170. }
  171. if (CollectionUtils.isEmpty(timePeriodExamRoomList)) {
  172. log.warn("[考场排班设置]时间段列表为空");
  173. throw new StatusException("保存失败,时间段列表为空");
  174. }
  175. // 获取当前机构
  176. OrgInfo org = orgCacheService.currentOrg();
  177. if (org == null) {
  178. log.warn("[考场排班设置]未找到当前机构");
  179. throw new StatusException("保存失败,未找到当前机构");
  180. }
  181. // 获取当前任务
  182. CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(org.getOrgId());
  183. if (curApplyTask == null) {
  184. log.warn("[考场排班设置]机构:{},当前未有启用的任务", org.getOrgId());
  185. throw new StatusException("保存失败,未有启用的任务");
  186. }
  187. // 校验考场信息
  188. ExamRoomEntity examRoom = examRoomService.getById(examRoomId);
  189. if (examRoom == null || !examRoom.getEnable()) {
  190. log.warn("[考场排班设置]未找到或已被禁用的考场:{}", examRoomId);
  191. throw new StatusException("保存失败,考场不存在或已被禁用");
  192. }
  193. // 校验考点信息
  194. ExamSiteCacheBean examSiteCacheBean = examSiteCacheService.getExamSiteById(examRoom.getExamSiteId());
  195. if (examSiteCacheBean == null) {
  196. log.warn("[考场排班设置]未找到考点:{}", examRoom.getExamSiteId());
  197. throw new StatusException("保存失败,未找到考点");
  198. }
  199. String lockKey = String.format(CacheConstants.LOCK_EXAM_SITE_CAPACITY, examRoom.getExamSiteId());
  200. if (concurrentService.isLocked(lockKey)) {
  201. log.warn("[考场排班设置]考点剩余可约数量更新中,不允许操作修改!lockKey:{}", lockKey);
  202. throw new StatusException("系统正在更新可预约数量,不允许保存");
  203. }
  204. //考点容量变更锁
  205. String examSiteLockKey = String.format(CacheConstants.LOCK_EXAM_SITE_CHANGE_CAPACITY, examRoom.getExamSiteId());
  206. RLock examSiteLock = (RLock) concurrentService.getLock(examSiteLockKey);
  207. try {
  208. if (!examSiteLock.tryLock()) {
  209. log.warn("[考场排班设置] 获取锁失败,同一个教学点不允许同时操作一个考点的容量修改, lockKey:{}", examSiteLockKey);
  210. throw new StatusException("其他老师正在修改该考点的容量,请稍后重试!");
  211. } else {
  212. // 获取已有时段数据
  213. List<TimePeriodExamSiteBean> existingTimePeriods = timePeriodService.listTimePeriodByExamRoomId(curApplyTask.getTaskId(), examRoomId);
  214. Map<Long, TimePeriodExamSiteBean> existingMap = existingTimePeriods.stream()
  215. .collect(Collectors.toMap(TimePeriodExamSiteBean::getId, t -> t));
  216. // 过滤出可编辑的数据
  217. List<TimePeriodExamSiteReq> editableList = timePeriodExamRoomList.stream()
  218. .filter(TimePeriodExamSiteReq::getEditable)
  219. .collect(Collectors.toList());
  220. if (editableList.isEmpty()) {
  221. log.warn("[考场排班设置]无可编辑数据");
  222. return;
  223. }
  224. // 构建实体列表
  225. List<TimePeriodExamRoomEntity> entityList = editableList.stream()
  226. .map(req -> createTimePeriodExamRoomEntity(req, examRoomId, userId))
  227. .collect(Collectors.toList());
  228. // 分离新增和更新
  229. List<TimePeriodExamRoomEntity> toBeSaved = new ArrayList<>();
  230. List<TimePeriodExamRoomEntity> toBeUpdated = new ArrayList<>();
  231. entityList.forEach(e -> {
  232. if (e.getId() == null) {
  233. toBeSaved.add(e);
  234. } else {
  235. toBeUpdated.add(e);
  236. }
  237. });
  238. // 检查是否可编辑
  239. List<Long> timePeriodIdsToEdit = new ArrayList<>();
  240. toBeSaved.forEach(e -> timePeriodIdsToEdit.add(e.getTimePeriodId()));
  241. toBeUpdated.forEach(e -> {
  242. TimePeriodExamSiteBean old = existingMap.get(e.getId());
  243. if (old != null && !old.getEnable().equals(e.getEnable())) {
  244. timePeriodIdsToEdit.add(e.getTimePeriodId());
  245. }
  246. });
  247. canEdit(timePeriodIdsToEdit, curApplyTask);
  248. // 待更新、保存时段ID
  249. Set<Long> updatedTimePeriodIds = new HashSet<>();
  250. toBeSaved.forEach(e -> updatedTimePeriodIds.add(e.getTimePeriodId()));
  251. toBeUpdated.forEach(e -> updatedTimePeriodIds.add(e.getTimePeriodId()));
  252. // 保存前先记录旧容量
  253. Map<Long, Integer> oldCapacityMap = new HashMap<>();
  254. for (Long timePeriodId : updatedTimePeriodIds) {
  255. int capacity = examSiteService.getExamSiteTimePeriodCapacity(examSiteCacheBean.getExamSiteId(), timePeriodId);
  256. oldCapacityMap.put(timePeriodId, capacity);
  257. }
  258. List<TimePeriodExamRoomEntity> verifyList = new ArrayList<>();
  259. //只处理禁用的时段
  260. List<TimePeriodExamRoomEntity> newTimePeriodList = toBeSaved.stream().filter(item -> !item.getEnable()).collect(Collectors.toList());
  261. if (!newTimePeriodList.isEmpty()) {
  262. verifyList.addAll(newTimePeriodList);
  263. }
  264. if (!toBeUpdated.isEmpty()) {
  265. verifyList.addAll(toBeUpdated);
  266. }
  267. //容量验证
  268. int availableCount, haveApplyCount, oldCount;
  269. for (TimePeriodExamRoomEntity toUpdate : verifyList) {
  270. TimePeriodExamSiteBean bean;
  271. if (toUpdate.getId() == null) {
  272. bean = new TimePeriodExamSiteBean();
  273. bean.setEnable(toUpdate.getEnable());
  274. bean.setTimePeriodId(toUpdate.getTimePeriodId());
  275. } else {
  276. bean = existingMap.get(toUpdate.getId());
  277. }
  278. //只处理从开启到关闭的时段
  279. if (bean != null && (bean.getId() == null || (bean.getEnable() && !toUpdate.getEnable()))) {
  280. // 剩余的容量,从缓存中获取
  281. availableCount = applyTaskCacheService.getApplyAvailableCount(examSiteCacheBean.getExamSiteId(), toUpdate.getTimePeriodId());
  282. // 修改之前的容量
  283. oldCount = oldCapacityMap.getOrDefault(toUpdate.getTimePeriodId(), 0);
  284. // 已预约的容量
  285. haveApplyCount = oldCount - availableCount;
  286. // 关闭之后的剩余容量
  287. int remainCount = oldCount - examRoom.getCapacity();
  288. log.warn("haveApplyCount:{}, remainCount:{}", haveApplyCount, remainCount);
  289. if (haveApplyCount > remainCount) {
  290. TimePeriodEntity timePeriod = timePeriodService.getById(toUpdate.getTimePeriodId());
  291. String dateStr = DateUtil.getShortDateByLongTime(timePeriod.getStartTime());
  292. String timeStr = DateUtil.getStartToEndTime(timePeriod.getStartTime(), timePeriod.getEndTime());
  293. String errorMessage = String.format("时段:%s %s,已预约%d人,当前已预约人数超出剩余容量%d人,无法关闭。", dateStr, timeStr, haveApplyCount,
  294. remainCount);
  295. log.error(errorMessage);
  296. throw new StatusException(errorMessage);
  297. }
  298. }
  299. }
  300. // 批量保存或更新
  301. if (!toBeSaved.isEmpty()) {
  302. //防止重复保存
  303. checkExistTimePeriodExamRoom(toBeSaved, Collections.emptyList());
  304. saveBatch(toBeSaved);
  305. }
  306. if (!toBeUpdated.isEmpty()) {
  307. List<Long> ids = toBeUpdated.stream()
  308. .map(TimePeriodExamRoomEntity::getId)
  309. .collect(Collectors.toList());
  310. checkExistTimePeriodExamRoom(toBeUpdated, ids);
  311. updateBatchById(toBeUpdated);
  312. }
  313. // 提交事务后刷新缓存
  314. TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  315. @Override
  316. public void afterCommit() {
  317. for (Long timePeriodId : updatedTimePeriodIds) {
  318. int oldCapacity = oldCapacityMap.getOrDefault(timePeriodId, 0);;
  319. int newCapacity = examSiteService.getExamSiteTimePeriodCapacity(examSiteCacheBean.getExamSiteId(), timePeriodId);
  320. applyTaskCacheService.refreshApplyAvailableCountCache(
  321. examRoom.getExamSiteId(),
  322. timePeriodId,
  323. oldCapacity,
  324. newCapacity
  325. );
  326. }
  327. }
  328. });
  329. }
  330. } catch (Exception e) {
  331. log.error("[考场排班设置]保存失败,原因:{}", e.getMessage(), e);
  332. throw new StatusException(e.getMessage());
  333. } finally {
  334. try {
  335. if (examSiteLock.isLocked() && examSiteLock.isHeldByCurrentThread()) {
  336. examSiteLock.unlock();
  337. log.info("[考场排班设置] 解锁成功,lockKey:{}", examSiteLockKey);
  338. }
  339. } catch (Exception e) {
  340. log.warn(e.getMessage());
  341. }
  342. }
  343. }
  344. private void checkExistTimePeriodExamRoom(List<TimePeriodExamRoomEntity> toBeSaved, List<Long> ids) {
  345. // 判断考场+时段是否在库中已经存在
  346. List<Long> examRoomIds = toBeSaved.stream()
  347. .map(TimePeriodExamRoomEntity::getExamRoomId)
  348. .distinct()
  349. .collect(Collectors.toList());
  350. List<Long> timePeriodIds = toBeSaved.stream()
  351. .map(TimePeriodExamRoomEntity::getTimePeriodId)
  352. .distinct()
  353. .collect(Collectors.toList());
  354. // 批量查询已存在的记录
  355. List<TimePeriodExamRoomEntity> existingRecords = getBaseMapper().listByExamRoomIdsAndTimePeriodIds(examRoomIds, timePeriodIds, ids);
  356. // 构建已存在的记录集合,用于快速查找
  357. Set<String> existingKeySet = existingRecords.stream()
  358. .map(e -> e.getExamRoomId() + "-" + e.getTimePeriodId())
  359. .collect(Collectors.toSet());
  360. // 检查是否有重复的记录
  361. for (TimePeriodExamRoomEntity item : toBeSaved) {
  362. String key = item.getExamRoomId() + "-" + item.getTimePeriodId();
  363. if (existingKeySet.contains(key)) {
  364. log.error("[考场排班设置]保存失败,该时间段已存在: examRoomId={}, timePeriodId={}", item.getExamRoomId(), item.getTimePeriodId());
  365. throw new StatusException("保存失败,时段重复");
  366. }
  367. }
  368. }
  369. @Override
  370. public List<ExamRoomEntity> listExamRoom(Long examSiteId, Long timePeriodId, Boolean enable) {
  371. return getBaseMapper().listExamRoom(examSiteId, timePeriodId, enable);
  372. }
  373. @Override
  374. public List<TimePeriodExamRoomEntity> listExamRoom(Long examRoomId) {
  375. LambdaQueryWrapper<TimePeriodExamRoomEntity> wrapper = new LambdaQueryWrapper<>();
  376. wrapper.eq(TimePeriodExamRoomEntity::getExamRoomId, examRoomId);
  377. return list(wrapper);
  378. }
  379. @Override
  380. public List<TimePeriodExamRoomEntity> listByExamRoomIdsAndTimePeriodId(List<Long> examRoomIds, Long timePeriodId) {
  381. return getBaseMapper().listByExamRoomIdsAndTimePeriodId(examRoomIds, timePeriodId);
  382. }
  383. @Override
  384. public TimePeriodExamRoomEntity getTimePeriodExamRoom(Long roomId, Long timePeriodId) {
  385. LambdaQueryWrapper<TimePeriodExamRoomEntity> wrapper = new LambdaQueryWrapper<>();
  386. wrapper.eq(TimePeriodExamRoomEntity::getExamRoomId, roomId);
  387. wrapper.eq(TimePeriodExamRoomEntity::getTimePeriodId, timePeriodId);
  388. return getOne(wrapper);
  389. }
  390. @Override
  391. public List<TimePeriodExamRoomEntity> listByExamRoomAndPeriodIds(Long examRoomId, Set<Long> periodIds) {
  392. return getBaseMapper().listByExamRoomAndPeriodIds(examRoomId, periodIds);
  393. }
  394. // 校验是否可编辑
  395. private void canEdit(List<Long> timePeriodExamRoomList, CurrentApplyTaskVO curApplyTask) {
  396. if (CollectionUtils.isNotEmpty(timePeriodExamRoomList)) {
  397. Long longToday = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(new Date()) + " 00:00:00");
  398. Date today = new Date(longToday);
  399. Date otherDay = DateUtil.addValues(today, Calendar.DAY_OF_MONTH, curApplyTask.getAllowApplyCancelDays());
  400. long longOtherDay = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(otherDay) + " 23:59:59");
  401. // 当前时间
  402. long now = System.currentTimeMillis();
  403. List<TimePeriodEntity> timePeriodEntities = timePeriodService.listByIds(timePeriodExamRoomList);
  404. Map<Long, TimePeriodEntity> timePeriodEntityMap = timePeriodEntities.stream()
  405. .collect(Collectors.toMap(TimePeriodEntity::getId, tpe -> tpe));
  406. for (Long timePeriodId : timePeriodExamRoomList) {
  407. TimePeriodEntity timePeriod = timePeriodEntityMap.get(timePeriodId);
  408. if (!isTimeEditable(now, timePeriod.getEndTime(), longOtherDay, timePeriod.getStartTime())) {
  409. throw new StatusException("保存失败," + DateUtil.getShortDateByLongTime(timePeriod.getStartTime()) + "可编辑时间范围已过");
  410. }
  411. }
  412. }
  413. }
  414. private TimePeriodExamRoomEntity createTimePeriodExamRoomEntity(TimePeriodExamSiteReq item, Long examRoomId, Long userId) {
  415. TimePeriodExamRoomEntity entity = new TimePeriodExamRoomEntity();
  416. BeanUtils.copyProperties(item, entity);
  417. entity.setExamRoomId(examRoomId);
  418. entity.setOperateId(userId);
  419. return entity;
  420. }
  421. }