1. 根据检查类型,配置 准备中 人数  2. 医生入座,才允许 患者 进入 准备中

1. 根据检查类型,配置 准备中 人数
2. 医生入座,才允许 患者 进入 准备中
已修改7个文件
118 ■■■■■ 文件已修改
jh-module-ecg/jh-module-ecg-api/src/main/java/cn/lihu/jh/module/ecg/enums/ErrorCodeConstants.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/config/MySpringEventListener.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/mysql/room/RoomMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueServiceImpl.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueServiceTxFunctions.java 55 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-server/src/main/resources/logback-spring.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-api/src/main/java/cn/lihu/jh/module/ecg/enums/ErrorCodeConstants.java
@@ -10,6 +10,7 @@
public interface ErrorCodeConstants {
    ErrorCode ECG_INNER_ERROR = new ErrorCode(1_010_000_000, "ECG内部错误");
    ErrorCode ECG_CONFIG_ERROR = new ErrorCode(1_010_000_001, "心电检查类型的最大准备人数配置不一致");
    ErrorCode APPOINTMENT_NOT_EXISTS = new ErrorCode(1_010_001_000, "预约不存在");
    ErrorCode APPOINTMENT_NOT_TODAY = new ErrorCode(1_010_001_001, "不是当天预约");
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/config/MySpringEventListener.java
@@ -1,26 +1,39 @@
package cn.lihu.jh.module.ecg.config;
import cn.lihu.jh.framework.common.exception.ServiceException;
import cn.lihu.jh.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.lihu.jh.module.ecg.Utils;
import cn.lihu.jh.module.ecg.enums.ErrorCodeConstants;
import cn.lihu.jh.module.ecg.service.callingscreen.BigScreenConfig;
import cn.lihu.jh.module.ecg.service.callingscreen.CallingScreenService;
import cn.lihu.jh.module.ecg.service.config.EcgConfigService;
import cn.lihu.jh.module.ecg.service.queue.QueueService;
import cn.lihu.jh.module.infra.api.config.ConfigApi;
import cn.lihu.jh.module.system.api.dict.DictDataApi;
import cn.lihu.jh.module.system.api.dict.dto.DictDataRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static cn.lihu.jh.module.ecg.Constants.*;
@Component
@Slf4j
public class MySpringEventListener {
    @Resource
    private ConfigApi configApi;
    @Resource
    private DictDataApi dictDataApi;
    @Resource
    private EcgConfigService ecgConfigService;
@@ -33,10 +46,23 @@
    @EventListener
    public void onApplicationEvent(ApplicationStartedEvent event) {
        System.out.println("应用启动完成,系统初始。。。");
        log.info("应用启动完成,系统初始。。。");
        Integer queueReadyMax = Integer.valueOf(configApi.getConfigValueByKey(ECG_QUEUE_READY_MAX_KEY));
        queueService.setQueueReadyMax( queueReadyMax );
        String strQueueReadyMax = configApi.getConfigValueByKey(ECG_QUEUE_READY_MAX_KEY);
        int[] queueReadyMax = Arrays.stream(strQueueReadyMax.split(","))
                .mapToInt(Integer::parseInt)
                .toArray();
        List<DictDataRespDTO> dictDataRespDTOList = dictDataApi.getDictDataList("ecg_check_type");
        if ( dictDataRespDTOList.size() != queueReadyMax.length) {
            log.error(ErrorCodeConstants.ECG_CONFIG_ERROR.getMsg());
        }
        Integer checkTypeNum = dictDataRespDTOList.size() < queueReadyMax.length ? dictDataRespDTOList.size() : queueReadyMax.length;
        Map max = new HashMap<Integer, Integer>();
        for (int i=0; i<checkTypeNum; i++) {
            max.put( Integer.valueOf(dictDataRespDTOList.get(i).getValue()), queueReadyMax[i]);
        }
        queueService.setCheckTypeReadyMax( max );
        BigScreenConfig bigScreenConfig = new BigScreenConfig();
        Integer waitingSize = Integer.valueOf(configApi.getConfigValueByKey(ECG_SCREEN_PANE_WAITING_KEY));
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/mysql/room/RoomMapper.java
@@ -6,10 +6,7 @@
import cn.lihu.jh.framework.mybatis.core.mapper.BaseMapperX;
import cn.lihu.jh.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.lihu.jh.module.ecg.dal.dataobject.room.RoomDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.*;
import cn.lihu.jh.module.ecg.controller.admin.room.vo.RoomPageReqVO;
import cn.lihu.jh.module.ecg.dal.dataobject.room.RoomStatisticsDO;
@@ -53,8 +50,14 @@
            "</script>")
    List<RoomDO> simpleRoomList(@Param("curStatusList") List<BedStatusEnum> curStatusList);
    @Select("SELECT * FROM lihu.clinic_room where room_id=#{roomId} and bed_no=#{bedNo}")
    @Results({
        @Result(property = "checkTypes", column = "check_types", typeHandler=com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler.class)
    })
    RoomDO getRoom(@Param("roomId")Long roomId, @Param("bedNo")String bedNo);
    @Select("SELECT * FROM lihu.clinic_room where room_id=#{roomId} and bed_no=#{bedNo} and doc_id=#{docId}")
    RoomDO getRoom(@Param("roomId")Long roomId, @Param("bedNo")String bedNo, @Param("docId")Long docId);
    RoomDO getRoomByRoomBedDoc(@Param("roomId")Long roomId, @Param("bedNo")String bedNo, @Param("docId")Long docId);
    @Select("SELECT * FROM lihu.clinic_room where doc_id=#{docId} limit 1")
    RoomDO getRoomByDocId(@Param("docId")Long docId);
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueService.java
@@ -2,6 +2,7 @@
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import cn.lihu.jh.framework.common.exception.ErrorCode;
import cn.lihu.jh.framework.common.pojo.CommonResult;
@@ -19,7 +20,7 @@
 */
public interface QueueService {
    void setQueueReadyMax(Integer max);
    void setCheckTypeReadyMax(Map<Integer, Integer> max);
    void startBiz();
    void closeBiz();
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueServiceImpl.java
@@ -2,7 +2,6 @@
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Resource;
import cn.lihu.jh.module.ecg.controller.admin.room.vo.MonitorInfoVO;
@@ -14,18 +13,14 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import cn.lihu.jh.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.lihu.jh.module.ecg.dal.dataobject.room.RoomDO;
import cn.lihu.jh.framework.common.exception.ErrorCode;
import cn.lihu.jh.framework.common.pojo.CommonResult;
import cn.lihu.jh.module.ecg.controller.admin.room.vo.RoomRespVO;
import cn.lihu.jh.module.ecg.dal.dataobject.queue.BedQueueStatisticDO;
import cn.lihu.jh.module.ecg.dal.dataobject.queue.QueueStatisticDO;
import cn.lihu.jh.module.ecg.dal.mysql.room.RoomMapper;
import cn.lihu.jh.module.ecg.enums.BedStatusEnum;
import cn.lihu.jh.module.ecg.enums.QueueStatusEnum;
import cn.lihu.jh.module.ecg.controller.admin.queue.vo.*;
import cn.lihu.jh.module.ecg.dal.dataobject.queue.QueueDO;
@@ -254,7 +249,7 @@
    @Override
    public CommonResult<RoomRespVO> getRoom(Long roomId, String bedNo, Long docId) {
        RoomDO roomDO = roomMapper.getRoom(roomId, bedNo, docId);
        RoomDO roomDO = roomMapper.getRoomByRoomBedDoc(roomId, bedNo, docId);
        if (null == roomDO) {
            return error(ROOM_NOT_SIT);
        }
@@ -346,9 +341,8 @@
        return patientStatisticVO;
    }
    @Override
    public void setQueueReadyMax(Integer max) {
        queueServiceTxFunctions.setQueueReadyMax( max );
    public void setCheckTypeReadyMax(Map<Integer, Integer> max) {
        queueServiceTxFunctions.setCheckTypeReadyMax( max );
    }
    public void startBiz() {
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueServiceTxFunctions.java
@@ -2,16 +2,8 @@
import cn.lihu.jh.framework.common.exception.ErrorCode;
import cn.lihu.jh.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.lihu.jh.framework.common.pojo.CommonResult;
import cn.lihu.jh.framework.common.pojo.PageResult;
import cn.lihu.jh.framework.common.util.object.BeanUtils;
import cn.lihu.jh.module.ecg.controller.admin.queue.vo.PatientStatisticVO;
import cn.lihu.jh.module.ecg.controller.admin.queue.vo.QueuePageReqVO;
import cn.lihu.jh.module.ecg.controller.admin.queue.vo.QueueSaveReqVO;
import cn.lihu.jh.module.ecg.controller.admin.room.vo.MonitorInfoVO;
import cn.lihu.jh.module.ecg.controller.admin.room.vo.RoomRespVO;
import cn.lihu.jh.module.ecg.dal.dataobject.devrent.DevRentDO;
import cn.lihu.jh.module.ecg.dal.dataobject.queue.BedQueueStatisticDO;
import cn.lihu.jh.module.ecg.dal.dataobject.queue.QueueDO;
import cn.lihu.jh.module.ecg.dal.dataobject.queue.QueueStatisticDO;
import cn.lihu.jh.module.ecg.dal.dataobject.room.RoomDO;
@@ -20,25 +12,22 @@
import cn.lihu.jh.module.ecg.dal.mysql.queue.queueMapper;
import cn.lihu.jh.module.ecg.dal.mysql.room.RoomMapper;
import cn.lihu.jh.module.ecg.enums.BedStatusEnum;
import cn.lihu.jh.module.ecg.enums.DevRentStateEnum;
import cn.lihu.jh.module.ecg.enums.QueueStatusEnum;
import cn.lihu.jh.module.system.api.oauth2.OAuth2TokenApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import static cn.lihu.jh.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.lihu.jh.framework.common.pojo.CommonResult.error;
import static cn.lihu.jh.framework.common.pojo.CommonResult.success;
import static cn.lihu.jh.module.ecg.enums.ErrorCodeConstants.*;
/**
@@ -72,7 +61,7 @@
    PriorityBlockingQueue<BedQueueBO> priorityQueue = new PriorityBlockingQueue<>();
    ConcurrentHashMap<String, BedQueueBO > mapBedVsQueue = new ConcurrentHashMap<>();
    Integer queueReadyMax = 0;
    Map<Integer, Integer> mapCheckTypeVsReadyMax = null;
    /**
     * 已关闭 或者 关闭中,可以开通工位
@@ -105,10 +94,9 @@
        bedQueueBO.setRoomId(roomId);
        bedQueueBO.setRoomName(roomName);
        bedQueueBO.setBedNo(bedNo);
        bedQueueBO.setMaxQueueNum(queueReadyMax);
        bedQueueBO.setMaxQueueNum(getBedReadyMax(roomId, bedNo));
        bedQueueBO.setQueueNum(new AtomicInteger(queueDOList.size()));
        bedQueueBO.setStatus(BedStatusEnum.OPENING.getStatus());
        priorityQueue.offer(bedQueueBO);
        mapBedVsQueue.put(String.format("%09d%s", roomId, bedNo), bedQueueBO);
        return GlobalErrorCodeConstants.SUCCESS;
@@ -215,6 +203,13 @@
        }
        bedQueueBO.setStatus(BedStatusEnum.DOCTOR_ON.getStatus());
        if (!priorityQueue.contains(bedQueueBO)) {
            priorityQueue.offer(bedQueueBO);
        } else {
            log.error("bedDoctorOn priorityQueue still exist!. " + roomId + " " + bedNo);
            return ECG_INNER_ERROR;
        }
        return GlobalErrorCodeConstants.SUCCESS;
    }
@@ -235,15 +230,7 @@
            return ROOM_INVALID_STATUS;
        }
        // 如果是在 PAUSE 状态离座的,需要重新加回 优先队列
        if (bedQueueBO.getStatus().equals(BedStatusEnum.PAUSE.getStatus())) {
            if (!priorityQueue.contains(bedQueueBO)) {
                priorityQueue.offer(bedQueueBO);
            } else {
                log.error("bedDoctorResume priorityQueue still exist!. " + roomId + " " + bedNo);
                return ECG_INNER_ERROR;
            }
        }
        priorityQueue.remove(bedQueueBO);
        bedQueueBO.setStatus(BedStatusEnum.OPENING.getStatus());
        return GlobalErrorCodeConstants.SUCCESS;
@@ -294,15 +281,15 @@
        List<QueueStatisticDO> queueStatisticDOList = queueMapper.queueStatistic(queueStatusList);
        bedQueueBOList.forEach(item -> {
            item.maxQueueNum = queueReadyMax;
            item.maxQueueNum = getBedReadyMax(item.roomId, item.bedNo);
            Optional<QueueStatisticDO> queueStatisticDOOptional = queueStatisticDOList.stream().filter(it->it.getRoomId()==item.roomId && it.getBedNo().equals(item.getBedNo())).findFirst();
            int queueNum = queueStatisticDOOptional.isPresent() ? queueStatisticDOOptional.get().getTotalInStatus() : 0;
            if ( queueReadyMax < queueNum )
            if ( item.maxQueueNum < queueNum )
                throw new RuntimeException("init: exceed max queue number!");
            item.queueNum.set( queueNum );
            mapBedVsQueue.put(String.format("%09d%s", item.roomId, item.bedNo), item);
            if (BedStatusEnum.PAUSE.getStatus() != item.getStatus()) {
            if (BedStatusEnum.DOCTOR_ON.getStatus() == item.getStatus()) {
                priorityQueue.offer(item);
            }
        });
@@ -406,8 +393,8 @@
        openingFlag.set(flag);
    }
    public void setQueueReadyMax(Integer max) {
        queueReadyMax = max;
    public void setCheckTypeReadyMax(Map<Integer, Integer> max) {
        mapCheckTypeVsReadyMax = max;
    }
    public BedQueueBO getBedQueueBO(Long roomId, String bedNo) {
@@ -427,4 +414,14 @@
                + " opening " + openingFlag.get());
    }
    private Integer getBedReadyMax(Long roomId, String bedNo) {
        RoomDO roomDO = roomMapper.getRoom(roomId, bedNo);
        Integer[] checkTypes = roomDO.getCheckTypes();
        Integer ret = 0;
        for (int i=0; i<checkTypes.length; i++) {
            Integer tmp = mapCheckTypeVsReadyMax.get(checkTypes[i]);
            ret = ret < tmp ? tmp : ret;  //取大值
        }
        return ret;
    }
}
jh-server/src/main/resources/logback-spring.xml
@@ -4,7 +4,7 @@
    <!-- 变量 jh.info.base-package,基础业务包 -->
    <springProperty scope="context" name="jh.info.base-package" source="jh.info.base-package"/>
    <!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level:级别从左显示 5 个字符宽度,%msg:日志消息,%n是换行符 -->
    <property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid]) %boldGreen(%-40.40logger{39}) | %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
    <property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid]) %boldGreen(%-40.40logger{39}) |%L| %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
    <!-- 控制台 Appender -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">