yxh
6 天以前 68ff33beff11310e830b0615b5a81f83fad0f683
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package cn.lihu.jh.module.ecg.controller.admin.callingscreen;
 
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;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
 
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
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;
 
@Tag(name = "叫号屏 ")
@RestController
@RequestMapping("/ecg/screen")
@Validated
@Slf4j
public class CallingScreenController {
 
    @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 = "列上显示的检查类型名称")
    @PermitAll
    public CommonResult<Map<Integer, List<String>>> displayColInfo()
    {
        Map<Integer, List<String>> map = callingScreenService.getDisplayColInfo();
        return success( map );
    }
 
    @GetMapping("/big-screen-data")
    @Operation(summary = "大屏叫号数据")
    @PermitAll
    public CommonResult<Map<Integer, List<ScreenQueueRespVO>>> callingData()
    {
        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);
        });
 
        return success( mapVO );
    }
 
    @GetMapping("/room-screen-data")
    @Operation(summary = "诊间屏数据")
    @PermitAll
    public CommonResult<Map<Integer, List<ScreenQueueRespVO>>> callingDataRoom(HttpServletRequest request, @RequestParam(value = "roomId", required = false)Long roomId)
    {
        String reqIp = ServletUtil.getClientIP(request);
 
        List<QueueDO> queueDOList1 = callingScreenService.getRoomCheckRelatedPatient(reqIp, roomId);
        List<QueueDO> queueDOList2 = callingScreenService.getRoomInstallRelatedPatient(reqIp, roomId);
 
        Map<Integer, List<ScreenQueueRespVO>> mapVO = new HashMap<>();
        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<>();
        }
    }
 
}