yxh
5 天以前 68ff33beff11310e830b0615b5a81f83fad0f683
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/controller/admin/callingscreen/CallingScreenController.java
@@ -3,7 +3,9 @@
import cn.hutool.extra.servlet.ServletUtil;
import cn.lihu.jh.framework.common.pojo.CommonResult;
import cn.lihu.jh.framework.common.util.object.BeanUtils;
import cn.lihu.jh.module.ecg.dal.dataobject.checktype.CheckTypeDO;
import cn.lihu.jh.module.ecg.dal.dataobject.queue.QueueDO;
import cn.lihu.jh.module.ecg.dal.mysql.checktype.CheckTypeMapper;
import cn.lihu.jh.module.ecg.service.callingscreen.CallingScreenService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -17,6 +19,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static cn.lihu.jh.framework.common.pojo.CommonResult.error;
import static cn.lihu.jh.framework.common.pojo.CommonResult.success;
@@ -30,6 +33,14 @@
    @Resource
    private CallingScreenService callingScreenService;
    /** 用于给屏幕数据补「排队号前缀」(check_type.seq_prefix) */
    @Resource
    private CheckTypeMapper checkTypeMapper;
    /** 【重叫】用于给屏幕数据补"最近一次叫号记录id"(call_patient) */
    @Resource
    private cn.lihu.jh.module.ecg.dal.mysql.call.CallMapper callMapper;
    @GetMapping("/display-col-info")
    @Operation(summary = "列上显示的检查类型名称")
@@ -48,10 +59,16 @@
        Map<Integer, List<QueueDO>> map = callingScreenService.getBigScreenPatient();
        Map<Integer, List<ScreenQueueRespVO>> mapVO = new HashMap<>();
        // 屏幕要显示「前缀 + 排队号」,设备未登录拿不到检查项目字典,故由后端一并下发(每次请求读一次)
        Map<Integer, String> seqPrefixMap = getSeqPrefixMap();
        // 【重叫】一并下发"最近一次叫号记录id",屏幕据此重新播报
        Map<String, Long> callIdMap = getLatestCallIdMap();
        map.keySet().forEach( displayCol -> {
            //log.info("dispayCol: " + displayCol);
            List<QueueDO> columnQueueDOList = map.get(displayCol);
            List<ScreenQueueRespVO> screenQueueRespVOList = BeanUtils.toBean(columnQueueDOList, ScreenQueueRespVO.class);
            fillSeqPrefix(screenQueueRespVOList, seqPrefixMap);
            fillCallId(screenQueueRespVOList, callIdMap);
            mapVO.put(displayCol, screenQueueRespVOList);
        });
@@ -69,9 +86,88 @@
        List<QueueDO> queueDOList2 = callingScreenService.getRoomInstallRelatedPatient(reqIp, roomId);
        Map<Integer, List<ScreenQueueRespVO>> mapVO = new HashMap<>();
        mapVO.put(1, BeanUtils.toBean(queueDOList1, ScreenQueueRespVO.class));
        mapVO.put(2, BeanUtils.toBean(queueDOList2, ScreenQueueRespVO.class));
        List<ScreenQueueRespVO> waitingVOList = BeanUtils.toBean(queueDOList1, ScreenQueueRespVO.class);
        List<ScreenQueueRespVO> installVOList = BeanUtils.toBean(queueDOList2, ScreenQueueRespVO.class);
        // 屏幕要显示「前缀 + 排队号」,设备未登录拿不到检查项目字典,故由后端一并下发(每次请求读一次)
        Map<Integer, String> seqPrefixMap = getSeqPrefixMap();
        Map<String, Long> callIdMap = getLatestCallIdMap();
        fillSeqPrefix(waitingVOList, seqPrefixMap);
        fillSeqPrefix(installVOList, seqPrefixMap);
        fillCallId(waitingVOList, callIdMap);
        fillCallId(installVOList, callIdMap);
        mapVO.put(1, waitingVOList);
        mapVO.put(2, installVOList);
        return success( mapVO );
    }
    /**
     * 给屏幕数据补上「排队号显示前缀」= {@code check_type.seq_prefix}。
     *
     * <p>【号统一(本需求)】排队号按检查项目各自编号,不同检查项目会出现相同数字,
     * 屏幕上必须带前缀才分得清(例:A5 / B5)。屏幕设备不登录、无法调用检查项目接口,
     * 因此在这里补齐。
     *
     * <p>每次请求查一次全表建映射(检查项目只有十几个,量级很小):
     * 不做长期缓存,避免管理员改了前缀后屏幕一直显示旧值。
     * 查不到配置时留空串——宁可只显示数字,也不要让屏幕报错或空白。
     */
    private void fillSeqPrefix(List<ScreenQueueRespVO> voList, Map<Integer, String> seqPrefixMap) {
        if (voList == null || voList.isEmpty() || seqPrefixMap == null) {
            return;
        }
        voList.forEach(vo -> vo.setSeqPrefix(seqPrefixMap.getOrDefault(vo.getBookCheckType(), "")));
    }
    /* ==================== 重叫:下发"最近一次叫号记录id" ==================== */
    /**
     * 给屏幕数据补上 {@code callId}(该患者最近一次叫号记录的 id)。
     *
     * <p>为什么需要:屏幕播报靠"数据变化"触发 —— 大屏判断"某患者新出现在叫号列"、
     * 诊间屏判断"诊中第一人变化"。而医生点「重叫」时**患者还是那个人、诊室还是那个诊室**,
     * 队列数据一点没变,两块屏自然不会再播。重叫会新增一条叫号记录(call_patient),
     * 把它的 id 下发后,屏幕只要发现 callId 变了就重新播报。
     */
    private void fillCallId(List<ScreenQueueRespVO> voList, Map<String, Long> callIdMap) {
        if (voList == null || voList.isEmpty() || callIdMap == null || callIdMap.isEmpty()) {
            return;
        }
        voList.forEach(vo -> {
            if (null != vo.getPatId()) {
                vo.setCallId(callIdMap.get(vo.getPatId()));
            }
        });
    }
    /** 一次查询取到「患者编号 → 最近一次叫号记录 id」;失败时返回空映射(屏幕按老逻辑播报) */
    private Map<String, Long> getLatestCallIdMap() {
        try {
            Map<String, Long> map = new HashMap<>();
            for (Map<String, Object> row : callMapper.selectLatestCallIds()) {
                Object patId = row.get("patId");
                Object callId = row.get("callId");
                if (null != patId && callId instanceof Number) {
                    map.put(String.valueOf(patId), ((Number) callId).longValue());
                }
            }
            return map;
        } catch (Exception e) {
            log.error("[getLatestCallIdMap] 读取最近叫号记录失败,重叫将不会触发屏幕重播", e);
            return new HashMap<>();
        }
    }
    /** 读一次检查项目配置,得到「检查项目值 → 排队号前缀」映射;失败时返回空映射(屏幕只显示号) */
    private Map<Integer, String> getSeqPrefixMap() {        try {
            return checkTypeMapper.simpleCheckTypeList().stream()
                    .filter(checkType -> null != checkType.getValue())
                    .collect(Collectors.toMap(CheckTypeDO::getValue,
                            checkType -> null == checkType.getSeqPrefix() ? "" : checkType.getSeqPrefix(),
                            (a, b) -> a));
        } catch (Exception e) {
            log.error("[getSeqPrefixMap] 读取检查项目前缀失败,屏幕将只显示号", e);
            return new HashMap<>();
        }
    }
}