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.mysql.room.RoomMapper;
|
import cn.lihu.jh.module.ecg.enums.QueueStatusEnum;
|
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.Resource;
|
|
import java.util.*;
|
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.PriorityBlockingQueue;
|
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicReference;
|
|
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<BedQueueBO> priorityQueue = new PriorityBlockingQueue<>();
|
ConcurrentHashMap<String, BedQueueBO > 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<QueueDO> getqueuePage(QueuePageReqVO pageReqVO) {
|
return queueMapper.selectPage(pageReqVO);
|
}
|
|
@Override
|
public List<QueueStatisticDO> queueStatistics(List<Byte> statusList) {
|
return queueMapper.queueStatistic(statusList);
|
}
|
|
public void initQueue() {
|
priorityQueue.clear();
|
mapBedVsQueue.clear();
|
|
// 从DB 获取 工位列表
|
List<RoomDO> roomDOList = roomMapper.simpleRoomList();
|
List<BedQueueBO> bedQueueBOList = roomDOList.stream().map(item -> BeanUtils.toBean(item, BedQueueBO.class)).toList();
|
|
// 从DB 获取 队列中 就诊准备中人员统计 列表
|
List<Byte> queueStatusList = new ArrayList<>();
|
queueStatusList.add(QueueStatusEnum.READY.getStatus());
|
List<QueueStatisticDO> queueStatisticDOList = queueMapper.queueStatistic(queueStatusList);
|
|
bedQueueBOList.forEach(item -> {
|
item.maxQueueNum = MAX_QUEUE_NUM;
|
Optional<QueueStatisticDO> 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();
|
}
|
|
public void reorderQueue() {
|
// 根据预约前后,从DB 获取 队列中 就诊准备中人员 列表
|
List<Byte> queueStatusList = new ArrayList<>();
|
queueStatusList.add(QueueStatusEnum.READY.getStatus());
|
List<QueueDO> queueDOList = queueMapper.getOrderedQueue(queueStatusList);
|
if (queueDOList.isEmpty())
|
return;
|
|
AtomicInteger seqNum = new AtomicInteger(1);
|
queueDOList.forEach(item -> {item.setSeqNum(seqNum.getAndIncrement());});
|
queueMapper.updateBatch(queueDOList);
|
|
curSeqNum.set( seqNum.get() );
|
}
|
|
/**
|
* 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);
|
}
|
}
|
|
@Override
|
public void queue(QueueSaveReqVO queueSaveReqVO) {
|
queueSaveReqVO.setStatus(QueueStatusEnum.WAITING.getStatus()); //排队中
|
QueueDO queue = BeanUtils.toBean(queueSaveReqVO, QueueDO.class);
|
queueMapper.insert(queue); // queue.getId();
|
|
hurryup();
|
}
|
|
private 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 void finishNextPatient(Long roomId, String bedNo) {
|
// 从 DB 把 就诊中的人 设置为就诊完成
|
Integer ret = queueMapper.updateQueueStatus(roomId, bedNo,
|
QueueStatusEnum.ONSTAGE.getStatus(), QueueStatusEnum.FINISH.getStatus());
|
System.out.println("完成数量: " + ret);
|
|
nextPatient(roomId, bedNo);
|
}
|
|
public void passNextPatient(Long roomId, String bedNo) {
|
// 从 DB 把 就诊中的人 设置为过号
|
Integer ret = queueMapper.updateQueueStatus(roomId, bedNo,
|
QueueStatusEnum.ONSTAGE.getStatus(), QueueStatusEnum.PASSED.getStatus());
|
System.out.println("完成数量: " + ret);
|
|
nextPatient(roomId, bedNo);
|
}
|
|
public List<QueueDO> getDoctorQueueByStatus(Long roomId, String bedNo, List<Byte> statusList) {
|
List<QueueDO> queueDOList = queueMapper.getDoctorQueueByStatus(roomId, bedNo, statusList);
|
return queueDOList;
|
}
|
|
}
|