package cn.lihu.jh.module.ecg.service.queue; import cn.lihu.jh.module.ecg.dal.dataobject.queue.QueueStatisticDO; import cn.lihu.jh.module.ecg.dal.dataobject.room.RoomDO; import cn.lihu.jh.module.ecg.dal.dataobject.room.RoomStatisticsDO; import cn.lihu.jh.module.ecg.dal.mysql.room.RoomMapper; import cn.lihu.jh.module.ecg.enums.QueueStatusEnum; import lombok.Data; import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import cn.lihu.jh.module.ecg.controller.admin.queue.vo.*; import cn.lihu.jh.module.ecg.dal.dataobject.queue.QueueDO; import cn.lihu.jh.framework.common.pojo.PageResult; import cn.lihu.jh.framework.common.util.object.BeanUtils; import cn.lihu.jh.module.ecg.dal.mysql.queue.queueMapper; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; import static cn.lihu.jh.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.lihu.jh.module.ecg.enums.ErrorCodeConstants.*; /** * 排队 Service 实现类 * * @author 芋道源码 */ @Service @Validated public class QueueServiceImpl implements QueueService { final static Integer MAX_QUEUE_NUM = 2; AtomicInteger curSeqNum = new AtomicInteger(0); PriorityBlockingQueue priorityQueue = new PriorityBlockingQueue<>(); ConcurrentHashMap mapBedVsQueue = new ConcurrentHashMap<>(); @Resource private queueMapper queueMapper; @Resource private RoomMapper roomMapper; @Override public Integer createqueue(QueueSaveReqVO createReqVO) { // 插入 QueueDO queue = BeanUtils.toBean(createReqVO, QueueDO.class); queueMapper.insert(queue); // 返回 return queue.getId(); } @Override public void updatequeue(QueueSaveReqVO updateReqVO) { // 校验存在 validatequeueExists(updateReqVO.getId()); // 更新 QueueDO updateObj = BeanUtils.toBean(updateReqVO, QueueDO.class); queueMapper.updateById(updateObj); } @Override public void deletequeue(Integer id) { // 校验存在 validatequeueExists(id); // 删除 queueMapper.deleteById(id); } private void validatequeueExists(Integer id) { if (queueMapper.selectById(id) == null) { throw exception(QUEUE_NOT_EXISTS); } } @Override public QueueDO getqueue(Integer id) { return queueMapper.selectById(id); } @Override public PageResult getqueuePage(QueuePageReqVO pageReqVO) { return queueMapper.selectPage(pageReqVO); } @Override public List queueStatistics(List statusList) { return queueMapper.queueStatistic(statusList); } @Override public void queue(QueueSaveReqVO queueSaveReqVO) { BedQueueBO bedQueueBO = priorityQueue.peek(); if (null == bedQueueBO) return; if (bedQueueBO.queueNum.get() == bedQueueBO.maxQueueNum) { queueSaveReqVO.setStatus(QueueStatusEnum.WAITING.getStatus()); //排队中 QueueDO queue = BeanUtils.toBean(queueSaveReqVO, QueueDO.class); queueMapper.insert(queue); // queue.getId(); } else if (bedQueueBO.queueNum.get() < bedQueueBO.maxQueueNum) { queueSaveReqVO.setStatus(QueueStatusEnum.READY.getStatus()); //候诊准备中 queueSaveReqVO.setRoomId(bedQueueBO.getRoomId()); queueSaveReqVO.setRoomName(bedQueueBO.getRoomName()); queueSaveReqVO.setBedNo(bedQueueBO.getBedNo()); queueSaveReqVO.setSeqNum(curSeqNum.get()); QueueDO queue = BeanUtils.toBean(queueSaveReqVO, QueueDO.class); queueMapper.insert(queue); // queue.getId(); curSeqNum.getAndIncrement(); bedQueueBO.queueNum.getAndIncrement(); BedQueueBO bedQueueBO2 = priorityQueue.poll(); priorityQueue.offer(bedQueueBO2); } } public void initQueue() { priorityQueue.clear(); mapBedVsQueue.clear(); // 从DB 获取 工位列表 List roomDOList = roomMapper.simpleRoomList(); List bedQueueBOList = roomDOList.stream().map(item -> BeanUtils.toBean(item, BedQueueBO.class)).toList(); // 从DB 获取 队列中 就诊准备中人员 列表 List queueStatusList = new ArrayList<>(); queueStatusList.add(QueueStatusEnum.READY.getStatus()); List queueStatisticDOList = queueMapper.queueStatistic(queueStatusList); bedQueueBOList.forEach(item -> { item.maxQueueNum = MAX_QUEUE_NUM; Optional queueStatisticDOOptional = queueStatisticDOList.stream().filter(it->it.getRoomId()==item.roomId && it.getBedNo().equals(item.getBedNo())).findFirst(); item.queueNum.set( queueStatisticDOOptional.isPresent() ? queueStatisticDOOptional.get().getTotalInStatus() : 0 ); priorityQueue.offer(item); mapBedVsQueue.put(String.format("%09d%s", item.roomId, item.bedNo), item); }); Integer num = queueMapper.getMaxSeqNum(); curSeqNum = new AtomicInteger(null == num ? 1 : ++num); hurryup(); } /** * TODO 新开队列时,需要把排队中的人 转到 就诊准备 状态 * 等到取下一个 排队中人员 的逻辑完成后,再回来不错 */ public void hurryup() { while (true) { BedQueueBO bedQueueBO = priorityQueue.peek(); if (null == bedQueueBO) return; if (bedQueueBO.queueNum.get() == bedQueueBO.maxQueueNum) return; QueueDO queue = queueMapper.getFirstInQueueByStatus(QueueStatusEnum.WAITING.getStatus()); if (null == queue) return; queue.setStatus(QueueStatusEnum.READY.getStatus()); //候诊准备中 queue.setRoomId(bedQueueBO.getRoomId()); queue.setRoomName(bedQueueBO.getRoomName()); queue.setBedNo(bedQueueBO.getBedNo()); queue.setSeqNum(curSeqNum.get()); queueMapper.updateById(queue); // queue.getId(); curSeqNum.getAndIncrement(); bedQueueBO.queueNum.getAndIncrement(); BedQueueBO bedQueueBO2 = priorityQueue.poll(); priorityQueue.offer(bedQueueBO2); } } public void nextPatient(Long roomId, String bedNo) { // 从 DB 把 序号最小的 就诊准备中的人 设置为就诊中 queueMapper.updateQueueStatus(roomId, bedNo, QueueStatusEnum.READY.getStatus(), QueueStatusEnum.ONSTAGE.getStatus()); // 优先队列中 该工位 就诊准备中人的数量 减一 BedQueueBO bo = mapBedVsQueue.get(String.format("%09d%s", roomId, bedNo)); boolean breturn = priorityQueue.remove(bo); bo.queueNum.getAndDecrement(); priorityQueue.offer(bo); hurryup(); } public List getDoctorQueueByStatus(Long roomId, String bedNo, List statusList) { List queueDOList = queueMapper.getDoctorQueueByStatus(roomId, bedNo, statusList); return queueDOList; } }