From fce96ef468291fb9a0e6a4d34ab371315e9485d4 Mon Sep 17 00:00:00 2001
From: yxh <172933527@qq.com>
Date: 星期六, 03 十月 2026 00:59:44 +0800
Subject: [PATCH] ai优化

---
 jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/mysql/queuesequence/QueueSequenceMapper.java |  133 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 132 insertions(+), 1 deletions(-)

diff --git a/jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/mysql/queuesequence/QueueSequenceMapper.java b/jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/mysql/queuesequence/QueueSequenceMapper.java
index 1485220..9ccf2a5 100644
--- a/jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/mysql/queuesequence/QueueSequenceMapper.java
+++ b/jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/mysql/queuesequence/QueueSequenceMapper.java
@@ -6,6 +6,8 @@
 import cn.lihu.jh.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.lihu.jh.framework.mybatis.core.mapper.BaseMapperX;
 import cn.lihu.jh.module.ecg.dal.dataobject.queuesequence.QueueSequenceDO;
+import cn.lihu.jh.module.ecg.dal.dataobject.queuesequence.SeqCounterDO;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import org.apache.ibatis.annotations.*;
 import cn.lihu.jh.module.ecg.controller.admin.queuesequence.vo.*;
 
@@ -26,7 +28,10 @@
                 .eqIfPresent(QueueSequenceDO::getQueueFull, reqVO.getQueueFull())
                 .eqIfPresent(QueueSequenceDO::getQueueVipFull, reqVO.getQueueVipFull())
                 .betweenIfPresent(QueueSequenceDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(QueueSequenceDO::getId));
+                // 銆愰绾︽椂娈电淮鎶ょ晫闈€�戞寜銆屾鏌ョ被鍨� 鈫� 鏃舵銆嶅崌搴忔帓鍒楋紝
+                // 渚夸簬鍦ㄥ悓涓�椤圭洰涓嬮『搴忔煡鐪�/缂栬緫鍚勬椂娈碉紙鍘熷疄鐜版寜 id 鍊掑簭锛岀淮鎶ゆ椂闅句互闃呰锛�
+                .orderByAsc(QueueSequenceDO::getCheckType)
+                .orderByAsc(QueueSequenceDO::getTimeSlot));
     }
 
     @Select(" select * from lihu.queue_sequence where check_type=#{checkType}; ")
@@ -52,4 +57,130 @@
 
     @Update("update lihu.queue_sequence set queue_vip_no = queue_vip_no + 1 where check_type=#{checkType} and time_slot=#{timeslot} and queue_vip_no=#{curQueueVipNo} and queue_vip_no < queue_vip_full; ")
     Integer updateGivenCheckTypeTimeslotVipSeqNo(@Param("checkType") Integer checkType, @Param("timeslot") Integer timeslot, @Param("curQueueVipNo") Integer curQueueVipNo);
+
+    @Update("UPDATE lihu.queue_sequence SET queue_no=queue_set,queue_vip_no=queue_vip_set WHERE deleted=0; ")
+    Integer initNumber();
+
+    /**
+     * 銆愪慨澶嶃�屾椂娈典笉鍏�/宸叉弧瀵艰嚧娌℃硶绛惧埌銆嶃�戝垽鏂寚瀹� (妫�鏌ョ被鍨�, 鏃舵) 鏄惁**杩樻湁鍙彇鍙�**銆�
+     * <p>
+     * 娉ㄦ剰锛氫笌 {@link #selectQueueNoForUpdate} 涓嶅悓锛屾湰鏂规硶**涓嶅姞 for update**銆�
+     * 涔熶笉杩斿洖鍏蜂綋鍙峰�� 鈥斺�� 瀹冨彧鐢ㄤ簬銆屽悜鍚庡鎵句竴涓彲鐢ㄦ椂娈点�嶆椂鐨勬帰娴嬶紝涓嶅弬涓庡苟鍙戝彇鍙凤紝
+     * 鐪熸鍙栧彿浠嶇敱 {@code selectQueueNoForUpdate} 鍦ㄤ簨鍔″唴瀹屾垚銆�
+     *
+     * @param includeVip true 鏃跺悓鏃惰姹� VIP 鍙蜂篃鏈変綑閲忥紙VIP 鎮h�呯敤锛�
+     * @return 1 = 鏈変綑閲忥紱0 = 璇ユ椂娈典笉瀛樺湪鎴栧凡婊�
+     */
+    @Select("select count(1) from lihu.queue_sequence "
+          + " where check_type = #{checkType} and time_slot = #{timeslot} "
+          + "   and queue_no < queue_full "
+          + "   and (#{includeVip} = 0 or queue_vip_no < queue_vip_full)")
+    Integer countAvailableTimeslot(@Param("checkType") Integer checkType,
+                                   @Param("timeslot") Integer timeslot,
+                                   @Param("includeVip") Integer includeVip);
+
+    // =========================================================================
+    // 銆愰渶姹傦細鎺掗槦搴忓彿瑙勫垯 = 绛惧埌搴忓彿銆戣鏁板櫒锛坰eq_counter 琛級
+    //
+    // 璁捐瑕佺偣锛堜袱娆″疄娴嬭俯鍧戝悗纭畾锛屽嬁鏀瑰洖锛夛細
+    //   鈶� 鏅�氬彿涓庨鐣欏彿鐢�**涓や釜鐙珛璁℃暟鍣�** 鈥斺�� 鍗曚釜璁℃暟鍣�"杩愮畻鍚庤烦杩�"蹇呯劧閲嶅彿锛�
+    //      鏅�氭偅鑰� candidate=10 鈫� 璺宠繃棰勭暀寰� 11锛涗笅涓�涓� candidate=11 鈫� 涔熷緱 11銆�
+    //   鈶� 鎺ㄨ繘鐢ㄥ崟鏉� INSERT..ON DUPLICATE KEY UPDATE锛堝師瀛愶級锛�
+    //      璇诲洖蹇呴』涓庢帹杩涘浜�**鍚屼竴浜嬪姟**锛屽惁鍒� REPEATABLE READ 浼氳鍒版棫蹇収銆�
+    //      瀹炴祴锛歛utoCommit=true 鏃� 160 娆″彇鍙蜂粎 75 涓敮涓�鍊硷紱鍖呬簨鍔″悗 160/160銆�
+    // =========================================================================
+
+    /**
+     * 鍘熷瓙鎺ㄨ繘銆愭櫘閫氬彿銆戣鏁板櫒锛屽苟杩斿洖鍒嗛厤鍒扮殑鏅�氬彿銆�
+     *
+     * <h4>璁℃暟鍣ㄨ涔夛紙鍏抽敭锛屽嬁鏀癸級</h4>
+     * {@code normal_next} 瀛樼殑鏄�**涓婁竴娆″凡鍒嗛厤鍑哄幓鐨勬櫘閫氬彿**锛堥娆′负 0锛夈��
+     * 鏈鍒嗛厤 {@code = normal_next + 1}锛涜嫢璇ュ�兼伆鏄鐣欏彿锛�10 鐨勫�嶆暟锛夛紝
+     * 鍒欐湰娆″垎閰嶅疄闄呬笂瑕佽烦鍒� {@code +2}锛屽苟鎶婅鏁板櫒涓�骞舵帹杩涘埌 {@code +2}銆�
+     *
+     * <pre>
+     *   normal_next: 0 鈫� 鍒嗛厤1 鈫� 1 鈫� 鍒嗛厤2 鈫� 鈥� 鈫� 9 鈫� 鍒嗛厤11(璺宠繃10) 鈫� 11 鈫� 鍒嗛厤12 鈫� 鈥�
+     *                                            鈫� 璁℃暟鍣� +2锛屽洜姝や笉浼氬湪涓嬩竴娆″啀浜у嚭 11
+     * </pre>
+     *
+     * <h4>涓轰粈涔堜笉鑳藉彧 +1</h4>
+     * 鑻ヨ鏁板櫒鍙� +1锛歿@code normal_next=10} 鏃跺垎閰� {@code nextNormalSeq(11)=11}锛�
+     * 鑰� {@code normal_next=11} 鏃跺張鍒嗛厤 11 鈥斺�� **鍚屼竴涓彿鍙戜袱娆�**銆�
+     * 鍗曞厓娴嬭瘯 {@code SeqRuleEnumTest#testNextNormalSeq_shouldSkipMultiplesOfTen} 鏇炬崟鑾锋闂銆�
+     * <p>
+     * 鏈� SQL 涓殑 {@code IF} 姝f槸"璺宠繃棰勭暀鍙锋椂棰濆 +1"锛岀瓑浠蜂簬 Java 鐨�
+     * {@code nextNormalSeq(normal_next + 1)}锛屼笖**鍦ㄤ竴鏉¤鍙ュ唴鍘熷瓙瀹屾垚**銆�
+     *
+     * @return 鏈鍒嗛厤鍒扮殑鏅�氬彿
+     */
+    // ==========================================================================
+    // 鈿狅笍 蹇呴』鍔� @InterceptorIgnore(dataPermission = "true")锛屽惁鍒欍�愰绾︾‘璁ょ洿鎺� 500銆�
+    //
+    // 瀹炴祴鏁呴殰锛�2026-10-01 绾夸笂鏃ュ織锛夛細
+    //   org.mybatis.spring.MyBatisSystemException: ... UnsupportedOperationException
+    //     at JsqlParserSupport.processInsert(JsqlParserSupport.java:107)
+    //     at DataPermissionInterceptor.beforePrepare(DataPermissionInterceptor.java:86)
+    //   ### The error may involve QueueSequenceMapper.advanceNormalSeq
+    //   锛堣皟鐢ㄩ摼 appointment/confirm 鈫� distributeSeqNoByRule 鈫� nextCheckInSeqNo 鈫� advanceNormalSeq锛�
+    //
+    // 鍘熷洜锛歁yBatis-Plus 鐨� DataPermissionInterceptor 浼氱敤 JSqlParser 瑙f瀽姣忔潯 SQL锛�
+    //   鑰� JSqlParser 鐨� processInsert **涓嶆敮鎸� MySQL 鐨� `INSERT ... ON DUPLICATE KEY UPDATE`**
+    //   璇硶锛岀洿鎺ユ姏 UnsupportedOperationException锛涜寮傚父绌块�忓埌涓氬姟灞傦紝瀵艰嚧绛惧埌澶辫触銆�
+    //   鈥斺�� 杩欐槸銆屾鏋舵嫤鎴櫒銆嶄笌銆孧ySQL 涓撴湁璇硶銆嶇殑鍐茬獊锛屼笌 SQL 鏈韩鏄惁姝g‘鏃犲叧銆�
+    //
+    // 涓轰粈涔堝彲浠ャ�佷篃搴旇蹇界暐鏁版嵁鏉冮檺锛�
+    //   1) seq_counter 琛�**鏃㈡病鏈� dept_id 涔熸病鏈� user_id**锛屾暟鎹潈闄愯鍒欏瀹冩湰灏辨棤鎰忎箟锛�
+    //   2) 鏈鍙ユ槸绾补鐨勫師瀛愯鏁板櫒鎺ㄨ繘锛屼笉娑夊強浠讳綍闇�瑕佹寜閮ㄩ棬/鐢ㄦ埛闅旂鐨勬暟鎹��
+    // ==========================================================================
+    @InterceptorIgnore(dataPermission = "true")
+    @Update("INSERT INTO lihu.seq_counter (check_type, seq_date, normal_next, reserved_next) "
+          + "VALUES (#{checkType}, #{seqDate}, 1, 10) "
+          + "ON DUPLICATE KEY UPDATE normal_next = normal_next + 1 "
+          + "  + IF((normal_next + 1) % 10 = 0, 1, 0)")
+    int advanceNormalSeq(@Param("checkType") Integer checkType,
+                         @Param("seqDate") java.time.LocalDate seqDate);
+
+    /**
+     * 鍘熷瓙鎺ㄨ繘銆愰鐣欏彿銆戣鏁板櫒锛屽苟杩斿洖鍒嗛厤鍒扮殑棰勭暀鍙凤紙鍔犳�ユ偅鑰呯敤锛夈��
+     * <p>
+     * 棰勭暀鍙峰簭鍒楋細10銆�20銆�30鈥︼紙鍥哄畾涓� 10 鐨勫�嶆暟锛夈��
+     * <p>
+     * 鍚屾牱闇�瑕� {@code @InterceptorIgnore(dataPermission = "true")}锛屽師鍥犺
+     * {@link #advanceNormalSeq} 涓婃柟鐨勮缁嗚鏄庯紙JSqlParser 涓嶆敮鎸佹湰璇硶锛夈��
+     *
+     * @return 鏈鍒嗛厤鍒扮殑棰勭暀鍙�
+     */
+    @InterceptorIgnore(dataPermission = "true")
+    @Update("INSERT INTO lihu.seq_counter (check_type, seq_date, normal_next, reserved_next) "
+          + "VALUES (#{checkType}, #{seqDate}, 1, 10) "
+          + "ON DUPLICATE KEY UPDATE reserved_next = reserved_next + 10")
+    int advanceReservedSeq(@Param("checkType") Integer checkType,
+                           @Param("seqDate") java.time.LocalDate seqDate);
+
+    /**
+     * 璇诲彇涓や釜璁℃暟鍣ㄧ殑褰撳墠鍊硷紙鍗虫湰娆¤鍒嗛厤鐨勫彿锛夈��
+     *
+     * <h4>鈿狅笍 蹇呴』涓� advance* 澶勪簬銆愬悓涓�浜嬪姟銆戝唴</h4>
+     * MySQL 榛樿 REPEATABLE READ锛氳嫢 SELECT 鍦ㄧ嫭绔嬩簨鍔′腑锛屼細璇诲埌浜嬪姟寮�濮嬫椂鐨勫揩鐓ф棫鍊硷紝
+     * 浠庤�屾妸宸茶鍒汉鐢ㄦ帀鐨勫彿閲嶅鍙戝嚭鍘汇��
+     * <p>
+     * 瀹炴祴瀵规瘮锛�8 绾跨▼ 脳 20 娆� = 160 娆″彇鍙凤級锛�
+     * <table border="1">
+     *   <tr><th>鏂瑰紡</th><th>鍞竴鍊�</th><th>缁撹</th></tr>
+     *   <tr><td>autoCommit=true锛堟帹杩涗笌璇诲洖鍚勮嚜鐙珛浜嬪姟锛�</td><td>75 / 160</td><td>馃敶 澶ч噺閲嶅彿</td></tr>
+     *   <tr><td>鏄惧紡浜嬪姟锛圔EGIN 鈫� 鎺ㄨ繘 鈫� 璇诲洖 鈫� COMMIT锛�</td><td><b>160 / 160</b></td><td>鉁� 鍙峰�� 1~160 杩炵画鏃犻噸</td></tr>
+     * </table>
+     * 璋冪敤鏂� {@code QueueSequenceServiceImpl#distributeSeqNoByRule} 宸叉爣娉� {@code @Transactional}锛�
+     * 杩欐槸**蹇呴』淇濇寔**鐨勫墠鎻愶細璇峰嬁鎶婃湰鏂规硶鎸埌鏃犱簨鍔$殑涓婁笅鏂囦腑鍗曠嫭璋冪敤銆�
+     *
+     * @return {@code [0]=normal_next, [1]=reserved_next}
+     */
+    @Select("SELECT normal_next, reserved_next FROM lihu.seq_counter "
+          + " WHERE check_type = #{checkType} AND seq_date = #{seqDate}")
+    @Results({
+        @Result(property = "normalNext", column = "normal_next"),
+        @Result(property = "reservedNext", column = "reserved_next")
+    })
+    SeqCounterDO getSeqCounter(@Param("checkType") Integer checkType,
+                               @Param("seqDate") java.time.LocalDate seqDate);
 }

--
Gitblit v1.9.3