From 1f23e7dfc186c65434eda46fd6756d41fd01e867 Mon Sep 17 00:00:00 2001
From: yxh <172933527@qq.com>
Date: 星期三, 11 十一月 2026 00:00:37 +0800
Subject: [PATCH] ai优化

---
 jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueServiceImpl.java |  495 +++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 441 insertions(+), 54 deletions(-)

diff --git a/jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueServiceImpl.java b/jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueServiceImpl.java
index a7042f0..e97c3eb 100644
--- a/jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueServiceImpl.java
+++ b/jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueServiceImpl.java
@@ -2,14 +2,18 @@
 
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.stream.Collectors;
 import javax.annotation.Resource;
 
 import cn.lihu.jh.module.ecg.Utils;
 import cn.lihu.jh.module.ecg.controller.admin.room.vo.MonitorInfoVO;
+import cn.lihu.jh.module.ecg.dal.dataobject.appointment.AppointmentDO;
 import cn.lihu.jh.module.ecg.dal.dataobject.checktype.CheckTypeDO;
 import cn.lihu.jh.module.ecg.dal.dataobject.devrent.DevRentDO;
 import cn.lihu.jh.module.ecg.dal.mysql.appointment.AppointmentMapper;
+import cn.lihu.jh.module.ecg.dal.mysql.checktype.CheckTypeMapper;
 import cn.lihu.jh.module.ecg.dal.mysql.devrent.DevRentMapper;
+import cn.lihu.jh.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.lihu.jh.module.ecg.enums.DevRentStateEnum;
 import cn.lihu.jh.module.system.api.oauth2.OAuth2TokenApi;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -18,6 +22,8 @@
 import org.apache.cxf.common.util.CollectionUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
 import org.springframework.validation.annotation.Validated;
 
 import cn.lihu.jh.module.ecg.dal.dataobject.room.RoomDO;
@@ -65,6 +71,13 @@
 
     @Resource
     private DevRentMapper devRentMapper;
+
+    /**
+     * 鐢ㄤ簬銆岃澶囬鐢�/瑁呮満銆嶅彇鏁版椂杩囨护鍑� {@code need_dev_ready = 1} 鐨勬鏌ラ」鐩�
+     * 锛堣 {@link #filterNeedDevReady}锛夈��
+     */
+    @Resource
+    private CheckTypeMapper checkTypeMapper;
 
     ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
 
@@ -182,9 +195,41 @@
         return ECG_INNER_ERROR;
     }
 
+    /**
+     * 銆屾湰璇婂鎺掗槦涓紙鏈垎閰嶅伐浣嶏級銆嶇殑鎮h�呭垪琛ㄣ��
+     *
+     * <p>宸ヤ綔鍙板�欒瘖鍒楄〃鎸� {@code room_id + bed_no} 鏌ワ紝鍙湅寰楀埌**宸插垎娴佸埌鏈伐浣�**鐨勬偅鑰咃紱
+     * 鑰�"鎺掗槦涓�(10)"鐨勬偅鑰� {@code bed_no} 涓虹┖锛堝ぇ灞忎細鏄剧ず銆佸伐浣滃彴鐪嬩笉鍒帮級锛�
+     * 杩欓噷鎸�**鏈伐浣嶅紑灞曠殑妫�鏌ラ」鐩�**鎶婁粬浠崟鐙煡鍑烘潵锛屼緵鍖荤敓鎵嬪伐鎷夊叆銆�
+     *
+     * <p>宸ヤ綅涓嶅瓨鍦ㄦ垨娌¢厤妫�鏌ラ」鐩椂杩斿洖绌哄垪琛紙璁拌鍛婏級锛屼笉鎶涘紓甯� 鈥斺�� 鍒楄〃涓虹┖涓嶅奖鍝嶄富娴佺▼銆�
+     */
     @Override
-    public ErrorCode startBedDoctorOn(Long roomId, String bedNo, Long docId, String docName) {
-        Future<ErrorCode> future = singleThreadExecutor.submit(new BedDoctorOnCallable(queueServiceTxFunctions, roomId, bedNo, docId, docName));
+    public List<QueueDO> getUnassignedWaitingPatient(Long roomId, String bedNo) {
+        RoomDO bed = (null == roomId || null == bedNo) ? null : roomMapper.getRoom(roomId, bedNo);
+        if (null == bed || null == bed.getCheckTypes() || 0 == bed.getCheckTypes().length) {
+            log.warn("[getUnassignedWaitingPatient] 宸ヤ綅涓嶅瓨鍦ㄦ垨鏈厤缃鏌ラ」鐩紝杩斿洖绌�. roomId={} bedNo={}",
+                    roomId, bedNo);
+            return new ArrayList<>();
+        }
+        return queueMapper.selectUnassignedWaitingByCheckTypes(
+                QueueStatusEnum.WAITING.getStatus(), bed.getCheckTypes());
+    }
+
+    /**
+     * 鎵嬪伐鎶婃煇浣嶃�屾帓闃熶腑銆嶆偅鑰呮媺鍏ユ湰宸ヤ綅锛堚啋 鍑嗗涓級銆�
+     *
+     * <p>鏉冮檺鐢� Controller 涓婄殑 {@code @RequireBedOwner} 淇濊瘉锛氬彧鏈夋湰宸ヤ綅涓讳汉鑳芥媺銆�
+     * 杩欓噷鍙仛涓氬姟鏍¢獙涓庢潯浠舵洿鏂帮紙骞跺彂瀹夊叏锛歿@code and status = 10}锛夛紝骞跺鐢ㄨ嚜鍔ㄥ垎娴佺殑浜插拰椤归�昏緫銆�
+     */
+    @Override
+    public ErrorCode pullWaitingPatient(Long roomId, String bedNo, Integer queueId) {
+        return queueServiceTxFunctions.pullWaitingPatient(roomId, bedNo, queueId);
+    }
+
+    @Override
+    public ErrorCode startBedDoctorOn(Long roomId, String bedNo, Long docId, String docName, Integer bedId) {
+        Future<ErrorCode> future = singleThreadExecutor.submit(new BedDoctorOnCallable(queueServiceTxFunctions, roomId, bedNo, docId, docName, bedId));
 
         try {
             ErrorCode ret = future.get();
@@ -213,6 +258,27 @@
         }
 
         //System.out.println("startBedDoctorOff ========");
+        return ECG_INNER_ERROR;
+    }
+
+    /**
+     * 銆愭湰娆¢渶姹傘�戠鐞嗗憳寮哄埗娓呯┖宸ヤ綅锛堜笉瑕佹眰鏄湰浜猴級銆�
+     * <p>
+     * 涓� {@link #startBedDoctorOff} 鍏辩敤鍚屼竴涓崟绾跨▼鎵ц鍣紝淇濊瘉鍚屼竴鏃跺埢鍙鐞嗕竴涓伐浣嶆搷浣滐紝
+     * 閬垮厤涓庛�屽彨鍙� / 鍏ュ骇 / 绂诲骇銆嶅苟鍙戞敼鍚屼竴琛屻��
+     */
+    @Override
+    public ErrorCode startBedDoctorOffByAdmin(Long roomId, String bedNo) {
+        Future<ErrorCode> future = singleThreadExecutor.submit(
+                () -> queueServiceTxFunctions.bedDoctorOffByAdmin(roomId, bedNo));
+        try {
+            return future.get();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            log.error("[绠$悊鍛樻竻绌哄伐浣峕 琚腑鏂�", e);
+        } catch (ExecutionException e) {
+            log.error("[绠$悊鍛樻竻绌哄伐浣峕 鎵ц澶辫触", e.getCause() != null ? e.getCause() : e);
+        }
         return ECG_INNER_ERROR;
     }
 
@@ -252,16 +318,81 @@
 
     @Override
     public void startHurryUpOneBed(Long roomId, String bedNo) {
-        singleThreadExecutor.execute(() -> {
-            queueServiceTxFunctions.hurryupOneBed(roomId, bedNo);
-        });
+        // 銆愮己闄蜂慨澶嶃�戝繀椤荤瓑浜嬪姟鎻愪氦鍚庡啀璺戯細瑙� runAfterCommit 鐨勮鏄�
+        runAfterCommit(() -> singleThreadExecutor.execute(() -> {
+            try {
+                queueServiceTxFunctions.hurryupOneBed(roomId, bedNo);
+            } catch (Exception e) {
+                // 鍘熷疄鐜颁笉鎹曡幏锛氬紓甯稿彧鐣欏湪宸ヤ綔绾跨▼閲岋紝鏃ュ織涓�鏉¢兘娌℃湁锛岀幇鍦烘棤浠庢帓鏌�
+                log.error("[hurryupOneBed] 鑷姩琛ヤ汉鎵ц寮傚父. 宸ヤ綅={}/{}锛堜笉褰卞搷涓绘祦绋嬶紝涓嬩竴杞細閲嶈瘯锛�",
+                        roomId, bedNo, e);
+            }
+        }));
+    }
+
+    /**
+     * 鎶娿�岃Е鍙戣嚜鍔ㄥ垎娴併�嶆帹杩熷埌**浜嬪姟鎻愪氦涔嬪悗**鍐嶆墽琛岋紱涓嶅湪浜嬪姟閲屽垯鐩存帴鎵ц銆�
+     *
+     * <p>銆愮己闄蜂慨澶嵚风幇鍦哄弽棣堛�戣繍鍔ㄨ瘯楠岀鍒板悗锛屾偅鑰呬竴鐩村仠鍦ㄥ尰鐢熷伐浣滃彴鐨�
+     * 銆屾湰璇婂鎺掗槦涓紙鏈垎閰嶅伐浣嶏級銆嶏紝蹇呴』鎵嬪伐鐐广�屾媺鍏ャ�嶆墠杩涘�欒瘖鍖恒��
+     *
+     * <p>鍘熷洜锛歿@link #queue} 鏄� {@code @Transactional}锛屾彃鍏ャ�屾帓闃熶腑銆嶈涔嬪悗**绔嬪嵆**鎶�
+     * 鍒嗘祦浠诲姟涓㈢粰 {@code singleThreadExecutor}銆傚伐浣滅嚎绋嬬敤鐨勬槸**鍙︿竴涓暟鎹簱杩炴帴**锛�
+     * READ COMMITTED 涓嬬湅涓嶅埌涓讳簨鍔″皻鏈彁浜ょ殑閭d竴琛� 鈬�
+     * {@code getFirstWaitingByCheckTypes} 杩斿洖 null 鈬� 杩欐鍒嗘祦浠�涔堥兘娌″仛灏遍��鍑猴紱
+     * 浜嬪姟鎻愪氦鍚庡張娌℃湁浠讳綍琛ュ伩 鈬� 鎮h�呮案杩滅暀鍦ㄣ�屾帓闃熶腑銆嶃��
+     *
+     * <p>涓轰粈涔堜綆棰戞鏌ラ」鐩紙杩愬姩璇曢獙銆侀閬撶數鐢熺悊锛夊嚑涔庡繀鐒朵腑鎷涖�侀珮棰戠殑鍗�"鐪嬭捣鏉ユ甯�"锛�
+     * 鎵ц鍣ㄥ钩鏃剁┖闂诧紝浠诲姟鑳�**绔嬪埢**鎵ц锛堝繀鐒舵棭浜庢彁浜わ級锛涢珮棰戦」鐩换鍔′細鎺掗槦锛�
+     * 杞埌鏃朵簨鍔″線寰�宸茬粡鎻愪氦锛屼簬鏄茎骞告垚鍔熴��
+     */
+    private void runAfterCommit(Runnable task) {
+        if (TransactionSynchronizationManager.isSynchronizationActive()) {
+            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                @Override
+                public void afterCommit() {
+                    task.run();
+                }
+            });
+        } else {
+            task.run();
+        }
+    }
+
+    @Override
+    public Map<String, Object> hurryUpNow(Long roomId, String bedNo) {
+        // 鍚屾鎵ц锛氳绔嬪埢杩斿洖"琛ヤ汉鍓嶅悗浜烘暟 + 缁撹"锛屽紓姝ュ氨鐪嬩笉鍒扮粨鏋滀簡
+        return queueServiceTxFunctions.hurryUpNow(roomId, bedNo);
     }
 
     @Override
     public void startHurryUpOneCheckType(Integer checkType) {
-        singleThreadExecutor.execute(() -> {
-            queueServiceTxFunctions.hurryupOneCheckType(checkType);
-        });
+        // 銆愮己闄蜂慨澶嶃�戝繀椤荤瓑浜嬪姟鎻愪氦鍚庡啀璺戯細瑙� runAfterCommit 鐨勮鏄�
+        runAfterCommit(() -> singleThreadExecutor.execute(() -> {
+            try {
+                queueServiceTxFunctions.hurryupOneCheckType(checkType);
+            } catch (Exception e) {
+                log.error("[hurryupOneCheckType] 鑷姩鍒嗘祦鎵ц寮傚父. checkType={}锛堜笉褰卞搷涓绘祦绋嬶紝涓嬩竴杞細閲嶈瘯锛�",
+                        checkType, e);
+            }
+        }));
+    }
+
+    /**
+     * 鍏滃簳锛氬**鏈夊尰鐢熷湪搴�**鐨勫伐浣嶈Е鍙戜竴娆¤嚜鍔ㄨˉ浜猴紙鐢� {@code QueueAutoRefillJob} 鍛ㄦ湡璋冪敤锛夈��
+     *
+     * <p>娉ㄦ剰鐢ㄧ殑鏄� {@code hurryupAllSeatedBeds} 鑰屼笉鏄� {@code hurryupAllBed}锛�
+     * 鍚庤�呬細鎶婃偅鑰呮帹杩�"宸插紑閫氫絾娌″尰鐢�"鐨勫伐浣嶏紝鍛ㄦ湡璺戜細鏀惧ぇ璇ュ壇浣滅敤銆�
+     */
+    @Override
+    public void startHurryUpAll() {
+        runAfterCommit(() -> singleThreadExecutor.execute(() -> {
+            try {
+                queueServiceTxFunctions.hurryupAllSeatedBeds();
+            } catch (Exception e) {
+                log.error("[hurryupAllSeatedBeds] 鍛ㄦ湡琛ヤ汉鎵ц寮傚父锛堜笅涓�杞户缁級", e);
+            }
+        }));
     }
 
     @Override
@@ -318,9 +449,7 @@
     @Override
     public PageResult<QueueDO> getqueuePage(QueuePageReqVO pageReqVO) {
         PageResult<QueueDO> queueDOPageResult = queueMapper.selectPage(pageReqVO);
-        queueDOPageResult.getList().forEach(queueDO -> {
-            queueDO.setTolerance(appointmentMapper.getByApplyNo(queueDO.getApplyNo()).getTolerance());
-        });
+        fillAppointmentInfo(queueDOPageResult.getList());
         return queueDOPageResult;
     }
 
@@ -357,8 +486,8 @@
     }
 
     @Override
-    public List<QueueDO> selectBookSeqNumByAppointIdList(List<Long> appointIdList) {
-        return queueMapper.selectBookSeqNumByAppointIdList(appointIdList);
+    public List<QueueDO> selectQueueByAppointIdList(List<Long> appointIdList) {
+        return queueMapper.selectQueueByAppointIdList(appointIdList);
     }
 
     // 甯歌妫�鏌� 鍙彿
@@ -419,28 +548,105 @@
         // 浠� DB 鎶� [瀹夎涓璢鐨勪汉 璁剧疆涓� [杩囧彿-瀹夎]
         Integer ret = queueMapper.updateBedQueueStatus(roomId, bedNo, QueueStatusEnum.INSTALLING.getStatus(), QueueStatusEnum.PASSED_INSTALL.getStatus());
 
-        startNextPatient(roomId, bedNo);
+        // 銆愭棦鏈夌瑪璇慨澶嶃�戣繖閲屽師鏈皟鐨勬槸 startNextPatient锛堝父瑙勬鏌ュ彇浜猴細鍊欒瘖涓� 鈫� 灏辫瘖涓級锛�
+        // 鑰岃鏈鸿繃鍙峰悗搴斿綋缁х画鍙�**瀹夎闃熷垪**閲岀殑涓嬩竴浣嶏紙宸查鐢�/宸插彫鍥�-瀹夎 鈫� 瀹夎涓級銆�
+        // 鐢变簬瑁呮満宸ヤ綅涓嶅弬涓庡垎娴併�佹病鏈�"鍊欒瘖涓�"鎮h�咃紝鍘熻皟鐢ㄥ疄闄呬笂浠�涔堜篃涓嶄細鍙戠敓锛�
+        // 琛ㄧ幇涓�"瑁呮満杩囧彿鍚庝笉浼氳嚜鍔ㄥ彨涓嬩竴浣�"銆�
+        startNextInstallPatient(roomId, bedNo);
     }
 
     public List<QueueDO> getBedQueueByStatus(Long roomId, String bedNo, List<Integer> statusList) {
         List<QueueDO> queueDOList = queueMapper.getBedQueueByStatus(roomId, bedNo, statusList);
-        if (!CollectionUtils.isEmpty(queueDOList)) {
-            queueDOList.forEach(queueDO -> {
-                queueDO.setTolerance(appointmentMapper.getByApplyNo(queueDO.getApplyNo()).getTolerance());
-            });
-        }
+        fillAppointmentInfo(queueDOList);
         return queueDOList;
+    }
+
+    /**
+     * 浠庨绾﹀崟琛ラ綈 queue 琛ㄤ笂娌℃湁鐨勬偅鑰呬俊鎭��
+     *
+     * <p>queue 琛ㄤ笉瀛樿繖浜涘瓧娈碉紝浣嗗尰鐢熺鍒楄〃鎺ュ彛闇�瑕佸睍绀猴紝鎵�浠ユ煡璇㈠悗鎸� applyNo 鍥炴煡棰勭害鍗曞~鍏咃細
+     * 澶氳�愯嵂銆佹�у埆銆佸嚭鐢熸棩鏈熴�佺櫥璁版椂闂淬�佸紑鍗曞尰甯堛�佸紑鍗曟棩鏈熴��</p>
+     *
+     * <h3>鈿狅笍 鎬ц兘淇锛氱敱 N+1 鏀逛负涓�娆℃壒閲忔煡璇�</h3>
+     * <p><b>鍘熷疄鐜�</b>鍦� {@code forEach} 閲屽姣忎竴琛岃皟鐢�
+     * {@code appointmentMapper.getByApplyNo(applyNo)}锛屽嵆**姣忚涓�娆� SQL**銆�
+     * 鍒楄〃姣忛〉 10 鏉� 鈬� 10 娆℃煡璇紱鑰岃 SQL
+     * 锛坽@code WHERE apply_no = ? AND deleted = 0}锛夊湪淇鍓�**鐢ㄤ笉涓婄储寮�**锛�
+     * 姣忔閮芥槸鍏ㄨ〃鎵弿 appointment锛堝疄娴� 16.6 涓囪锛岀害 549 ms/娆★級锛�
+     * 涓�椤靛氨瑕� 4.5~5.5 绉� 鈥斺�� 杩欐槸銆岄槦鍒楀垪琛ㄦ墦寮�寰堟參銆嶇殑鐩存帴鍘熷洜銆�</p>
+     *
+     * <p><b>鐜板疄鐜�</b>鏀逛负锛氬厛鏀堕泦鏈〉鎵�鏈� applyNo锛堝幓閲嶏級鈫� **涓�娆�**
+     * {@code getByApplyNoList} 鎵归噺鍙栧洖 鈫� 鍐呭瓨閲屾寜 applyNo 寤烘槧灏勫啀鍥炲~銆�
+     * 涓�椤� SQL 浠� 10 娆¢檷鍒� 1 娆°��</p>
+     *
+     * <p>娉細閰嶅宸蹭簬 {@code 26_add_index_appointment_apply_no.sql}
+     * 缁� {@code appointment.apply_no} 鍔犱笂绱㈠紩锛�
+     * 浣嗗嵆渚挎湁绱㈠紩锛孨+1 浠嶆槸 10 娆″線杩旓紝鏁呬袱澶勪竴璧锋敼鎵嶆槸鏈�浼樸��</p>
+     */
+    @Override
+    public void fillAppointmentInfo(List<QueueDO> queueDOList) {
+        if (CollectionUtils.isEmpty(queueDOList)) {
+            return;
+        }
+        // 1. 鏀堕泦鏈闇�瑕佸洖鏌ョ殑鐢宠鍗曞彿锛堣烦杩囩┖鍊硷級銆�
+        //    鐢� LinkedHashSet 鍘婚噸锛氬悓涓�椤甸噷鐞嗚涓� apply_no 鍞竴锛屼絾鍘婚噸鍚� IN 鍒楄〃鏇寸煭銆佹洿瀹夊叏銆�
+        Set<String> applyNoSet = new LinkedHashSet<>();
+        for (QueueDO queueDO : queueDOList) {
+            if (queueDO != null && queueDO.getApplyNo() != null && !queueDO.getApplyNo().isEmpty()) {
+                applyNoSet.add(queueDO.getApplyNo());
+            }
+        }
+        if (applyNoSet.isEmpty()) {
+            return;
+        }
+
+        // 2. 涓�娆℃壒閲忓彇鍥烇紙SQL 鍐呴儴宸插甫 deleted = 0锛夈��
+        //    娉ㄦ剰锛歁ySQL 鐨� IN () 浼氳娉曢敊璇紝鏁呭繀椤讳繚璇佸垪琛ㄩ潪绌� 鈥斺�� 涓婇潰宸插垽绌恒��
+        List<AppointmentDO> appointmentList = appointmentMapper.getByApplyNoList(new ArrayList<>(applyNoSet));
+
+        // 3. 鎸� applyNo 寤烘槧灏勶紱涓埆 applyNo 鏌ヤ笉鍒伴绾﹀崟鏄甯告儏鍐碉紙鍘嗗彶鑴忔暟鎹級锛岃烦杩囧嵆鍙��
+        Map<String, AppointmentDO> appointmentMap = appointmentList.stream()
+                .filter(item -> item != null && item.getApplyNo() != null)
+                .collect(Collectors.toMap(AppointmentDO::getApplyNo, item -> item, (a, b) -> a));
+
+        // 4. 鍐呭瓨鍥炲~锛屼笉鍐嶉�愭潯鏌ュ簱
+        queueDOList.forEach(queueDO -> {
+            if (queueDO == null || queueDO.getApplyNo() == null || queueDO.getApplyNo().isEmpty()) {
+                return;
+            }
+            AppointmentDO appointment = appointmentMap.get(queueDO.getApplyNo());
+            if (null == appointment) {
+                return;
+            }
+            queueDO.setTolerance(appointment.getTolerance());
+            // 闇�姹�2锛氬簥杈规爣璁帮紙HIS zdy.ISCB锛夈�俼ueue 琛ㄥ凡鏈夎鍒楋紝
+            // 浣嗗銆�22_* 鑴氭湰鎵ц鍓嶅氨宸插叆闃熴�嶇殑琛岋紝闈犺繖閲屽洖鏌ヨˉ濉紝淇濊瘉灞忓箷/椤甸潰鑳界湅鍒般��
+            if (queueDO.getIsBedside() == null) {
+                queueDO.setIsBedside(appointment.getIsBedside());
+            }
+            queueDO.setPatGender(appointment.getPatGender());
+            queueDO.setPatBirthday(appointment.getPatBirthday());
+            queueDO.setRegisterDate(appointment.getRegisterDate());
+            queueDO.setDoctor(appointment.getDoctor());
+            queueDO.setDoctorTime(appointment.getDoctorTime());
+            // 闇�姹�1锛氳ˉ骞抽摵鐨勬偅鑰呬俊鎭潵婧愬瓧娈碉紙鐥呭巻鍖�/搴婂彿/鐢佃瘽/鏉ユ簮/灏辫瘖鍗″彿绛夛級
+            queueDO.setPatSrc(appointment.getPatSrc());
+            queueDO.setPatMobile(appointment.getPatMobile());
+            queueDO.setPatPhone(appointment.getPatPhone());
+            queueDO.setPatWardDesc(appointment.getPatWardDesc());
+            queueDO.setPatBedNo(appointment.getPatBedNo());
+            queueDO.setMedicalCard(appointment.getMedicalCard());
+            queueDO.setDoctorAdviceNo(appointment.getDoctorAdviceNo());
+            queueDO.setOutpatientNo(appointment.getOutpatientNo());
+            queueDO.setPatIdentityId(appointment.getPatIdentityId());
+        });
     }
 
     @Override
 
     public List<QueueDO> getRoomQueueByStatus(Long roomId, List<Integer> statusList) {
         List<QueueDO> queueDOList = queueMapper.getRoomQueueByStatus(roomId, statusList);
-        if (!CollectionUtils.isEmpty(queueDOList)) {
-            queueDOList.forEach(queueDO -> {
-                queueDO.setTolerance(appointmentMapper.getByApplyNo(queueDO.getApplyNo()).getTolerance());
-            });
-        }
+        fillAppointmentInfo(queueDOList);
         return queueDOList;
     }
 
@@ -453,18 +659,33 @@
                 patientStatisticVO.setReadyNum(item.getTotalInStatus());
             } else if (QueueStatusEnum.FINISH.getStatus() == item.getStatus()) {
                 patientStatisticVO.setFinishedNum(item.getTotalInStatus());
-            } else if (QueueStatusEnum.PASSED.getStatus() == item.getStatus()) {
-                patientStatisticVO.setPassedNum(item.getTotalInStatus());
+            } else if (QueueStatusEnum.PASSED.getStatus() == item.getStatus()
+                    || QueueStatusEnum.PASSED_WAITING.getStatus() == item.getStatus()) {
+                // 銆愰渶姹�4 鍙e緞缁熶竴銆戣繃鍙� = 宸茶繃鍙�(5) + 宸茶繃鍙�-鎺掗槦(3)銆�
+                // 鍘熷厛鍙畻 5锛岃�屽垪琛ㄤ笌灞忓箷閮藉惈 3锛屽鑷�"杩囧彿"鏁板瓧姣斿疄闄呭皯銆�
+                int cur = patientStatisticVO.getPassedNum() == null ? 0 : patientStatisticVO.getPassedNum();
+                patientStatisticVO.setPassedNum(cur + item.getTotalInStatus());
             }
         });
 
         // 缁熻 璇ュ伐浣嶇被鍨嬬殑銆愭帓闃熶腑銆戜汉鍛樻暟閲�
+        // 銆怮7 纭銆戞澶勫埢鎰忕粺璁�**鍏ㄩ」鐩�**锛堣宸ヤ綅鎵�鍚鏌ョ被鍨嬶級鐨�"鎺掗槦涓�"鎬绘暟锛�
+        // 璇箟涓�"鍏ㄩ櫌杩樻湁澶氬皯浜虹瓑鐫�鍋氳繖绫绘鏌�"锛屼笌"鏈伐浣嶄竴鐪煎彲瑙佺殑鍊欒瘖浜烘暟"浜掕ˉ銆�
+        // 涓斿凡琛� deleted=0 / book_date=浠婃棩锛堣 QueueMapper.checkTypeAndStatusStatistic锛夈��
         RoomDO roomDO = getRoomDO(roomId, bedNo);
         Integer[] checkTypes = roomDO.getCheckTypes();
-        List<Integer> statusList = new ArrayList<>();
-        statusList.add(QueueStatusEnum.WAITING.getStatus());
-        Integer num = queueMapper.checkTypeAndStatusStatistic(checkTypes, statusList);
-        patientStatisticVO.setQueuingNum(num);
+        int queuingNum = 0;
+        // 銆愰槻寰°�慶heckTypes 涓虹┖鏃朵笉鑳芥嫾 `book_check_type in ()`锛圡ySQL 璇硶閿欒锛夈��
+        // 瀹炴祴璇ュ満鏅細璁╃粺璁℃帴鍙� 500锛岃繘鑰屽鑷村尰鐢熺椤堕儴缁熻鏁村潡鎶ラ敊銆�
+        if (checkTypes != null && checkTypes.length > 0) {
+            List<Integer> statusList = new ArrayList<>();
+            statusList.add(QueueStatusEnum.WAITING.getStatus());
+            Integer num = queueMapper.checkTypeAndStatusStatistic(checkTypes, statusList);
+            queuingNum = num == null ? 0 : num;
+        } else {
+            log.warn("[getPatientStatistic][宸ヤ綅鏈厤缃鏌ョ被鍨嬶紝鎺掗槦涓寜 0 璁 roomId={} bedNo={}", roomId, bedNo);
+        }
+        patientStatisticVO.setQueuingNum(queuingNum);
 
         return patientStatisticVO;
     }
@@ -506,8 +727,19 @@
         bedQueueStatisticDOList.forEach(item -> {
             if (QueueStatusEnum.READY.getStatus() == item.getStatus()) {
                 patientStatisticVO.setReadyNum(item.getTotalInStatus());
-            } else if (QueueStatusEnum.PASSED.getStatus() == item.getStatus()) {
-                patientStatisticVO.setPassedNum(item.getTotalInStatus());
+            } else if (QueueStatusEnum.PASSED.getStatus() == item.getStatus()
+                    || QueueStatusEnum.PASSED_WAITING.getStatus() == item.getStatus()) {
+                // 銆愰渶姹�4 鍙e緞缁熶竴銆戣繃鍙� = 宸茶繃鍙�(5) + 宸茶繃鍙�-鎺掗槦(3)銆�
+                //
+                // 涓� getPatientStatistic 淇濇寔鍚屼竴鍙e緞銆傚師瀹炵幇鍙垽 PASSED(5)锛�
+                // 鑰岄鐢ㄧ晫闈㈢殑鍒楄〃/灞忓箷閮藉惈 status=3锛屽鑷淬�岃繃鍙枫�嶆暟瀛楁瘮瀹為檯灏�
+                // 鈥斺�� 杩欐鏄敤鎴峰弽棣堢殑銆岀粺璁′笌瀹為檯涓嶇銆嶃��
+                //
+                // 鍙︼細鍘熷疄鐜扮敤 setPassedNum(item.getTotalInStatus())锛�**瑕嗙洊**鑰岄潪绱姞锛夛紝
+                // 鍥� SQL 鏄� group by status锛宻tatus=3 涓� status=5 鏄袱琛岋紝
+                // 瑕嗙洊浼氬彧淇濈暀鏈�鍚庝竴琛� 鈫� 鏀逛负绱姞銆�
+                int cur = patientStatisticVO.getPassedNum() == null ? 0 : patientStatisticVO.getPassedNum();
+                patientStatisticVO.setPassedNum(cur + item.getTotalInStatus());
             }
         });
 
@@ -527,10 +759,17 @@
         // 缁熻 璇ュ伐浣嶇被鍨嬬殑銆愭帓闃熶腑銆戜汉鍛樻暟閲�
         RoomDO roomDO = getRoomDO(roomId, bedNo);
         Integer[] checkTypes = roomDO.getCheckTypes();
-        List<Integer> statusList = new ArrayList<>();
-        statusList.add(QueueStatusEnum.WAITING.getStatus());
-        Integer num = queueMapper.checkTypeAndStatusStatistic(checkTypes, statusList);
-        patientStatisticVO.setQueuingNum(num);
+        Integer num = 0;
+        // 銆愰槻寰°�慶heckTypes 涓虹┖鏃朵笉鑳芥嫾 `book_check_type in ()`锛圡ySQL 璇硶閿欒锛夛紝
+        // 瀹炴祴璇ュ満鏅細璁╃粺璁℃帴鍙� 500銆佸尰鐢熺椤堕儴缁熻鏁村潡鎶ラ敊銆備笌 getPatientStatistic 淇濇寔涓�鑷淬��
+        if (checkTypes != null && checkTypes.length > 0) {
+            List<Integer> statusList = new ArrayList<>();
+            statusList.add(QueueStatusEnum.WAITING.getStatus());
+            num = queueMapper.checkTypeAndStatusStatistic(checkTypes, statusList);
+        } else {
+            log.warn("[getBedDevReadyStatistic][宸ヤ綅鏈厤缃鏌ョ被鍨嬶紝鎺掗槦涓寜 0 璁 roomId={} bedNo={}", roomId, bedNo);
+        }
+        patientStatisticVO.setQueuingNum(num == null ? 0 : num);
 
         return patientStatisticVO;
     }
@@ -548,6 +787,19 @@
 
     public void closeBiz() {
         queueServiceTxFunctions.setOpeningFlag(0);
+
+        // 銆愭湰娆¢渶姹傘�戦棴璇婃椂娓呯┖褰撶彮宸ヤ綅锛坉oc_id / doc_name 缃┖锛岀姸鎬佹敼鍥炵┖闂诧級銆�
+        //
+        // 鑳屾櫙锛氬伐浣嶄笉鍐嶅洜銆岀┖闂茶秴鏃� / 浠ょ墝澶辨晥 / 鍒锋柊椤甸潰銆嶈閲婃斁锛堥伩鍏嶅尰鐢熺寮�涓�浼氬効灏变涪宸ヤ綅锛夛紝
+        // 鍥犳闇�瑕佷竴涓厹搴� 鈥斺�� 姣忓ぉ闂瘖鏃剁粺涓�娓呯┖锛岄槻姝㈠尰鐢熶笅鐝繕绂诲骇瀵艰嚧宸ヤ綅闀挎湡琚崰鐢ㄣ��
+        // 鍏堟竻搴擄紝鍐嶇敱涓嬮潰鐨� startBedReload() 鎸夊簱閲嶆柊瑁呰浇鍐呭瓨锛屼繚璇佷簩鑰呬竴鑷淬��
+        try {
+            queueServiceTxFunctions.closeBizClearBeds();
+        } catch (Exception e) {
+            // 娓呯┖澶辫触涓嶈兘闃绘柇闂瘖娴佺▼鏈韩
+            log.error("[闂瘖] 娓呯┖褰撶彮宸ヤ綅澶辫触锛堜笉褰卞搷闂瘖锛�", e);
+        }
+
         startBedReload();
     }
 
@@ -559,7 +811,93 @@
         // 浼氬湪 HurryUpOnBed 閲岄潰澶勭悊 妫�鏌ラ」鐩�.浜插拰鎬�
 
         startHurryUpOneBed(roomId, bedNo);
+
+        // 銆愯瘖鏂�戣ˉ浜哄惊鐜湁涓夐亾闂ㄩ椄锛堟湭寮�璇� / 宸插仠姝㈠�欒瘖 / 鍊欒瘖鍖哄凡婊★級锛�
+        // 浠讳竴鏉℃垚绔嬫椂鎮h�呬細**鍋滃湪銆屽凡鍙洖(15)銆嶄笉杩涘�欒瘖鍖�**銆�
+        // 鐜板湪 nextPatient 鏀寔鐩存帴浠庛�屽凡鍙洖銆嶅彨鍙凤紙2026-10-29 淇锛夛紝杩欓噷鍙ˉ涓�鏉℃棩蹇楁柟渚跨幇鍦烘帓鏌ャ��
+        if (null != updateNum && updateNum > 0) {
+            try {
+                QueueDO stillRecalled = queueMapper.getBedQueueItemByPatAndStatus(
+                        roomId, bedNo, patId, checkType, QueueStatusEnum.RECALLED.getStatus());
+                if (null != stillRecalled) {
+                    log.warn("[recallPatient] 宸茬疆涓恒�屽凡鍙洖銆嶏紝浣嗘湭杩涘叆鍊欒瘖鍖�"
+                                    + "锛堝彲鑳藉師鍥狅細鏈紑璇� / 宸插仠姝㈠�欒瘖 / 鍊欒瘖鍖哄凡婊★級锛屽彨鍙锋椂灏嗙洿鎺ヤ粠銆屽凡鍙洖銆嶅彇浜�. "
+                                    + "宸ヤ綅={}/{} patId={} seqNum={}",
+                            roomId, bedNo, patId, stillRecalled.getSeqNum());
+                }
+            } catch (Exception e) {
+                log.warn("[recallPatient] 妫�鏌ャ�屽凡鍙洖銆嶆槸鍚﹁繘鍏ュ�欒瘖鍖烘椂寮傚父锛堜笉褰卞搷鍙洖缁撴灉锛�. 宸ヤ綅={}/{} patId={}",
+                        roomId, bedNo, patId, e);
+            }
+        }
         return updateNum;
+    }
+
+    // ==================== 闇�姹�2锛氭挙閿�銆屽彨鍙� / 妫�鏌ュ畬鎴愩�� ====================
+
+    /**
+     * 鎾ら攢銆屾鏌ュ畬鎴愩�嶏細鎶婃湰宸ヤ綅浠婃棩鐨勬寚瀹氭偅鑰呬粠 宸插氨璇�(40) 閫�鍥� **鍊欒瘖涓�(20)**銆�
+     * <p>
+     * <b>Q9 纭</b>锛氭挙閿�鍚庡洖鍒�**鍊欒瘖鍖�**锛堣�岄潪"灏辫瘖涓�"锛夛紝渚夸簬鍖荤敓閲嶆柊鍙彿銆�
+     * <p>
+     * 鏀跺熬蹇呴』璋� {@link #startHurryUpOneBed}锛氬畠浼氶噸鏂拌绠楄宸ヤ綅鐨�
+     * {@code readyPatNum} 骞跺埛鏂板垎娴侀槦鍒椾紭鍏堢骇銆傝嫢涓嶅悓姝ュ唴瀛樿鏁帮紝
+     * {@code hurryupOneCheckType} 浼氭姏鍑� {@code exceed max queue number}銆�
+     *
+     * @return 鍙楀奖鍝嶈鏁帮紙0 琛ㄧず娌℃壘鍒拌鎮h�呬粖鏃ョ殑宸插畬鎴愯褰曪級
+     */
+    @Override
+    public Integer undoFinishPatient(Long roomId, String bedNo, String patId, Integer checkType) {
+        Integer updateNum = queueMapper.undoFinishPatient(roomId, bedNo, patId, checkType,
+                QueueStatusEnum.FINISH.getStatus(), QueueStatusEnum.READY.getStatus());
+        if (null != updateNum && updateNum > 0) {
+            startHurryUpOneBed(roomId, bedNo);
+        }
+        return updateNum;
+    }
+
+    /**
+     * 鎾ら攢銆岃鐐瑰彨鍙枫�嶏細鎶婃湰宸ヤ綅褰撳墠 灏辫瘖涓�(30) 鐨勬偅鑰呴��鍥� **鍊欒瘖涓�(20)**銆�
+     *
+     * @return 鍙楀奖鍝嶈鏁帮紙0 琛ㄧず褰撳墠娌℃湁灏辫瘖涓殑鎮h�咃級
+     */
+    @Override
+    public Integer undoCallPatient(Long roomId, String bedNo) {
+        Integer updateNum = queueMapper.undoCallPatient(roomId, bedNo,
+                QueueStatusEnum.ONSTAGE.getStatus(), QueueStatusEnum.READY.getStatus());
+        if (null != updateNum && updateNum > 0) {
+            startHurryUpOneBed(roomId, bedNo);
+        }
+        return updateNum;
+    }
+
+    @Override
+    public QueueDO getBedLastFinishedQueueItem(Long roomId, String bedNo) {
+        return queueMapper.getBedLastFinishedQueueItem(roomId, bedNo, QueueStatusEnum.FINISH.getStatus());
+    }
+
+    // ==================== 闇�姹�3锛氬仠姝㈠�欒瘖寮�鍏� ====================
+
+    @Override
+    public ErrorCode setStopReady(Long roomId, String bedNo, boolean stop) {
+        // 璧板崟绾跨▼鎵ц鍣紝涓� bedDoctorPause/Resume 淇濇寔涓�鑷寸殑涓茶鍖栧鐞嗭紝
+        // 閬垮厤涓庡垎娴侀槦鍒楃殑骞跺彂淇敼鍐茬獊銆�
+        Future<ErrorCode> future = singleThreadExecutor.submit(
+                () -> queueServiceTxFunctions.setStopReady(roomId, bedNo, stop));
+        try {
+            return future.get();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            log.error("[setStopReady] 琚腑鏂� roomId={} bedNo={}", roomId, bedNo, e);
+        } catch (ExecutionException e) {
+            log.error("[setStopReady] 鎵ц寮傚父 roomId={} bedNo={}", roomId, bedNo, e);
+        }
+        return ECG_INNER_ERROR;
+    }
+
+    @Override
+    public Boolean getStopReady(Long roomId, String bedNo) {
+        return queueServiceTxFunctions.getStopReady(roomId, bedNo);
     }
 
     @Override
@@ -614,10 +952,14 @@
         queueStatusList.add(QueueStatusEnum.READY.getStatus());
         queueStatusList.add(QueueStatusEnum.ONSTAGE.getStatus());
         queueStatusList.add(QueueStatusEnum.PASSED.getStatus());
+        // 銆愰渶姹�4 鍙e緞缁熶竴銆戣ˉ涓� PASSED_WAITING(3)銆屽凡杩囧彿-鎺掗槦銆嶃��
+        // 鍘熷厛鍒楄〃鍙惈 5锛岃�屽ぇ灞�/璇婇棿灞忔煡璇㈠惈 3锛屽鑷村悓涓�鎮h�呭湪涓嶅悓鐣岄潰鍑虹幇涓庡惁涓嶄竴鑷达紱
+        // 缁熻渚т篃灏� 3 璁″叆"杩囧彿"锛堣 getPatientStatistic / getBedDevReadyStatistic锛夈��
+        queueStatusList.add(QueueStatusEnum.PASSED_WAITING.getStatus());
         queueStatusList.add(QueueStatusEnum.AFFINITY.getStatus());
         List<QueueDO> queueDOList = getBedQueueByStatus(roomId, bedNo, queueStatusList);
 
-        //鎶� [浜插拰鐨刔 鎸埌涓婚」鍚庨潰
+        //鎶� [浜插拰鐨刔 鎸埌涓婚」鍚庨潰锛堝悓鎺掗槦鍙� + 鍚屾偅鑰呮墠绠椾竴缁勶紝瑙� Utils#insertAffinityItemsAfterMain锛�
         List<QueueDO> affinityWaitingList = new ArrayList<>();
         ListIterator<QueueDO> iterator = queueDOList.listIterator();
         while (iterator.hasNext()) {
@@ -627,14 +969,7 @@
                 affinityWaitingList.add(item);
             }
         }
-        affinityWaitingList.forEach(affinityWaitingItem -> {
-            for (int i = queueDOList.size() - 1; i >= 0; i--) {
-                if (affinityWaitingItem.getSeqNum() == queueDOList.get(i).getSeqNum()) {
-                    queueDOList.add(i + 1, affinityWaitingItem);
-                    break;
-                }
-            }
-        });
+        Utils.insertAffinityItemsAfterMain(queueDOList, affinityWaitingList);
 
         return queueDOList;
     }
@@ -659,9 +994,31 @@
         queueStatusList.add(QueueStatusEnum.INSTALLING.getStatus());
         queueDOList.addAll(0, getBedQueueByStatus(roomId, bedNo, queueStatusList)); // 褰撳墠宸ヤ綅鐨�
 
-        //鎶� [浜插拰鐨刔 鎸埌涓婚」鍚庨潰
+        // ======================================================================
+        // 銆愪慨澶嶃�戝彧淇濈暀銆岄渶瑕佽澶囬鐢ㄣ�嶇殑妫�鏌ラ」鐩��
+        //
+        // 鑳屾櫙锛氫笂闈袱澶勬煡璇㈢殑鏉′欢鏄� `room_id = ? AND status IN (...)`
+        // 锛坓etRoomQueueByStatus 鐢氳嚦**涓嶅惈 bed_no**锛夛紝**瀹屽叏涓嶇湅 book_check_type**銆�
+        // 鑰岃嚜鍔ㄥ垎娴侊紙QueueMapper#getFirstWaitingByCheckTypes + preemptWaitingPatientById锛夋槸**鎸夊伐浣� checkTypes 杩囨护**鐨勶紝
+        // 鎵�浠ュ彧鏈�"浜哄伐鎶婃偅鑰呮媺杩涙潵"杩欐潯璺緞浼氭紡 鈥斺�� 琛ㄧ幇涓�
+        // 銆岃澶囬鐢ㄣ�嶉〉閿欒鍑虹幇甯歌蹇冪數鍥�(100)銆佸钩鏉胯繍鍔ㄥ績鐢�(400)绛�**涓嶉渶棰嗙敤璁惧**鐨勬偅鑰呫��
+        //
+        // 鍒ゅ畾渚濇嵁鐢ㄩ厤缃� `check_type.need_dev_ready`锛�
+        //   1 = 闇�瑕佽澶囬鐢紙濡� 鍔ㄦ�佸績鐢� 200銆佸姩鎬佽鍘� 300锛�
+        //   0 = 涓嶉渶瑕侊紙甯歌蹇冪數鍥俱�佸钩鏉胯繍鍔ㄥ績鐢� 鈥︼級
+        //
+        // 鏀惧湪鏈嶅姟灞傝�屼笉鏄敼 SQL锛氫竴娆℃煡璇㈠緱鍒伴泦鍚堝悗鍦ㄥ唴瀛樿繃婊わ紝閫昏緫闆嗕腑銆佹槗璇伙紝
+        // 涓斾笉闇�瑕佷负澶氭暟鎹簮/鍔ㄦ�佽〃鍚嶉澶栬皟鏁� SQL銆傛湰璇婂寰呭畨瑁呮偅鑰呴噺绾у緢灏忥紙鍑犲崄琛岋級銆�
+        // ======================================================================
+        queueDOList = filterNeedDevReady(queueDOList);
+
+        // 娉ㄦ剰锛氫笅闈㈢敤 lambda锛屾崟鑾风殑鍙橀噺蹇呴』鏄� effectively final锛�
+        // 鏁呰繖閲屽彟璧蜂竴涓� final 鍙橀噺锛岃�屼笉鏄鐢ㄤ笂闈㈢殑 queueDOList锛堝畠宸茶閲嶆柊璧嬪�硷級銆�
+        final List<QueueDO> installQueueList = queueDOList;
+
+        //鎶� [浜插拰鐨刔 鎸埌涓婚」鍚庨潰锛堝悓鎺掗槦鍙� + 鍚屾偅鑰呮墠绠椾竴缁勶紝瑙� Utils#insertAffinityItemsAfterMain锛�
         List<QueueDO> affinityReceivedList = new ArrayList<>();
-        ListIterator<QueueDO> iterator = queueDOList.listIterator();
+        ListIterator<QueueDO> iterator = installQueueList.listIterator();
         while (iterator.hasNext()) {
             QueueDO item = iterator.next();
             if (item.getStatus() == QueueStatusEnum.AFFINITY_INSTALL.getStatus()) {
@@ -669,16 +1026,46 @@
                 affinityReceivedList.add(item);
             }
         }
-        affinityReceivedList.forEach(affinityReceivedItem -> {
-            for (int i = queueDOList.size() - 1; i >= 0; i--) {
-                if (affinityReceivedItem.getSeqNum() == queueDOList.get(i).getSeqNum()) {
-                    queueDOList.add(i + 1, affinityReceivedItem);
-                    break;
-                }
+        Utils.insertAffinityItemsAfterMain(installQueueList, affinityReceivedList);
+
+        return installQueueList;
+    }
+
+    /**
+     * 鍙繚鐣欍�岄渶瑕佽澶囬鐢ㄣ�嶏紙{@code check_type.need_dev_ready = 1}锛夌殑妫�鏌ラ」鐩殑鎮h�呫��
+     *
+     * <p>鐢ㄤ簬銆岃澶囬鐢� / 瑁呮満銆嶅彇鏁帮細杩欎簺宸ヤ綅鍙簲澶勭悊闇�瑕侀鐢ㄨ澶囩殑妫�鏌ラ」鐩紝
+     * 鍚﹀垯浼氬嚭鐜板父瑙勫績鐢靛浘绛夋偅鑰呮贩鍏ヨ澶囨祦绋嬨��
+     *
+     * <p>閰嶇疆寮傚父锛堟煡涓嶅埌妫�鏌ラ」鐩級鏃�**杩斿洖鍘熷垪琛�**锛屽畞鍙鏄剧ず涔熶笉瑕佹妸鎮h��"钘忚捣鏉�"銆�
+     */
+    private List<QueueDO> filterNeedDevReady(List<QueueDO> queueDOList) {
+        if (null == queueDOList || queueDOList.isEmpty()) {
+            return queueDOList;
+        }
+        List<CheckTypeDO> needDevList = checkTypeMapper.selectList(
+                new LambdaQueryWrapperX<CheckTypeDO>().eq(CheckTypeDO::getNeedDevReady, 1));
+        if (null == needDevList || needDevList.isEmpty()) {
+            log.warn("[filterNeedDevReady] 鏈厤缃换浣昜闇�瑕佽澶囬鐢╙鐨勬鏌ラ」鐩紝璺宠繃杩囨护浠ュ厤鎮h�呭叏閮ㄤ笉鍙");
+            return queueDOList;
+        }
+        Set<Integer> needDevCheckTypes = new HashSet<>();
+        needDevList.forEach(ct -> {
+            if (null != ct.getValue()) {
+                needDevCheckTypes.add(ct.getValue());
             }
         });
 
-        return queueDOList;
+        List<QueueDO> filtered = new ArrayList<>();
+        for (QueueDO item : queueDOList) {
+            if (needDevCheckTypes.contains(item.getBookCheckType())) {
+                filtered.add(item);
+            } else {
+                log.info("[filterNeedDevReady] 杩囨护鎺変笉闇�瑕佽澶囬鐢ㄧ殑鎮h��. patId={} 妫�鏌ラ」鐩�={} 鐘舵��={}",
+                        item.getPatId(), item.getBookCheckType(), item.getStatus());
+            }
+        }
+        return filtered;
     }
 
     private RoomDO getRoomDO(Long roomId, String bedNo) {

--
Gitblit v1.9.3