From c24d16a37523a49080392610357872ce580cbc38 Mon Sep 17 00:00:00 2001
From: liusheng <337615773@qq.com>
Date: 星期一, 26 十月 2026 14:03:33 +0800
Subject: [PATCH] 代码提交

---
 ruoyi-phone/src/main/java/com/ruoyi/phone/api/PhoneFacade.java                                             |    4 
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/SatisfactionSubtaskServiceImpl.java   |   71 
 ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtask.java                                         |   48 
 smartor/src/main/java/com/smartor/service/impl/ServiceSLTDHealthcareRecordServiceImpl.java                 |    5 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchivetag.java                          |   89 +
 ruoyi-phone/src/main/java/com/ruoyi/phone/service/impl/PhoneServiceImpl.java                               |   13 
 ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java                                     |   17 
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/controller/SltdSatisfactionController.java         |   31 
 smartor/src/main/java/com/smartor/domain/ServiceSubtaskExportVO.java                                       |   48 
 ruoyi-task/src/main/java/com/ruoyi/task/domain/entity/ServiceSubtaskEntity.java                            |   64 
 ruoyi-common/src/main/java/com/ruoyi/common/core/service/HisGatherApi.java                                 |  123 +
 smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskAnswerServiceImpl.java                        |   44 
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/row/SatisfactionSubtaskQuery.java           |   44 
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/PatSatisfactionReqVO.java                |   12 
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/mapper/SatisfactionMapper.java                     |   22 
 ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskDetailMapper.java                             |   30 
 ruoyi-admin/src/main/resources/application.yml                                                             |    7 
 ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/SltdGatherReq.java                            |   86 +
 ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/VisitSubtaskDraft.java                        |   46 
 ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskCountReq.java                                 |   22 
 ruoyi-inhospvisit/src/main/resources/mapper/inhospvisit/PatMedInhospMapper.xml                             |    2 
 smartor/src/main/java/com/smartor/service/impl/SvyTaskSingleServiceImpl.java                               |    6 
 ruoyi-admin/src/main/java/com/ruoyi/web/component/RedisMqReceiver.java                                     |   24 
 ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskMapper.java                                   |   34 
 ruoyi-admin/src/main/resources/logback.xml                                                                 |   14 
 ruoyi-common/src/main/java/com/ruoyi/common/core/service/TaskOpsTriggerApi.java                            |   86 +
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/SltdMydTotalVO.java                      |   22 
 ruoyi-task/src/main/java/com/ruoyi/task/service/impl/ServiceSubtaskServiceImpl.java                        |  532 +++++--
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/config/SatisfactionSwitch.java                     |   74 
 smartor/src/main/java/com/smartor/service/impl/PatMedInhospServiceImpl.java                                |   12 
 ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskStatistic.java                                |   38 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchive.java                             |  442 ++++++
 ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskRes.java                                      |   48 
 ruoyi-inhospvisit/src/main/java/com/ruoyi/inhospvisit/support/VisitSubtaskFactory.java                     |   27 
 ruoyi-task/src/main/java/com/ruoyi/task/domain/VO/ServiceSubtaskVO.java                                    |   65 
 ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/InhospPositionRecord.java                     |   71 
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/entity/SatisfactionStatQuery.java           |   12 
 ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskExport.java                                   |    4 
 ruoyi-task/src/main/java/com/ruoyi/task/api/contract/VisitTaskCreateApiImpl.java                           |    8 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchivecontact.java                      |  132 +
 ruoyi-outpatientvisit/src/main/java/com/ruoyi/outpatientvisit/service/OuthospVisitTaskService.java         |    7 
 ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml                                         |  875 +++++++++--
 ruoyi-othervisit/src/main/java/com/ruoyi/othervisit/service/OperationVisitTaskService.java                 |    4 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java                                               |    4 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java                                  |    5 
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/PatSatisfactionServiceImpl.java       |   51 
 ruoyi-task/src/main/java/com/ruoyi/task/controller/ServiceSubtaskController.java                           |   42 
 ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskDetailMapper.xml                                   |   55 
 ruoyi-satisfaction/src/main/resources/mapper/satisfaction/SatisfactionMapper.xml                           |  464 +++++
 ruoyi-datacollection/src/main/java/com/ruoyi/datacollection/service/impl/HisDataCollectionServiceImpl.java |  299 ++-
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/QuestionCountKsOrBqVO.java               |   16 
 51 files changed, 3,551 insertions(+), 750 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/component/RedisMqReceiver.java b/ruoyi-admin/src/main/java/com/ruoyi/web/component/RedisMqReceiver.java
index 1eeec66..6d71121 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/component/RedisMqReceiver.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/component/RedisMqReceiver.java
@@ -334,9 +334,9 @@
                         serviceOutPath.setParam6(subId);
                         serviceOutPath.setCreateTime(new Date());
                         serviceOutPath.setOrgid(serviceSubtask.getOrgid());
-                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
+                        serviceOutPath.setDeptCode(serviceSubtask.getLeaveldeptcode());
                         serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
-                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
+                        serviceOutPath.setDeptName(serviceSubtask.getLeaveldeptname());
                         serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                         iServiceOutPathService.insertServiceOutPath(serviceOutPath);
 //                                sendMagParam.setUrl(ip + ":" + req_path + "/followvisit/particty?param1=" + taskId + "&param2=" + patid + "&param5=false");
@@ -372,9 +372,9 @@
                         serviceOutPath.setParam3(ivrTask1.getTaskName());
                         serviceOutPath.setCreateTime(new Date());
                         serviceOutPath.setOrgid(serviceSubtask.getOrgid());
-                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
+                        serviceOutPath.setDeptCode(serviceSubtask.getLeaveldeptcode());
                         serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
-                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
+                        serviceOutPath.setDeptName(serviceSubtask.getLeaveldeptname());
                         serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                         iServiceOutPathService.insertServiceOutPath(serviceOutPath);
                         String format = String.format("%03X", serviceOutPath.getId());
@@ -412,9 +412,9 @@
                         serviceOutPath.setParam3(ivrTask1.getTaskName());
                         serviceOutPath.setCreateTime(new Date());
                         serviceOutPath.setOrgid(serviceSubtask.getOrgid());
-                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
+                        serviceOutPath.setDeptCode(serviceSubtask.getLeaveldeptcode());
                         serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
-                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
+                        serviceOutPath.setDeptName(serviceSubtask.getLeaveldeptname());
                         serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                         iServiceOutPathService.insertServiceOutPath(serviceOutPath);
                         String url = "";
@@ -514,9 +514,9 @@
                         serviceOutPath.setParam6(subId);
                         serviceOutPath.setCreateTime(new Date());
                         serviceOutPath.setOrgid(serviceSubtask.getOrgid());
-                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
+                        serviceOutPath.setDeptCode(serviceSubtask.getLeaveldeptcode());
                         serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
-                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
+                        serviceOutPath.setDeptName(serviceSubtask.getLeaveldeptname());
                         serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                         iServiceOutPathService.insertServiceOutPath(serviceOutPath);
                         String format = String.format("%03X", serviceOutPath.getId());
@@ -534,9 +534,9 @@
                         serviceOutPath.setParam6(subId);
                         serviceOutPath.setCreateTime(new Date());
                         serviceOutPath.setOrgid(serviceSubtask.getOrgid());
-                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
+                        serviceOutPath.setDeptCode(serviceSubtask.getLeaveldeptcode());
                         serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
-                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
+                        serviceOutPath.setDeptName(serviceSubtask.getLeaveldeptname());
                         serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                         iServiceOutPathService.insertServiceOutPath(serviceOutPath);
                         String format = String.format("%03X", serviceOutPath.getId());
@@ -558,9 +558,9 @@
                         serviceOutPath.setParam3(ivrTask1.getTaskName());
                         serviceOutPath.setParam6(subId);
                         serviceOutPath.setCreateTime(new Date());
-                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
+                        serviceOutPath.setDeptCode(serviceSubtask.getLeaveldeptcode());
                         serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
-                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
+                        serviceOutPath.setDeptName(serviceSubtask.getLeaveldeptname());
                         serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                         serviceOutPath.setOrgid(serviceSubtask.getOrgid());
                         iServiceOutPathService.insertServiceOutPath(serviceOutPath);
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 49041c9..30df966 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -38,8 +38,11 @@
   # 鏃ュ織璺緞 绀轰緥锛� Windows閰嶇疆D:/ruoyi/logs锛孡inux閰嶇疆 /home/ruoyi/logs,涓嶅~鍚岀骇鐩綍logs锛�
   path: D:/health/logs
   # 瀛楃缂栫爜
+  # console 榛樿 GBK锛圵indows cmd 浠g爜椤� 936锛夛紱Linux 閮ㄧ讲鐢� -DCONSOLE_CHARSET=UTF-8 瑕嗙洊銆�
+  # 涓嶈兘渚濊禆 JVM 榛樿瀛楃闆嗭細JDK8 涓枃 Windows 鏄� GBK锛孞DK18+ 琚浐瀹氫负 UTF-8銆�
+  # 鏃ュ織鏂囦欢濮嬬粓 UTF-8锛圴S Code / Notepad++ 鎸� UTF-8 鎵撳紑姝e父锛夈��
   charset:
-    console: UTF-8
+    console: ${CONSOLE_CHARSET:GBK}
     file: UTF-8
   # 鏃ュ織鏂囦欢閰嶇疆
   file:
@@ -75,7 +78,7 @@
     # 鍥介檯鍖栬祫婧愭枃浠惰矾寰�
     basename: i18n/messages
   profiles:
-    active: nhfy
+    active: sltd
 
   # 鏂囦欢涓婁紶
   servlet:
diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml
index 07456aa..b4d25fe 100644
--- a/ruoyi-admin/src/main/resources/logback.xml
+++ b/ruoyi-admin/src/main/resources/logback.xml
@@ -10,8 +10,20 @@
     <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
 
     <!-- 鎺у埗鍙拌緭鍑� -->
+    <!--
+        鎺у埗鍙扮紪鐮佸繀椤诲拰銆岃繍琛岀幆澧冦�嶄竴鑷达紝鍚﹀垯涓枃涔辩爜锛�"閸掔娀娅�"銆�"閻絻鐦�" 杩欑锛夛細
+          路 Windows cmd锛氫唬鐮侀〉 936锛屽彧璁� GBK
+          路 Linux 缁堢锛氬彧璁� UTF-8
+        鑰� JVM 榛樿瀛楃闆嗕笉鑳戒緷璧栵細JDK8+涓枃Windows 鏄� GBK锛孞DK18+锛圝EP 400锛夎鍥哄畾鎴� UTF-8锛�
+        鍚屼竴涓� jar 鍦ㄥ紑鍙戞満锛圝DK21锛夊拰鏈嶅姟鍣紙JDK8锛変笂榛樿鍊煎彲鑳界浉鍙嶃��
+
+        鎵�浠ヨ繖閲屽仛鎴愬彲閰嶏細榛樿 GBK锛圵indows 閮ㄧ讲锛屽紑鍙戞満 JDK21 涔熸甯革級锛�
+        Linux 閮ㄧ讲鏃跺惎鍔ㄥ姞涓�涓弬鏁板嵆鍙細  java -DCONSOLE_CHARSET=UTF-8 -jar smartor-sufang.jar
+        鏃ュ織鏂囦欢锛坰ys-info.log 绛夛級濮嬬粓 UTF-8锛屼笉鍙楄繖閲屽奖鍝嶃��
+    -->
     <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
-        <encoder charset="UTF-8">
+        <encoder>
+            <charset>${CONSOLE_CHARSET:-GBK}</charset>
             <pattern>${log.pattern}</pattern>
         </encoder>
     </appender>
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchive.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchive.java
new file mode 100644
index 0000000..5914177
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchive.java
@@ -0,0 +1,442 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.Date;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.core.domain.entity.PatArchive;
+import com.ruoyi.common.core.domain.entity.PatArchivecontact;
+import com.ruoyi.common.core.domain.entity.PatArchivetag;
+
+/**
+ * 鎮h�呮。妗堝璞� pat_archive
+ *
+ * @author smartor
+ * @date 2023-03-04
+ */
+@ApiModel(value = "PatArchive", description = "鎮h�呮。妗堝璞�")
+@Data
+public class PatArchive extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鑷ID
+     */
+    @ApiModelProperty("鑷ID")
+    private Long id;
+
+    /**
+     * 鐖禝D
+     */
+    @ApiModelProperty("鐖禝D")
+    private Long pid;
+
+    /**
+     * GUID
+     */
+    @ApiModelProperty("GUID")
+    private String guid;
+
+    /**
+     * 濮撳悕
+     */
+    @ApiModelProperty("鎮h�呯紪鍙�")
+    @Excel(name = " 鎮h�呯紪鍙� ")
+    private String patientno;
+
+    /**
+     * 鏈嶅姟鏍囪瘑锛�0锛岄渶瑕侊紝1锛屼笉闇�瑕�
+     */
+    @ApiModelProperty("鏈嶅姟鏍囪瘑锛�0锛岄渶瑕侊紝1锛屼笉闇�瑕�")
+    @Excel(name = " 鏈嶅姟鏍囪瘑锛�0锛岄渶瑕侊紝1锛屼笉闇�瑕� ")
+    private String notrequiredFlag;
+
+    /**
+     * 涓嶈鏈嶅姟鐨勫師鍥�
+     */
+    @ApiModelProperty("涓嶈鏈嶅姟鐨勫師鍥�")
+    @Excel(name = " 涓嶈鏈嶅姟鐨勫師鍥� ")
+    private String notrequiredreason;
+
+    /**
+     * 涓嶈鏈嶅姟鐨勬搷浣滃尰鐢�
+     */
+    @ApiModelProperty("涓嶈鏈嶅姟鐨勬搷浣滃尰鐢�")
+    private String filterDrname;
+
+
+    /**
+     * 涓嶈鏈嶅姟鐨勬搷浣滃尰鐢�
+     */
+    @ApiModelProperty("涓嶈鏈嶅姟鐨勬搷浣滃尰鐢熺紪鐮�")
+    private String filterDrcode;
+
+    /**
+     * 鏉ユ簮(1锛欻IS锛�2锛氭暟鎹钩鍙帮紱3锛氭枃浠跺鍏ワ級
+     */
+    @ApiModelProperty("鏉ユ簮(1锛欻IS锛�2锛氭暟鎹钩鍙帮紱3锛氭枃浠跺鍏ワ級")
+    @Excel(name = " 鏉ユ簮(1锛欻IS锛�2锛氭暟鎹钩鍙帮紱3锛氭枃浠跺鍏ワ級 ")
+    private Long sourcefrom;
+
+    /**
+     * his绯荤粺鐨勬偅鑰卛d
+     */
+    @ApiModelProperty("his绯荤粺鐨勬偅鑰卛d")
+    @Excel(name = "his绯荤粺鐨勬偅鑰卛d")
+    private String patidHis;
+
+    /**
+     * his绯荤粺鐨勬偅鑰卛d
+     */
+    @ApiModelProperty("his绯荤粺鐨勬偅鑰卛d")
+    @Excel(name = "his绯荤粺鐨勬偅鑰卛d")
+    private String sdFlag;
+
+    /**
+     * 濮撳悕
+     */
+    @ApiModelProperty("濮撳悕")
+    @Excel(name = " 濮撳悕 ")
+    private String name;
+
+    /**
+     * 鎬у埆  1:鐢� 2:濂�
+     */
+    @ApiModelProperty("鎬у埆")
+    @Excel(name = " 鎬у埆 ")
+    private Long sex;
+
+    /**
+     * 璇佷欢绫诲瀷
+     */
+    @ApiModelProperty("璇佷欢绫诲瀷")
+    @Excel(name = " 璇佷欢绫诲瀷 ")
+    private String idcardtype;
+
+
+    /**
+     * 璇佷欢鍙风爜
+     */
+    @ApiModelProperty("绫嶈疮")
+    @Excel(name = " 绫嶈疮 ")
+    private String nativePlace;
+
+    /**
+     * 浣忛櫌鍙�
+     */
+    @ApiModelProperty(value = "浣忛櫌鍙�")
+    private String inhospno;
+
+    /**
+     * 璇佷欢鍙风爜
+     */
+    @ApiModelProperty("灞呬綇鍦�")
+    @Excel(name = " 灞呬綇鍦� ")
+    private String placeOfResidence;
+
+    /**
+     * 璇佷欢鍙风爜
+     */
+    @ApiModelProperty("鍑虹敓鍦�")
+    @Excel(name = " 鍑虹敓鍦� ")
+    private String birthplace;
+
+    /**
+     * 璇佷欢鍙风爜
+     */
+    @ApiModelProperty("璇佷欢鍙风爜")
+    @Excel(name = " 璇佷欢鍙风爜 ")
+    private String idcardno;
+
+    /**
+     * 鐢熸棩
+     */
+    @ApiModelProperty("鐢熸棩")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = " 鐢熸棩 ", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date birthdate;
+
+    /**
+     * 鍏ラ櫌鏃堕棿
+     */
+    @ApiModelProperty("鍏ラ櫌鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = " 鐢熸棩 ", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date inhosptime;
+
+    /**
+     * 骞撮緞
+     */
+    @ApiModelProperty("骞撮緞")
+    @Excel(name = " 骞撮緞 ")
+    private Long age;
+    /**
+     * 骞撮緞
+     */
+    @ApiModelProperty("骞撮緞鍗曚綅")
+    @Excel(name = " 骞撮緞鍗曚綅 ")
+    private String ageUnit;
+
+    /**
+     * 寤烘。鏃堕棿
+     */
+    @ApiModelProperty("寤烘。鏃堕棿")
+    @Excel(name = " 寤烘。鏃堕棿 ")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date archivetime;
+
+    /**
+     * 寤烘。浜�
+     */
+    @ApiModelProperty("寤烘。浜�")
+    @Excel(name = " 寤烘。浜� ")
+    private String archiveby;
+
+    /**
+     * 鎵嬫満鍙风爜
+     */
+    @ApiModelProperty("鎵嬫満鍙风爜")
+    @Excel(name = " 鎵嬫満鍙风爜 ")
+    private String telcode;
+
+    /**
+     * 鎵嬫満鐭彿
+     */
+    @ApiModelProperty("鎵嬫満鐭彿")
+    @Excel(name = " 鎵嬫満鐭彿 ")
+    private String telshortcode;
+
+
+    /**
+     * 浜插睘鍙风爜
+     */
+    @ApiModelProperty("浜插睘鍙风爜")
+    @Excel(name = " 浜插睘鍙风爜 ")
+    private String relativetelcode;
+
+    /**
+     * 姘戞棌
+     */
+    @ApiModelProperty("姘戞棌")
+    @Excel(name = " 姘戞棌 ")
+    private String nation;
+
+    /**
+     * 鏈烘瀯ID
+     */
+    @ApiModelProperty("鏈烘瀯ID")
+    @Excel(name = " 鏈烘瀯ID ")
+    private String orgid;
+
+    /**
+     * 鏈烘瀯ID
+     */
+    @ApiModelProperty("闄㈠尯")
+    @Excel(name = " 闄㈠尯 ")
+    private String campusid;
+
+    /**
+     * 寰俊openid
+     */
+    @ApiModelProperty("寰俊openid")
+    @Excel(name = " 寰俊openid ")
+    private String openid;
+
+    /**
+     * 鍒犻櫎鏍囪
+     */
+    @ApiModelProperty("鍒犻櫎鏍囪")
+    private String delFlag;
+
+    /**
+     * 涓婁紶鏍囪
+     */
+    @ApiModelProperty("涓婁紶鏍囪")
+    private Long isupload;
+
+    /**
+     * 涓婁紶鏃堕棿
+     */
+    @ApiModelProperty("涓婁紶鏃堕棿")
+    private Date uploadTime;
+
+    /**
+     * 鏍囩
+     */
+    @ApiModelProperty("鏍囩")
+    @Excel(name = " 鏍囩 ", cellType = Excel.ColumnType.STRING)
+    private String tag;
+
+    /**
+     * 鏍囩
+     */
+    @ApiModelProperty("鏍囩id")
+    @Excel(name = " 鏍囩id ", cellType = Excel.ColumnType.STRING)
+    private Long tagid;
+
+    @ApiModelProperty("鏍囩闆嗗悎")
+    private List<PatArchivetag> tagList;
+
+    @ApiModelProperty("浜插睘闆嗗悎")
+    private List<PatArchivecontact> patArchivecontactList;
+
+    /**
+     * 鏍囩
+     */
+    @ApiModelProperty("鎮h�呯被鍨�")
+    @Excel(name = " 鎮h�呯被鍨� ", cellType = Excel.ColumnType.STRING)
+    private String pattype;
+
+    /**
+     * 閽夐拤鍙�
+     */
+    @ApiModelProperty("閽夐拤鍙�")
+    @Excel(name = " 閽夐拤鍙� ")
+    private String dduserid;
+
+    /**
+     * 閽夐拤鍙�
+     */
+    @ApiModelProperty("绉戝")
+    @Excel(name = " 绉戝 ")
+    private String dept;
+
+    /**
+     * 閽夐拤鍙�
+     */
+    @ApiModelProperty("绉戝")
+    @Excel(name = " 绉戝 ")
+    private String deptcode;
+    /**
+     * 鍖荤敓濮撳悕
+     */
+    @ApiModelProperty("鍖荤敓濮撳悕")
+    @Excel(name = " 鍖荤敓濮撳悕 ")
+    private String drname;
+
+    /**
+     * 鍖荤敓缂栫爜
+     */
+    @ApiModelProperty("鍖荤敓缂栫爜")
+    @Excel(name = " 鍖荤敓缂栫爜 ")
+    private String drcode;
+
+    /**
+     * 閽夐拤鍙�
+     */
+    @ApiModelProperty("绉戝")
+    @Excel(name = " 绉戝 ")
+    private String bedNo;
+
+    /**
+     * 浼氬憳灞炴��:0闈炰細鍛橈紝1涓�鑸細鍛樸��2閲嶈浼氬憳
+     */
+    @ApiModelProperty("浼氬憳灞炴��:0闈炰細鍛橈紝1涓�鑸細鍛樸��2閲嶈浼氬憳 -1铏氭嫙鎮h��")
+    @Excel(name = " 浼氬憳灞炴��:0闈炰細鍛橈紝1涓�鑸細鍛樸��2閲嶈浼氬憳 -1铏氭嫙鎮h��")
+    private String viptype;
+
+    @ApiModelProperty("鍑洪櫌鐥呭尯鍚嶇О")
+    private String leavehospitaldistrictname;
+
+    @ApiModelProperty("鍑洪櫌鐥呭尯缂栧彿")
+    private String leavehospitaldistrictcode;
+
+
+    /**
+     * 鍑洪櫌鏂瑰紡搴忓彿
+     */
+    @ApiModelProperty("鍑洪櫌鏂瑰紡搴忓彿")
+    @Excel(name = " 鍑洪櫌鏂瑰紡搴忓彿 ")
+    private String outWayId;
+
+    /**
+     * 鍑洪櫌鏂瑰紡鍚嶇О
+     */
+    @ApiModelProperty("鍑洪櫌鏂瑰紡鍚嶇О")
+    @Excel(name = " 鍑洪櫌鏂瑰紡鍚嶇О ")
+    private String outWayName;
+
+    @ApiModelProperty("鐓ф姢鍦烘墍锛�1瀹跺涵   2鍏昏�佹満鏋�")
+    @Excel(name = " 鐓ф姢鍦烘墍锛�1瀹跺涵   2鍏昏�佹満鏋� ")
+    private String careFacilities;
+
+    @ApiModelProperty("鐓ф姢鍦烘墍锛�1瀹跺涵   2鍏昏�佹満鏋�")
+    @Excel(name = " 鐓ф姢鍦烘墍锛�1瀹跺涵   2鍏昏�佹満鏋� ")
+    private String casePath;
+
+    @ApiModelProperty("鍙楁暀鑲茬▼搴�")
+    @Excel(name = "鍙楁暀鑲茬▼搴�")
+    private String degreeOfEducation;
+
+    @ApiModelProperty("濠氬Щ鐘跺喌")
+    @Excel(name = "濠氬Щ鐘跺喌")
+    private String maritalStatus;
+
+    @ApiModelProperty("瀹跺涵浜哄潎鏀跺叆")
+    @Excel(name = "瀹跺涵浜哄潎鏀跺叆")
+    private String income;
+
+    @ApiModelProperty("鍖讳繚绫诲瀷")
+    @Excel(name = "鍖讳繚绫诲瀷")
+    private String medicareType;
+
+    @ApiModelProperty("涓昏鐓ф姢浜�")
+    @Excel(name = "涓昏鐓ф姢浜�")
+    private String carePerson;
+
+    @ApiModelProperty("涓昏鐓ф姢浜哄勾榫�")
+    @Excel(name = "涓昏鐓ф姢浜哄勾榫�")
+    private String casePersonAge;
+
+    /**
+     * 骞撮緞
+     */
+    @ApiModelProperty("骞撮緞")
+    @Excel(name = " 绗簩骞撮緞 ")
+    private Long age2;
+
+    /**
+     * 骞撮緞
+     */
+    @ApiModelProperty("骞撮緞鍗曚綅")
+    @Excel(name = " 绗簩骞撮緞鍗曚綅 ")
+    private String ageUnit2;
+
+    /**
+     * pageNum
+     */
+    @ApiModelProperty("pageNum")
+    private Integer pageNum;
+
+    /**
+     * pageSize
+     */
+    @ApiModelProperty("pageSize")
+    private Integer pageSize;
+    /**
+     * pageNum
+     */
+    @ApiModelProperty("pn")
+    private Integer pn;
+
+    /**
+     * pageSize
+     */
+    @ApiModelProperty("ps")
+    private Integer ps;
+
+    @ApiModelProperty(value = "鏈�鍚庡紑濮嬫椂闂�")
+    private String lastStartTime;
+
+    @ApiModelProperty(value = "鏈�鍚庣粨鏉熸椂闂�")
+    private String lastEndTime;
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchivecontact.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchivecontact.java
new file mode 100644
index 0000000..32eb03c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchivecontact.java
@@ -0,0 +1,132 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.core.domain.entity.PatArchivecontact;
+
+/**
+ * 鎮h�呰仈绯绘柟寮忓璞� pat_archivecontact
+ *
+ * @author ruoyi
+ * @date 2023-12-05
+ */
+@Data
+@ApiModel(value = "鎮h�呰仈绯绘柟寮忓璞�")
+public class PatArchivecontact extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鑷ID
+     */
+    private Long id;
+
+    /**
+     * 鍏宠仈鎮h�匢D
+     */
+    @Excel(name = " 鍏宠仈鎮h�匢D ")
+    @ApiModelProperty(value = "鍏宠仈鎮h�匢D")
+    private Long patid;
+
+    /**
+     * 鑱旂郴鏂瑰紡
+     */
+    @Excel(name = " 鑱旂郴鏂瑰紡 ")
+    @ApiModelProperty(value = "鑱旂郴鏂瑰紡")
+    private String contactway;
+
+    /**
+     * 鍏崇郴
+     */
+    @Excel(name = " 鍏崇郴 ")
+    @ApiModelProperty(value = "鍏崇郴")
+    private String relation;
+
+    /**
+     * 鏁版嵁鏉ユ簮
+     */
+    @Excel(name = " 鏁版嵁鏉ユ簮 ")
+    @ApiModelProperty(value = "鏁版嵁鏉ユ簮")
+    private Long datasource;
+
+    /**
+     * 鏄惁榛樿
+     */
+    @Excel(name = " 鏄惁榛樿 ")
+    @ApiModelProperty(value = "鏄惁榛樿")
+    private Long isdefault;
+
+    /**
+     * 鏈烘瀯ID
+     */
+    @Excel(name = " 鏈烘瀯ID ")
+    @ApiModelProperty(value = "鏈烘瀯ID")
+    private String orgid;
+
+    /**
+     * 鍒犻櫎鏍囪
+     */
+    private String delFlag;
+
+    /**
+     * 涓婁紶鏍囪
+     */
+    @Excel(name = " 涓婁紶鏍囪 ")
+    @ApiModelProperty(value = "涓婁紶鏍囪")
+    private Long isupload;
+
+    /**
+     * 涓婁紶鏃堕棿
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = " 涓婁紶鏃堕棿 ", width = 30, dateFormat = "yyyy-MM-dd")
+    @ApiModelProperty(value = "涓婁紶鏃堕棿")
+    private Date uploadTime;
+
+    /**
+     * 鑱旂郴濮撳悕
+     */
+    @Excel(name = " 鑱旂郴濮撳悕 ")
+    @ApiModelProperty(value = "鑱旂郴濮撳悕")
+    private String contactname;
+
+    /**
+     * 鐖禝D
+     */
+    @Excel(name = "鐖禝D")
+    @ApiModelProperty(value = "鐖禝D")
+    private Long pid;
+
+    /**
+     * GUID
+     */
+    @Excel(name = "GUID")
+    @ApiModelProperty(value = "GUID")
+    private String guid;
+
+    /**
+     * pageNum
+     */
+    @ApiModelProperty(value = "pageNum")
+    @Excel(name = "pageNum")
+    private Integer pageNum;
+
+    /**
+     * pageSize
+     */
+    @ApiModelProperty(value = "pageSize")
+    @Excel(name = "pageSize")
+    private Integer pageSize;
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("id", getId()).append("patid", getPatid()).append("contactway", getContactway()).append("relation", getRelation()).append("datasource", getDatasource()).append("isdefault", getIsdefault()).append("orgid", getOrgid()).append("delFlag", getDelFlag()).append("updateBy", getUpdateBy()).append("updateTime", getUpdateTime()).append("createBy", getCreateBy()).append("createTime", getCreateTime()).append("isupload", getIsupload()).append("uploadTime", getUploadTime()).append("contactname", getContactname()).append("pid", getPid()).append("guid", getGuid()).toString();
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchivetag.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchivetag.java
new file mode 100644
index 0000000..9fbcc74
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/PatArchivetag.java
@@ -0,0 +1,89 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.core.domain.entity.PatArchivetag;
+
+/**
+ * 鎮h�呮。妗堟爣绛惧璞� pat_archivetag
+ *
+ * @author ruoyi
+ * @date 2023-06-02
+ */
+@Data
+@ApiModel(value = "PatArchivetag", description = "鎮h�呮。妗堟爣绛惧璞�")
+public class PatArchivetag extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鑷ID
+     */
+    @ApiModelProperty(value = "鑷ID")
+    private Long id;
+
+    /**
+     * 鏍囩鍒嗙被ID
+     */
+    @ApiModelProperty(value = "鏍囩鍒嗙被ID")
+    private Long tagcategoryid;
+
+    /**
+     * 鏍囩ID
+     */
+    @ApiModelProperty(value = "鏍囩ID")
+    private Long tagid;
+
+    /**
+     * 鏈烘瀯ID
+     */
+    @ApiModelProperty(value = "鏈烘瀯ID")
+    private String orgid;
+
+    /**
+     * 鍒犻櫎鏍囪
+     */
+    @ApiModelProperty(value = "鍒犻櫎鏍囪")
+    private String delFlag;
+
+    /**
+     * 涓婁紶鏍囪
+     */
+    @ApiModelProperty(value = "涓婁紶鏍囪")
+    private Long isupload;
+
+    /**
+     * 涓婁紶鏃堕棿
+     */
+    @ApiModelProperty(value = "涓婁紶鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = " 涓婁紶鏃堕棿 ", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date uploadTime;
+
+    /**
+     * 鏍囩鍚嶇О(浣滀负鍏ヨ繑鍙備娇鐢紝琛ㄤ腑娌℃湁)
+     */
+    @ApiModelProperty(value = "鏍囩鍚嶇О")
+    private String tagname;
+
+    /**
+     * 妗fID
+     */
+    @ApiModelProperty(value = "妗fID")
+    private Long patid;
+
+    /**
+     * 鏄惁瀛樺湪鎿嶄綔锛�1 鏂板 2淇敼 3鍒犻櫎")(浣滀负鍏ヨ繑鍙備娇鐢紝琛ㄤ腑娌℃湁)
+     */
+    @ApiModelProperty(value = "鏄惁瀛樺湪鎿嶄綔锛�1 鏂板 2淇敼 3鍒犻櫎")
+    private Integer isoperation;
+
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
index 65282ec..605ebc8 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
@@ -47,6 +47,23 @@
     }
 
     /**
+     * 浠呭綋 key 涓嶅瓨鍦ㄦ椂鍐欏叆锛圫ETNX 璇箟锛夛紝鐢ㄤ簬<b>骞傜瓑/闃查噸澶嶆彁浜�</b>
+     * <p>
+     * 2026-10-21 鏂板锛氶棶鍗锋彁浜ゆ帴鍙o紙{@code /smartor/subtaskAnswer/saveQuestionAnswer}锛夋槸
+     * {@code @Async} 寮傛澶勭悊锛屾偅鑰呯閲嶅鐐瑰嚮/缃戠粶閲嶈瘯浼氬苟鍙戝啓澶氫唤鏄庣粏锛岄渶瑕佺敤鍘熷瓙鍗犱綅鎸℃帀銆�
+     *
+     * @param key      Redis 閿�
+     * @param value    鍐欏叆鐨勫��
+     * @param timeout  杩囨湡鏃堕棿
+     * @param timeUnit 鏃堕棿棰楃矑搴�
+     * @return {@code true} = 鍗犱綅鎴愬姛锛堟湰娆″簲缁х画澶勭悊锛夛紱{@code false} = 宸插瓨鍦紙閲嶅璇锋眰锛屽簲蹇界暐锛�
+     */
+    public <T> boolean setCacheObjectIfAbsent(final String key, final T value, final long timeout, final TimeUnit timeUnit) {
+        Boolean ok = redisTemplate.opsForValue().setIfAbsent(key, value, timeout, timeUnit);
+        return Boolean.TRUE.equals(ok);
+    }
+
+    /**
      * 璁剧疆鏈夋晥鏃堕棿
      *
      * @param key     Redis閿�
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/HisGatherApi.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/HisGatherApi.java
new file mode 100644
index 0000000..87f4e71
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/HisGatherApi.java
@@ -0,0 +1,123 @@
+package com.ruoyi.common.core.service;
+
+import com.ruoyi.common.core.service.dto.InhospPositionRecord;
+import com.ruoyi.common.core.service.dto.SltdGatherReq;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * HIS 閲囬泦鑳藉姏濂戠害 鈥斺�� 鏂板崕 / 娌冲崡 / 鐪佺珛鍚屽痉锛堝崡鍗庨檮涓�锛�/ 鐤剧梾瀛楀吀銆�
+ *
+ * <h3>涓轰粈涔堟湁杩欎釜濂戠害</h3>
+ * HIS 閲囬泦鐨勮皟搴︾紪鎺掞紙鍘� {@code RyTask#dealHisData}锛夊凡鎼繘 {@code ruoyi-datacollection}锛�
+ * 浣嗗洓涓噰闆嗗疄鐜板綋鍓�<b>浠嶅湪 smartor</b>锛�
+ * <ul>
+ *   <li>{@code IXHGatherPatArchiveServiceImpl}锛堟柊鍗庯紝鍚绾﹀仠璇婏級</li>
+ *   <li>{@code IHNGatherPatArchiveServiceImpl}锛堟渤鍗楋級</li>
+ *   <li>{@code IServiceSLTDHealthcareRecordServiceImpl}锛堢渷绔嬪悓寰� / 鍗楀崕闄勪竴锛屾潵鏈潵锛�</li>
+ *   <li>{@code IIcd10Service#queryAddIcd10}锛堢柧鐥呭瓧鍏稿閲忥級</li>
+ * </ul>
+ * {@code ruoyi-datacollection} 涓嶄緷璧� smartor锛堝惁鍒欐柊妯″潡灏辫鍗曚綋缁戞锛夛紝
+ * 鎵�浠ユ寜 {@code doc/璺ㄦā鍧楁暟鎹闂師鍒欎笌鏀跺彛鏂规.md} 璧�<b>濂戠害</b>锛�
+ * 濂戠害澹版槑鍦� ruoyi-common锛宻martor 渚х敤绾浆鍙戠殑 Bridge 瀹炵幇
+ * 锛坽@code com.smartor.service.impl.bridge.HisGatherApiBridge}锛夈��
+ *
+ * <h3>鈿狅笍 杩欐槸銆愯繃娓°�戝绾︼紝褰㈡�佸埢鎰忎笌鏃� Service 涓�鑷�</h3>
+ * 閫愭柟娉曢暅鍍忔棦鏈� Service 鏂规硶锛氬悓鍚嶈涔夈�佸悓鍙傛暟鍚箟銆佸悓杩斿洖绫诲瀷
+ * 锛�<b>鍞竴渚嬪</b>锛歿@link #gatherSltdHealthcareRecords} 杩斿洖鏉℃暟鑰岄潪 List锛屽師鍥犺璇ユ柟娉曟敞閲婏級锛�
+ * 浣� Bridge 鍙仛"寤� VO + 杞彂"锛�<b>涓嶅湪 Bridge 閲屽姞浠讳綍涓氬姟鍒ゆ柇</b>銆�
+ *
+ * <h3>灏嗘潵鍔ㄤ綔锛堝垎闃舵鎼縼锛�</h3>
+ * 閲囬泦瀹炵幇鎸夋壒鎼繘 {@code ruoyi-datacollection}锛堣
+ * {@code doc/鏁版嵁閲囬泦妯″潡鍖朹璋冪爺涓庡疄鏂芥柟妗�.md}锛夛細鎼畬涓�鎵癸紝瀵瑰簲鏂规硶灏变粠鏈绾﹀垹闄わ紝
+ * 鍏ㄩ儴鎼畬鍚庢湰濂戠害涓� smartor 鐨� Bridge 涓�璧峰垹闄わ紝鏀朵负妯″潡鍐呴儴鎺ュ彛銆�
+ *
+ * @see com.ruoyi.common.core.service.dto.SltdGatherReq 鐪佺珛鍚屽痉/鍗楀崕闄勪竴閲囬泦鍏ュ弬
+ */
+public interface HisGatherApi {
+
+    /**
+     * 鏂板崕锛氶噰闆嗗嚭鍏ラ櫌淇℃伅骞惰惤 {@code pat_med_inhosp} / {@code pat_archive}
+     * 锛堝師 {@code IXHGatherPatArchiveService#getInHospDataGather}锛夈��
+     *
+     * @param cry       鍑哄叆闄㈢被鍨嬶細0-鍏ラ櫌锛�1-鍑洪櫌
+     * @param startTime 寮�濮嬫椂闂�
+     * @param endTime   缁撴潫鏃堕棿
+     */
+    void gatherXhInhospRecords(String cry, LocalDateTime startTime, LocalDateTime endTime);
+
+    /**
+     * 娌冲崡锛氶噰闆嗘暟鎹紙鍘� {@code IHNGatherPatArchiveService#hnDataGather}锛�
+     * 鍏ュ弬 {@code HnDataGatherVO} 鍙湁 startTime / endTime 涓や釜瀛楁锛屾晠杩欓噷鐩存帴浼犱袱涓� Date锛夈��
+     *
+     * @param startTime 寮�濮嬪嚭闄㈡棩鏈�
+     * @param endTime   缁撴潫鍑洪櫌鏃ユ湡
+     */
+    void gatherHnRecords(Date startTime, Date endTime);
+
+    /**
+     * 鐪佺珛鍚屽痉 / 鍗楀崕闄勪竴锛氶噰闆嗙瀹ょ梾鍖轰俊鎭�
+     * 锛堝師 {@code IServiceSLTDHealthcareRecordService#queryDeptWardAreaInfoList}锛夈��
+     *
+     * @param req 鍙渶 {@code orgId} + {@code campusIds}
+     * @return 鍘� Service 鐨勮繑鍥炲�硷紝鍘熸牱閫忓嚭锛堝彲鑳戒负 {@code null}锛�
+     */
+    Boolean gatherSltdDeptWardArea(SltdGatherReq req);
+
+    /**
+     * 鐪佺珛鍚屽痉 / 鍗楀崕闄勪竴锛氶噰闆嗗尰闄㈢敤鎴蜂俊鎭�
+     * 锛堝師 {@code IServiceSLTDHealthcareRecordService#queryHospUserInfoList}锛夈��
+     *
+     * @param req 鍙渶 {@code orgId} + {@code campusId} + {@code statusList}
+     * @return 鍘� Service 鐨勮繑鍥炲�硷紝鍘熸牱閫忓嚭锛堝彲鑳戒负 {@code null}锛�
+     */
+    Boolean gatherSltdHospUser(SltdGatherReq req);
+
+    /**
+     * 鐪佺珛鍚屽痉 / 鍗楀崕闄勪竴锛氶噰闆嗚瘖鐤楄褰曪紙棰勫叆闄� / 鍏ラ櫌 / 鍑洪櫌锛�
+     * 锛堝師 {@code IServiceSLTDHealthcareRecordService#queryHealthcareRecordList}锛夈��
+     * <p>
+     * 鈿狅笍 <b>鍞竴鍋忕"閫愭柟娉曢暅鍍�"鐨勫湴鏂癸細杩斿洖鏉℃暟銆�</b>鍘熷疄鐜颁涪寮� List 杩斿洖鍊硷紝浣嗘潵鏈潵鏌ヨ鎺ュ彛
+     * 鍗曟鏈�澶氳繑鍥� 1500 鏉′笖<b>鎴柇涓嶆姤閿�</b>锛岀紪鎺掍晶蹇呴』鎷垮埌"杩欐鍒板簳杩斿洖浜嗗嚑鏉�"鎵嶈兘鍒ゆ柇鏄惁瑕佹媶灏忛噸閲囷紝
+     * 鍚﹀垯灏辨槸闈欓粯涓㈡暟鎹紙2026-10 宸茶俯杩囷細7 鏈堢梾鍖轰汉鏁版瘮鐪熷疄鍊煎皯锛夈�傝繖閲屽彧閫忓嚭 {@code size}锛�
+     * 涓嶅仛浠讳綍涓氬姟鍒ゆ柇銆�
+     *
+     * @param req 閲囬泦鍏ュ弬锛堝悇瀛楁鍚箟涓� {@code ServiceSLTDInhospReqVO} 鍚屽悕锛�
+     * @return 鏈鎺ュ彛<b>瀹為檯杩斿洖</b>鐨勮褰曟潯鏁帮紱== 1500 琛ㄧず鍙兘宸茶鎴柇
+     */
+    int gatherSltdHealthcareRecords(SltdGatherReq req);
+
+    /**
+     * 鐪佺珛鍚屽痉 / 鍗楀崕闄勪竴锛氭煡璇㈡煇涓湪闄㈡偅鑰�<b>褰撳墠</b>鐨勭瀹� / 鐥呭尯 / 搴婁綅
+     * 锛堟潵鏈潵 {@code /osj/hbos-thirdparty-integration/standard/common/healthcareRecord/dtcQueryHealthcareRecordList}锛�
+     * 涓�"鍏ラ櫌閲囬泦"鏄悓涓�涓帴鍙o紝鍖哄埆鍙槸鎸� {@code healthcareRecordNo} 鍗曟煡锛夈��
+     * <p>
+     * 鈿狅笍 <b>鍙彇鏁般�佷笉钀藉簱</b>锛氫笌搴撳唴姣斿銆佸喅瀹氭敼鍝簺瀛楁锛屽睘浜庨噰闆嗘ā鍧�
+     * 锛坽@code ruoyi-datacollection}锛夛紝涓嶅湪杩欓噷鍒ゆ柇銆�
+     * <p>
+     * 鍏ュ弬绾﹀畾锛堢敱璋冪敤鏂瑰~锛夛細{@code orgId} + {@code campusId} + {@code statusList=["FH0109.24"]}
+     * + {@code healthcareRecordNo}銆傚叾涓� {@code statusList} 鏄彲闈犵殑"鐪熷湪闄�"杩囨护 鈥斺��
+     * 鎮h�呭凡鍑洪櫌/棰勫嚭闄㈡椂鎺ュ彛杩斿洖<b>绌哄垪琛�</b>銆�
+     * <p>
+     * 鍙栨暟澶辫触锛圚TTP 寮傚父 / 杩斿洖闈� 200 / 杩斿洖浣撲负绌猴級鏃�<b>鎶� RuntimeException</b>锛�
+     * 鐢辫皟鐢ㄦ柟鎸�"璇ユ偅鑰呰繖涓�杞け璐�"璁℃暟骞剁户缁笅涓�涓偅鑰� 鈥斺�� 涓嶈繑鍥炵┖鍒楄〃锛�
+     * 鍚﹀垯"鎺ュ彛鎸備簡"鍜�"鎮h�呭凡涓嶅湪闄�"浼氳娣锋垚鍚屼竴浠朵簨銆�
+     *
+     * @param req 瑙佷笂
+     * @return 褰撳墠浣嶇疆璁板綍锛�<b>绌哄垪琛� = 璇ユ偅鑰呭綋鍓嶄笉鍦�"鍏ラ櫌"鐘舵��</b>锛堜笉鏄け璐ワ級
+     */
+    List<InhospPositionRecord> querySltdInhospPosition(SltdGatherReq req);
+
+    /**
+     * 鐤剧梾瀛楀吀澧為噺閲囬泦锛堝師 {@code IIcd10Service#queryAddIcd10}锛夈��
+     * <p>
+     * 瀹冨睘浜�"妗f瀛楀吀鍩�"锛屼笉鏄� HIS 閲囬泦瀹炵幇锛屼絾瀹冨氨鍦ㄥ悓涓�娆¢噰闆嗚疆娆¢噷琚Е鍙�
+     * 锛堝師 {@code RyTask#dealHisData} 鐨� {@code sltd.gather.sysuser=2} 鍒嗘敮锛夛紝
+     * 鎵�浠ヤ竴骞剁撼鍏ユ湰濂戠害锛岄伩鍏嶆柊妯″潡涓轰竴琛岃皟鐢ㄥ啀寮�涓�涓绾︺��
+     *
+     * @return 鏂板鏉℃暟
+     */
+    int gatherIcd10();
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/TaskOpsTriggerApi.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/TaskOpsTriggerApi.java
new file mode 100644
index 0000000..efc0af5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/TaskOpsTriggerApi.java
@@ -0,0 +1,86 @@
+package com.ruoyi.common.core.service;
+
+/**
+ * 浠诲姟杩愮淮瑙﹀彂鑳藉姏 鈥斺�� <b>绔彛鍙嶈浆</b>濂戠害銆�
+ *
+ * <h3>涓轰粈涔堥渶瑕佸畠锛堣В ruoyi-task 鈫� ruoyi-quartz 寰幆渚濊禆锛�</h3>
+ * {@code /smartor/serviceSubtask} 涓嬫湁 6 涓�屾墜宸ヨЕ鍙戝悓姝�/鎴/寮傚父鎺ㄩ�併�嶇殑杩愮淮绔偣
+ * 锛坽@code syncMedInhospForShiyi} / {@code syncMedInhospForShiyiYesterday} /
+ * {@code syncMedInhospForShiyiDaysBefore} / {@code syncMedOperForShiyi} /
+ * {@code dealSubtaskDeadline} / {@code sendExceptInfo}锛夛紝
+ * 瀹冧滑鍘熷厛鐢� {@code ruoyi-admin} 鐨� {@code ServiceSubtaskController} 鐩存帴璋冪敤
+ * {@code ruoyi-quartz} 鐨� {@code RyTask} / {@code ICollectHISService}銆�
+ * <p>
+ * 浠诲姟妯″潡鍖栧悗杩� 6 涓鐐圭殑<b>褰掑睘</b>鎼繘 {@code ruoyi-task}锛屼絾瀹冧滑鐨�<b>瀹炵幇涓嶈兘鎼�</b>锛�
+ * <ul>
+ *   <li>{@code RyTask}锛�2214 琛岋級娉ㄥ叆 <b>绾� 20 涓� smartor service</b> + {@code com.smartor.mapper.*}
+ *       鈥斺�� 鎼蛋浼氳 {@code ruoyi-task -> smartor}锛岃�� smartor 鏈� 35 涓枃浠跺紩鐢ㄤ换鍔″煙瀹炰綋锛�
+ *       褰㈡垚纭惊鐜紱</li>
+ *   <li>{@code collectHIS*} 鏈川鏄� <b>HIS 鏁版嵁閲囬泦</b>锛坽@code CollectHISMapper} + {@code MzGather*}
+ *       甯搁噺/鏋氫妇锛夛紝灞� quartz 鍩燂紝涓嶆槸浠诲姟鍩熴��</li>
+ * </ul>
+ * 鍥犳閲囩敤<b>绔彛鍙嶈浆</b>锛氭帴鍙e畾涔夊湪 {@code ruoyi-common}锛堝敮涓�鑳藉悓鏃舵弧瓒�
+ * 銆宺uoyi-task 涓嶄緷璧� ruoyi-quartz銆�+銆宺uoyi-quartz 渚濊禆 ruoyi-task銆嶇殑浣嶇疆锛夛紝
+ * 鐢� {@code ruoyi-quartz} 鎻愪緵瀹炵幇銆傝繖鏍风鐐瑰湪浠诲姟妯″潡鍐呫�佸疄鐜板湪 quartz 鍐咃紝
+ * 缂栬瘧鏈�<b>鏃犵幆</b>銆�
+ *
+ * <h3>鈿狅笍 瀹炵幇蹇呴』淇濇寔"绾惉杩�"</h3>
+ * 瀹炵幇鏂瑰彧鍋氳浆鍙戯紝<b>涓嶅緱</b>鍔犲叆鍘婚噸銆佺姸鎬佹満銆侀粯璁ゅ�艰ˉ榻愮瓑鏂伴�昏緫 鈥斺��
+ * 閭d簺璇箟鍘熸湰灏卞湪 {@code RyTask} / {@code ICollectHISService} 閲屻��
+ *
+ * <h3>璋冪敤鏂瑰姟蹇呴檷绾�</h3>
+ * 鍙栦笉鍒板疄鐜帮紙quartz 鏈墦杩涘簲鐢� / 瀹瑰櫒寮傚父锛夋椂锛岃皟鐢ㄦ柟搴旀寜"鏈Е鍙�"澶勭悊骞舵墦 WARN锛�
+ * 涓嶈璁╄繍缁寸鐐规姏 500銆�
+ *
+ * @see VisitTaskCreateApi 鍚屼竴鎵嬫硶锛堟帴鍙e湪 ruoyi-common銆佸疄鐜扮敱褰掑睘鏂规彁渚涳級鐨勫厛渚�
+ */
+public interface TaskOpsTriggerApi {
+
+    /**
+     * 甯備竴锛氬悓姝ヤ綇闄俊鎭紙鍘� {@code ICollectHISService#syncMedInhosp}锛夈��
+     *
+     * @param startTime 寮�濮嬫椂闂�
+     * @param endTime   缁撴潫鏃堕棿
+     * @return 鍚屾鏉℃暟
+     */
+    Integer syncMedInhosp(String startTime, String endTime);
+
+    /**
+     * 閲囬泦鏄ㄥぉ鑷充粖鐨� HIS 鏁版嵁锛堝師 {@code RyTask#collectHISYesterday}锛夈��
+     */
+    void collectHISYesterday();
+
+    /**
+     * 閲囬泦 N 澶╁墠鐨� HIS 鏁版嵁锛堝師 {@code RyTask#collectHISDaysBefore}锛夈��
+     *
+     * @param daysBefore 澶╂暟
+     */
+    void collectHISDaysBefore(Long daysBefore);
+
+    /**
+     * 甯備竴锛氬悓姝ユ墜鏈俊鎭紙鍘� {@code ICollectHISService#syncOper}锛夈��
+     *
+     * @param startTime 寮�濮嬫椂闂�
+     * @param endTime   缁撴潫鏃堕棿
+     * @return 鍚屾鏉℃暟
+     */
+    Integer syncOper(String startTime, String endTime);
+
+    /**
+     * 澶勭悊瀛愪换鍔℃埅姝紙鍘� {@code RyTask#dealSubtaskDeadline}锛夈��
+     *
+     * @param orgid       鏈烘瀯 id
+     * @param deadlineDay 鎴澶╂暟
+     */
+    void dealSubtaskDeadline(String orgid, Integer deadlineDay);
+
+    /**
+     * 鍙戦�佸紓甯告彁閱掞紙鍘� {@code RyTask#sendExceptInfo}锛夈��
+     * <p>
+     * 鈿狅笍 鍘熸柟娉曠鍚嶅甫 {@code throws Exception}锛屾澶�<b>鍘熸牱淇濈暀</b>锛�
+     * 璋冪敤鏂癸紙杩愮淮绔偣锛変篃澹版槑浜� {@code throws Exception}锛岃涓轰笉鍙樸��
+     *
+     * @throws Exception 鍘熷疄鐜板彲鑳芥姏鍑虹殑寮傚父
+     */
+    void sendExceptInfo() throws Exception;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/InhospPositionRecord.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/InhospPositionRecord.java
new file mode 100644
index 0000000..a2f3019
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/InhospPositionRecord.java
@@ -0,0 +1,71 @@
+package com.ruoyi.common.core.service.dto;
+
+import lombok.Data;
+
+/**
+ * 鍦ㄩ櫌鎮h��"褰撳墠鎵�鍦ㄤ綅缃�"锛堢瀹� / 鐥呭尯 / 搴婁綅锛夆�斺��
+ * {@link com.ruoyi.common.core.service.HisGatherApi} 鐨勫绾� DTO銆�
+ *
+ * <h3>鏁版嵁鏉ユ簮涓庤涔�</h3>
+ * 鏉ヨ嚜鏉ユ湭鏉� {@code dtcQueryHealthcareRecordList}锛�<b>灏辨槸 south-china 鍏ラ櫌閲囬泦鐢ㄧ殑鍚屼竴涓帴鍙�</b>锛夛紝
+ * 鐢� {@code healthcareRecordNo} 鍗曟煡銆侀厤 {@code statusList=["FH0109.24"]}锛堝湪闄級鏃讹紝
+ * 杩斿洖鐨�<b>鏄鎮h�呮鍒荤殑鐘舵��</b>锛屼笉鏄巻鍙插垎娈碉細
+ * <ul>
+ *   <li>{@code deptId}/{@code deptName} 鈥斺�� 褰撳墠绉戝锛�</li>
+ *   <li>{@code areaId}/{@code areaName} 鈥斺�� 褰撳墠鐥呭尯锛�</li>
+ *   <li>{@code bedNumber} 鈥斺�� 褰撳墠搴婁綅鍙凤紙瀹炴祴鍦ㄩ櫌鎮h�呮亽鏈夊�硷級锛�</li>
+ *   <li>{@code healthcareRecordStatus} 鈥斺�� 褰撳墠璇婄枟鐘舵�侊紙{@code FH0109.24}=鍦ㄩ櫌锛夈��</li>
+ * </ul>
+ * 鎺ュ彛杩斿洖 {@code data: []}锛堢┖鏁扮粍锛夎〃绀鸿鎮h�呭綋鍓�<b>涓嶅湪"鍏ラ櫌"鐘舵��</b>
+ * 锛堝凡鍑洪櫌 {@code FH0109.27} / 棰勫嚭闄� / 棰勫叆闄㈢瓑锛夛紝姝ゆ椂璋冪敤鏂瑰簲璺宠繃銆佷笉鍔ㄥ簱鍐呬綅缃��
+ *
+ * <h3>涓轰粈涔堟槸濂戠害 DTO</h3>
+ * 閲囬泦瀹炵幇锛圚TTP 璋冪敤锛夊綋鍓嶄粛鍦� smartor锛岃�� {@code ruoyi-datacollection}
+ * 涓嶈兘渚濊禆 smartor锛屾墍浠ョ被鍨嬪0鏄庡湪 common锛堜笌 {@link SltdGatherReq} 鍚屼竴鎵嬫硶锛夈��
+ * 瀛楁鍚嶄笌鎺ュ彛 JSON銆佷笌 smartor 鐨� {@code ServiceSLTDInhospResDTO} 鍙e緞涓�鑷淬��
+ *
+ * @author smartor
+ */
+@Data
+public class InhospPositionRecord {
+
+    /**
+     * 璇婄枟璁板綍鍙凤紙鍗� {@code pat_med_inhosp.serialnum}锛�
+     */
+    private String healthcareRecordNo;
+
+    /**
+     * 鎮h�呭鍚嶏紙浠呯敤浜庢棩蹇楀畾浣嶏級
+     */
+    private String patientName;
+
+    /**
+     * 褰撳墠绉戝ID 鈥斺�� 瀵瑰簲 {@code pat_med_inhosp.deptcode}
+     */
+    private Long deptId;
+
+    /**
+     * 褰撳墠绉戝鍚嶇О 鈥斺�� 瀵瑰簲 {@code pat_med_inhosp.deptname}
+     */
+    private String deptName;
+
+    /**
+     * 褰撳墠鐥呭尯ID 鈥斺�� 瀵瑰簲 {@code pat_med_inhosp.hospitaldistrictcode} 涓� {@code hospitaldistrictid}
+     */
+    private Long areaId;
+
+    /**
+     * 褰撳墠鐥呭尯鍚嶇О 鈥斺�� 瀵瑰簲 {@code pat_med_inhosp.hospitaldistrictname}
+     */
+    private String areaName;
+
+    /**
+     * 褰撳墠搴婁綅鍙� 鈥斺�� 瀵瑰簲 {@code pat_med_inhosp.bed_no}锛涗负绌鸿〃绀� HIS 渚у綋鍓嶆病鏈夊簥浣�
+     */
+    private String bedNumber;
+
+    /**
+     * 褰撳墠璇婄枟鐘舵�侊細{@code FH0109.24}=鍦ㄩ櫌
+     */
+    private String healthcareRecordStatus;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/SltdGatherReq.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/SltdGatherReq.java
new file mode 100644
index 0000000..4d0bf1c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/SltdGatherReq.java
@@ -0,0 +1,86 @@
+package com.ruoyi.common.core.service.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 鐪佺珛鍚屽痉 / 鍗楀崕闄勪竴锛堟潵鏈潵鎺ュ彛锛夐噰闆嗗叆鍙� 鈥斺�� {@link com.ruoyi.common.core.service.HisGatherApi} 鐨勫绾� DTO銆�
+ *
+ * <h3>瀛楁鍙e緞</h3>
+ * 鍙繚鐣�"閲囬泦缂栨帓鐪熸浼氳缃�"鐨勫瓧娈碉紝鍚箟涓� smartor 鐨�
+ * {@code ServiceSLTDInhospReqVO} / {@code ServiceSLTDDeptReqVO} <b>鍚屽悕鍚屼箟</b>
+ * 锛堣繖涓や釜鍐呴儴 VO 涓嶈兘琚柊妯″潡渚濊禆锛屾晠鍦ㄦ鍋氬绾﹀壇鏈級銆�
+ * smartor 渚� Bridge 璐熻矗閫愬瓧娈垫惉杩愶紝涓嶅仛浠讳綍琛ュ�兼垨鍒ゆ柇銆�
+ *
+ * <h3>涓轰粈涔堜竴涓� DTO 绠′笁绉嶉噰闆�</h3>
+ * 绉戝鐥呭尯锛堢敤 {@code orgId + campusIds}锛夈�佺敤鎴蜂俊鎭紙{@code orgId + campusId + statusList}锛夈��
+ * 璇婄枟璁板綍锛堝叾浣欐椂闂�/鐘舵�佸瓧娈碉級鍦ㄥ師瀹炵幇閲屾湰灏辨槸鍚屼竴鏃忓叆鍙傦紝鍒嗗紑瀹氫箟鍙細璁� Bridge 澶氬嚑娈垫惉杩愩��
+ *
+ * @author smartor
+ */
+@Data
+public class SltdGatherReq {
+
+    /**
+     * 鏈烘瀯ID锛堥噰闆嗙紪鎺掑浐瀹氫紶 20001001锛�
+     */
+    private String orgId;
+
+    /**
+     * 闄㈠尯ID锛堢敤鎴蜂俊鎭�佽瘖鐤楄褰曠敤锛�
+     */
+    private Long campusId;
+
+    /**
+     * 闄㈠尯ID闆嗗悎锛堢瀹ょ梾鍖虹敤锛�
+     */
+    private List<Long> campusIds;
+
+    /**
+     * 灏辫瘖鏃堕棿-寮�濮嬫椂闂达紙棰勫叆闄㈢敤锛泍yyy-MM-dd锛�
+     */
+    private String encounterTimeStart;
+
+    /**
+     * 灏辫瘖鏃堕棿-缁撴潫鏃堕棿锛堥鍏ラ櫌鐢紱yyyy-MM-dd锛�
+     */
+    private String encounterTimeEnd;
+
+    /**
+     * 鍏ラ櫌鏃堕棿-寮�濮嬫椂闂达紙鍏ラ櫌鐢紱yyyy-MM-dd锛�
+     */
+    private String startHeadTime;
+
+    /**
+     * 鍏ラ櫌鏃堕棿-缁撴潫鏃堕棿锛堝叆闄㈢敤锛泍yyy-MM-dd锛�
+     */
+    private String startTailTime;
+
+    /**
+     * 鍑洪櫌鏃堕棿-寮�濮嬫椂闂达紙鍑洪櫌鐢紱yyyy-MM-dd锛�
+     */
+    private String preOutHospitalHeadDate;
+
+    /**
+     * 鍑洪櫌鏃堕棿-缁撴潫鏃堕棿锛堝嚭闄㈢敤锛泍yyy-MM-dd锛�
+     */
+    private String preOutHospitalTailDate;
+
+    /**
+     * 璇婄枟鐘舵�侀泦鍚堬紙濡� FH0109.22 / FH0109.24 / FH0109.27锛�
+     */
+    private List<String> statusList;
+
+    /**
+     * 璇婄枟绫诲瀷闆嗗悎锛堝嚭闄㈤噰闆嗕細鏄惧紡缃� null锛�
+     */
+    private List<String> healthcareRecordTypeList;
+
+    /**
+     * 璇婄枟璁板綍鍙凤紙= {@code pat_med_inhosp.serialnum}锛夛紱
+     * 鐩墠鍙湁"鍦ㄩ櫌淇℃伅鍒锋柊"鐢ㄥ畠鎸夋偅鑰呭崟鏌ュ綋鍓嶄綅缃�
+     * 锛坽@link com.ruoyi.common.core.service.HisGatherApi#querySltdInhospPosition}锛夈��
+     */
+    private String healthcareRecordNo;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/VisitSubtaskDraft.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/VisitSubtaskDraft.java
index 7974c9c..42b9ee3 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/VisitSubtaskDraft.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/dto/VisitSubtaskDraft.java
@@ -85,10 +85,20 @@
     private String managementDoctorCode;
 
     // ==================== 绉戝/鐥呭尯锛堝師 patMedInhosp锛宼ype 4/5 浼氭敼鍐欙級 ====================
-    /** 绉戝缂栫爜锛坱ype 1/2/3 鍙� leave 缁村害锛泃ype 4/5 鍙栧叆闄㈢淮搴︼級 */
+    // 2026-11锛歴ervice_subtask 鐨� deptcode/deptname 鍒楁敼鍚嶄负 leaveldeptcode/leaveldeptname锛�
+    //          鍘� sendlimit* 绌洪棽鍒楀鐢ㄤ负銆屽湪闄㈢淮搴︺�嶇殑 hospitaldistrictcode/name锛堝湪闄㈢梾鍖猴級銆乨eptcode/name锛堝湪闄㈢瀹わ級銆�
+    /** 鍑洪櫌绉戝缂栫爜锛堣惤 service_subtask.leaveldeptcode锛涘師瀛楁鍚� deptcode锛� */
+    private String leaveldeptcode;
+    /** 鍑洪櫌绉戝鍚嶇О锛堣惤 service_subtask.leaveldeptname锛涘師瀛楁鍚� deptname锛� */
+    private String leaveldeptname;
+    /** 鍦ㄩ櫌绉戝缂栫爜锛堣惤 service_subtask.deptcode锛� */
     private String deptcode;
-    /** 绉戝鍚嶇О */
+    /** 鍦ㄩ櫌绉戝鍚嶇О锛堣惤 service_subtask.deptname锛� */
     private String deptname;
+    /** 鍦ㄩ櫌鐥呭尯缂栫爜锛堣惤 service_subtask.hospitaldistrictcode锛� */
+    private String hospitaldistrictcode;
+    /** 鍦ㄩ櫌鐥呭尯鍚嶇О锛堣惤 service_subtask.hospitaldistrictname锛� */
+    private String hospitaldistrictname;
     /** 绂婚櫌鐥呭尯缂栫爜锛坱ype 4/5 鍙栧叆闄㈢梾鍖猴級 */
     private String leavehospitaldistrictcode;
     /** 绂婚櫌鐥呭尯鍚嶇О */
@@ -419,6 +429,22 @@
         this.managementDoctorCode = managementDoctorCode;
     }
 
+    public String getLeaveldeptcode() {
+        return leaveldeptcode;
+    }
+
+    public void setLeaveldeptcode(String leaveldeptcode) {
+        this.leaveldeptcode = leaveldeptcode;
+    }
+
+    public String getLeaveldeptname() {
+        return leaveldeptname;
+    }
+
+    public void setLeaveldeptname(String leaveldeptname) {
+        this.leaveldeptname = leaveldeptname;
+    }
+
     public String getDeptcode() {
         return deptcode;
     }
@@ -435,6 +461,22 @@
         this.deptname = deptname;
     }
 
+    public String getHospitaldistrictcode() {
+        return hospitaldistrictcode;
+    }
+
+    public void setHospitaldistrictcode(String hospitaldistrictcode) {
+        this.hospitaldistrictcode = hospitaldistrictcode;
+    }
+
+    public String getHospitaldistrictname() {
+        return hospitaldistrictname;
+    }
+
+    public void setHospitaldistrictname(String hospitaldistrictname) {
+        this.hospitaldistrictname = hospitaldistrictname;
+    }
+
     public String getLeavehospitaldistrictcode() {
         return leavehospitaldistrictcode;
     }
diff --git a/ruoyi-datacollection/src/main/java/com/ruoyi/datacollection/service/impl/HisDataCollectionServiceImpl.java b/ruoyi-datacollection/src/main/java/com/ruoyi/datacollection/service/impl/HisDataCollectionServiceImpl.java
index 4ebe673..805a713 100644
--- a/ruoyi-datacollection/src/main/java/com/ruoyi/datacollection/service/impl/HisDataCollectionServiceImpl.java
+++ b/ruoyi-datacollection/src/main/java/com/ruoyi/datacollection/service/impl/HisDataCollectionServiceImpl.java
@@ -16,8 +16,10 @@
 import java.time.LocalTime;
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -41,6 +43,21 @@
  *       鈥斺�� 閭f槸"椤烘墜浼樺寲"锛屼細鏀瑰彉鏌ヨ璇箟锛屽洖褰掓椂鏃犳硶閫愭潯姣斿銆�</li>
  * </ul>
  *
+ * <h3>2026-10 淇锛氭帴鍙� 1500 鏉′笂闄愬鑷寸殑闈欓粯涓㈡暟</h3>
+ * 鏉ユ湭鏉� {@code dtcQueryHealthcareRecordList} <b>鍗曟鏈�澶氳繑鍥� 1500 鏉�</b>锛岃秴鍑洪儴鍒嗙洿鎺ユ埅鏂紝
+ * 涓� {@code code} 浠嶆槸 200銆佷笉鎶ラ敊銆傚師"4 澶╀竴娈�"鍦ㄥ嚭闄㈤珮宄版湡锛堥櫌鍐呮瘡澶� 380~500 鏉★級蹇呯劧瓒呴檺锛�
+ * 浜庢槸姣忔鎮勬倓灏戝嚑鍗佹潯 鈥斺�� 琛ㄧ幇涓�"鍥炴函璺戞垚鍔熶簡锛屼絾鏌愭湀鐥呭尯浜烘暟姣旂湡瀹炲�煎皯鍑犳潯"銆�
+ * <p>
+ * 鐜板湪鐨勫仛娉曪紙瑙� {@link #gatherRange}锛夛細
+ * <ol>
+ *   <li>濂戠害鏂规硶鏀逛负杩斿洖鏉℃暟锛岀紪鎺掍晶鎹鍒ゆ柇鏄惁瑙﹂《锛�</li>
+ *   <li>瑙﹂《灏辫<b>鏃ユ湡浜屽垎</b>閲嶉噰锛�4 澶� 鈫� 2 澶� 鈫� 1 澶╋級锛�</li>
+ *   <li>鍗曟棩浠嶈Е椤跺氨鎸� {@code statusList} <b>鎷嗙姸鎬�</b>閲嶉噰锛堢姸鎬佷簰鏂ワ紝鍙棤鎹熸媶鍒嗭級锛�</li>
+ *   <li>杩炲崟鏃ュ崟鐘舵�侀兘瑙﹂《鏃舵墦 ERROR锛堝弬鏁板凡鏃犳硶鍐嶆媶锛夛紝鎶�"杩欐涓嶅畬鏁�"鍠婂嚭鏉ワ紝鑰屼笉鏄户缁潤榛樸��</li>
+ * </ol>
+ * 浜屽垎鍙湪瑙﹂《鏃跺彂鐢燂紝姝e父鍒嗘浠嶇劧鍙彂 1 娆¤姹傦紝涓嶄細鎶婃棩甯稿洖婧殑璇锋眰閲忕炕鍑犲�嶃��
+ *
+ *
  * <h3>瀹冧笉绠′粈涔�</h3>
  * 鐪熸鐨勯噰闆嗗姩浣滐紙HTTP 鍙栨暟銆佸叆搴擄級涓嶅湪鏈被锛氶偅閲屼粛鍦� smartor锛岀粡
  * {@link HisGatherApi} 濂戠害璋冪敤锛屽悗缁垎鎵规惉杩涙湰妯″潡銆�
@@ -55,6 +72,47 @@
      * 鐪佺珛鍚屽痉 / 鍗楀崕闄勪竴鐨勬満鏋処D锛堝師瀹炵幇閲岀殑瀛楅潰閲� {@code "20001001"}锛�
      */
     private static final String SLTD_ORG_ID = "20001001";
+
+    /**
+     * 鏉ユ湭鏉ユ煡璇㈡帴鍙g殑鍗曟杩斿洖涓婇檺锛氳秴杩囪繖涓潯鏁�<b>涓嶆姤閿欍�佸彧鎴柇</b>銆�
+     * <p>
+     * 瀹炴祴 {@code dtcQueryHealthcareRecordList} 鏈� 1500 鏉$‖涓婇檺锛坽@code code} 浠嶄负 200锛�
+     * 鍒嗛〉鍙傛暟 {@code pageNo/pageSize/current/size} 鍧囨棤鏁堬級锛屾墍浠ュ彧鑳介潬璋冪敤鏂硅瘑鍒苟鎷嗗垎銆�
+     */
+    private static final int HIS_QUERY_LIMIT = 1500;
+
+    /**
+     * 鍥炴函鏃朵竴娈垫渶澶氳法鍑犲ぉ锛�4 澶╀负鍘嗗彶鍊硷級銆�
+     * <p>
+     * 娈甸暱鍙奖鍝�"骞虫椂瑕佸彂鍑犳璇锋眰"锛屽畨鍏ㄦ�х敱 {@link #gatherRange} 鐨勮Е椤朵簩鍒嗕繚璇侊紝
+     * 鎵�浠ヤ笉蹇呬负浜嗕繚瀹堟妸瀹冩敼鎴� 1 澶╋紙閭d細璁╂棩甯稿洖婧姹傞噺缈� 4 鍊嶏級銆�
+     */
+    private static final int BACKFILL_SEGMENT_DAYS = 4;
+
+    /**
+     * 棰勫叆闄� / 鍏ラ櫌 / 鍑洪櫌涓夌被閲囬泦鍚勮嚜鐨勭姸鎬佺爜锛堜笌鍘熷疄鐜颁竴涓�瀵瑰簲锛屾娊甯搁噺渚夸簬鎸夌姸鎬佹媶鍒嗛噸閲囷級
+     */
+    private static final List<String> PRE_ADMIT_STATUS = Collections.unmodifiableList(Arrays.asList("FH0109.22", "FH0109.23", "FH0109.53"));
+
+    private static final List<String> ADMIT_STATUS = Collections.singletonList("FH0109.24");
+
+    private static final List<String> DISCHARGE_STATUS = Collections.unmodifiableList(Arrays.asList("FH0109.27", "FH0109.25"));
+
+    /**
+     * 璇婄枟璁板綍鐨勪笁绫婚噰闆嗗彛寰勶細鍐冲畾鏃ユ湡鏉′欢钀藉湪 DTO 鐨勫摢涓�缁勫瓧娈典笂銆�
+     */
+    private enum RecordKind {
+
+        PRE_ADMIT("棰勫叆闄�"),
+        ADMIT("鍏ラ櫌"),
+        DISCHARGE("鍑洪櫌");
+
+        private final String label;
+
+        RecordKind(String label) {
+            this.label = label;
+        }
+    }
 
     /**
      * 褰撴椂绔欑偣鏍囪瘑锛堝師 {@code RyTask} 鐨� {@code @Value("${spring.profiles.active}")}锛�
@@ -173,91 +231,56 @@
                     hisGatherApi.gatherIcd10();
                 }
 
-                // nhfy/sltd鍥炴函30澶╁垎娈甸噰闆嗗垽鏂紙姣忔鏈�澶�4澶╋級
+                // nhfy/sltd鍥炴函30澶╁垎娈甸噰闆嗗垽鏂紙姣忔鏈�澶� BACKFILL_SEGMENT_DAYS 澶╋紝瑙﹂《鑷姩浜屽垎锛�
                 boolean isBackfill = (active.trim().equals("nhfy") || active.trim().equals("sltd")) && StringUtils.isNotBlank(todayZeroStr);
                 if (isBackfill) {
                     DateTimeFormatter dateFmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-                    LocalDate segStart = todayZero.toLocalDate().minusDays(30);
                     LocalDate segEndDate = todayZero.toLocalDate();
+                    // 绐楀彛 = [鍏ュ弬鏃ユ湡 - 30 澶�, 鍏ュ弬鏃ユ湡]锛屼袱绔兘鍚��
+                    // 鈿狅笍 鍏ュ弬鏃ユ湡"涔嬪悗"鐨勬暟鎹笉鍦ㄧ獥鍙e唴锛氭兂琛� 2026-07-31 灏辫浼� 2026-07-31锛屼紶 07-30 涓嶄細甯﹀嚭 7/31銆�
+                    LocalDate segStart = segEndDate.minusDays(30);
                     int segCount = 0;
+                    long fetchedTotal = 0L;
                     while (!segStart.isAfter(segEndDate)) {
-                        LocalDate segEnd = segStart.plusDays(3);
+                        LocalDate segEnd = segStart.plusDays(BACKFILL_SEGMENT_DAYS - 1L);
                         if (segEnd.isAfter(segEndDate)) {
                             segEnd = segEndDate;
                         }
                         segCount++;
                         log.info("銆恉ealHisData銆憑}鍥炴函绗瑊}娈甸噰闆嗭紝鏃ユ湡鑼冨洿锛歿} ~ {}", active.trim(), segCount, segStart.format(dateFmt), segEnd.format(dateFmt));
                         for (Long cid : campusidList) {
-                            collectSegmentData(cid, segStart.format(dateFmt), segEnd.format(dateFmt));
+                            fetchedTotal += collectSegmentData(cid, segStart.format(dateFmt), segEnd.format(dateFmt));
                         }
                         segStart = segEnd.plusDays(1);
                     }
-                    log.info("銆恉ealHisData銆憑}鍥炴函閲囬泦瀹屾垚锛屽叡{}娈�", active.trim(), segCount);
+                    log.info("銆恉ealHisData銆憑}鍥炴函閲囬泦瀹屾垚锛屽叡{}娈碉紝绐楀彛{} ~ {}锛屾帴鍙h繑鍥炶褰曞悎璁}鏉�", active.trim(), segCount,
+                            segEndDate.minusDays(30).format(dateFmt), segEndDate.format(dateFmt), fetchedTotal);
                 }
 
                 // 鐪佺珛鍚屽痉鏁版嵁閲囬泦锛堥潪鍥炴函妯″紡鎵嶆墽琛岋級
                 if (!isBackfill) {
+                    DateTimeFormatter dateFmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                     for (Long cid : campusidList) {
-                        log.info("銆恉ealHisData銆戠渷绔嬪悓寰烽鍏ラ櫌寮�濮嬮噰闆嗘暟鎹紝闄㈠尯锛歿}", cid);
-                        String nowTime = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
-                        SltdGatherReq serviceSLTDInhospReqVO = new SltdGatherReq();
-                        serviceSLTDInhospReqVO.setOrgId(SLTD_ORG_ID);
-                        serviceSLTDInhospReqVO.setCampusId(cid);
-                        serviceSLTDInhospReqVO.setEncounterTimeStart(nowTime);
-                        serviceSLTDInhospReqVO.setEncounterTimeEnd(nowTime);
+                        // sltd 鍙噰"浠婂ぉ"锛沶hfy 閲�"鏄ㄥぉ ~ 浠婂ぉ"锛堜笌鍘熷疄鐜颁竴鑷达級
+                        String nowTime = LocalDate.now().format(dateFmt);
+                        String head = nowTime;
+                        String tail = nowTime;
                         if (active.trim().equals("nhfy")) {
-                            serviceSLTDInhospReqVO.setEncounterTimeStart(yesterdayZero.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
-                            serviceSLTDInhospReqVO.setEncounterTimeEnd(todayZero.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+                            head = yesterdayZero.format(dateFmt);
+                            tail = todayZero.format(dateFmt);
                         }
-                        List<String> list = new ArrayList<>();
-                        list.add("FH0109.22");
-                        list.add("FH0109.23");
-                        list.add("FH0109.53");
-                        serviceSLTDInhospReqVO.setStatusList(list);
-//                        log.info("銆恉ealHisData銆戠渷绔嬪悓寰封�滈鍏ラ櫌鈥濋噰闆嗘暟鎹叆鍙傦細{}", serviceSLTDInhospReqVO);
-                        hisGatherApi.gatherSltdHealthcareRecords(serviceSLTDInhospReqVO);
+
+                        log.info("銆恉ealHisData銆戠渷绔嬪悓寰封�滈鍏ラ櫌鈥濆紑濮嬮噰闆嗘暟鎹紝闄㈠尯锛歿}", cid);
+                        gatherRange(cid, RecordKind.PRE_ADMIT, head, tail, PRE_ADMIT_STATUS);
                         log.info("銆恉ealHisData銆戠渷绔嬪悓寰封�滈鍏ラ櫌鈥濈祼鏉熼噰闆嗘暟鎹紝闄㈠尯锛歿}", cid);
 
                         log.info("銆恉ealHisData銆戠渷绔嬪悓寰封�滃叆闄⑩�濆紑濮嬮噰闆嗘暟鎹紝闄㈠尯锛歿}", cid);
-                        serviceSLTDInhospReqVO.setOrgId(SLTD_ORG_ID);
-                        serviceSLTDInhospReqVO.setCampusId(cid);
-                        serviceSLTDInhospReqVO.setEncounterTimeStart(null);
-                        serviceSLTDInhospReqVO.setEncounterTimeEnd(null);
-                        serviceSLTDInhospReqVO.setStartHeadTime(nowTime);
-                        serviceSLTDInhospReqVO.setStartTailTime(nowTime);
-                        if (active.trim().equals("nhfy")) {
-                            serviceSLTDInhospReqVO.setStartHeadTime(yesterdayZero.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
-                            serviceSLTDInhospReqVO.setStartTailTime(todayZero.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
-                        }
-                        List<String> listStr = new ArrayList<>();
-                        listStr.add("FH0109.24");
-                        serviceSLTDInhospReqVO.setStatusList(listStr);
-//                        log.info("銆恉ealHisData銆戠渷绔嬪悓寰封�滃叆闄⑩�濋噰闆嗘暟鎹叆鍙傦細{}", serviceSLTDInhospReqVO);
-                        hisGatherApi.gatherSltdHealthcareRecords(serviceSLTDInhospReqVO);
+                        gatherRange(cid, RecordKind.ADMIT, head, tail, ADMIT_STATUS);
                         log.info("銆恉ealHisData銆戠渷绔嬪悓寰封�滃叆闄⑩�濈祼鏉熼噰闆嗘暟鎹紝闄㈠尯锛歿}", cid);
 
                         log.info("銆恉ealHisData銆戠渷绔嬪悓寰封�滃嚭闄⑩�濆紑濮嬮噰闆嗘暟鎹紝闄㈠尯锛歿}", cid);
-                        serviceSLTDInhospReqVO.setStartHeadTime(null);
-                        serviceSLTDInhospReqVO.setStartTailTime(null);
-                        serviceSLTDInhospReqVO.setEncounterTimeStart(null);
-                        serviceSLTDInhospReqVO.setEncounterTimeEnd(null);
-                        serviceSLTDInhospReqVO.setPreOutHospitalHeadDate(nowTime);
-                        serviceSLTDInhospReqVO.setPreOutHospitalTailDate(nowTime);
-                        if (active.trim().equals("nhfy")) {
-                            serviceSLTDInhospReqVO.setPreOutHospitalHeadDate(yesterdayZero.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
-                            serviceSLTDInhospReqVO.setPreOutHospitalTailDate(todayZero.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
-                        }
-                        serviceSLTDInhospReqVO.setHealthcareRecordTypeList(null);
-                        List<String> list2 = new ArrayList<>();
-//                    list2.add("FH0108.02");
-                        //鍑洪櫌
-                        list2.add("FH0109.27");
-                        //棰勫嚭闄�
-                        list2.add("FH0109.25");
-                        serviceSLTDInhospReqVO.setStatusList(list2);
-//                        log.info("銆恉ealHisData銆戠渷绔嬪悓寰封�滃嚭闄⑩�濋噰闆嗘暟鎹叆鍙傦細{}", serviceSLTDInhospReqVO);
-                        hisGatherApi.gatherSltdHealthcareRecords(serviceSLTDInhospReqVO);
-                        log.info("銆恉ealHisData銆戠渷绔嬪悓寰封�滃嚭闄⑩�濇潫閲囬泦鏁版嵁锛岄櫌鍖猴細{}", cid);
+                        gatherRange(cid, RecordKind.DISCHARGE, head, tail, DISCHARGE_STATUS);
+                        log.info("銆恉ealHisData銆戠渷绔嬪悓寰封�滃嚭闄⑩�濈祼鏉熼噰闆嗘暟鎹紝闄㈠尯锛歿}", cid);
                     }
                 }
 
@@ -268,74 +291,124 @@
     }
 
     /**
-     * 鍒嗘閲囬泦鏁版嵁锛堥鍏ラ櫌銆佸叆闄€�佸嚭闄級
-     * 鐢ㄤ簬nhfy/sltd鍥炴函閲囬泦锛屾瘡娆℃渶澶氭煡璇�7澶╂暟鎹�
+     * 鍒嗘閲囬泦鏁版嵁锛堥鍏ラ櫌銆佸叆闄€�佸嚭闄級銆�
+     * <p>
+     * 娈甸暱瑙� {@link #BACKFILL_SEGMENT_DAYS}锛屾瘡绫婚噰闆嗗唴閮ㄨ繕浼氬仛"瑙﹂《浜屽垎"锛堣 {@link #gatherRange}锛夛紝
+     * 鍥犳涓嶄細鍥犱负鏉ユ湭鏉ユ帴鍙� 1500 鏉′笂闄愯�屾倓鎮勫皯鏁版嵁銆�
      *
      * @param cid          闄㈠尯ID
      * @param startDateStr 鏃ユ湡寮�濮� yyyy-MM-dd
      * @param endDateStr   鏃ユ湡缁撴潫 yyyy-MM-dd
+     * @return 鏈涓夌被閲囬泦鎺ュ彛杩斿洖鐨勮褰曟暟鍚堣锛堝洖婧粨鏉熸椂鐢ㄤ簬鎬婚噺鏍稿锛�
      */
-    private void collectSegmentData(Long cid, String startDateStr, String endDateStr) {
-//        // 棰勫叆闄�
+    private int collectSegmentData(Long cid, String startDateStr, String endDateStr) {
+        int count = 0;
+
         log.info("銆恉ealHisData銆戦鍏ラ櫌寮�濮嬮噰闆嗘暟鎹紝闄㈠尯锛歿}锛屾椂闂存锛歿} ~ {}", cid, startDateStr, endDateStr);
-        SltdGatherReq reqVO = new SltdGatherReq();
-        reqVO.setOrgId(SLTD_ORG_ID);
-        reqVO.setCampusId(cid);
-        reqVO.setEncounterTimeStart(startDateStr);
-        reqVO.setEncounterTimeEnd(endDateStr);
-        List<String> preAdmitStatus = new ArrayList<>();
-        preAdmitStatus.add("FH0109.22");
-        preAdmitStatus.add("FH0109.23");
-        preAdmitStatus.add("FH0109.53");
-        reqVO.setStatusList(preAdmitStatus);
-        log.info("銆恉ealHisData銆戦鍏ラ櫌閲囬泦鏁版嵁鍏ュ弬锛歿}", reqVO);
-        try {
-            hisGatherApi.gatherSltdHealthcareRecords(reqVO);
-        } catch (Exception e) {
-            // 鍗曠被鏁版嵁澶辫触涓嶅啀鍚戜笂鎶涳細鍚﹀垯涓�娈靛け璐ヤ細璁╂湰娆″洖婧悗闈㈢殑鎵�鏈夋閮戒笉鎵ц
-            log.error("銆恉ealHisData銆戦鍏ラ櫌閲囬泦澶辫触锛岃烦杩囪绫荤户缁�傞櫌鍖猴細{}锛屾椂闂存锛歿} ~ {}", cid, startDateStr, endDateStr, e);
-        }
+        count += gatherRange(cid, RecordKind.PRE_ADMIT, startDateStr, endDateStr, PRE_ADMIT_STATUS);
         log.info("銆恉ealHisData銆戦鍏ラ櫌绲備簡閲囬泦鏁版嵁锛岄櫌鍖猴細{}", cid);
 
-        // 鍏ラ櫌
         log.info("銆恉ealHisData銆戝叆闄㈠紑濮嬮噰闆嗘暟鎹紝闄㈠尯锛歿}锛屾椂闂存锛歿} ~ {}", cid, startDateStr, endDateStr);
-        reqVO = new SltdGatherReq();
-        reqVO.setOrgId(SLTD_ORG_ID);
-        reqVO.setCampusId(cid);
-        reqVO.setStartHeadTime(startDateStr);
-        reqVO.setStartTailTime(endDateStr);
-        List<String> admitStatus = new ArrayList<>();
-        admitStatus.add("FH0109.24");
-        reqVO.setStatusList(admitStatus);
-        log.info("銆恉ealHisData銆戝叆闄㈤噰闆嗘暟鎹叆鍙傦細{}", reqVO);
-        try {
-            hisGatherApi.gatherSltdHealthcareRecords(reqVO);
-        } catch (Exception e) {
-            // 鍗曠被鏁版嵁澶辫触涓嶅啀鍚戜笂鎶涳細鍚﹀垯涓�娈靛け璐ヤ細璁╂湰娆″洖婧悗闈㈢殑鎵�鏈夋閮戒笉鎵ц
-            log.error("銆恉ealHisData銆戝叆闄㈤噰闆嗗け璐ワ紝璺宠繃璇ョ被缁х画銆傞櫌鍖猴細{}锛屾椂闂存锛歿} ~ {}", cid, startDateStr, endDateStr, e);
-        }
+        count += gatherRange(cid, RecordKind.ADMIT, startDateStr, endDateStr, ADMIT_STATUS);
         log.info("銆恉ealHisData銆戝叆闄㈢祩浜嗛噰闆嗘暟鎹紝闄㈠尯锛歿}", cid);
 
-        // 鍑洪櫌
         log.info("銆恉ealHisData銆戝嚭闄㈠紑濮嬮噰闆嗘暟鎹紝闄㈠尯锛歿}锛屾椂闂存锛歿} ~ {}", cid, startDateStr, endDateStr);
-        reqVO = new SltdGatherReq();
-        reqVO.setOrgId(SLTD_ORG_ID);
-        reqVO.setCampusId(cid);
-        reqVO.setPreOutHospitalHeadDate(startDateStr);
-        reqVO.setPreOutHospitalTailDate(endDateStr);
-        List<String> dischargeStatus = new ArrayList<>();
-        //鍑洪櫌
-        dischargeStatus.add("FH0109.27");
-        //棰勫嚭闄�
-        dischargeStatus.add("FH0109.25");
-        reqVO.setStatusList(dischargeStatus);
-        log.info("銆恉ealHisData銆戝嚭闄㈤噰闆嗘暟鎹叆鍙傦細{}", reqVO);
-        try {
-            hisGatherApi.gatherSltdHealthcareRecords(reqVO);
-        } catch (Exception e) {
-            // 鍗曠被鏁版嵁澶辫触涓嶅啀鍚戜笂鎶涳細鍚﹀垯涓�娈靛け璐ヤ細璁╂湰娆″洖婧悗闈㈢殑鎵�鏈夋閮戒笉鎵ц
-            log.error("銆恉ealHisData銆戝嚭闄㈤噰闆嗗け璐ワ紝璺宠繃璇ョ被缁х画銆傞櫌鍖猴細{}锛屾椂闂存锛歿} ~ {}", cid, startDateStr, endDateStr, e);
-        }
+        count += gatherRange(cid, RecordKind.DISCHARGE, startDateStr, endDateStr, DISCHARGE_STATUS);
         log.info("銆恉ealHisData銆戝嚭闄㈢粨鏉熼噰闆嗘暟鎹紝闄㈠尯锛歿}", cid);
+
+        return count;
+    }
+
+    /**
+     * 鎸夐噰闆嗗彛寰勭粍瑁呭叆鍙傦細涓夌被鐨勫尯鍒彧鍦�"鏃ユ湡鏉′欢钀藉湪鍝竴缁勫瓧娈典笂"銆�
+     *
+     * @param cid      闄㈠尯ID
+     * @param kind     棰勫叆闄� / 鍏ラ櫌 / 鍑洪櫌
+     * @param from     璧峰鏃ユ湡 yyyy-MM-dd
+     * @param to       鎴鏃ユ湡 yyyy-MM-dd锛堝惈锛�
+     * @param statuses 璇ュ彛寰勫搴旂殑鐘舵�佺爜
+     */
+    private SltdGatherReq buildReq(Long cid, RecordKind kind, String from, String to, List<String> statuses) {
+        SltdGatherReq req = new SltdGatherReq();
+        req.setOrgId(SLTD_ORG_ID);
+        req.setCampusId(cid);
+        switch (kind) {
+            case PRE_ADMIT:
+                req.setEncounterTimeStart(from);
+                req.setEncounterTimeEnd(to);
+                break;
+            case ADMIT:
+                req.setStartHeadTime(from);
+                req.setStartTailTime(to);
+                break;
+            case DISCHARGE:
+                req.setPreOutHospitalHeadDate(from);
+                req.setPreOutHospitalTailDate(to);
+                // 鍑洪櫌閲囬泦鍙寜鍑洪櫌鏃堕棿杩囨护锛岃瘖鐤楃被鍨嬫樉寮忕疆 null锛堜笌鍘熷疄鐜颁竴鑷达級
+                req.setHealthcareRecordTypeList(null);
+                break;
+            default:
+                break;
+        }
+        req.setStatusList(statuses);
+        return req;
+    }
+
+    /**
+     * 閲囦竴娈碉紝蹇呰鏃舵媶灏忛噸閲囷紝杩斿洖杩欐瀹為檯鍙栧埌鐨勮褰曟暟銆�
+     *
+     * <p>鏉ユ湭鏉ユ帴鍙e崟娆℃渶澶氳繑鍥� {@link #HIS_QUERY_LIMIT} 鏉★紝瓒呭嚭閮ㄥ垎<b>鐩存帴鎴柇涓斾笉鎶ラ敊</b>锛�
+     * 鎵�浠ュ彧鑳界敤"杩斿洖鏉℃暟瑙﹂《"鏉ヨ瘑鍒紝骞舵寜涓嬮潰鐨勯『搴忔媶鍒嗭紙<b>鍙湁瑙﹂《鎵嶄細鎷嗭紝骞虫椂浠嶆槸 1 娆¤姹�</b>锛夛細
+     * <ol>
+     *   <li>璺ㄥ澶╋細鏃ユ湡瀵瑰崐鎷嗭紝閫掑綊閲嶉噰锛�</li>
+     *   <li>宸茬缉鍒板崟澶╋細鎸� {@code statusList} 鎷嗭紙鐘舵�佷簰鏂ワ紝鎷嗗紑鏃笉婕忎篃涓嶉噸锛夛紱</li>
+     *   <li>鍗曟棩鍗曠姸鎬佷粛瑙﹂《锛氭墦 ERROR 鈥斺�� 璇锋眰鍙傛暟缁村害宸茬敤灏斤紝鍙兘闈犱汉鐪嬫棩蹇楄ˉ閲囥��</li>
+     * </ol>
+     *
+     * @param cid      闄㈠尯ID
+     * @param kind     棰勫叆闄� / 鍏ラ櫌 / 鍑洪櫌
+     * @param from     璧峰鏃ユ湡 yyyy-MM-dd
+     * @param to       鎴鏃ユ湡 yyyy-MM-dd锛堝惈锛�
+     * @param statuses 璇ュ彛寰勫搴旂殑鐘舵�佺爜
+     * @return 瀹為檯鍙栧埌鐨勮褰曟暟锛堟媶鍒嗗悗涓哄悇瀛愭涔嬪拰锛�
+     */
+    private int gatherRange(Long cid, RecordKind kind, String from, String to, List<String> statuses) {
+        SltdGatherReq req = buildReq(cid, kind, from, to, statuses);
+        log.info("銆恉ealHisData銆憑}閲囬泦鍏ュ弬锛歿}", kind.label, req);
+
+        int count;
+        try {
+            count = hisGatherApi.gatherSltdHealthcareRecords(req);
+        } catch (Exception e) {
+            // 鍗曠被鏁版嵁澶辫触涓嶅悜涓婃姏锛氬惁鍒欎竴娈靛け璐ヤ細璁╂湰娆″洖婧悗闈㈢殑鎵�鏈夋閮戒笉鎵ц
+            log.error("銆恉ealHisData銆憑}閲囬泦澶辫触锛岃烦杩囪绫荤户缁�傞櫌鍖猴細{}锛屾椂闂存锛歿} ~ {}", kind.label, cid, from, to, e);
+            return 0;
+        }
+        if (count < HIS_QUERY_LIMIT) {
+            return count;
+        }
+
+        // 鍛戒腑涓婇檺锛氭帴鍙d笉鎶ラ敊锛屽彧鏄妸瓒呭嚭鐨勬暟鎹涪鎺夛紝蹇呴』鎷嗗皬閲嶉噰
+        LocalDate start = LocalDate.parse(from);
+        LocalDate end = LocalDate.parse(to);
+        if (start.isBefore(end)) {
+            LocalDate mid = start.plusDays(ChronoUnit.DAYS.between(start, end) / 2);
+            log.warn("銆恉ealHisData銆憑}涓�娆¤繑鍥炶Е杈炬帴鍙d笂闄� {} 鏉★紝鎸夋棩鏈熶簩鍒嗛噸閲囥�傞櫌鍖猴細{}锛寋} ~ {} => {} ~ {} / {} ~ {}",
+                    kind.label, HIS_QUERY_LIMIT, cid, from, to, from, mid, mid.plusDays(1), to);
+            return gatherRange(cid, kind, from, mid.toString(), statuses)
+                    + gatherRange(cid, kind, mid.plusDays(1).toString(), to, statuses);
+        }
+        if (statuses.size() > 1) {
+            log.warn("銆恉ealHisData銆憑}鍗曟棩浠嶈Е杈炬帴鍙d笂闄� {} 鏉★紝鎸夌姸鎬佹媶鍒嗛噸閲囥�傞櫌鍖猴細{}锛屾棩鏈燂細{}锛岀姸鎬侊細{}",
+                    kind.label, HIS_QUERY_LIMIT, cid, from, statuses);
+            int sum = 0;
+            for (String status : statuses) {
+                sum += gatherRange(cid, kind, from, to, Collections.singletonList(status));
+            }
+            return sum;
+        }
+        log.error("銆恉ealHisData銆憑}鍗曟棩鍗曠姸鎬佷粛瑙﹁揪鎺ュ彛涓婇檺 {} 鏉★紝宸叉棤娉曞啀鎷嗗垎锛屾湰娆℃暟鎹彲鑳戒笉瀹屾暣锛侀櫌鍖猴細{}锛屾棩鏈燂細{}锛岀姸鎬侊細{}",
+                kind.label, HIS_QUERY_LIMIT, cid, from, statuses);
+        return count;
     }
 }
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
index 032ee22..bab599b 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
@@ -52,6 +52,11 @@
         configMap.put("sfStatistics", defaultConfig.entryTtl(Duration.ofMinutes(20)));
         configMap.put("sfStatisticsJoy", defaultConfig.entryTtl(Duration.ofMinutes(20)));
         configMap.put("selectPatMedOuthospList", defaultConfig.entryTtl(Duration.ofMinutes(20)));
+        // 闅忚鍒嗙被缁熻锛�/smartor/serviceSubtask/getSfStatisticsCount锛夛細
+        // 涔嬪墠娌℃湁鍦ㄨ繖閲岀櫥璁帮紝璧扮殑鏄病鏈� TTL 鐨勯粯璁ら厤缃� 鈥斺�� 缂撳瓨姘镐笉杩囨湡锛�
+        // 缁熻鍖洪棿鍖呭惈鈥滀粖澶┾�濇椂椤甸潰浼氫竴鐩存樉绀虹涓�娆℃煡璇㈢殑鏃ф暟瀛楋紝Redis 閲屼篃浼氭棤闄愬爢绉��
+        // 杩欓噷缁� 20 鍒嗛挓锛屼笌鍏跺畠缁熻缂撳瓨淇濇寔涓�鑷淬��
+        configMap.put("getSfStatisticsScript", defaultConfig.entryTtl(Duration.ofMinutes(20)));
         return RedisCacheManager.builder(connectionFactory).cacheDefaults(defaultConfig).withInitialCacheConfigurations(configMap).build();
     }
 
diff --git a/ruoyi-inhospvisit/src/main/java/com/ruoyi/inhospvisit/support/VisitSubtaskFactory.java b/ruoyi-inhospvisit/src/main/java/com/ruoyi/inhospvisit/support/VisitSubtaskFactory.java
index d5f44db..3b6de07 100644
--- a/ruoyi-inhospvisit/src/main/java/com/ruoyi/inhospvisit/support/VisitSubtaskFactory.java
+++ b/ruoyi-inhospvisit/src/main/java/com/ruoyi/inhospvisit/support/VisitSubtaskFactory.java
@@ -119,14 +119,24 @@
         d.setHospno(inhosp.getInhospno());
         d.setDrcode(inhosp.getDrcode());
         d.setDrname(inhosp.getDrname());
-        d.setDeptcode(inhosp.getLeaveldeptcode());
-        d.setDeptname(inhosp.getLeaveldeptname());
+        d.setLeaveldeptcode(inhosp.getLeaveldeptcode());
+        d.setLeaveldeptname(inhosp.getLeaveldeptname());
         d.setLeavehospitaldistrictcode(inhosp.getLeavehospitaldistrictcode());
         d.setLeavehospitaldistrictname(inhosp.getLeavehospitaldistrictname());
+        // ---- 2026-11 鏂板锛氬湪闄㈢淮搴﹁惤銆屽鐢ㄥ垪銆� ----
+        //   鑳屾櫙锛歴ervice_subtask 鐨� deptcode/deptname 鏀瑰悕 leaveldeptcode/leaveldeptname锛�
+        //         鍘� sendlimitabegin/aend銆乻endlimitpbegin/pend 鍥涗釜绌哄垪澶嶇敤涓�
+        //         hospitaldistrictcode/name锛堝湪闄㈢梾鍖猴級銆乨eptcode/name锛堝湪闄㈢瀹わ級銆�
+        //   鍙e緞锛氬嚭闄㈢淮搴︿粛鎸夊師鍐欐硶钀� leavel*锛堜笅闈� type 4/5 鐨勮鐩栦篃淇濇寔鍘熸牱锛岃惤搴撲綅缃笉鍙橈級锛�
+        //         杩欓噷鍙槸鎶� pat_med_inhosp 鐨勩�屽湪闄㈢瀹� / 鍦ㄩ櫌鐥呭尯銆嶉澶栧瓨涓�浠斤紝渚夸簬鎸夊湪闄㈢淮搴︾粺璁°��
+        d.setDeptcode(inhosp.getDeptcode());
+        d.setDeptname(inhosp.getDeptname());
+        d.setHospitaldistrictcode(inhosp.getHospitaldistrictcode());
+        d.setHospitaldistrictname(inhosp.getHospitaldistrictname());
         // ---- 鍘� L1128-1134锛歵ype 4/5 鏀圭敤鍏ラ櫌缁村害 ----
         if (type != null && (type == 4 || type == 5)) {
-            d.setDeptcode(inhosp.getDeptcode());
-            d.setDeptname(inhosp.getDeptname());
+            d.setLeaveldeptcode(inhosp.getDeptcode());
+            d.setLeaveldeptname(inhosp.getDeptname());
             d.setLeavehospitaldistrictcode(inhosp.getHospitaldistrictcode());
             d.setLeavehospitaldistrictname(inhosp.getHospitaldistrictname());
         }
@@ -266,8 +276,13 @@
         d.setInhospid(inhosp.getInhospid());
         d.setDrcode(inhosp.getDrcode());
         d.setDrname(inhosp.getDrname());
-        d.setDeptcode(inhosp.getLeaveldeptcode());
-        d.setDeptname(inhosp.getLeaveldeptname());
+        d.setLeaveldeptcode(inhosp.getLeaveldeptcode());
+        d.setLeaveldeptname(inhosp.getLeaveldeptname());
+        // 2026-11锛氬叆闄�/鍦ㄩ櫌缁村害钀姐�屽鐢ㄥ垪銆嶏紙鍙e緞鍚� boxedServiceSubtask锛�
+        d.setDeptcode(inhosp.getDeptcode());
+        d.setDeptname(inhosp.getDeptname());
+        d.setHospitaldistrictcode(inhosp.getHospitaldistrictcode());
+        d.setHospitaldistrictname(inhosp.getHospitaldistrictname());
         d.setLeavehospitaldistrictcode(inhosp.getLeavehospitaldistrictcode());
         d.setLeavehospitaldistrictname(inhosp.getLeavehospitaldistrictname());
         // ---- 鍘� L1242-1251 ----
diff --git a/ruoyi-inhospvisit/src/main/resources/mapper/inhospvisit/PatMedInhospMapper.xml b/ruoyi-inhospvisit/src/main/resources/mapper/inhospvisit/PatMedInhospMapper.xml
index fd25c50..15c47f3 100644
--- a/ruoyi-inhospvisit/src/main/resources/mapper/inhospvisit/PatMedInhospMapper.xml
+++ b/ruoyi-inhospvisit/src/main/resources/mapper/inhospvisit/PatMedInhospMapper.xml
@@ -1233,7 +1233,7 @@
             AND visit_time &lt; DATE_ADD(#{endDate}, INTERVAL 1 DAY)
         </if>
         <if test="deptcodeList != null and deptcodeList.size() > 0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="deptcodeList" item="deptcode" open="(" separator="," close=")">
                 #{deptcode}
             </foreach>
diff --git a/ruoyi-othervisit/src/main/java/com/ruoyi/othervisit/service/OperationVisitTaskService.java b/ruoyi-othervisit/src/main/java/com/ruoyi/othervisit/service/OperationVisitTaskService.java
index 027a325..e43d7ee 100644
--- a/ruoyi-othervisit/src/main/java/com/ruoyi/othervisit/service/OperationVisitTaskService.java
+++ b/ruoyi-othervisit/src/main/java/com/ruoyi/othervisit/service/OperationVisitTaskService.java
@@ -283,8 +283,8 @@
 //        serviceSubtask.setInhospid(patMedOperation1.getInhospid());
         serviceSubtask.setDrcode(patMedOperation1.getDrcode());
         serviceSubtask.setDrname(patMedOperation1.getDrname());
-        serviceSubtask.setDeptcode(patMedOperation1.getDeptcode());
-        serviceSubtask.setDeptname(patMedOperation1.getDeptname());
+        serviceSubtask.setLeaveldeptcode(patMedOperation1.getDeptcode());
+        serviceSubtask.setLeaveldeptname(patMedOperation1.getDeptname());
         serviceSubtask.setTemplateid(serviceTask.getTemplateid());
         serviceSubtask.setTemplatename(serviceTask.getTemplatename());
         serviceSubtask.setPatid(patArchive.getId());
diff --git a/ruoyi-outpatientvisit/src/main/java/com/ruoyi/outpatientvisit/service/OuthospVisitTaskService.java b/ruoyi-outpatientvisit/src/main/java/com/ruoyi/outpatientvisit/service/OuthospVisitTaskService.java
index cd436ba..611941d 100644
--- a/ruoyi-outpatientvisit/src/main/java/com/ruoyi/outpatientvisit/service/OuthospVisitTaskService.java
+++ b/ruoyi-outpatientvisit/src/main/java/com/ruoyi/outpatientvisit/service/OuthospVisitTaskService.java
@@ -318,10 +318,13 @@
         // ---- 鏉ヨ嚜闂ㄨ瘖璁板綍 ----
         d.setDrcode(row.getDrcode());
         d.setDrname(row.getDrname());
-        d.setDeptcode(row.getDeptcode());
+        // 2026-11锛氳崏绋跨殑 deptcode/deptname 宸叉敼鍚嶄负 leaveldeptcode/leaveldeptname锛堝嚭闄㈢淮搴﹀垪锛夛紝
+        //          闂ㄨ瘖绉戝缁х画钀藉悓涓�鍒楋紝闂ㄨ瘖渚�**涓嶅~**鍏ラ櫌缁村害閭e洓涓鐢ㄥ垪
+        //          鈥斺�� 涓庢敼閫犲墠鐨勮惤搴撲綅缃畬鍏ㄤ竴鑷达紙闂ㄨ瘖鍚勯」缁熻灏辨槸鎸夎繖鍒楄繃婊ょ殑锛夈��
+        d.setLeaveldeptcode(row.getDeptcode());
         d.setInhospid(row.getId());
         d.setHospno(row.getOuthospno());
-        d.setDeptname(row.getDeptname());
+        d.setLeaveldeptname(row.getDeptname());
         d.setLeavediagname(row.getDiagname());
         d.setLeaveicd10code(row.getIcd10code());
         d.setVisitDeptCode(row.getDeptcode());
diff --git a/ruoyi-phone/src/main/java/com/ruoyi/phone/api/PhoneFacade.java b/ruoyi-phone/src/main/java/com/ruoyi/phone/api/PhoneFacade.java
index 97c9b44..721fc42 100644
--- a/ruoyi-phone/src/main/java/com/ruoyi/phone/api/PhoneFacade.java
+++ b/ruoyi-phone/src/main/java/com/ruoyi/phone/api/PhoneFacade.java
@@ -158,11 +158,11 @@
      */
     private boolean available(String method) {
         if (!phoneSwitch.isEnabled()) {
-            log.warn("銆愮數璇濄�戞ā鍧楀凡鍏抽棴锛堝弬鏁伴厤缃� phone.enabled=false锛夛紝{} 鏈璋冪敤闄嶇骇涓虹┖缁撴灉", method);
+            log.info("銆愮數璇濄�戞ā鍧楀凡鍏抽棴锛堝弬鏁伴厤缃� phone.enabled=false锛夛紝{} 鏈璋冪敤闄嶇骇涓虹┖缁撴灉", method);
             return false;
         }
         if (phoneService == null) {
-            log.warn("銆愮數璇濄�戞湭鎵惧埌鐢佃瘽妯″潡瀹炵幇锛圛PhoneService 缂哄け锛夛紝{} 鏈璋冪敤闄嶇骇涓虹┖缁撴灉", method);
+            log.info("銆愮數璇濄�戞湭鎵惧埌鐢佃瘽妯″潡瀹炵幇锛圛PhoneService 缂哄け锛夛紝{} 鏈璋冪敤闄嶇骇涓虹┖缁撴灉", method);
             return false;
         }
         return true;
diff --git a/ruoyi-phone/src/main/java/com/ruoyi/phone/service/impl/PhoneServiceImpl.java b/ruoyi-phone/src/main/java/com/ruoyi/phone/service/impl/PhoneServiceImpl.java
index 33123ee..b6e3e55 100644
--- a/ruoyi-phone/src/main/java/com/ruoyi/phone/service/impl/PhoneServiceImpl.java
+++ b/ruoyi-phone/src/main/java/com/ruoyi/phone/service/impl/PhoneServiceImpl.java
@@ -1234,7 +1234,7 @@
     }
 
     private List<PullTaskVO> getPullTaskList(List<String> subIds, String cacheName) {
-        log.error("浠诲姟鎷夊彇subIds鐨勫�兼槸澶氬皯锛歿}", subIds);
+        log.info("浠诲姟鎷夊彇subIds鐨勫�兼槸澶氬皯锛歿}", subIds);
         //pullTaskVOList鐢ㄤ簬鏁版嵁杩斿洖
         List<PullTaskVO> pullTaskVOList = new ArrayList<>();
         //newValue0鐢ㄤ簬淇濆瓨娌℃湁澶勭悊鐨勫瓙 浠诲姟
@@ -1259,14 +1259,18 @@
                     taskSubtaskApi.updateSubtask(serviceSubtask);
                     continue;
                 }
+                log.info("serviceSubtask.getTaskid()鏈夊�煎悧锛燂紵锛焮}",serviceSubtask.getTaskid());
                 ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
+                log.info("serviceTask鏈夊�煎悧锛燂紵锛焮}",serviceTask);
                 IvrTaskTemplate ivrTaskTemplate = ivrTaskTemplateService.selectIvrTaskTemplateByID(serviceSubtask.getTemplateid());
+                log.info("ivrTaskTemplate鏈夊�煎悧锛燂紵锛焮}",ivrTaskTemplate);
                 if (ObjectUtils.isEmpty(ivrTaskTemplate)) continue;
                 //閫氳繃浠诲姟妯℃澘涓殑"绗竴娆¢棶棰樼紪鍙�"鑾峰彇绗竴涓棶棰�;
                 IvrTaskTemplateScript ivrTaskTemplateScript = null;
                 IvrTaskTemplateScript ivrTaskTemplateScript1 = new IvrTaskTemplateScript();
                 ivrTaskTemplateScript1.setTemplateID(ivrTaskTemplate.getId());
                 List<IvrTaskTemplateScript> ivrTaskTemplateScripts = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptList(ivrTaskTemplateScript1);
+                log.info("ivrTaskTemplateScripts鏈夊�煎悧锛燂紵锛焮}",ivrTaskTemplateScripts.size());
                 aa:
                 for (IvrTaskTemplateScript ivrTaskTemplateScript2 : ivrTaskTemplateScripts) {
                     if (ivrTaskTemplate.getFirstQuestionNum() == Long.valueOf(ivrTaskTemplateScript2.getSort())) {
@@ -1276,7 +1280,7 @@
                 }
                 //濡傛灉ivrTaskTemplateScript涓虹┖锛屼篃灏辨病鏈夊線涓嬫墽琛岀殑蹇呰浜�
                 if (ObjectUtils.isEmpty(ivrTaskTemplateScript)) {
-                    log.error("---------杩欎釜ivrTaskTemplate.getId()鐨勯棶棰樹负绌猴細{}", ivrTaskTemplate.getId());
+                    log.info("---------杩欎釜ivrTaskTemplate.getId()鐨勯棶棰樹负绌猴細{}", ivrTaskTemplate.getId());
                     continue;
                 }
                 //鑾峰彇閫氶厤绗﹀尮閰嶈繃鍚庣殑闂
@@ -1284,7 +1288,7 @@
                 if (StringUtils.isEmpty(scriptContent)) scriptContent = ivrTaskTemplateScript.getScriptContent();
                 String scrContent = getObject(serviceSubtask, scriptContent);
                 String kcb = serviceTask.getKcb() + "," + scrContent;
-
+                log.info("---------杩欎釜kcb鏄暐锛歿}", kcb);
                 //灏佽杩斿洖鏁版嵁
                 //taskId = 瀛愪换鍔D + 闂ID +闂搴忓彿
                 pullTaskVO.setTaskid(subId);
@@ -1295,13 +1299,14 @@
                 if (cacheName.equals("cache-0")) pullTaskVO.setDisplayNo("2");
                 else pullTaskVO.setDisplayNo("2");
                 pullTaskVOList.add(pullTaskVO);
+                log.info("---------杩欎釜pullTaskVO鏄暐锛歿}", pullTaskVO);
                 redisCache.setCacheObject(subId.trim() + "-" + serviceSubtask.getPhone().trim(), ivrTaskTemplateScript.getId().toString(), 120, TimeUnit.MINUTES);
             } else {
                 newValue0.add(subIds.get(i));
                 redisCache.setCacheListRight(cacheName, newValue0);
             }
         }
-
+        log.info("111111111浠诲姟鎷夊彇pullTaskVOList鐨勫�兼槸澶氬皯锛歿}", pullTaskVOList);
         return pullTaskVOList;
     }
 
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
index ff0e3e7..8cde35d 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
@@ -1558,10 +1558,10 @@
     private String resolveShiyiCampus(ServiceSubtask serviceSubtask) {
         SysDept sysDeptVo = new SysDept();
         List<SysDept> sysDepts = new ArrayList<>();
-        if (ObjectUtils.isNotEmpty(serviceSubtask.getDeptcode())) {
+        if (ObjectUtils.isNotEmpty(serviceSubtask.getLeaveldeptcode())) {
             sysDeptVo.setDeptType("1");
             sysDeptVo.setOrgid(serviceSubtask.getOrgid());
-            sysDeptVo.setDeptCode(serviceSubtask.getDeptcode());
+            sysDeptVo.setDeptCode(serviceSubtask.getLeaveldeptcode());
             sysDeptService.selectDeptList(sysDeptVo);
         } else if (ObjectUtils.isNotEmpty(serviceSubtask.getLeavehospitaldistrictcode())) {
             sysDeptVo.setDeptType("2");
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/config/SatisfactionSwitch.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/config/SatisfactionSwitch.java
index 6603274..cb326b7 100644
--- a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/config/SatisfactionSwitch.java
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/config/SatisfactionSwitch.java
@@ -52,6 +52,24 @@
     public static final String CONFIG_KEY = "satisfaction.enabled";
 
     /**
+     * 婊℃剰搴︺�岀患鍚堝緱鍒嗗彛寰勩�嶇珯鐐瑰弬鏁伴敭鍚嶃��
+     * <p>
+     * 鍊煎彇 {@link com.ruoyi.satisfaction.service.strategy.SatisfactionSites} 鐨勬爣璇嗭細
+     * <ul>
+     *   <li>{@code sltd}锛堥粯璁わ級鈥斺�� 鐪佺珛鍚屽痉鍙e緞锛氭寜閫夐」鏂囨鍒や簲妗e姞鏉冿紱</li>
+     *   <li>{@code common}锛堝埆鍚� {@code nanhua}锛夆�斺�� 閫氱敤/鍗楀崕鍙e緞锛氭寜鏄庣粏 score 姹傚钩鍧囥��</li>
+     * </ul>
+     * 鏈弬鏁版槸 2026-10-21 鏂板鐨勶細{@code /smartor/serviceSubtaskDetail/sltdMydTotalByScore}
+     * 鍘熸潵鎶婂彛寰勫啓姝绘垚 SLTD锛屽崡鍗庤皟鐢ㄦ椂浜旀。鏂囨涓�鏉¢兘鍖归厤涓嶄笂锛岀患鍚堝緱鍒嗘亽涓� 0.00銆�
+     */
+    public static final String SITE_CONFIG_KEY = "satisfaction.site";
+
+    /**
+     * 鏈厤缃珯鐐规椂鐨勯粯璁ゅ彛寰勶細淇濇寔鍘嗗彶琛屼负锛圫LTD 鍙e緞锛�
+     */
+    private static final String DEFAULT_SITE = com.ruoyi.satisfaction.service.strategy.SatisfactionSites.SLTD;
+
+    /**
      * 杩涚▼鍐呯紦瀛樻湁鏁堟湡锛堟绉掞級
      */
     private static final long CACHE_TTL_MILLIS = 10_000L;
@@ -77,6 +95,16 @@
     private volatile long cachedAt;
 
     /**
+     * 鏈�杩戜竴娆¤В鏋愬埌鐨勩�岀患鍚堝緱鍒嗗彛寰勩�嶇珯鐐�
+     */
+    private volatile String cachedSite;
+
+    /**
+     * 鏈�杩戜竴娆¤В鏋愮珯鐐圭殑鏃堕棿鎴�
+     */
+    private volatile long cachedSiteAt;
+
+    /**
      * Spring 浣跨敤鐨勬瀯閫犲櫒銆�
      * <p>
      * 鈿狅笍 <b>蹇呴』鏄惧紡鏍囨敞 {@code @Autowired}</b>锛氭湰绫绘湁涓や釜鍏紑鏋勯�犲櫒
@@ -99,6 +127,9 @@
         // 闈� Spring 鐜涓嬫病鏈�"鏀归厤缃悗绛� 10 绉�"鐨勬蹇碉紝鐩存帴绂佺敤缂撳瓨锛屼繚璇佹柇瑷�鍗虫椂鍙
         this.cachedEnabled = resolve();
         this.cachedAt = System.currentTimeMillis() + CACHE_TTL_MILLIS * 1000L;
+        // 娴嬭瘯鐢ㄧ殑 FixedProvider 瀵逛换浣� key 閮借繑鍥炲悓涓�涓�硷紝杩欓噷涓嶈璇妸瀹冨綋鎴愮珯鐐归厤缃�
+        this.cachedSite = DEFAULT_SITE;
+        this.cachedSiteAt = System.currentTimeMillis() + CACHE_TTL_MILLIS * 1000L;
     }
 
     /**
@@ -121,13 +152,48 @@
      */
     public void invalidateCache() {
         this.cachedEnabled = null;
+        this.cachedSite = null;
+    }
+
+    /**
+     * 褰撳墠鐨�<b>缁煎悎寰楀垎鍙e緞绔欑偣</b>锛坽@code sys_config: satisfaction.site}锛岃繍琛屾椂鐑锛屾渶澶� 10 绉掑欢杩燂級
+     * <p>
+     * 鏈厤缃椂杩斿洖 {@link #DEFAULT_SITE}锛坽@code sltd}锛夛紝淇濇寔鍘嗗彶琛屼负涓嶅彉锛�
+     * 鍗楀崕閮ㄧ讲璇锋妸璇ュ弬鏁伴厤鎴� {@code common}锛堝埆鍚� {@code nanhua}锛夈��
+     *
+     * @return 褰掍竴鍖栧悗鐨勭珯鐐规爣璇嗭紙瑙� {@link com.ruoyi.satisfaction.service.strategy.SatisfactionSites}锛�
+     */
+    public String site() {
+        long now = System.currentTimeMillis();
+        String cached = this.cachedSite;
+        if (cached != null && now - this.cachedSiteAt < CACHE_TTL_MILLIS) {
+            return cached;
+        }
+        String site = resolveSite();
+        this.cachedSite = site;
+        this.cachedSiteAt = now;
+        return site;
+    }
+
+    /**
+     * 瑙f瀽绔欑偣鍙e緞锛歴ys_config 浼樺厛锛岀己鐪佺敤 {@link #DEFAULT_SITE}
+     */
+    private String resolveSite() {
+        String value = readConfig(SITE_CONFIG_KEY);
+        if (value != null) {
+            String site = com.ruoyi.satisfaction.service.strategy.SatisfactionSites.normalize(value);
+            log.debug("銆愭弧鎰忓害銆戠患鍚堝緱鍒嗗彛寰勫彇鑷� sys_config锛歿}={} -> site={}", SITE_CONFIG_KEY, value, site);
+            return site;
+        }
+        log.debug("銆愭弧鎰忓害銆憇ys_config 涓湭閰嶇疆 {}锛屽洖钀介粯璁ょ珯鐐� {}锛堝悓寰峰彛寰勶級", SITE_CONFIG_KEY, DEFAULT_SITE);
+        return DEFAULT_SITE;
     }
 
     /**
      * 瑙f瀽褰撳墠寮�鍏冲�硷細sys_config 浼樺厛锛屽叾娆� yml 鍏滃簳
      */
     private boolean resolve() {
-        String value = readFromSysConfig();
+        String value = readConfig(CONFIG_KEY);
         if (value != null) {
             if (!"true".equalsIgnoreCase(value) && !"false".equalsIgnoreCase(value)) {
                 log.warn("銆愭弧鎰忓害銆憇ys_config 涓� {} 鐨勫�间笉鏄� true/false锛堝疄闄�=銆寋}銆嶏級锛屽皢鎸夈�屼笉鏄� false 鍗冲惎鐢ㄣ�嶅鐞�",
@@ -145,7 +211,7 @@
     /**
      * 璇� sys_config 鐨勫師濮嬮敭鍊硷紱娌℃湁瀹炵幇銆佹病鏈夎繖涓�琛屻�佹垨璇诲簱澶辫触閮借繑鍥� {@code null}
      */
-    private String readFromSysConfig() {
+    private String readConfig(String key) {
         if (configServiceProvider == null) {
             return null;
         }
@@ -154,7 +220,7 @@
             if (configService == null) {
                 return null;
             }
-            String value = configService.selectConfigByKey(CONFIG_KEY);
+            String value = configService.selectConfigByKey(key);
             if (value == null || value.trim().isEmpty()) {
                 return null;
             }
@@ -162,7 +228,7 @@
         } catch (Exception e) {
             // 瀹瑰櫒娌℃湁瀹炵幇銆佹暟鎹簮寮傚父銆丼QL 鎶ラ敊鈥︹�︿竴寰嬫寜"鍙傛暟缂哄け"澶勭悊锛坒ail-open锛夛紝缁濅笉褰卞搷涓绘祦绋�
             log.warn("銆愭弧鎰忓害銆戣鍙� sys_config 鐨� {} 澶辫触锛屾湰娆℃寜鏈厤缃鐞嗭紙fail-open锛夛細{}",
-                    CONFIG_KEY, e.toString());
+                    key, e.toString());
             return null;
         }
     }
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/controller/SltdSatisfactionController.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/controller/SltdSatisfactionController.java
index 88e3810..c89ab48 100644
--- a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/controller/SltdSatisfactionController.java
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/controller/SltdSatisfactionController.java
@@ -2,6 +2,7 @@
 
 import com.ruoyi.common.annotation.AddOrgId;
 import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.satisfaction.config.SatisfactionSwitch;
 import com.ruoyi.satisfaction.domain.ServiceSubtaskDetailRatioExport;
 import com.ruoyi.satisfaction.domain.dto.QuestionResultDTO;
 import com.ruoyi.satisfaction.domain.row.SatisfactionSubtaskQuery;
@@ -12,7 +13,6 @@
 import com.ruoyi.satisfaction.domain.vo.SltdMydTotalVO;
 import com.ruoyi.satisfaction.service.SatisfactionSubtaskService;
 import com.ruoyi.satisfaction.service.strategy.SatisfactionScoreStrategyResolver;
-import com.ruoyi.satisfaction.service.strategy.SatisfactionSites;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.apache.commons.collections4.CollectionUtils;
@@ -53,11 +53,22 @@
 public class SltdSatisfactionController extends BaseController {
 
     /**
-     * 绔欑偣鍙e緞绛栫暐瑙f瀽鍣細缁煎悎婊℃剰搴﹀緱鍒嗘寜绔欑偣锛堢渷绔嬪悓寰凤級鍙栫瓥鐣ヨ绠楋紝
+     * 绔欑偣鍙e緞绛栫暐瑙f瀽鍣細缁煎悎婊℃剰搴﹀緱鍒嗘寜绔欑偣鍙栫瓥鐣ヨ绠楋紝
      * 涓嶅啀鎶婄畻娉曚笌甯搁噺鍐欏湪 Controller 閲屻��
+     * <p>
+     * 绔欑偣鏉ヨ嚜 {@code sys_config: satisfaction.site}锛堣 {@link SatisfactionSwitch#site()}锛夛細
+     * 鍚屽痉鐢� {@code sltd}锛堜簲妗f枃妗堝姞鏉冿級锛屽崡鍗庣敤 {@code common}锛堟寜鏄庣粏 score 姹傚钩鍧囷級銆�
      */
     @Autowired
     private SatisfactionScoreStrategyResolver satisfactionScoreStrategyResolver;
+
+    /**
+     * 杩愯鏃堕厤缃紙绔欑偣鍙e緞锛夈��2026-10-21 鏂板锛�
+     * 鍘熸潵杩欓噷鎶婂彛寰勫啓姝绘垚 {@code SatisfactionSites.SLTD}锛屽崡鍗庣殑鏁版嵁锛堟病鏈�"寰堟弧鎰�/婊℃剰/鈥�"浜旀。鏂囨锛�
+     * 涓�鏉¢�夐」閮藉尮閰嶄笉涓� 鈫� 缁煎悎寰楀垎鎭掍负 0.00銆�
+     */
+    @Autowired
+    private SatisfactionSwitch satisfactionSwitch;
 
     @Autowired
     private SatisfactionSubtaskService satisfactionSubtaskService;
@@ -83,8 +94,22 @@
                 query.setServiceType(st);
                 query.setEndOutHospTime(sltdMydTotalVO.getEndOutHospTime());
                 query.setStartOutHospTime(sltdMydTotalVO.getStartOutHospTime());
+                //瀹屾垚鏃堕棿锛氶〉闈㈡彁浜ょ殑鏄� startFinishTime / endFinishTime銆�
+                //鍘熸潵杩欎袱涓潯浠舵病鏈夊悜涓嬩紶锛屽彇瀛愪换鍔$殑 SQL 瀹屽叏娌℃湁鏃堕棿鏉′欢
+                //鈫� 鍙e緞鍋忓ぇ锛堢粺璁′簡鍏ㄩ儴鍘嗗彶锛変笖 service_subtask 琚暣琛ㄦ壂鎻�
+                query.setStartFinishTime(sltdMydTotalVO.getStartFinishTime());
+                query.setEndFinishTime(sltdMydTotalVO.getEndFinishTime());
                 query.setDeptOrDistrict(sltdMydTotalVO.getDeptOrDistrict());
+                //鐥呭尯 / 绉戝锛氭寜銆屼紶杩涙潵鐨勬槸鍝竴缁勫弬鏁般�嶅喅瀹氳繃婊ゅ摢涓�鍒楋紝涓嶅啀涓�寰嬫寜绂婚櫌鐥呭尯杩囨护
+                //  hospitaldistrictcodes      鈫� hospitaldistrictcode      鍦ㄩ櫌/褰撳墠鐥呭尯
+                //  leavehospitaldistrictcodes 鈫� leavehospitaldistrictcode 绂婚櫌鐥呭尯
+                //  deptcodes                  鈫� deptcode                 鍦ㄩ櫌/褰撳墠绉戝
+                //  leaveldeptcodes            鈫� leaveldeptcode           绂婚櫌绉戝
+                //鍘熸潵 hospitaldistrictcodes 杩欎釜瀛楁鍦� VO 涓婃牴鏈笉瀛樺湪锛岃 Jackson 闈欓粯涓㈠純锛�
+                //瀵艰嚧鐥呭尯鏉′欢浠庢湭鎷艰繘 SQL锛堟煡 40003514 鐥呭尯鍗存妸楠ㄧ绛夊叾瀹冪梾鍖虹殑鏁版嵁涓�璧风粺璁′簡锛�
+                query.setHospitaldistrictcodes(sltdMydTotalVO.getHospitaldistrictcodes());
                 query.setLeavehospitaldistrictcodes(sltdMydTotalVO.getLeavehospitaldistrictcodes());
+                query.setDeptcodes(sltdMydTotalVO.getDeptcodes());
                 query.setLeaveldeptcodes(sltdMydTotalVO.getLeaveldeptcodes());
                 //鏈烘瀯/闄㈠尯鐢� @AddOrgId 娉ㄥ叆锛岃惤鍒版煡璇㈡潯浠朵笂锛岄伩鍏嶈法鏈烘瀯鍙栨暟
                 query.setOrgid(sltdMydTotalVO.getOrgid());
@@ -165,7 +190,7 @@
      */
     private String calcMydScore(List<ServiceSubtaskDetailRatioExport> exportList) {
         BigDecimal score = satisfactionScoreStrategyResolver
-                .resolve(SatisfactionSites.SLTD)
+                .resolve(satisfactionSwitch.site())
                 .comprehensiveScore(exportList);
         return score == null ? "0.00" : score.toPlainString();
     }
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/entity/SatisfactionStatQuery.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/entity/SatisfactionStatQuery.java
index a94666b..e5b497a 100644
--- a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/entity/SatisfactionStatQuery.java
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/entity/SatisfactionStatQuery.java
@@ -53,6 +53,18 @@
     private List<String> hospitaldistrictcodes;
 
     /**
+     * 绂婚櫌绉戝闆嗗悎锛堝搴� service_subtask.leaveldeptcode锛�
+     */
+    @ApiModelProperty(value = "绂婚櫌绉戝闆嗗悎")
+    private List<String> leaveldeptcodes;
+
+    /**
+     * 绂婚櫌鐥呭尯闆嗗悎锛堝搴� service_subtask.leavehospitaldistrictcode锛�
+     */
+    @ApiModelProperty(value = "绂婚櫌鐥呭尯闆嗗悎")
+    private List<String> leavehospitaldistrictcodes;
+
+    /**
      * 鍩虹妯℃澘Ids锛坕vr 鐢� templateid锛岄棶鍗风敤 svyid锛�
      */
     @ApiModelProperty(value = "鍩虹妯℃澘Ids")
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/row/SatisfactionSubtaskQuery.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/row/SatisfactionSubtaskQuery.java
index f2ca5ae..0ae8446 100644
--- a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/row/SatisfactionSubtaskQuery.java
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/row/SatisfactionSubtaskQuery.java
@@ -51,20 +51,54 @@
     private Date endOutHospTime;
 
     /**
-     * 缁村害鏍囪瘑锛歿@code 1} 琛ㄧず鎸夌梾鍖鸿繃婊�
+     * 瀹屾垚寮�濮嬫椂闂达紙鎸� finishtime 杩囨护锛屽搴旈〉闈㈡彁浜ょ殑 {@code startFinishTime}锛�
      * <p>
-     * 鈿狅笍 鍘� SQL 鐢ㄧ殑鏄� {@code <if test="deptOrDistrict==1">}锛堜笌鏁板瓧姣旇緝锛夛紝
-     * 鍥犳杩欓噷鏄� {@code Integer}锛屽彇鍊艰涔変笌鍘熸潵涓�鑷淬��
+     * 鈿狅笍 2026-10-21 鏂板锛氬師鏉ュ彧鏈� outHospTime 涓や釜瀛楁锛岃�岄〉闈㈡彁浜ょ殑鏄�
+     * {@code startFinishTime / endFinishTime}锛孋ontroller 涔熸病鏈夋妸瀹冧滑浼犱笅鏉ワ紝
+     * 浜庢槸鍙栧瓙浠诲姟鏃�<b>瀹屽叏娌℃湁鏃堕棿鏉′欢</b> 鈥斺�� 鏃㈠鑷寸粺璁″彛寰勪笉瀵癸紝涔熷鑷�
+     * {@code service_subtask} 琚叏閲忔壂鎻忋�佷笅娓告槑缁嗙粺璁℃嬁鍒板嚑涓囦釜 id銆�
+     */
+    private Date startFinishTime;
+
+    /**
+     * 瀹屾垚缁撴潫鏃堕棿锛堟寜 finishtime 杩囨护锛�
+     */
+    private Date endFinishTime;
+
+    /**
+     * 缁村害缁勫悎鏂瑰紡锛氱梾鍖虹淮搴︿笌绉戝缁村害涔嬮棿鍙� AND 杩樻槸 OR銆�
+     * <ul>
+     *   <li>{@code 1}锛氱梾鍖� AND 绉戝锛堥〉闈㈤粯璁ゅ�硷級</li>
+     *   <li>{@code 2}锛氱梾鍖� OR 绉戝</li>
+     *   <li>鍏跺畠鍙栧�硷細娌跨敤鏃ц涓猴紙鍙湅绉戝锛�</li>
+     * </ul>
+     * 瀛楁绫诲瀷鏄� {@code String}锛堝叆鍙傛槸 JSON 瀛楃涓诧級锛孲QL 閲岀敤 {@code q.deptOrDistrict==1}
+     * 涓庢暟瀛楁瘮杈� 鈥斺�� OGNL 浼氭妸 {@code "1"} 杞垚鏁板瓧鍐嶆瘮锛岀粨璁轰笌瀛楃涓叉瘮杈冧竴鑷达紝
+     * 杩欓噷淇濈暀鍘熷啓娉曚笉鍔紝閬垮厤鏀瑰彛寰勩��
      */
     private String deptOrDistrict = "1";
 
     /**
-     * 鐥呭尯浠g爜鍒楄〃锛堜粎鍦� {@code deptOrDistrict == 1} 鏃剁敓鏁堬級
+     * 鍦ㄩ櫌/褰撳墠鐥呭尯浠g爜鍒楄〃 鈫� 钀藉埌 {@code service_subtask.hospitaldistrictcode}
+     * <p>
+     * 涓� {@link #leavehospitaldistrictcodes} 鏄�屽悓涓�缁村害鐨勪袱鍒椼�嶏細鍝釜鍙傛暟浼犺繘鏉ュ氨杩囨护鍝竴鍒楋紝
+     * 涓嶅啀涓�寰嬫寜绂婚櫌鐥呭尯杩囨护锛堝崡鍗庤繖鎵规暟鎹梾鍖哄啓鍦� hospitaldistrictcode锛�
+     * leavehospitaldistrictcode 鍩烘湰涓虹┖锛屽彧璁ゅ悗鑰呬細璁╃粺璁″彧鍓╁嚑鏉★級銆�
+     */
+    private List<String> hospitaldistrictcodes;
+
+    /**
+     * 绂婚櫌鐥呭尯浠g爜鍒楄〃 鈫� 钀藉埌 {@code service_subtask.leavehospitaldistrictcode}
      */
     private List<String> leavehospitaldistrictcodes;
 
     /**
-     * 绉戝浠g爜鍒楄〃
+     * 鍦ㄩ櫌/褰撳墠绉戝浠g爜鍒楄〃 鈫� 钀藉埌 {@code service_subtask.deptcode}
+     */
+    private List<String> deptcodes;
+
+    /**
+     * 绂婚櫌绉戝浠g爜鍒楄〃 鈫� 钀藉埌 {@code service_subtask.leaveldeptcode}
      */
     private List<String> leaveldeptcodes;
 }
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/PatSatisfactionReqVO.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/PatSatisfactionReqVO.java
index a665a83..fc98def 100644
--- a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/PatSatisfactionReqVO.java
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/PatSatisfactionReqVO.java
@@ -90,5 +90,17 @@
     @ApiModelProperty(value = "鐥呭尯闆嗗悎")
     private List<String> hospitaldistrictcodes;
 
+    /**
+     * 绂婚櫌绉戝闆嗗悎锛堝搴� service_subtask.leaveldeptcode锛�
+     */
+    @ApiModelProperty(value = "绂婚櫌绉戝闆嗗悎")
+    private List<String> leaveldeptcodes;
+
+    /**
+     * 绂婚櫌鐥呭尯闆嗗悎锛堝搴� service_subtask.leavehospitaldistrictcode锛�
+     */
+    @ApiModelProperty(value = "绂婚櫌鐥呭尯闆嗗悎")
+    private List<String> leavehospitaldistrictcodes;
+
 
 }
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/QuestionCountKsOrBqVO.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/QuestionCountKsOrBqVO.java
index 7412daf..4aa1cf0 100644
--- a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/QuestionCountKsOrBqVO.java
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/QuestionCountKsOrBqVO.java
@@ -26,9 +26,9 @@
     private static final long serialVersionUID = 1L;
 
     /**
-     * 绉戝涓庣梾鍖虹殑鏌ヨ鏄痮r杩樻槸and:   1:and(榛樿)(绂婚櫌鐥呭尯涓庣闄㈢瀹ょ粍鍚�)     2:or(绂婚櫌鐥呭尯涓庣闄㈢瀹ょ粍鍚�)    3:and(绂婚櫌鐥呭尯涓庨殢璁跨瀹ょ粍鍚�)   4:or(绂婚櫌鐥呭尯涓庨殢璁跨瀹ょ粍鍚�)
+     * 绉戝涓庣梾鍖虹殑鏌ヨ鏄痮r杩樻槸and:   1:and(榛樿)(绂婚櫌鐥呭尯涓庣闄㈢瀹ょ粍鍚�)     2:or(绂婚櫌鐥呭尯涓庣闄㈢瀹ょ粍鍚�)    3:and(鍦ㄩ櫌鐥呭尯涓庡湪闄㈢瀹ょ粍鍚�)   4:or(鍦ㄩ櫌鐥呭尯涓庡湪闄㈢瀹ょ粍鍚�)
      */
-    @ApiModelProperty(value = "绉戝涓庣梾鍖虹殑鏌ヨ鏄痮r杩樻槸and:   1:and(榛樿)(绂婚櫌鐥呭尯涓庣闄㈢瀹ょ粍鍚�)     2:or(绂婚櫌鐥呭尯涓庣闄㈢瀹ょ粍鍚�)    3:and(绂婚櫌鐥呭尯涓庨殢璁跨瀹ょ粍鍚�)   4:or(绂婚櫌鐥呭尯涓庨殢璁跨瀹ょ粍鍚�)")
+    @ApiModelProperty(value = "绉戝涓庣梾鍖虹殑鏌ヨ鏄痮r杩樻槸and:   1:and(榛樿)(绂婚櫌鐥呭尯涓庣闄㈢瀹ょ粍鍚�)     2:or(绂婚櫌鐥呭尯涓庣闄㈢瀹ょ粍鍚�)    3:and(鍦ㄩ櫌鐥呭尯涓庡湪闄㈢瀹ょ粍鍚�)   4:or(鍦ㄩ櫌鐥呭尯涓庨殢鍦ㄩ櫌瀹ょ粍鍚�)")
     private String deptOrDistrict = "1";
 
     /**
@@ -51,6 +51,18 @@
     private List<String> leaveldeptcodes;
 
     /**
+     * 鍦ㄩ櫌鐥呭尯缂栧彿闆嗗悎锛堝搴� service_subtask.hospitaldistrictcode锛�
+     */
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯闆嗗悎")
+    private List<String> hospitaldistrictcodes;
+
+    /**
+     * 鍦ㄩ櫌绉戝缂栧彿闆嗗悎锛堝搴� service_subtask.deptcode锛�
+     */
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝闆嗗悎")
+    private List<String> deptcodes;
+
+    /**
      * 寮�濮嬪嚭闄㈡棩鏈�
      */
     @JsonFormat(pattern = "yyyy-MM-dd")
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/SltdMydTotalVO.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/SltdMydTotalVO.java
index 13e34d8..670979c 100644
--- a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/SltdMydTotalVO.java
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/domain/vo/SltdMydTotalVO.java
@@ -36,6 +36,28 @@
     private List<String> leavehospitaldistrictcodes;
 
     /**
+     * 鐥呭尯缂栧彿闆嗗悎锛堥〉闈€�岀梾鍖恒�嶉�夋嫨鍣ㄥ疄闄呬紶鐨勫瓧娈靛悕锛夈��
+     * <p>
+     * 鈿狅笍 <b>2026-10-21 淇銆屾寜鐥呭尯缁熻鍗存妸鍒殑鐥呭尯鏁版嵁涔熺畻杩涙潵銆�</b>锛�
+     * 鍓嶇鎻愪氦鐨勬槸 {@code hospitaldistrictcodes}锛岃�屾湰 VO 鍙湁 {@code leavehospitaldistrictcodes}锛�
+     * Jackson 閬囧埌鏈煡瀛楁鐩存帴涓㈠純锛堟湭寮�鍚� FAIL_ON_UNKNOWN_PROPERTIES锛夛紝
+     * 浜庢槸鐥呭尯鏉′欢琚�<b>闈欓粯涓㈠純</b>锛孲QL 閲� {@code leavehospitaldistrictcode IN (...)} 姘歌繙涓嶆嫾锛�
+     * 缁熻鑼冨洿閫�鍖栨垚銆屾湰闄㈠尯 + 璇ユ湇鍔$被鍨� + 璇ユ椂闂存銆嶇殑鍏ㄩ儴鏁版嵁 鈥斺�� 鎵�浠ユ煡 40003514 鐥呭尯鍗存妸楠ㄧ绠楄繘鏉ヤ簡銆�
+     * <p>
+     * 鐜板湪涓や釜瀛楁閮芥帴鍙楋紝鍙栨暟鏃� {@code hospitaldistrictcodes} 浼樺厛锛堣 {@code SltdSatisfactionController}锛夈��
+     */
+    @ApiModelProperty(value = "鐥呭尯code闆嗗悎(椤甸潰鐥呭尯閫夋嫨鍣ㄤ紶鍏ワ紱涓� leavehospitaldistrictcodes 绛変环锛屼紭鍏堜娇鐢�)")
+    private List<String> hospitaldistrictcodes;
+
+    /**
+     * 閮ㄩ棬/绉戝 code 闆嗗悎锛堥〉闈€�岀瀹ゃ�嶉�夋嫨鍣ㄥ疄闄呬紶鐨勫瓧娈靛悕锛屽搴斿湪闄㈢瀹わ級銆�
+     * <p>
+     * 涓� {@code leaveldeptcodes} 鏄悓涓�缁村害鐨勪袱涓垪锛氬摢涓紶杩涙潵灏辨寜鍝竴鍒楄繃婊ゃ��
+     */
+    @ApiModelProperty(value = "绉戝code闆嗗悎(椤甸潰绉戝閫夋嫨鍣ㄤ紶鍏ワ紝瀵瑰簲鍦ㄩ櫌绉戝锛涗笌 leaveldeptcodes 鎸夊垪鍖哄垎)")
+    private List<String> deptcodes;
+
+    /**
      * 閮ㄩ棬code
      */
     @Excel(name = "  閮ㄩ棬code")
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/mapper/SatisfactionMapper.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/mapper/SatisfactionMapper.java
index 34ce21d..268abc8 100644
--- a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/mapper/SatisfactionMapper.java
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/mapper/SatisfactionMapper.java
@@ -57,6 +57,28 @@
      */
     List<String> selectSatisfactionSubtaskTypes(PatSatisfactionReqVO patSatisfactionReqVO);
 
+    /**
+     * 婊℃剰搴︾粺璁★細鏈鏉′欢涓�<b>鐪熸涓嬪彂杩囦换鍔�</b>鐨勬ā鏉� id锛堝幓閲嶏級銆�
+     * <p>
+     * <b>涓轰粈涔堥渶瑕佸畠</b>锛歿@code /statistics} 鐨勯鐩潵婧愭槸
+     * {@code SatisfactionScriptMapper.querySvyScriptByCategory} / {@code queryIvrScriptByAssort}锛�
+     * 鍙寜銆屾弧鎰忓害鍒嗙被銆嶅彇搴撻噷鐨勫叏閮ㄩ鐩紝<b>涓嶇湅妯℃澘銆佷笉鐪嬫椂闂�</b>銆�
+     * 棰樺簱閲屾瘡澶氭寕杩涗竴濂楀巻鍙查棶鍗锋ā鏉匡紙棰樼洰杩樺湪銆佷絾浠庢潵娌′笅鍙戣繃浠诲姟锛夛紝
+     * 缁熻缁撴灉灏变細澶氬嚭涓�鏁存壒銆屽緱鍒� 0 / 绛旈浜烘暟 0銆嶇殑琛�
+     * 锛堝疄娴嬶細婊℃剰搴﹀垎绫讳笅 6 濂楁ā鏉� 69 閬撻锛屾湰鏈熷彧鏈� 2 濂� 25 閬撻鏈夋暟鎹級銆�
+     * <p>
+     * 杩欓噷鎸変笌 {@link #selectSatisfactionSubtaskTypes} <b>瀹屽叏鐩稿悓鐨勬潯浠�</b>
+     * 锛坥rgid銆乻erviceTypes銆佺瀹� OR 鐥呭尯銆佺闄㈢瀹� OR 鐥呭尯銆佹椂闂村厹搴曞彛寰勶級鍙栨ā鏉� id锛�
+     * 璋冪敤鏂规嵁姝ゆ妸棰樺簱棰樼洰瑁佸壀鎴愩�屾湰鏈熺湡姝e湪鐢ㄧ殑妯℃澘銆嶏紝
+     * 浣胯繑鍥炶鏁板彧鐢卞綋鍓嶇敓鏁堢殑闂嵎鍐冲畾锛岃�屼笉鏄搴撳巻鍙茬Н绱��
+     *
+     * @param query 鏌ヨ鏉′欢锛堝鐢� {@link PatSatisfactionReqVO} 鐨勫瓧娈碉級
+     * @param type  service_subtask.type锛�1 璇煶銆�2 闂嵎
+     * @return 鍘婚噸鍚庣殑 libtemplateid 鍒楄〃锛堝彲鑳戒负绌猴級
+     */
+    List<Long> selectSatisfactionActiveTemplateIds(@Param("q") PatSatisfactionReqVO query,
+                                                   @Param("type") String type);
+
     // ================================================================ 濉姤閲忕粺璁�
 
     /**
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/PatSatisfactionServiceImpl.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/PatSatisfactionServiceImpl.java
index fd18c80..16e57c9 100644
--- a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/PatSatisfactionServiceImpl.java
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/PatSatisfactionServiceImpl.java
@@ -218,6 +218,8 @@
             for (SatisfactionIvrScriptRow ivrLibaTemplateScript : ivrLibaTemplateScripts) {
                 scriptRefs.add(new SatScriptRef(ivrLibaTemplateScript.getTemplateid(), ivrLibaTemplateScript.getScriptid(), ivrLibaTemplateScript.getScriptContent(), ivrLibaTemplateScript.getDimension()));
             }
+            // 鍙繚鐣欐湰鏈熺湡姝d笅鍙戣繃浠诲姟鐨勬ā鏉匡細棰樺簱閲屾寕鐫�鐨勫巻鍙叉ā鏉匡紙浠庢湭涓嬪彂锛変笉鍐嶅崰琛�
+            scriptRefs = keepActiveTemplates(scriptRefs, activeTemplateIds(patSatisfactionReqVO, "1"));
             buildSatisfactionDetailEntities(patSatisfactionReqVO, "1", true, scriptRefs, patSatisfactionDetailEntities, personTotals);
         }
 
@@ -233,6 +235,8 @@
                 // 闂嵎鐨勯�夐」琛ㄦ寜 svy_lib_template_script 鐨勪富閿叧鑱�
                 scriptRefs.add(new SatScriptRef(svyLibTemplateScript.getSvyid(), svyLibTemplateScript.getId(), svyLibTemplateScript.getScriptContent(), svyLibTemplateScript.getDimension()));
             }
+            // 鍙繚鐣欐湰鏈熺湡姝d笅鍙戣繃浠诲姟鐨勬ā鏉匡細棰樺簱閲屾寕鐫�鐨勫巻鍙叉ā鏉匡紙浠庢湭涓嬪彂锛変笉鍐嶅崰琛�
+            scriptRefs = keepActiveTemplates(scriptRefs, activeTemplateIds(patSatisfactionReqVO, "2"));
             buildSatisfactionDetailEntities(patSatisfactionReqVO, "2", false, scriptRefs, patSatisfactionDetailEntities, personTotals);
         }
         result.setTotalAnswerRate(Arith.div(personTotals[0], personTotals[1]));
@@ -272,6 +276,8 @@
                 for (SatisfactionIvrScriptRow ivrLibaTemplateScript : ivrLibaTemplateScripts) {
                     scriptRefs.add(new SatScriptRef(ivrLibaTemplateScript.getTemplateid(), ivrLibaTemplateScript.getScriptid(), ivrLibaTemplateScript.getScriptContent(), ivrLibaTemplateScript.getDimension()));
                 }
+                // 鍙繚鐣欐湰鏈熺湡姝d笅鍙戣繃浠诲姟鐨勬ā鏉匡細棰樺簱閲屾寕鐫�鐨勫巻鍙叉ā鏉匡紙浠庢湭涓嬪彂锛変笉鍐嶅崰琛�
+                scriptRefs = keepActiveTemplates(scriptRefs, activeTemplateIds(patSatisfactionReqVO, "1"));
                 buildSatisfactionDetailEntities(patSatisfactionReqVO, "1", true, scriptRefs, patSatisfactionDetailEntities, personTotals);
             }
         }
@@ -286,6 +292,8 @@
                     // 闂嵎鐨勯�夐」琛ㄦ寜 svy_lib_template_script 鐨勪富閿叧鑱�
                     scriptRefs.add(new SatScriptRef(svyLibTemplateScript.getSvyid(), svyLibTemplateScript.getId(), svyLibTemplateScript.getScriptContent(), svyLibTemplateScript.getDimension()));
                 }
+                // 鍙繚鐣欐湰鏈熺湡姝d笅鍙戣繃浠诲姟鐨勬ā鏉匡細棰樺簱閲屾寕鐫�鐨勫巻鍙叉ā鏉匡紙浠庢湭涓嬪彂锛変笉鍐嶅崰琛�
+                scriptRefs = keepActiveTemplates(scriptRefs, activeTemplateIds(patSatisfactionReqVO, "2"));
                 buildSatisfactionDetailEntities(patSatisfactionReqVO, "2", false, scriptRefs, patSatisfactionDetailEntities, personTotals);
             }
         }
@@ -578,6 +586,8 @@
         statQuery.setEndTime(reqVO.getEndTime());
         statQuery.setDeptcodes(reqVO.getDeptcodes());
         statQuery.setHospitaldistrictcodes(reqVO.getHospitaldistrictcodes());
+        statQuery.setLeaveldeptcodes(reqVO.getLeaveldeptcodes());
+        statQuery.setLeavehospitaldistrictcodes(reqVO.getLeavehospitaldistrictcodes());
         statQuery.setLibTemplateIds(CollectionUtils.isEmpty(templateIds) ? templateIds
                 : templateIds.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList()));
         return statQuery;
@@ -1080,6 +1090,47 @@
     // 杩欓噷鎶婁笁澶勬瀯閫犳敹鏁涗负甯姪鏂规硶锛屾潯浠朵笌鍘熸潵閫愬瓧瀵瑰簲銆�
 
     /**
+     * 鏈湡鍐�<b>鐪熸涓嬪彂杩囦换鍔�</b>鐨勬ā鏉� id 闆嗗悎锛堢┖闆嗗悎琛ㄧず鏈鏉′欢涓嬫病鏈変换浣曚换鍔★級銆�
+     * <p>
+     * 鑳屾櫙锛歿@code /statistics} 鐨勯鐩潵婧愭槸銆屾弧鎰忓害鍒嗙被銆嶄笅鐨勫叏閲忛搴撻鐩�
+     * 锛坽@link SatisfactionScriptMapper#querySvyScriptByCategory} /
+     * {@link SatisfactionScriptMapper#queryIvrScriptByAssort}锛夛紝
+     * 鏃笉鐪嬫ā鏉夸篃涓嶇湅鏃堕棿銆傞搴撻噷鍙鎸傝繘杩囦竴濂楀巻鍙查棶鍗锋ā鏉�
+     * 锛堥鐩繕鍦ㄣ�佷絾浠庢潵娌′笅鍙戣繃浠诲姟锛夛紝缁熻缁撴灉灏变細澶氬嚭涓�鏁存壒
+     * 銆屽钩鍧囧垎 0 / 鏈�楂樺垎 0 / 绛旈浜烘暟 0銆嶇殑琛屻��
+     * <p>
+     * 瀹炴祴锛堜附姘� smartor_sltd锛屾煇娆″叆鍙傦級锛氭弧鎰忓害鍒嗙被涓� 6 濂楁ā鏉垮叡 69 閬撻锛�
+     * 鑰屾湰鏈熷彧鏈� 2 濂楁ā鏉垮叡 25 閬撻鐪熸涓嬪彂杩囷紝浜庢槸椤甸潰鏄剧ず 69 琛屻�佸叾涓� 44 琛屽叏 0銆�
+     * 鐢ㄦ湰鏂规硶瑁佹帀鏃犱换鍔℃ā鏉垮悗锛岃鏁板洖鍒� 25銆�
+     *
+     * @param reqVO 鍘熷璇锋眰锛堟潯浠朵笌銆屾湁鏁版嵁銆嶅垽鏂悓鍙e緞锛氭満鏋勩�佹湇鍔$被鍨嬨�佺瀹� OR 鐥呭尯銆佹椂闂村厹搴曪級
+     * @param type  service_subtask.type锛�1 璇煶銆�2 闂嵎
+     */
+    private Set<Long> activeTemplateIds(PatSatisfactionReqVO reqVO, String type) {
+        List<Long> ids = satisfactionMapper.selectSatisfactionActiveTemplateIds(reqVO, type);
+        if (CollectionUtils.isEmpty(ids)) return Collections.emptySet();
+        return new HashSet<>(ids);
+    }
+
+    /**
+     * 鍙繚鐣欐湰鏈熺湡姝d笅鍙戣繃浠诲姟鐨勬ā鏉跨殑棰樼洰锛堢┖闆嗗悎鏃惰繑鍥炵┖鍒楄〃锛屽嵆銆屾湰鏈熸病鏈変换鍔� 鈫� 涓嶅嚭琛屻�嶏級銆�
+     * <p>
+     * 淇濈暀 {@code scriptRefs} 鐨勫師鏈夐『搴忥紝鍥犱负杩斿洖椤哄簭灏辨槸椤甸潰灞曠ず椤哄簭銆�
+     */
+    private List<SatScriptRef> keepActiveTemplates(List<SatScriptRef> scriptRefs, Set<Long> activeTemplateIds) {
+        if (CollectionUtils.isEmpty(scriptRefs) || CollectionUtils.isEmpty(activeTemplateIds)) {
+            return new ArrayList<>();
+        }
+        List<SatScriptRef> kept = new ArrayList<>(scriptRefs.size());
+        for (SatScriptRef scriptRef : scriptRefs) {
+            if (scriptRef.getTemplateId() != null && activeTemplateIds.contains(scriptRef.getTemplateId())) {
+                kept.add(scriptRef);
+            }
+        }
+        return kept;
+    }
+
+    /**
      * 婊℃剰搴﹀垎绫绘煡璇紙璇煶渚э級銆�
      * <p>
      * 鈿狅笍 <b>涓庡師鏂囦竴鑷达細鍙紶 orgid锛�<u>涓嶄紶 type</u></b>銆傚師瀹炵幇鏄�
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/SatisfactionSubtaskServiceImpl.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/SatisfactionSubtaskServiceImpl.java
index b5a976b..6f7b876 100644
--- a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/SatisfactionSubtaskServiceImpl.java
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/SatisfactionSubtaskServiceImpl.java
@@ -42,6 +42,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.Collectors;
 
 /**
@@ -69,12 +70,58 @@
     @Autowired
     private SatisfactionScriptMapper satisfactionScriptMapper;
 
-    public List<ServiceSubtaskDetailRatioExport> statQuestionOption(List<Long> taskIds, Date startFinishTime, Date endFinishTime, Date startOutHospTime, Date endOutHospTime, String scriptContent, Double scoreStart, Double scoreEnd, String valueType, List<Long> subtaskIds) {
-        //鍏堟竻鐞嗕竴涓嬮噸澶嶆暟鎹�
-        List<Long> repeatIds = satisfactionMapper.selectRepeatDetailIds();
-        if (!CollectionUtils.isEmpty(repeatIds)) {
-            satisfactionMapper.deleteRepeatDetailByIds(repeatIds);
+    /**
+     * 閲嶅鏄庣粏娓呯悊鐨勨�滄渶杩戜竴娆℃墽琛屾椂闂粹�濓紙姣锛夈�傝 {@link #cleanRepeatDetailsIfDue()}銆�
+     */
+    private static final AtomicLong LAST_REPEAT_CLEAN_AT = new AtomicLong(0L);
+
+    /**
+     * 閲嶅鏄庣粏娓呯悊鐨勬渶灏忛棿闅旓細10 鍒嗛挓銆�
+     */
+    private static final long REPEAT_CLEAN_INTERVAL_MS = TimeUnit.MINUTES.toMillis(10);
+
+    /**
+     * 娓呯悊 service_subtask_detail 閲岀殑閲嶅鏄庣粏锛堝悓涓� sub_id + questiontext 鍙暀鏈�鏂颁竴鏉★級銆�
+     * <p>
+     * 鈿狅笍 <b>涓轰粈涔堣鏈夎妭娴�</b>锛歿@code selectRepeatDetailIds} 鏄竴鏉�
+     * 銆屽鏁村紶 service_subtask_detail 鎸� (sub_id, questiontext) 鍒嗙粍 + HAVING COUNT(*) &gt; 1銆嶇殑
+     * 鍏ㄨ〃鑱氬悎锛屼笖<b>娌℃湁浠讳綍鏃ユ湡/鐥呭尯/瀛愪换鍔¤寖鍥�</b>锛涗竴鏃︽煡鍑洪噸澶嶈繕浼氭墽琛岄�昏緫鍒犻櫎锛堝啓鎿嶄綔锛夈��
+     * 鍘熷疄鐜板湪姣忔婊℃剰搴︾粺璁¤姹傚墠閮芥棤鏉′欢璺戜竴閬嶏紝浜庢槸锛�
+     * <ul>
+     *   <li>缁熻鎺ュ彛鐨勬�ц兘涓庣敤鎴锋墍閫夋潯浠�<b>瀹屽叏鏃犲叧</b>锛屾槑缁嗚〃瓒婂ぇ瓒婃參锛�</li>
+     *   <li>涓�涓彧璇绘帴鍙e湪鍋峰伔鍋� DML銆�</li>
+     * </ul>
+     * 鑰岀粺璁� SQL 鏈韩宸茬粡鐢� {@code d.id = (SELECT MAX(...))} 鍋氫簡鈥滃悓棰樺彧鍙栨渶鏂颁竴鏉♀�濈殑鍘婚噸锛�
+     * 鎵�浠ヨ繖涓墠缃竻鐞嗗鏈缁熻缁撴灉<b>涓嶆槸蹇呴渶</b>鐨勩�傝繖閲屾敼鎴愨�滄瘡涓疄渚嬫渶澶� 10 鍒嗛挓娓呬竴娆♀�濓紝
+     * 鏃繚鐣欐竻鐞嗚兘鍔涳紝鍙堜笉璁╂瘡涓姹傞兘涓哄畠涔板崟銆�
+     * <p>
+     * 鏇村交搴曠殑鍋氭硶鏄妸瀹冩尓鍒板畾鏃朵换鍔¢噷锛堝彧鐣欎竴涓淮鎶ゅ叆鍙o級锛岄渶瑕佺殑璇濆彲浠ュ啀璋冩暣銆�
+     */
+    private void cleanRepeatDetailsIfDue() {
+        long now = System.currentTimeMillis();
+        long last = LAST_REPEAT_CLEAN_AT.get();
+        if (now - last < REPEAT_CLEAN_INTERVAL_MS) {
+            return;
         }
+        // CAS 鎶㈠崰锛氬苟鍙戣姹傞噷鍙斁涓�涓嚎绋嬪幓娓呯悊锛屽叾浣欑洿鎺ヨ繑鍥�
+        if (!LAST_REPEAT_CLEAN_AT.compareAndSet(last, now)) {
+            return;
+        }
+        try {
+            List<Long> repeatIds = satisfactionMapper.selectRepeatDetailIds();
+            if (!CollectionUtils.isEmpty(repeatIds)) {
+                satisfactionMapper.deleteRepeatDetailByIds(repeatIds);
+                log.info("婊℃剰搴︾粺璁″墠缃竻鐞嗭細閫昏緫鍒犻櫎閲嶅鏄庣粏 {} 鏉�", repeatIds.size());
+            }
+        } catch (Exception e) {
+            // 娓呯悊澶辫触涓嶈兘褰卞搷缁熻鏈韩
+            log.warn("婊℃剰搴︾粺璁″墠缃竻鐞嗛噸澶嶆槑缁嗗け璐ワ紝宸茶烦杩囨湰娆℃竻鐞�", e);
+        }
+    }
+
+    public List<ServiceSubtaskDetailRatioExport> statQuestionOption(List<Long> taskIds, Date startFinishTime, Date endFinishTime, Date startOutHospTime, Date endOutHospTime, String scriptContent, Double scoreStart, Double scoreEnd, String valueType, List<Long> subtaskIds) {
+        //鍓嶇疆娓呯悊閲嶅鏄庣粏锛堝凡鑺傛祦锛氭瘡涓疄渚嬫渶澶� 10 鍒嗛挓涓�娆★紝涓嶅啀姣忎釜璇锋眰閮借窇鍏ㄨ〃 GROUP BY锛�
+        cleanRepeatDetailsIfDue();
         List<ServiceSubtaskDetailRatioExport> serviceSubtaskDetailRatioExports = satisfactionMapper.statQuestionOption(taskIds, startOutHospTime, endOutHospTime, startFinishTime, endFinishTime, scoreStart, scoreEnd, scriptContent, valueType, subtaskIds);
 
         // 澶勭悊 targetvalue锛氭寜 & 鍒嗗壊鎴愬鏉¤褰�
@@ -271,9 +318,10 @@
             return Collections.emptyMap();
         }
 
-        // 2. 鍒ゆ柇鎸夌瀹よ繕鏄寜鐥呭尯
-        boolean byDept = vo.getLeaveldeptcodes() != null;
-        boolean byDistrict = !byDept && vo.getLeavehospitaldistrictcodes() != null;
+        // 2. 鍒ゆ柇鎸夌瀹よ繕鏄寜鐥呭尯锛堢闄� / 鍦ㄩ櫌涓ょ粍鍙傛暟閮界畻锛�
+        boolean byDept = vo.getLeaveldeptcodes() != null || vo.getDeptcodes() != null;
+        boolean byDistrict = !byDept
+                && (vo.getLeavehospitaldistrictcodes() != null || vo.getHospitaldistrictcodes() != null);
         if (!byDept && !byDistrict) {
             return Collections.emptyMap();
         }
@@ -384,11 +432,8 @@
     }
 
     public List<ServiceSubtaskDetailRatioExport> statQuestionOptionBySubtaskIds(List<Long> subtaskIds, Date startOutHospTime, Date endOutHospTime, Date startFinishTime, Date endFinishTime, String scriptContent, Double scoreStart, Double scoreEnd, String valueType) {
-        //鍏堟竻鐞嗕竴涓嬮噸澶嶆暟鎹�
-        List<Long> repeatIds = satisfactionMapper.selectRepeatDetailIds();
-        if (!CollectionUtils.isEmpty(repeatIds)) {
-            satisfactionMapper.deleteRepeatDetailByIds(repeatIds);
-        }
+        //鍓嶇疆娓呯悊閲嶅鏄庣粏锛堝凡鑺傛祦锛氭瘡涓疄渚嬫渶澶� 10 鍒嗛挓涓�娆★紝涓嶅啀姣忎釜璇锋眰閮借窇鍏ㄨ〃 GROUP BY锛�
+        cleanRepeatDetailsIfDue();
 
         List<ServiceSubtaskDetailRatioExport> serviceSubtaskDetailRatioExports = satisfactionMapper.statQuestionOptionBySubtaskIds(subtaskIds, startOutHospTime, endOutHospTime, startFinishTime, endFinishTime, scoreStart, scoreEnd, scriptContent, valueType);
         // SQL 宸叉寜銆岄鐩� + 閫夐」銆嶆眹鎬绘暟閲忥紝杩欓噷鍐嶆寜棰樼洰鍚堝苟锛堜笉鍚屾ā鏉跨殑 targetvalue 閫夐」椤哄簭涓嶅悓锛屽悓涓�閫夐」浼氭媶鎴愬琛岋級锛�
diff --git a/ruoyi-satisfaction/src/main/resources/mapper/satisfaction/SatisfactionMapper.xml b/ruoyi-satisfaction/src/main/resources/mapper/satisfaction/SatisfactionMapper.xml
index e17a7b9..05ae104 100644
--- a/ruoyi-satisfaction/src/main/resources/mapper/satisfaction/SatisfactionMapper.xml
+++ b/ruoyi-satisfaction/src/main/resources/mapper/satisfaction/SatisfactionMapper.xml
@@ -26,10 +26,10 @@
         </if>
         <if test="type != null and type != ''">and type = #{type}</if>
         <if test="startTime != null">
-            and visit_time &gt;= #{startTime}
+            and IFNULL(visit_time, IFNULL(finishtime, create_time)) &gt;= #{startTime}
         </if>
         <if test="endTime != null">
-            and visit_time &lt; date_add(#{endTime}, interval 1 day)
+            and IFNULL(visit_time, IFNULL(finishtime, create_time)) &lt; date_add(#{endTime}, interval 1 day)
         </if>
         <if test="libTemplateIds != null and libTemplateIds.size() > 0">
             and libtemplateid IN
@@ -51,9 +51,29 @@
                 OR
             </if>
             <if test="deptcodes != null and deptcodes.size() > 0">
-                deptcode IN
+                leaveldeptcode IN
                 <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
                     #{deptcode}
+                </foreach>
+            </if>
+            )
+        </if>
+        <!-- 绂婚櫌婊℃剰搴︼細鎸夌闄㈢瀹�/鐥呭尯杩囨护锛堢瀹� OR 鐥呭尯锛屼笌椤甸潰鍙e緞涓�鑷达級 -->
+        <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) or (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+            AND (
+            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
+                leavehospitaldistrictcode IN
+                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," close=")">
+                    #{leavehospitaldistrictcode}
+                </foreach>
+            </if>
+            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+                OR
+            </if>
+            <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+                leaveldeptcode IN
+                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," close=")">
+                    #{leaveldeptcode}
                 </foreach>
             </if>
             )
@@ -67,18 +87,57 @@
         from service_subtask
         where del_flag = 0
         <if test="questionType != null">and type = #{questionType}</if>
-        <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
-            AND leavehospitaldistrictcode IN
-            <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator=","
-                     close=")">
-                #{hospitaldistrictcode}
-            </foreach>
+        <!--
+            2026-10-21 淇锛堝崡鍗� /statistics 鏌ヤ笉鍒版暟鎹級锛�
+            鍘熸潵鏄�宭eavehospitaldistrictcode IN(...) AND deptcode IN(...)銆嶄袱鏉$嫭绔嬫潯浠讹紝
+            鑰屾弧鎰忓害瀛愪换鍔★紙service_subtask.type=2 + service_type 6/14/15/16锛�
+            閫氬父鍙啓 deptcode銆乴eavehospitaldistrictcode 涓� NULL锛堝崡鍗� 3803 鏉″叏閮ㄤ负 NULL锛夛紝
+            涓や釜鏉′欢姘歌繙涓嶅彲鑳藉悓鏃舵弧瓒� 鈫� 璇ユ柟娉曡繑鍥炵┖ 鈫� 鍚庨潰 hasVoice/hasQuestionnaire 閮戒负 false
+            鈫� 鏁翠釜缁熻鎺ュ彛杩斿洖绌恒��
+
+            杩欓噷鏀规垚涓� selectSatisfactionSendCount / selectSatisfactionFillPersonCountByQuestion
+            瀹屽叏涓�鑷寸殑銆岀瀹� OR 鐥呭尯銆嶅彛寰勶紙鍚屼竴涓〉闈紝鍥涘 SQL 蹇呴』鍚屽彛寰勶紝鍚﹀垯浼氬嚭鐜�
+            "鏈夌被鍨嬫病鏁版嵁"鎴�"鏈夋暟鎹病绫诲瀷"鐨勫壊瑁傦級銆�
+        -->
+        <if test="(hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0) or (deptcodes != null and deptcodes.size() > 0)">
+            AND (
+            <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
+                leavehospitaldistrictcode IN
+                <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="("
+                         separator="," close=")">
+                    #{hospitaldistrictcode}
+                </foreach>
+            </if>
+            <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0 and deptcodes != null and deptcodes.size() > 0">
+                OR
+            </if>
+            <if test="deptcodes != null and deptcodes.size() > 0">
+                leaveldeptcode IN
+                <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
+                    #{deptcode}
+                </foreach>
+            </if>
+            )
         </if>
-        <if test="deptcodes != null and deptcodes.size() > 0">
-            AND deptcode IN
-            <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
-                #{deptcode}
-            </foreach>
+        <!-- 绂婚櫌婊℃剰搴︼細鎸夌闄㈢瀹�/鐥呭尯杩囨护锛堢瀹� OR 鐥呭尯锛屼笌椤甸潰鍙e緞涓�鑷达級 -->
+        <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) or (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+            AND (
+            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
+                leavehospitaldistrictcode IN
+                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," close=")">
+                    #{leavehospitaldistrictcode}
+                </foreach>
+            </if>
+            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+                OR
+            </if>
+            <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+                leaveldeptcode IN
+                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," close=")">
+                    #{leaveldeptcode}
+                </foreach>
+            </if>
+            )
         </if>
         <if test="serviceTypes != null and serviceTypes.size() > 0">
             AND service_type IN
@@ -86,9 +145,83 @@
                 #{serviceType}
             </foreach>
         </if>
+        <!--
+            鏃堕棿鍙e緞锛氭弧鎰忓害瀛愪换鍔★紙type=2锛夌殑 visit_time 缁忓父涓虹┖锛堝崡鍗� 3803 鏉″叏涓� NULL锛夛紝
+            鍙寜 visit_time 杩囨护浼氭妸杩欎簺鏁版嵁鏁存壒鎺掗櫎銆傝繖閲屾寜
+            visit_time -> finishtime -> create_time 渚濇鍏滃簳锛屼笌鍏朵綑涓夋潯缁熻 SQL 淇濇寔涓�鑷淬��
+        -->
         <if test="startTime != null and endTime != null">
-            AND visit_time &gt;= #{startTime}
-            AND visit_time &lt; date_add(#{endTime}, interval 1 day)
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) &gt;= #{startTime}
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) &lt; date_add(#{endTime}, interval 1 day)
+        </if>
+    </select>
+
+    <!-- ================================================
+         鏈鏉′欢涓嬨�岀湡姝d笅鍙戣繃浠诲姟銆嶇殑妯℃澘 id锛堝幓閲嶏級
+
+         鐢ㄩ�旓細鎶婇搴撻鐩紙svy_lib_template_script / ivr_liba_template_script锛�
+         瑁佸壀鎴愭湰鏈熺湡姝e湪鐢ㄧ殑妯℃澘锛岄伩鍏嶃�岄搴撻噷鎸傜潃涓�鍫嗕粠鏉ユ病涓嬪彂杩囩殑鍘嗗彶妯℃澘銆�
+         瀵艰嚧 /statistics 澶氬嚭涓�鏁存壒 0 鍒嗗尯闂寸殑琛岋紙瀹炴祴 69 琛� 鈫� 搴斿彧鏈� 25 琛岋級銆�
+
+         鈿狅笍 鏉′欢蹇呴』涓� selectSatisfactionSubtaskTypes 閫愭潯涓�鑷达紙鍙槸澶氫簡 type 涓� libtemplateid 涓ゅ垪锛夛紝
+            鍚﹀垯浼氬嚭鐜般�屾湁绫诲瀷鐨勬ā鏉胯瑁佹帀 / 瑁佸壀鍚庢病鏈夋暟鎹�嶇殑鍓茶銆�
+         ================================================ -->
+    <select id="selectSatisfactionActiveTemplateIds" resultType="java.lang.Long">
+        select distinct libtemplateid
+        from service_subtask
+        where del_flag = 0
+        and libtemplateid is not null
+        <if test="type != null and type != ''">and type = #{type}</if>
+        <if test="(q.hospitaldistrictcodes != null and q.hospitaldistrictcodes.size() > 0) or (q.deptcodes != null and q.deptcodes.size() > 0)">
+            AND (
+            <if test="q.hospitaldistrictcodes != null and q.hospitaldistrictcodes.size() > 0">
+                leavehospitaldistrictcode IN
+                <foreach collection="q.hospitaldistrictcodes" item="hospitaldistrictcode" open="("
+                         separator="," close=")">
+                    #{hospitaldistrictcode}
+                </foreach>
+            </if>
+            <if test="q.hospitaldistrictcodes != null and q.hospitaldistrictcodes.size() > 0 and q.deptcodes != null and q.deptcodes.size() > 0">
+                OR
+            </if>
+            <if test="q.deptcodes != null and q.deptcodes.size() > 0">
+                leaveldeptcode IN
+                <foreach collection="q.deptcodes" item="deptcode" open="(" separator="," close=")">
+                    #{deptcode}
+                </foreach>
+            </if>
+            )
+        </if>
+        <!-- 绂婚櫌婊℃剰搴︼細鎸夌闄㈢瀹�/鐥呭尯杩囨护锛堢瀹� OR 鐥呭尯锛屼笌椤甸潰鍙e緞涓�鑷达級 -->
+        <if test="(q.leavehospitaldistrictcodes != null and q.leavehospitaldistrictcodes.size() > 0) or (q.leaveldeptcodes != null and q.leaveldeptcodes.size() > 0)">
+            AND (
+            <if test="q.leavehospitaldistrictcodes != null and q.leavehospitaldistrictcodes.size() > 0">
+                leavehospitaldistrictcode IN
+                <foreach collection="q.leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," close=")">
+                    #{leavehospitaldistrictcode}
+                </foreach>
+            </if>
+            <if test="(q.leavehospitaldistrictcodes != null and q.leavehospitaldistrictcodes.size() > 0) and (q.leaveldeptcodes != null and q.leaveldeptcodes.size() > 0)">
+                OR
+            </if>
+            <if test="q.leaveldeptcodes != null and q.leaveldeptcodes.size() > 0">
+                leaveldeptcode IN
+                <foreach collection="q.leaveldeptcodes" item="leaveldeptcode" open="(" separator="," close=")">
+                    #{leaveldeptcode}
+                </foreach>
+            </if>
+            )
+        </if>
+        <if test="q.serviceTypes != null and q.serviceTypes.size() > 0">
+            AND service_type IN
+            <foreach collection="q.serviceTypes" item="serviceType" open="(" separator="," close=")">
+                #{serviceType}
+            </foreach>
+        </if>
+        <!-- 鏃堕棿鍙e緞锛歷isit_time -> finishtime -> create_time 渚濇鍏滃簳锛屼笌鍏朵綑鍥涙潯缁熻 SQL 淇濇寔涓�鑷� -->
+        <if test="q.startTime != null and q.endTime != null">
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) &gt;= #{q.startTime}
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) &lt; date_add(#{q.endTime}, interval 1 day)
         </if>
     </select>
 
@@ -303,10 +436,10 @@
         and d.del_flag=0
         <!-- 鍒嗘瘝蹇呴』鍜屾槑缁嗙敤鍚屼竴濂楁椂闂存潯浠讹紝鍚﹀垯閫変簡鏃堕棿鑼冨洿鍚庢瘮渚嬩細鎸夊叏閲忓巻鍙茶绋�閲� -->
         <if test="startOutHospTime != null">
-            AND date_format(s.endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
+            AND date_format(IFNULL(s.endtime, IFNULL(s.finishtime, s.create_time)),'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
         </if>
         <if test="endOutHospTime != null">
-            AND date_format(s.endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
+            AND date_format(IFNULL(s.endtime, IFNULL(s.finishtime, s.create_time)),'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
         </if>
         <if test="startFinishTime != null">
             AND date_format(s.finishtime,'%y%m%d') &gt;= date_format(#{startFinishTime},'%y%m%d')
@@ -340,10 +473,10 @@
         AND s.sendstate = 6
         and d.del_flag=0
         <if test="startOutHospTime != null">
-            AND date_format(s.endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
+            AND date_format(IFNULL(s.endtime, IFNULL(s.finishtime, s.create_time)),'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
         </if>
         <if test="endOutHospTime != null">
-            AND date_format(s.endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
+            AND date_format(IFNULL(s.endtime, IFNULL(s.finishtime, s.create_time)),'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
         </if>
         <if test="startFinishTime != null">
             AND date_format(s.finishtime,'%y%m%d') &gt;= date_format(#{startFinishTime},'%y%m%d')
@@ -371,8 +504,8 @@
         MAX(t.task_name) AS taskName,
         d.asrtext AS optionresult,
         d.score AS score,
-        MAX(s.deptcode) AS deptcode,
-        MAX(s.deptname) AS deptname,
+        MAX(s.leaveldeptcode) AS deptcode,
+        MAX(s.leaveldeptname) AS deptname,
         MAX(s.leavehospitaldistrictcode) AS leavehospitaldistrictcode,
         MAX(s.leavehospitaldistrictname) AS leavehospitaldistrictname,
         d.targetvalue AS targetvalue,
@@ -430,10 +563,10 @@
         AND d.del_flag=0
         <!-- 鍒嗘瘝涓庢槑缁嗙敤鍚屼竴濂楁椂闂存潯浠讹紝鍚﹀垯閫変簡鏃ユ湡鍖洪棿鍚庡悇閫夐」姣斾緥鍚堣涓嶅埌 100% -->
         <if test="startOutHospTime != null">
-            AND date_format(s.endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
+            AND date_format(IFNULL(s.endtime, IFNULL(s.finishtime, s.create_time)),'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
         </if>
         <if test="endOutHospTime != null">
-            AND date_format(s.endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
+            AND date_format(IFNULL(s.endtime, IFNULL(s.finishtime, s.create_time)),'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
         </if>
         <if test="startFinishTime != null">
             AND date_format(s.finishtime,'%y%m%d') &gt;= date_format(#{startFinishTime},'%y%m%d')
@@ -473,10 +606,10 @@
             '%')
         </if>
         <if test="startOutHospTime != null">
-            AND date_format(s.endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
+            AND date_format(IFNULL(s.endtime, IFNULL(s.finishtime, s.create_time)),'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
         </if>
         <if test="endOutHospTime != null">
-            AND date_format(s.endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
+            AND date_format(IFNULL(s.endtime, IFNULL(s.finishtime, s.create_time)),'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
         </if>
         <if test="startFinishTime != null">
             AND date_format(s.finishtime,'%y%m%d') &gt;= date_format(#{startFinishTime},'%y%m%d')
@@ -500,8 +633,8 @@
     <select id="statQuestionOptionByKsOrBq" resultType="com.ruoyi.satisfaction.domain.dto.QuestionCountKsOrBqDTO"
             parameterType="com.ruoyi.satisfaction.domain.vo.QuestionCountKsOrBqVO">
         SELECT
-        s.deptname AS deptname,
-        s.leavehospitaldistrictname AS leavehospitaldistrictname,
+        IFNULL(s.leaveldeptname, s.deptname) AS deptname,
+        IFNULL(s.leavehospitaldistrictname, s.hospitaldistrictname) AS leavehospitaldistrictname,
         d.questiontext AS questionText,
         d.targetvalue AS targetvalue, -- 鎵�鏈夐�夐」鎷兼帴
         d.asrtext AS asrtext, -- 鐢ㄦ埛瀹為檯閫変腑鐨勯�夐」
@@ -530,29 +663,59 @@
                 </foreach>
             </if>
             <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
-                AND deptcode IN
+                AND leaveldeptcode IN
                 <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                          close=")">
                     #{leaveldeptcode}
                 </foreach>
             </if>
+            <!-- 鍦ㄩ櫌婊℃剰搴︼細鎸夊湪闄㈢梾鍖�/鍦ㄩ櫌绉戝鍒楄繃婊わ紙鍙湪浼犱簡杩欑粍鍙傛暟鏃剁敓鏁堬級 -->
+            <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
+                AND hospitaldistrictcode IN
+                <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="("
+                         separator=","
+                         close=")">
+                    #{hospitaldistrictcode}
+                </foreach>
+            </if>
+            <if test="deptcodes != null and deptcodes.size() > 0">
+                AND deptcode IN
+                <foreach collection="deptcodes" item="deptcode" open="(" separator=","
+                         close=")">
+                    #{deptcode}
+                </foreach>
+            </if>
         </if>
+        <!--
+            2026-10-21 淇锛氬師鏉� deptOrDistrict==2 鏃跺啓鐨勬槸
+              銆孉ND leavehospitaldistrictcode IN (...) OR deptcode IN (...)銆嶏紝
+            娌℃湁鎷彿 鈥斺�� SQL 閲� AND 浼樺厛绾ч珮浜� OR锛屽疄闄呯瓑浠蜂簬
+              (鍏ㄩ儴 AND 鏉′欢 AND 鐥呭尯 IN ...) OR 绉戝 IN ...
+            浜庢槸銆岀瀹ゅ懡涓�嶉偅涓�鏀畬鍏ㄧ粫杩囦簡 service_type / 鏃ユ湡 / del_flag 绛夋墍鏈夋潯浠讹紝
+            鍗楀崕锛堢梾鍖轰负绌恒�佹寜绉戝鏌ワ級浼氭崬鍥炲叏搴撳巻鍙叉暟鎹� 鈫� 鏁版嵁鏄庢樉涓嶅銆�
+            杩欓噷琛ラ綈鎷彿锛岃 2 = 绉戝 OR 鐥呭尯銆�
+        -->
         <if test="deptOrDistrict ==2">
+            AND (
             <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-                AND leavehospitaldistrictcode IN
+                leavehospitaldistrictcode IN
                 <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
                          separator=","
                          close=")">
                     #{leavehospitaldistrictcode}
                 </foreach>
             </if>
+            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0 and leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+                OR
+            </if>
             <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
-                OR deptcode IN
+                leaveldeptcode IN
                 <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                          close=")">
                     #{leaveldeptcode}
                 </foreach>
             </if>
+            )
         </if>
     </select>
 
@@ -571,8 +734,8 @@
                 s.leavehospitaldistrictname AS name,
             </when>
             <otherwise>
-                s.deptcode AS code,
-                s.deptname AS name,
+                s.leaveldeptcode AS code,
+                s.leaveldeptname AS name,
             </otherwise>
         </choose>
         CAST(d.score AS DECIMAL(10,4)) AS w
@@ -625,10 +788,10 @@
                 </if>
             </when>
             <otherwise>
-                AND s.deptcode IS NOT NULL AND s.deptcode &lt;&gt; ''
-                AND s.deptname IS NOT NULL AND s.deptname &lt;&gt; ''
+                AND s.leaveldeptcode IS NOT NULL AND s.leaveldeptcode &lt;&gt; ''
+                AND s.leaveldeptname IS NOT NULL AND s.leaveldeptname &lt;&gt; ''
                 <if test="deptCodes != null and deptCodes.size() > 0">
-                    AND s.deptcode IN
+                    AND s.leaveldeptcode IN
                     <foreach collection="deptCodes" item="deptCode" open="(" separator="," close=")">
                         #{deptCode}
                     </foreach>
@@ -661,10 +824,10 @@
         </if>
         <if test="type != null and type != ''">and ss.type = #{type}</if>
         <if test="startTime != null">
-            and ss.visit_time &gt;= #{startTime}
+            and IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) &gt;= #{startTime}
         </if>
         <if test="endTime != null">
-            and ss.visit_time &lt; date_add(#{endTime}, interval 1 day)
+            and IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) &lt; date_add(#{endTime}, interval 1 day)
         </if>
         <if test="libTemplateIds != null and libTemplateIds.size() > 0">
             and ss.libtemplateid IN
@@ -686,9 +849,29 @@
                 OR
             </if>
             <if test="deptcodes != null and deptcodes.size() > 0">
-                ss.deptcode IN
+                ss.leaveldeptcode IN
                 <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
                     #{deptcode}
+                </foreach>
+            </if>
+            )
+        </if>
+        <!-- 绂婚櫌婊℃剰搴︼細鎸夌闄㈢瀹�/鐥呭尯杩囨护锛堢瀹� OR 鐥呭尯锛屼笌椤甸潰鍙e緞涓�鑷达級 -->
+        <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) or (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+            AND (
+            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
+                ss.leavehospitaldistrictcode IN
+                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," close=")">
+                    #{leavehospitaldistrictcode}
+                </foreach>
+            </if>
+            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+                OR
+            </if>
+            <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+                ss.leaveldeptcode IN
+                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," close=")">
+                    #{leaveldeptcode}
                 </foreach>
             </if>
             )
@@ -716,10 +899,10 @@
         </if>
         <if test="type != null and type != ''">and ss.type = #{type}</if>
         <if test="startTime != null">
-            and ss.visit_time &gt;= #{startTime}
+            and IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) &gt;= #{startTime}
         </if>
         <if test="endTime != null">
-            and ss.visit_time &lt; date_add(#{endTime}, interval 1 day)
+            and IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) &lt; date_add(#{endTime}, interval 1 day)
         </if>
         <if test="libTemplateIds != null and libTemplateIds.size() > 0">
             and ss.libtemplateid IN
@@ -741,9 +924,29 @@
                 OR
             </if>
             <if test="deptcodes != null and deptcodes.size() > 0">
-                ss.deptcode IN
+                ss.leaveldeptcode IN
                 <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
                     #{deptcode}
+                </foreach>
+            </if>
+            )
+        </if>
+        <!-- 绂婚櫌婊℃剰搴︼細鎸夌闄㈢瀹�/鐥呭尯杩囨护锛堢瀹� OR 鐥呭尯锛屼笌椤甸潰鍙e緞涓�鑷达級 -->
+        <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) or (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+            AND (
+            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
+                ss.leavehospitaldistrictcode IN
+                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," close=")">
+                    #{leavehospitaldistrictcode}
+                </foreach>
+            </if>
+            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+                OR
+            </if>
+            <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+                ss.leaveldeptcode IN
+                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," close=")">
+                    #{leaveldeptcode}
                 </foreach>
             </if>
             )
@@ -767,10 +970,10 @@
         </if>
         <if test="type != null and type != ''">and ss.type = #{type}</if>
         <if test="startTime != null">
-            and ss.visit_time &gt;= #{startTime}
+            and IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) &gt;= #{startTime}
         </if>
         <if test="endTime != null">
-            and ss.visit_time &lt; date_add(#{endTime}, interval 1 day)
+            and IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) &lt; date_add(#{endTime}, interval 1 day)
         </if>
         <if test="libTemplateIds != null and libTemplateIds.size() > 0">
             and ss.libtemplateid IN
@@ -792,9 +995,29 @@
                 OR
             </if>
             <if test="deptcodes != null and deptcodes.size() > 0">
-                ss.deptcode IN
+                ss.leaveldeptcode IN
                 <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
                     #{deptcode}
+                </foreach>
+            </if>
+            )
+        </if>
+        <!-- 绂婚櫌婊℃剰搴︼細鎸夌闄㈢瀹�/鐥呭尯杩囨护锛堢瀹� OR 鐥呭尯锛屼笌椤甸潰鍙e緞涓�鑷达級 -->
+        <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) or (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+            AND (
+            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
+                ss.leavehospitaldistrictcode IN
+                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," close=")">
+                    #{leavehospitaldistrictcode}
+                </foreach>
+            </if>
+            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+                OR
+            </if>
+            <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+                ss.leaveldeptcode IN
+                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," close=")">
+                    #{leaveldeptcode}
                 </foreach>
             </if>
             )
@@ -832,10 +1055,10 @@
         </if>
         <if test="type != null and type != ''">and ss.type = #{type}</if>
         <if test="startTime != null">
-            and ss.visit_time &gt;= #{startTime}
+            and IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) &gt;= #{startTime}
         </if>
         <if test="endTime != null">
-            and ss.visit_time &lt; date_add(#{endTime}, interval 1 day)
+            and IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) &lt; date_add(#{endTime}, interval 1 day)
         </if>
         <if test="libTemplateIds != null and libTemplateIds.size() > 0">
             and ss.libtemplateid IN
@@ -857,9 +1080,29 @@
                 OR
             </if>
             <if test="deptcodes != null and deptcodes.size() > 0">
-                ss.deptcode IN
+                ss.leaveldeptcode IN
                 <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
                     #{deptcode}
+                </foreach>
+            </if>
+            )
+        </if>
+        <!-- 绂婚櫌婊℃剰搴︼細鎸夌闄㈢瀹�/鐥呭尯杩囨护锛堢瀹� OR 鐥呭尯锛屼笌椤甸潰鍙e緞涓�鑷达級 -->
+        <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) or (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+            AND (
+            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
+                ss.leavehospitaldistrictcode IN
+                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," close=")">
+                    #{leavehospitaldistrictcode}
+                </foreach>
+            </if>
+            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+                OR
+            </if>
+            <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+                ss.leaveldeptcode IN
+                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," close=")">
+                    #{leaveldeptcode}
                 </foreach>
             </if>
             )
@@ -918,24 +1161,125 @@
             AND service_type = #{q.serviceType}
         </if>
         <if test="q.startOutHospTime != null">
-            AND date_format(endtime,'%y%m%d') &gt;= date_format(#{q.startOutHospTime},'%y%m%d')
+            AND date_format(IFNULL(endtime, IFNULL(finishtime, create_time)),'%y%m%d') &gt;= date_format(#{q.startOutHospTime},'%y%m%d')
         </if>
         <if test="q.endOutHospTime != null">
-            AND date_format(endtime,'%y%m%d') &lt;= date_format(#{q.endOutHospTime},'%y%m%d')
+            AND date_format(IFNULL(endtime, IFNULL(finishtime, create_time)),'%y%m%d') &lt;= date_format(#{q.endOutHospTime},'%y%m%d')
         </if>
+        <!--
+            2026-10-21 鏂板锛氭寜銆屽畬鎴愭椂闂淬�嶈繃婊わ紙椤甸潰鎻愪氦鐨� startFinishTime / endFinishTime锛夈��
+            鍙e緞涓� statQuestionOptionBySubtaskIds 閲岀殑
+            date_format(s.finishtime,'%y%m%d') 鍖洪棿瀹屽叏绛変环锛堝弬鏁伴兘鏄� yyyy-MM-dd 闆剁偣锛夛紝
+            浣嗚繖閲屽埢鎰忓啓鎴� finishtime 鐨勮8鍖洪棿鑰屼笉鐢� date_format()锛�
+            鍒椾笂濂楀嚱鏁颁細璁╃储寮曞け鏁堬紝瑁稿尯闂存墠鑳借蛋 (鈥�, finishtime) 绱㈠紩銆�
+            涓婄嚎鍓嶈繖閲屽畬鍏ㄦ病鏈夋椂闂存潯浠讹紝service_subtask 浼氳鏁磋〃鎵弿锛�
+            涓嬫父鍐嶆妸鎵�鏈夊巻鍙叉弧鎰忓害瀛愪换鍔� id 鐏岃繘 IN 鍒楄〃 鈥斺�� 杩欐槸璇ユ帴鍙f參鐨勪富鍥犮��
+        -->
+        <if test="q.startFinishTime != null">
+            AND finishtime &gt;= #{q.startFinishTime}
+        </if>
+        <if test="q.endFinishTime != null">
+            AND finishtime &lt; DATE_ADD(#{q.endFinishTime}, INTERVAL 1 DAY)
+        </if>
+        <!--
+            绉戝 / 鐥呭尯鍙e緞锛�2026-10-21 閲嶆瀯锛氳繃婊ゅ摢涓�鍒楃敱鍏ュ弬鍐冲畾锛�
+            ==================================================================
+            鍥涗釜鍙傛暟鍚勮嚜瀵瑰簲涓�鍒楋紝璋佷紶杩涙潵灏辫繃婊よ皝锛屼笉鍐嶄竴寰嬫寜銆岀闄㈢梾鍖恒�嶈繃婊わ細
+              hospitaldistrictcodes      鈫� hospitaldistrictcode      鍦ㄩ櫌/褰撳墠鐥呭尯
+              leavehospitaldistrictcodes 鈫� leavehospitaldistrictcode 绂婚櫌鐥呭尯
+              deptcodes                  鈫� deptcode                 鍦ㄩ櫌/褰撳墠绉戝
+              leaveldeptcodes            鈫� leaveldeptcode           绂婚櫌绉戝
+            鍚屼竴缁村害閲屼袱涓弬鏁伴兘浼狅紙灏戣锛夋椂鎸� OR 鈥斺�� 瀹冧滑鏄悓涓�浠朵簨鐨勪袱涓垪鍐欐硶锛�
+            鐥呭尯缁村害涓庣瀹ょ淮搴︿箣闂寸敱 deptOrDistrict 鍐冲畾锛�1/3 = AND锛�2/4 = OR銆�
+            鑳屾櫙锛氬崡鍗庤繖鎵规暟鎹殑鐥呭尯鍐欏湪 hospitaldistrictcode锛堝疄娴� 40003514 鏈� 409 鏉★級锛�
+            leavehospitaldistrictcode 鍩烘湰涓虹┖锛涘彧璁ょ闄㈢梾鍖轰細璁╃粺璁″彧鍓� 5 鏉°��
+        -->
+        <!-- 1/3锛氱梾鍖� AND 绉戝 -->
         <if test="q.deptOrDistrict==1">
-            <if test="q.leavehospitaldistrictcodes != null and q.leavehospitaldistrictcodes.size() > 0">
-                AND leavehospitaldistrictcode IN
-                <foreach collection="q.leavehospitaldistrictcodes" item="districtcode" open="(" separator="," close=")">
-                    #{districtcode}
-                </foreach>
+            <if test="(q.hospitaldistrictcodes != null and q.hospitaldistrictcodes.size() > 0) or (q.leavehospitaldistrictcodes != null and q.leavehospitaldistrictcodes.size() > 0)">
+                AND (
+                <trim prefixOverrides="OR">
+                    <if test="q.hospitaldistrictcodes != null and q.hospitaldistrictcodes.size() > 0">
+                        hospitaldistrictcode IN
+                        <foreach collection="q.hospitaldistrictcodes" item="districtcode" open="(" separator="," close=")">
+                            #{districtcode}
+                        </foreach>
+                    </if>
+                    <if test="q.leavehospitaldistrictcodes != null and q.leavehospitaldistrictcodes.size() > 0">
+                        OR leavehospitaldistrictcode IN
+                        <foreach collection="q.leavehospitaldistrictcodes" item="districtcode" open="(" separator="," close=")">
+                            #{districtcode}
+                        </foreach>
+                    </if>
+                </trim>
+                )
+            </if>
+            <if test="(q.deptcodes != null and q.deptcodes.size() > 0) or (q.leaveldeptcodes != null and q.leaveldeptcodes.size() > 0)">
+                AND (
+                <trim prefixOverrides="OR">
+                    <if test="q.deptcodes != null and q.deptcodes.size() > 0">
+                        deptcode IN
+                        <foreach collection="q.deptcodes" item="deptcode" open="(" separator="," close=")">
+                            #{deptcode}
+                        </foreach>
+                    </if>
+                    <if test="q.leaveldeptcodes != null and q.leaveldeptcodes.size() > 0">
+                        OR leaveldeptcode IN
+                        <foreach collection="q.leaveldeptcodes" item="deptcode" open="(" separator="," close=")">
+                            #{deptcode}
+                        </foreach>
+                    </if>
+                </trim>
+                )
             </if>
         </if>
-        <if test="q.leaveldeptcodes != null and q.leaveldeptcodes.size() > 0">
-            AND deptcode IN
-            <foreach collection="q.leaveldeptcodes" item="deptcode" open="(" separator="," close=")">
-                #{deptcode}
-            </foreach>
+        <!-- 2/4锛氱梾鍖� OR 绉戝 -->
+        <if test="q.deptOrDistrict==2">
+            <if test="(q.hospitaldistrictcodes != null and q.hospitaldistrictcodes.size() > 0) or (q.leavehospitaldistrictcodes != null and q.leavehospitaldistrictcodes.size() > 0) or (q.deptcodes != null and q.deptcodes.size() > 0) or (q.leaveldeptcodes != null and q.leaveldeptcodes.size() > 0)">
+                AND (
+                <trim prefixOverrides="OR">
+                    <if test="q.hospitaldistrictcodes != null and q.hospitaldistrictcodes.size() > 0">
+                        hospitaldistrictcode IN
+                        <foreach collection="q.hospitaldistrictcodes" item="districtcode" open="(" separator="," close=")">
+                            #{districtcode}
+                        </foreach>
+                    </if>
+                    <if test="q.leavehospitaldistrictcodes != null and q.leavehospitaldistrictcodes.size() > 0">
+                        OR leavehospitaldistrictcode IN
+                        <foreach collection="q.leavehospitaldistrictcodes" item="districtcode" open="(" separator="," close=")">
+                            #{districtcode}
+                        </foreach>
+                    </if>
+                    <if test="q.deptcodes != null and q.deptcodes.size() > 0">
+                        OR deptcode IN
+                        <foreach collection="q.deptcodes" item="deptcode" open="(" separator="," close=")">
+                            #{deptcode}
+                        </foreach>
+                    </if>
+                    <if test="q.leaveldeptcodes != null and q.leaveldeptcodes.size() > 0">
+                        OR leaveldeptcode IN
+                        <foreach collection="q.leaveldeptcodes" item="deptcode" open="(" separator="," close=")">
+                            #{deptcode}
+                        </foreach>
+                    </if>
+                </trim>
+                )
+            </if>
+        </if>
+        <!-- 鍏跺畠鍙栧�硷細淇濇寔鏃ц涓猴紝鍙湅绉戝锛堝垪鍚屾牱鎸夊叆鍙傚尯鍒嗭級 -->
+        <if test="q.deptOrDistrict != null and q.deptOrDistrict != '1' and q.deptOrDistrict != '2'">
+            <if test="q.deptcodes != null and q.deptcodes.size() > 0">
+                AND deptcode IN
+                <foreach collection="q.deptcodes" item="deptcode" open="(" separator="," close=")">
+                    #{deptcode}
+                </foreach>
+            </if>
+            <if test="q.leaveldeptcodes != null and q.leaveldeptcodes.size() > 0">
+                AND leaveldeptcode IN
+                <foreach collection="q.leaveldeptcodes" item="deptcode" open="(" separator="," close=")">
+                    #{deptcode}
+                </foreach>
+            </if>
         </if>
     </select>
 
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/VisitTaskCreateApiImpl.java b/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/VisitTaskCreateApiImpl.java
index cb337ac..07bebac 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/VisitTaskCreateApiImpl.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/VisitTaskCreateApiImpl.java
@@ -270,8 +270,16 @@
         e.setDrname(d.getDrname());
         e.setManagementDoctor(d.getManagementDoctor());
         e.setManagementDoctorCode(d.getManagementDoctorCode());
+        // 2026-11锛歞eptcode/deptname 鍒楀凡鏀瑰悕 leaveldeptcode/leaveldeptname锛堝嚭闄㈢淮搴︼級锛�
+        //          鍘� sendlimit* 鍥涗釜绌哄垪澶嶇敤涓� hospitaldistrictcode/name锛堝湪闄㈢梾鍖猴級銆乨eptcode/name锛堝湪闄㈢瀹わ級銆�
+        e.setLeaveldeptcode(d.getLeaveldeptcode());
+        e.setLeaveldeptname(d.getLeaveldeptname());
+        // 鈿狅笍 杩� 4 鍒楀彧鏈夈�屽嚭闄㈤殢璁裤�嶄細濉�硷紙VisitSubtaskFactory 浠� pat_med_inhosp 鍙栵級锛�
+        //    闂ㄨ瘖/鎵嬫湳/鎵爜/绛斿嵎绛夎矾寰勭殑鑽夌閲屼粛鏄� null 鈥斺�� 涓庢敼閫犲墠杩欎簺鍒椾笉鍐欑殑鏁堟灉涓�鑷淬��
         e.setDeptcode(d.getDeptcode());
         e.setDeptname(d.getDeptname());
+        e.setHospitaldistrictcode(d.getHospitaldistrictcode());
+        e.setHospitaldistrictname(d.getHospitaldistrictname());
         e.setLeavehospitaldistrictcode(d.getLeavehospitaldistrictcode());
         e.setLeavehospitaldistrictname(d.getLeavehospitaldistrictname());
         e.setLeaveicd10code(d.getLeaveicd10code());
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/controller/ServiceSubtaskController.java b/ruoyi-task/src/main/java/com/ruoyi/task/controller/ServiceSubtaskController.java
index ae47d97..4087dd9 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/controller/ServiceSubtaskController.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/controller/ServiceSubtaskController.java
@@ -160,6 +160,10 @@
     @ApiOperation("鏌ヨ鎮h�呴殢璁夸俊鎭�")
     @PostMapping("/patItem")
     public Map<String, Object> patItem(@RequestBody ServiceSubtaskVO serviceSubtaskVO) {
+        // ==== 涓存椂璇婃柇璁℃椂锛氱‘璁ゆ參鍦ㄥ摢涓�娈靛悗鏁存鍒犻櫎鍗冲彲锛堝彧鍔犳棩蹇楋紝涓嶆敼閫昏緫锛�====
+        long tTotal = System.currentTimeMillis();
+        long tMark = tTotal;
+
         serviceSubtaskVO.setPageNum(PageUtils.getOffset(serviceSubtaskVO.getPageNum(), serviceSubtaskVO.getPageSize()));
         List<ServiceSubtaskRes> serviceSubtaskList = null;
         LoginUser loginUser = getLoginUser();
@@ -172,17 +176,26 @@
             serviceSubtaskEntity.setContinueContent(ObjectUtils.isNotEmpty(serviceSubtaskVO.getContinueContent()) ? serviceSubtaskVO.getContinueContent().toString() : null);
             serviceSubtaskList = serviceSubtaskService.patItem(serviceSubtaskEntity);
         }
+        log.info("[patItem鑰楁椂] 1.鍒楄〃椤�(涓ら樁娈靛垎椤�)={}ms锛岃鏁�={}", System.currentTimeMillis() - tMark,
+                serviceSubtaskList == null ? -1 : serviceSubtaskList.size());
+        tMark = System.currentTimeMillis();
 
         // 鎵归噺鏌� subtask_record锛�1娆QL鏇夸唬寰幆涓璑娆″崟鐙煡
-        List<Long> subtaskIds = serviceSubtaskList.stream().map(ServiceSubtaskRes::getId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());
-        Map<Long, List<ServiceSubtaskRecord>> recordMap = serviceSubtaskRecordService.selectRecordMapBySubtaskIds(subtaskIds);
-
-        for (ServiceSubtaskRes serviceSubtask : serviceSubtaskList) {
-            serviceSubtask.setServiceSubtaskRecordList(recordMap.getOrDefault(serviceSubtask.getId(), new ArrayList<>()));
-        }
+//        List<Long> subtaskIds = serviceSubtaskList.stream().map(ServiceSubtaskRes::getId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());
+//        Map<Long, List<ServiceSubtaskRecord>> recordMap = serviceSubtaskRecordService.selectRecordMapBySubtaskIds(subtaskIds);
+//        log.info("[patItem鑰楁椂] 2.subtask_record鎵归噺={}ms锛屽叆鍙俰d鏁�={}", System.currentTimeMillis() - tMark, subtaskIds.size());
+//        tMark = System.currentTimeMillis();
+//
+//        for (ServiceSubtaskRes serviceSubtask : serviceSubtaskList) {
+//            serviceSubtask.setServiceSubtaskRecordList(recordMap.getOrDefault(serviceSubtask.getId(), new ArrayList<>()));
+//        }
+        log.info("[patItem鑰楁椂] 3.璁板綍鍥炲~={}ms", System.currentTimeMillis() - tMark);
+        tMark = System.currentTimeMillis();
 
 //      patItemCount 璧癛edis缂撳瓨鐗堬紝閬垮厤姣忔鍏ㄨ〃鑱氬悎鎵弿
         Map<String, Object> map = getPatItemCountWithCache(serviceSubtaskEntity);
+        log.info("[patItem鑰楁椂] 4.缁熻patItemCount(鍚紦瀛�)={}ms", System.currentTimeMillis() - tMark);
+        tMark = System.currentTimeMillis();
         map.put("serviceSubtaskList", serviceSubtaskList);
         List<Map<String, Object>> list = new ArrayList<>();
         list.add(map);
@@ -200,6 +213,8 @@
             total = CollectionUtils.isNotEmpty(serviceSubtasks) ? serviceSubtasks.size() : 0L;
         }
 
+        log.info("[patItem鑰楁椂] 5.缁勮杩斿洖total={}={}ms锛屾暣浣撳悎璁�={}ms", total,
+                System.currentTimeMillis() - tMark, System.currentTimeMillis() - tTotal);
         return getDataTable3(total, list);
     }
 
@@ -774,7 +789,12 @@
     @AddOrgId(field = "orgid", paramIndex = 0, campusField = "campusid")
     @PostMapping("/getSfStatisticsCountDetails")
     public AjaxResult getSfStatisticsCountDetails(@RequestBody ServiceSubtaskCountReq serviceSubtaskCountReq) {
-        if (serviceSubtaskCountReq.getLeavehospitaldistrictcodes().size() == 0 && serviceSubtaskCountReq.getDeptcodes().size() == 0) {
+        boolean noDeptOrDistrict = CollectionUtils.isEmpty(serviceSubtaskCountReq.getLeavehospitaldistrictcodes())
+                && CollectionUtils.isEmpty(serviceSubtaskCountReq.getDeptcodes())
+                && CollectionUtils.isEmpty(serviceSubtaskCountReq.getLeaveldeptcodes())
+                && CollectionUtils.isEmpty(serviceSubtaskCountReq.getHospitaldeptcodes())
+                && CollectionUtils.isEmpty(serviceSubtaskCountReq.getHospitaldistrictcodes());
+        if (noDeptOrDistrict) {
             return error("绉戝鎴栫梾鍖轰笉鑳戒负绌�");
         }
         //澶嶈瘖缁熻
@@ -980,23 +1000,31 @@
                 serviceSubtaskEntity.setSendstates(new ArrayList<>(Arrays.asList(4L)));
         }
         if (ObjectUtils.isNotEmpty(userId)) {
+            long tRedis = System.currentTimeMillis();
             Map<String, Object> redisMap = redisCache.getCacheObject(userId + "patItemCount");
+            log.info("[patItem鑰楁椂] 4.1 Redis鍙朿ount缂撳瓨={}ms", System.currentTimeMillis() - tRedis);
             Boolean redisFlag = false;
             if (MapUtils.isNotEmpty(redisMap)) {
+                long tCmp = System.currentTimeMillis();
                 ServiceSubtaskEntity oldCondition = (ServiceSubtaskEntity) redisMap.get("searchCondition");
                 if (ObjectUtils.isNotEmpty(oldCondition) && isSameCondition(oldCondition, serviceSubtaskEntity)) {
                     redisFlag = true;
                     map = redisMap;
                     redisCache.setCacheObject(userId + "patItemCount", map, 60, TimeUnit.MINUTES);
                 }
+                log.info("[patItem鑰楁椂] 4.2 鏉′欢姣斿={}ms锛屽懡涓�={}", System.currentTimeMillis() - tCmp, redisFlag);
             }
             if (!redisFlag) {
+                long tCalc = System.currentTimeMillis();
                 map = serviceSubtaskService.patItemCount(serviceSubtaskEntity);
+                log.info("[patItem鑰楁椂] 4.3 count鑱氬悎(鏈懡涓紦瀛橈紝璧板簱)={}ms", System.currentTimeMillis() - tCalc);
                 map.put("searchCondition", serviceSubtaskEntity);
                 redisCache.setCacheObject(userId + "patItemCount", map, 120, TimeUnit.MINUTES);
             }
         } else {
+            long tCalc = System.currentTimeMillis();
             map = serviceSubtaskService.patItemCount(serviceSubtaskEntity);
+            log.info("[patItem鑰楁椂] 4.3 count鑱氬悎(鏃犵櫥褰曚汉锛岃蛋搴�)={}ms", System.currentTimeMillis() - tCalc);
         }
         return map;
     }
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtask.java b/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtask.java
index 9ba99a6..c00bd91 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtask.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtask.java
@@ -202,32 +202,32 @@
     private Date createTimeNew;
 
     /**
-     * 涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌鐥呭尯缂栫爜锛堝師 sendlimitabegin 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒�")
-    private String sendlimitabegin;
+    @Excel(name = " 鍦ㄩ櫌鐥呭尯缂栫爜 ")
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯缂栫爜")
+    private String hospitaldistrictcode;
 
     /**
-     * 涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌鐥呭尯鍚嶇О锛堝師 sendlimitaend 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒�")
-    private String sendlimitaend;
+    @Excel(name = " 鍦ㄩ櫌鐥呭尯鍚嶇О ")
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯鍚嶇О")
+    private String hospitaldistrictname;
 
     /**
-     * 涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌绉戝缂栫爜锛堝師 sendlimitpbegin 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒�")
-    private String sendlimitpbegin;
+    @Excel(name = " 鍦ㄩ櫌绉戝缂栫爜 ")
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝缂栫爜")
+    private String deptcode;
 
     /**
-     * 涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌绉戝鍚嶇О锛堝師 sendlimitpend 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒�")
-    private String sendlimitpend;
+    @Excel(name = " 鍦ㄩ櫌绉戝鍚嶇О ")
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝鍚嶇О")
+    private String deptname;
 
     /**
      * 鏅氫笂寮�濮嬪彂閫佹椂闂撮檺鍒�
@@ -300,11 +300,11 @@
     private Date pulltime;
 
     /**
-     * 閮ㄩ棬code
+     * 鍑洪櫌绉戝缂栫爜锛堝師 deptcode 鍒楋紝宸叉敼鍚� leaveldeptcode锛�
      */
-    @Excel(name = "  閮ㄩ棬code")
-    @ApiModelProperty(value = "閮ㄩ棬code")
-    private String deptcode;
+    @Excel(name = "  鍑洪櫌绉戝缂栫爜")
+    @ApiModelProperty(value = "鍑洪櫌绉戝缂栫爜")
+    private String leaveldeptcode;
 
     /**
      * 鍖荤敓缂栫爜
@@ -496,11 +496,11 @@
     private String patguid;
 
     /**
-     * 绉戝鍚嶇О
+     * 鍑洪櫌绉戝鍚嶇О锛堝師 deptname 鍒楋紝宸叉敼鍚� leaveldeptname锛�
      */
-    @Excel(name = "绉戝鍚嶇О")
-    @ApiModelProperty(value = "绉戝鍚嶇О")
-    private String deptname;
+    @Excel(name = "鍑洪櫌绉戝鍚嶇О")
+    @ApiModelProperty(value = "鍑洪櫌绉戝鍚嶇О")
+    private String leaveldeptname;
 
     /**
      * 灏辫瘖鏃ユ湡
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskCountReq.java b/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskCountReq.java
index 5ce66dd..1a090a7 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskCountReq.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskCountReq.java
@@ -61,11 +61,20 @@
     @ApiModelProperty(value = "鏈嶅姟绫诲瀷")
     private List<Long> serviceType;
 
-    @ApiModelProperty(value = "鐥呭尯Code闆嗗悎")
+    @ApiModelProperty(value = "绂婚櫌鐥呭尯Code闆嗗悎")
     private List<String> leavehospitaldistrictcodes;
+
+    @ApiModelProperty(value = "绂婚櫌绉戝Code闆嗗悎")
+    private List<String>  leaveldeptcodes;
 
     @ApiModelProperty(value = "绉戝Code闆嗗悎")
     private List<String> deptcodes;
+
+    @ApiModelProperty(value = "鐥呭尯Code闆嗗悎")
+    private List<String> hospitaldistrictcodes;
+
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝Code闆嗗悎")
+    private List<String> hospitaldeptcodes;
 
     @ApiModelProperty(value = "瀛愪换鍔d闆嗗悎")
     private List<Long> subTaskIds;
@@ -157,6 +166,17 @@
     private String groupKeyType;
 
     /**
+     * 瀹為檯鐢ㄤ簬鈥滅粨鏋滃垎缁勨�濈殑鍒楀悕锛堜粎鏈嶅姟绔唴閮ㄤ娇鐢紝涓嶄粠璇锋眰浼犲叆锛夈��
+     * <p>
+     * 鍘嗗彶鍘熷洜锛歿@link #groupKey} 鏃㈢敤浜� getSfStatistics 鐨� {@code AND ${groupKey} IN (...)} 杩囨护锛�
+     * 鍙堣褰撴垚鍒嗙粍鍒楋紱浣� {@code groupKey = 'deptcode'} 鏃讹紝鍘熷疄鐜版槸鍦ㄥ唴瀛橀噷鎸�
+     * {@code leaveldeptcode} 鍒嗙粍鐨勶紝杩囨护鍒椾笌鍒嗙粍鍒楀苟涓嶇浉鍚屻��
+     * 涓轰簡鎶婄疮鍔犱笅鎺ㄥ埌鏁版嵁搴撳悗鍙e緞涓嶅彉锛岃繖閲屾妸涓や欢浜嬫媶寮�锛歡roupKey 璐熻矗杩囨护锛実roupColumn 璐熻矗鍒嗙粍銆�
+     */
+    @JsonIgnore
+    private String groupColumn;
+
+    /**
      * 鍒嗙粍key
      */
     @ApiModelProperty(value = "鍒嗙粍key")
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskExport.java b/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskExport.java
index 457f2a0..34b6af9 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskExport.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskExport.java
@@ -32,8 +32,8 @@
      * 绉戝鍚嶇О
      */
     @Excel(name = "绉戝鍚嶇О")
-    @ApiModelProperty(value = "绉戝鍚嶇О")
-    private String deptname;
+    @ApiModelProperty(value = "鍑洪櫌绉戝鍚嶇О锛堝師 deptname锛屽垪宸叉敼鍚� leaveldeptname锛�")
+    private String leaveldeptname;
 
     /**
      * 鍙戦�佷汉
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskRes.java b/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskRes.java
index ad0080a..d65bf63 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskRes.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskRes.java
@@ -209,32 +209,32 @@
     private Date createTimeNew;
 
     /**
-     * 涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌鐥呭尯缂栫爜锛堝師 sendlimitabegin 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒�")
-    private String sendlimitabegin;
+    @Excel(name = " 鍦ㄩ櫌鐥呭尯缂栫爜 ")
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯缂栫爜")
+    private String hospitaldistrictcode;
 
     /**
-     * 涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌鐥呭尯鍚嶇О锛堝師 sendlimitaend 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒�")
-    private String sendlimitaend;
+    @Excel(name = " 鍦ㄩ櫌鐥呭尯鍚嶇О ")
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯鍚嶇О")
+    private String hospitaldistrictname;
 
     /**
-     * 涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌绉戝缂栫爜锛堝師 sendlimitpbegin 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒�")
-    private String sendlimitpbegin;
+    @Excel(name = " 鍦ㄩ櫌绉戝缂栫爜 ")
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝缂栫爜")
+    private String deptcode;
 
     /**
-     * 涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌绉戝鍚嶇О锛堝師 sendlimitpend 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒�")
-    private String sendlimitpend;
+    @Excel(name = " 鍦ㄩ櫌绉戝鍚嶇О ")
+    @ApiModelProperty(value = "绉戝鍚嶇О锛堝叆闄㈢淮搴︼級")
+    private String deptname;
 
     /**
      * 鏅氫笂寮�濮嬪彂閫佹椂闂撮檺鍒�
@@ -315,11 +315,11 @@
     private Date pulltime;
 
     /**
-     * 閮ㄩ棬code
+     * 鍑洪櫌绉戝缂栫爜锛堝師 deptcode 鍒楋紝宸叉敼鍚� leaveldeptcode锛�
      */
-    @Excel(name = "  閮ㄩ棬code")
-    @ApiModelProperty(value = "閮ㄩ棬code")
-    private String deptcode;
+    @Excel(name = "  鍑洪櫌绉戝缂栫爜")
+    @ApiModelProperty(value = "鍑洪櫌绉戝缂栫爜")
+    private String leaveldeptcode;
 
     /**
      * 鍖荤敓缂栫爜
@@ -505,11 +505,11 @@
     private String patguid;
 
     /**
-     * 绉戝鍚嶇О
+     * 鍑洪櫌绉戝鍚嶇О锛堝師 deptname 鍒楋紝宸叉敼鍚� leaveldeptname锛�
      */
-    @Excel(name = "绉戝鍚嶇О")
-    @ApiModelProperty(value = "绉戝鍚嶇О")
-    private String deptname;
+    @Excel(name = "鍑洪櫌绉戝鍚嶇О")
+    @ApiModelProperty(value = "鍑洪櫌绉戝鍚嶇О")
+    private String leaveldeptname;
 
     /**
      * 灏辫瘖鏃ユ湡
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskStatistic.java b/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskStatistic.java
index e0f31f1..2a8e164 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskStatistic.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/domain/ServiceSubtaskStatistic.java
@@ -1,5 +1,6 @@
 package com.ruoyi.task.domain;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.ruoyi.common.annotation.Excel;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -85,6 +86,18 @@
     @ApiModelProperty(value = "鍑洪櫌绉戝鍚嶇О")
     @Excel(name = " 鍑洪櫌鐥呭尯鍚嶇О ")
     private String deptname;
+
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯缂栧彿")
+    private String hospitaldistrictcode;
+
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯鍚嶇О")
+    private String hospitaldistrictname;
+
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝缂栧彿")
+    private String hospitaldeptcode;
+
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝鍚嶇О")
+    private String hospitaldeptname;
 
     @ApiModelProperty(value = "鍑洪櫌浜烘")
     @Excel(name = " 鍑洪櫌浜烘 ")
@@ -353,4 +366,29 @@
     @ApiModelProperty(value = "杩囨护鎮h�呰鎯�")
     private List<ServiceSubtask> filterCountList;
 
+    /**
+     * 鍒嗙粍閿�硷紙drcode / leaveldeptcode / leavehospitaldistrictcode 鐨勫疄闄呭彇鍊硷級銆�
+     * <p>
+     * 浠呮湇鍔$鍐呴儴浣跨敤锛氱粺璁℃敼鎴愭暟鎹簱 GROUP BY 涔嬪悗锛屽強鏃剁巼銆佹弧鎰忓害棰樼洰閲忛兘鏄彟涓�鏉�
+     * 鎸夊悓涓�鍒嗙粍閿仛鍚堢殑 SQL锛岃繖閲岀敤瀹冩妸涓ら儴鍒嗙粨鏋滃璧锋潵銆�
+     * 鐢� @JsonIgnore 淇濊瘉涓嶄細澶氳繑鍥炲瓧娈电粰鍓嶇锛屼篃涓嶅奖鍝� @Cacheable 鐨� Redis 搴忓垪鍖栥��
+     */
+    @JsonIgnore
+    private String groupCode;
+
+    /**
+     * 棣栨闅忚璁板綍鏁帮紙visit_count = 1 鐨勮鏁帮級銆�
+     * <p>
+     * 浠呮湇鍔$鍐呴儴浣跨敤锛氬師鍐呭瓨缁熻閲屸�滈娆¢殢璁跨巼鈥濆彧鍦ㄨ鍒嗙粍瀛樺湪棣栨闅忚璁板綍鏃舵墠浼氳璧嬪��
+     * 锛堜笉瀛樺湪鍒欐槸 null 鑰屼笉鏄� 0.00%锛夛紝杩欓噷鐢ㄥ畠澶嶅埢杩欎釜鍙e緞銆�
+     */
+    @JsonIgnore
+    private Long firstVisitCount;
+
+    /**
+     * 鍐嶆闅忚璁板綍鏁帮紙visit_count &gt; 1 鐨勮鏁帮級銆備粎鏈嶅姟绔唴閮ㄤ娇鐢紝鐢ㄩ�斿悓涓娿��
+     */
+    @JsonIgnore
+    private Long againVisitCount;
+
 }
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/domain/VO/ServiceSubtaskVO.java b/ruoyi-task/src/main/java/com/ruoyi/task/domain/VO/ServiceSubtaskVO.java
index 3295b8a..840f7e3 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/domain/VO/ServiceSubtaskVO.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/domain/VO/ServiceSubtaskVO.java
@@ -223,32 +223,32 @@
     private Date senddate;
 
     /**
-     * 涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌鐥呭尯缂栫爜锛堝師 sendlimitabegin 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒�")
-    private String sendlimitabegin;
+    @Excel(name = " 鍦ㄩ櫌鐥呭尯缂栫爜 ")
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯缂栫爜")
+    private String hospitaldistrictcode;
 
     /**
-     * 涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌鐥呭尯鍚嶇О锛堝師 sendlimitaend 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒�")
-    private String sendlimitaend;
+    @Excel(name = " 鍦ㄩ櫌鐥呭尯鍚嶇О ")
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯鍚嶇О")
+    private String hospitaldistrictname;
 
     /**
-     * 涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌绉戝缂栫爜锛堝師 sendlimitpbegin 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒�")
-    private String sendlimitpbegin;
+    @Excel(name = " 鍦ㄩ櫌绉戝缂栫爜 ")
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝缂栫爜")
+    private String deptcode;
 
     /**
-     * 涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌绉戝鍚嶇О锛堝師 sendlimitpend 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒�")
-    private String sendlimitpend;
+    @Excel(name = " 鍦ㄩ櫌绉戝鍚嶇О ")
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝鍚嶇О")
+    private String deptname;
 
     /**
      * 鏅氫笂寮�濮嬪彂閫佹椂闂撮檺鍒�
@@ -351,17 +351,24 @@
     private Long bhsms;
 
     /**
-     * 閮ㄩ棬code
+     * 鍑洪櫌绉戝缂栫爜锛堝師 deptcode 鍒楋紝宸叉敼鍚� leaveldeptcode锛�
      */
-    @Excel(name = "  閮ㄩ棬code")
-    @ApiModelProperty(value = "閮ㄩ棬code")
-    private String deptcode;
+    @Excel(name = "  鍑洪櫌绉戝缂栫爜")
+    @ApiModelProperty(value = "鍑洪櫌绉戝缂栫爜")
+    private String leaveldeptcode;
     /**
      * 閮ㄩ棬code
      */
     @Excel(name = "  閮ㄩ棬code")
-    @ApiModelProperty(value = "閮ㄩ棬code闆嗗悎")
+    @ApiModelProperty(value = "绂婚櫌閮ㄩ棬code闆嗗悎")
     private List<String> leaveldeptcodes;
+
+    /**
+     * 鍦ㄩ櫌閮ㄩ棬code
+     */
+    @Excel(name = "鍦ㄩ櫌閮ㄩ棬code")
+    @ApiModelProperty(value = "鍦ㄩ櫌閮ㄩ棬code")
+    private List<String> deptcodes;
 
     /**
      * 鏍囩鐘舵��
@@ -550,11 +557,12 @@
     private String diagname;
 
     /**
-     * 绉戝鍚嶇О
+     * 鍑洪櫌绉戝鍚嶇О锛堝師 deptname 鍒楋紝宸叉敼鍚� leaveldeptname锛�
      */
-    @Excel(name = "绉戝鍚嶇О")
-    @ApiModelProperty(value = "绉戝鍚嶇О")
-    private String deptname;
+    @Excel(name = "鍑洪櫌绉戝鍚嶇О")
+    @ApiModelProperty(value = "鍑洪櫌绉戝鍚嶇О")
+    private String leaveldeptname;
+
 //
 //    /**
 //     * 灏辫瘖鏃ユ湡
@@ -590,7 +598,6 @@
      */
     @ApiModelProperty(value = "鍑洪櫌鐥呭尯缂栧彿")
     private String leavehospitaldistrictcode;
-
     /**
      * 鍑洪櫌鐥呭尯缂栧彿
      */
@@ -598,6 +605,12 @@
     private List<String> leavehospitaldistrictcodes;
 
     /**
+     * 鍦ㄩ櫌鐥呭尯闆嗗悎
+     */
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯闆嗗悎")
+    private List<String> hospitaldistrictcodes;
+
+    /**
      * 鍑洪櫌鐥呭尯鍚嶇О
      */
     @ApiModelProperty(value = "鍑洪櫌鐥呭尯鍚嶇О")
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/domain/entity/ServiceSubtaskEntity.java b/ruoyi-task/src/main/java/com/ruoyi/task/domain/entity/ServiceSubtaskEntity.java
index 7b833ac..881db8f 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/domain/entity/ServiceSubtaskEntity.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/domain/entity/ServiceSubtaskEntity.java
@@ -11,6 +11,7 @@
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+
 import com.ruoyi.task.domain.TaskSendTimeVO;
 
 /**
@@ -236,32 +237,32 @@
     private Date senddate;
 
     /**
-     * 涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌鐥呭尯缂栫爜锛堝師 sendlimitabegin 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒�")
-    private String sendlimitabegin;
+    @Excel(name = " 鍦ㄩ櫌鐥呭尯缂栫爜 ")
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯缂栫爜")
+    private String hospitaldistrictcode;
 
     /**
-     * 涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌鐥呭尯鍚嶇О锛堝師 sendlimitaend 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒�")
-    private String sendlimitaend;
+    @Excel(name = " 鍦ㄩ櫌鐥呭尯鍚嶇О ")
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯鍚嶇О")
+    private String hospitaldistrictname;
 
     /**
-     * 涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌绉戝缂栫爜锛堝師 sendlimitpbegin 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒�")
-    private String sendlimitpbegin;
+    @Excel(name = " 鍦ㄩ櫌绉戝缂栫爜 ")
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝缂栫爜")
+    private String deptcode;
 
     /**
-     * 涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌绉戝鍚嶇О锛堝師 sendlimitpend 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒�")
-    private String sendlimitpend;
+    @Excel(name = " 鍦ㄩ櫌绉戝鍚嶇О ")
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝鍚嶇О")
+    private String deptname;
 
     /**
      * 鏅氫笂寮�濮嬪彂閫佹椂闂撮檺鍒�
@@ -359,17 +360,24 @@
     private Long bhsms;
 
     /**
-     * 閮ㄩ棬code
+     * 鍑洪櫌绉戝缂栫爜锛堝師 deptcode 鍒楋紝宸叉敼鍚� leaveldeptcode锛�
      */
-    @Excel(name = "  閮ㄩ棬code")
-    @ApiModelProperty(value = "閮ㄩ棬code")
-    private String deptcode;
+    @Excel(name = "  鍑洪櫌绉戝缂栫爜")
+    @ApiModelProperty(value = "鍑洪櫌绉戝缂栫爜")
+    private String leaveldeptcode;
+    /**
+     * 绂婚櫌閮ㄩ棬code闆嗗悎
+     */
+    @Excel(name = "绂婚櫌閮ㄩ棬code闆嗗悎")
+    @ApiModelProperty(value = "绂婚櫌閮ㄩ棬code闆嗗悎")
+    private List<String> leaveldeptcodes;
+
     /**
      * 閮ㄩ棬code
      */
     @Excel(name = "  閮ㄩ棬code")
     @ApiModelProperty(value = "閮ㄩ棬code闆嗗悎")
-    private List<String> leaveldeptcodes;
+    private List<String> deptcodes;
 
     /**
      * 鏍囩鐘舵��
@@ -557,11 +565,11 @@
     private String diagname;
 
     /**
-     * 绉戝鍚嶇О
+     * 鍑洪櫌绉戝鍚嶇О锛堝師 deptname 鍒楋紝宸叉敼鍚� leaveldeptname锛�
      */
-    @Excel(name = "绉戝鍚嶇О")
-    @ApiModelProperty(value = "绉戝鍚嶇О")
-    private String deptname;
+    @Excel(name = "鍑洪櫌绉戝鍚嶇О")
+    @ApiModelProperty(value = "鍑洪櫌绉戝鍚嶇О")
+    private String leaveldeptname;
 //
 //    /**
 //     * 灏辫瘖鏃ユ湡
@@ -605,6 +613,12 @@
     private List<String> leavehospitaldistrictcodes;
 
     /**
+     * 鍦ㄩ櫌鐥呭尯闆嗗悎锛堝搴� hospitaldistrictcode 鍒楋紝2026-11 涓� VO 瀵归綈鍚庤ˉ涓婏級
+     */
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯闆嗗悎")
+    private List<String> hospitaldistrictcodes;
+
+    /**
      * 鍑洪櫌鐥呭尯鍚嶇О
      */
     @ApiModelProperty(value = "鍑洪櫌鐥呭尯鍚嶇О")
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskDetailMapper.java b/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskDetailMapper.java
index 6999280..fe75f48 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskDetailMapper.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskDetailMapper.java
@@ -42,6 +42,36 @@
     public ServiceSubtaskDetailDTO isExistServiceSubtaskDetail(@Param("subid") Long subid, @Param("scriptid") Long scriptid);
 
     /**
+     * 閫昏緫鍒犻櫎鏌愪釜瀛愪换鍔′笅鐨勫叏閮ㄦ槑缁嗭紙<b>鍞竴鐨勬壒閲忚蒋鍒犲叆鍙�</b>锛�
+     * <p>
+     * 2026-10-21 鏀跺彛锛氶�氱敤 UPDATE锛坲pdateServiceSubtaskDetail / updateSSDByCondition锛夊凡涓嶅啀鎺ュ彈
+     * 瀹㈡埛绔紶鍏ョ殑 delFlag锛岄渶瑕佽蒋鍒犲彧鑳借皟杩欓噷锛屼究浜庡姞鏃ュ織銆佸姞鎿嶄綔浜恒�佸姞鏍¢獙銆�
+     *
+     * @param subId 瀛愪换鍔� id
+     * @return 鍙楀奖鍝嶈鏁�
+     */
+    public int softDeleteServiceSubtaskDetailBySubId(@Param("subId") Long subId);
+
+    /**
+     * 閫昏緫鍒犻櫎鍗曟潯鏄庣粏
+     *
+     * @param id 鏄庣粏 id
+     * @return 鍙楀奖鍝嶈鏁�
+     */
+    public int softDeleteServiceSubtaskDetailById(@Param("id") Long id);
+
+    /**
+     * 澶嶆椿涓�鏉¤閫昏緫鍒犻櫎鐨勬槑缁嗭紙鍙厑璁哥疆鍥� '0'锛�
+     * <p>
+     * 鐢ㄤ簬"淇濆瓨绛旀鏃跺懡涓巻鍙茶鍒犲壇鏈�"鐨勫満鏅細鍏堟妸鍐呭 UPDATE 涓婂幓锛屽啀璋冩湰鏂规硶缃洖 del_flag='0'锛�
+     * 杩欐牱鍚屼竴 (sub_id, scriptid) 涓嶄細鍐嶅爢鍑洪噸澶嶅壇鏈��
+     *
+     * @param id 鏄庣粏 id
+     * @return 鍙楀奖鍝嶈鏁�
+     */
+    public int reviveServiceSubtaskDetail(@Param("id") Long id);
+
+    /**
      * 鏌ヨ璇煶浠诲姟鍛煎彨鏄庣粏鍒楄〃
      *
      * @param serviceSubtaskDetail 璇煶浠诲姟鍛煎彨鏄庣粏
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskMapper.java b/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskMapper.java
index e23f262..12d41a7 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskMapper.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskMapper.java
@@ -44,6 +44,21 @@
      */
     public List<ServiceSubtask> selectServiceSubtaskList(ServiceSubtaskEntity serviceSubtaskVO);
 
+    /**
+     * 鍒嗛〉绗竴闃舵锛氬彧鍙栧綋鍓嶉〉鐨勫瓙浠诲姟 id銆�
+     * <p>
+     * where / order 涓� {@link #selectServiceSubtaskList} 鍏辩敤鍚屼竴浠� XML 鐗囨
+     * 锛坽@code serviceSubtaskWhere} / {@code serviceSubtaskOrderByPaged}锛夛紝
+     * 淇濊瘉涓ゆ潯璇彞鍙e緞涓�鑷达紝涓嶄細鍑虹幇銆岀涓�闃舵閫夊嚭琛屻�佺浜岄樁娈靛張琚繃婊ゆ帀銆嶃��
+     * <p>
+     * 涔嬫墍浠ヨ鍗曠嫭涓�鏉★細鍒楄〃璇彞 select 绾� 100 鍒楋紝娣辩炕椤垫椂琚� offset 璺宠繃鐨勬瘡涓�琛�
+     * 閮借鍥炶〃璇绘暣琛岋紱鑰屽彧鍙� id 鐨勮鍙ュ彲浠ヨ蛋瑕嗙洊绱㈠紩骞舵彁鍓嶆埅鏂��
+     *
+     * @param serviceSubtaskVO 鏌ヨ鏉′欢锛坧ageNum 鏄� offset銆乸ageSize 鏄瘡椤垫潯鏁帮紝鐢辫皟鐢ㄦ柟绠楀ソ锛�
+     * @return 褰撳墠椤电殑瀛愪换鍔� id锛屽凡鎸夋帓搴忚鍒欐帓濂藉簭
+     */
+    public List<Long> selectServiceSubtaskIdsPage(ServiceSubtaskEntity serviceSubtaskVO);
+
     
 
     /**
@@ -163,6 +178,25 @@
 
     public List<ServiceSubtask> getSfStatistics(ServiceSubtaskCountReq serviceSubtaskCountReq);
 
+    /**
+     * 闅忚鍒嗙被缁熻锛氭寜鍒嗙粍锛坓roupKey=drcode / leaveldeptcode / leavehospitaldistrictcode锛夊湪搴撻噷鑱氬悎銆�
+     * <p>
+     * 鐢ㄤ簬鏇夸唬鈥滄妸 getSfStatistics 鍛戒腑鐨勫叏閮ㄦ槑缁嗚鎹炲洖鍐呭瓨鍐嶉�愯绱姞鈥濈殑鑰佸仛娉曪紝
+     * 鍙繑鍥炲垎缁勬暟锛堝嚑鍗佽锛夌殑缁撴灉锛涚粺璁″彛寰勪笌 {@code getStatisticCategory} 瀹屽叏涓�鑷淬��
+     *
+     * @param serviceSubtaskCountReq 鏌ヨ鏉′欢锛堝繀椤诲凡璁剧疆 groupKey / groupKeyList锛�
+     * @return 姣忎釜鍒嗙粍鐨勮仛鍚堢粺璁�
+     */
+    public List<ServiceSubtaskStatistic> getSfStatisticsScriptSum(ServiceSubtaskCountReq serviceSubtaskCountReq);
+
+    /**
+     * 闅忚鍒嗙被缁熻锛氭弧鎰忓害棰樼洰閲忔寜鍒嗙粍鑱氬悎锛堟浛浠� getSfStatisticsCategory 鐨� IN 澶у垪琛� + 鍐呭瓨杩囨护锛夈��
+     *
+     * @param serviceSubtaskCountReq 鏌ヨ鏉′欢锛堝繀椤诲凡璁剧疆 groupKey / groupKeyList / configValue锛�
+     * @return 姣忚鍖呭惈 groupCode銆乯oyAllCount銆乯oyCount 涓変釜閿�
+     */
+    public List<Map<String, Object>> getSfStatisticsScriptJoySum(ServiceSubtaskCountReq serviceSubtaskCountReq);
+
     public List<ServiceSubtaskStatistic> getSpecialSfStatistics(ServiceSubtaskCountReq serviceSubtaskCountReq);
 
     public List<ServiceSubtask> getSfStatisticsHyperlink(ServiceSubtaskCountReq serviceSubtaskCountReq);
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/service/impl/ServiceSubtaskServiceImpl.java b/ruoyi-task/src/main/java/com/ruoyi/task/service/impl/ServiceSubtaskServiceImpl.java
index 18d40e8..bad652a 100644
--- a/ruoyi-task/src/main/java/com/ruoyi/task/service/impl/ServiceSubtaskServiceImpl.java
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/service/impl/ServiceSubtaskServiceImpl.java
@@ -383,8 +383,8 @@
                 patTaskRelevance.setDiagname(serviceSubtask1.getLeavediagname());
                 patTaskRelevance.setPatid(serviceSubtask1.getPatid());
                 patTaskRelevance.setSendStatus(serviceSubtask1.getSendstate());
-                patTaskRelevance.setDeptcode(serviceSubtask1.getDeptcode());
-                patTaskRelevance.setDeptName(serviceSubtask1.getDeptname());
+                patTaskRelevance.setDeptcode(serviceSubtask1.getLeaveldeptcode());
+                patTaskRelevance.setDeptName(serviceSubtask1.getLeaveldeptname());
                 patTaskRelevance.setLeavehospitaldistrictcode(serviceSubtask1.getLeavehospitaldistrictcode());
                 patTaskRelevance.setLeavehospitaldistrictname(serviceSubtask1.getLeavehospitaldistrictname());
                 patTaskRelevance.setInhosptime(serviceSubtask1.getInhosptime());
@@ -404,8 +404,8 @@
                 patTaskRelevance.setTelcode(serviceSubtask1.getPhone());
                 patTaskRelevance.setFinishtime(serviceSubtask1.getFinishtime());
                 patTaskRelevance.setAddr(serviceSubtask1.getAddr());
-                patTaskRelevance.setDeptName(serviceSubtask1.getDeptname());
-                patTaskRelevance.setDeptcode(serviceSubtask1.getDeptcode());
+                patTaskRelevance.setDeptName(serviceSubtask1.getLeaveldeptname());
+                patTaskRelevance.setDeptcode(serviceSubtask1.getLeaveldeptcode());
                 patTaskRelevance.setBedNo(serviceSubtask1.getBedNo());
                 patTaskRelevance.setDiagname(serviceSubtask1.getLeavediagname());
                 patTaskRelevance.setPatid(serviceSubtask1.getPatid());
@@ -469,6 +469,12 @@
         List<ServiceSubtask> selectServiceSubtaskList = getServiceSubtasks(serviceSubtaskEntity);
 
         List<ServiceSubtaskRes> serviceSubtaskResList = new ArrayList<>();
+        // 鍚屼竴娆¤姹傦紙鍒楄〃鍒嗛〉 / 鍏ㄩ噺瀵煎嚭锛夐噷锛宨nhospid 涓� patid 楂樺害閲嶅
+        // 锛堝啀娆¢殢璁裤�佸悓涓�鎮h�呭浠诲姟閮戒細鎸囧悜鍚屼竴鏉′綇闄㈣褰�/鍚屼竴浠芥。妗堬級銆�
+        // 鍘熸潵姣忚閮借 2 娆″崟鏉℃煡璇紝瀵煎嚭鍑犲崈琛屽氨鏄嚑鍗兠�2 娆″線杩旓紱杩欓噷鎸� id 鍋氳繘绋嬪唴缂撳瓨锛�
+        // 鎶娿�屾瘡琛� 2 娆°�嶅帇鎴愩�屾瘡涓笉鍚� id 1 娆°�嶏紝鍙栨暟璇箟涓嶅彉銆�
+        Map<Long, PatMedInhosp> inhospCache = new HashMap<>();
+        Map<Long, PatArchive> archiveCache = new HashMap<>();
         for (ServiceSubtask serviceSubtask : selectServiceSubtaskList) {
             ServiceSubtaskRes serviceSubtaskRes = DtoConversionUtils.sourceToTarget(serviceSubtask, ServiceSubtaskRes.class);
             if (ObjectUtils.isNotEmpty(serviceSubtask.getContinueContent())) {
@@ -486,9 +492,9 @@
                     serviceSubtaskRes.setCurrentPreachform(serviceSubtask.getPreachform().split(",")[0]);
                 }
             }
-            PatMedInhosp inhosp = inhospVisitFacade.selectPatMedInhospByInhospid(serviceSubtask.getInhospid());
+            PatMedInhosp inhosp = loadInhospCached(inhospCache, serviceSubtask.getInhospid());
             if (ObjectUtils.isNotEmpty(inhosp)) {
-                PatArchive patArchive = taskArchivePort.findByPatid(inhosp.getPatid());
+                PatArchive patArchive = loadArchiveCached(archiveCache, inhosp.getPatid());
                 if (ObjectUtils.isNotEmpty(patArchive)) {
                     Map<String, String> stringStringMap = calculateAge(patArchive.getBirthdate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), LocalDate.now());
                     serviceSubtaskRes.setAge(StringUtils.isNotEmpty(stringStringMap.get("age")) ? Long.valueOf(stringStringMap.get("age")) : null);
@@ -502,6 +508,36 @@
             serviceSubtaskResList.add(serviceSubtaskRes);
         }
         return serviceSubtaskResList;
+    }
+
+    /**
+     * 鎸� inhospid 鍙栦綇闄㈣褰曪紙甯﹁繘绋嬪唴缂撳瓨锛夈��
+     * <p>
+     * 鍙槸鎶娿�屽悓涓�娆¤姹傚唴鍚屼竴涓� id 鍙煡涓�娆°�嶈繖浠朵簨鏀跺彛锛�<b>涓嶆敼鍙樺彇鏁拌涔�</b>锛�
+     * 鏌ヤ笉鍒帮紙null锛変篃浼氱紦瀛橈紝閬垮厤鍚屼竴鎵规暟鎹噷瀵逛笉瀛樺湪鐨� id 鍙嶅鎵撳簱銆�
+     * 缂撳瓨鐢熷懡鍛ㄦ湡 = 鍗曟 {@code patItem} 璋冪敤锛屼笉璺ㄨ姹傘�佷笉鍏变韩銆�
+     */
+    private PatMedInhosp loadInhospCached(Map<Long, PatMedInhosp> cache, Long inhospid) {
+        if (inhospid == null) {
+            return null;
+        }
+        if (!cache.containsKey(inhospid)) {
+            cache.put(inhospid, inhospVisitFacade.selectPatMedInhospByInhospid(inhospid));
+        }
+        return cache.get(inhospid);
+    }
+
+    /**
+     * 鎸� patid 鍙栨偅鑰呮。妗堬紙甯﹁繘绋嬪唴缂撳瓨锛夛紝璇箟鍚� {@link #loadInhospCached}銆�
+     */
+    private PatArchive loadArchiveCached(Map<Long, PatArchive> cache, Long patid) {
+        if (patid == null) {
+            return null;
+        }
+        if (!cache.containsKey(patid)) {
+            cache.put(patid, taskArchivePort.findByPatid(patid));
+        }
+        return cache.get(patid);
     }
 
     public List<ServiceSubtask> getServiceSubtasks(ServiceSubtaskEntity serviceSubtaskEntity) {
@@ -524,8 +560,63 @@
                 }
             }
         }
-        List<ServiceSubtask> selectServiceSubtaskList = this.selectServiceSubtaskList(serviceSubtaskEntity);
-        return selectServiceSubtaskList;
+        // 鍒嗛〉璇锋眰璧般�屼袱闃舵銆嶏細鍏堝彧鍙栧綋椤� id锛屽啀鎸� id 鍥炶〃銆�
+        // 鍒楄〃 select 绾� 100 鍒楋紝娣辩炕椤垫椂琚� offset 璺宠繃鐨勬瘡涓�琛屽師鏈兘瑕佸洖琛ㄨ鏁磋锛�
+        // 鍙彇 id 鐨勬煡璇㈣兘璧拌鐩栫储寮曞苟鎻愬墠鎴柇锛屼唬浠峰皬寰楀銆�
+        if (serviceSubtaskEntity.getPageNum() != null && serviceSubtaskEntity.getPageSize() != null) {
+            return selectServiceSubtaskPage(serviceSubtaskEntity);
+        }
+        return this.selectServiceSubtaskList(serviceSubtaskEntity);
+    }
+
+    /**
+     * 涓ら樁娈靛垎椤碉細鈶� 鍙煡 id锛堣鐩栫储寮� + limit offset锛夆憽 鎸� id 鍥炶〃鍙栨暣琛屻��
+     * <p>
+     * 绗簩闃舵澶嶇敤 {@code selectServiceSubtaskList} 鐨� subIdList 鏉′欢鍥炶〃锛�
+     * 蹇呴』鎶� pageNum/pageSize 鎽樻帀 鈥斺�� 鍚﹀垯浼氬湪銆屽綋椤� id 闆嗗悎銆嶄笂鍐嶇炕涓�娆¢〉銆�
+     * <p>
+     * 缁熻缂撳瓨锛圕ontroller 鐨� {@code getPatItemCountWithCache}锛夌敤 ReflectUtils 姣斿鏁翠釜
+     * entity 浣滀负缂撳瓨鍛戒腑鏉′欢锛寋@code subIdList} 鍙備笌姣斿锛屾墍浠ョ敤瀹屽繀椤诲師鏍疯繕鍘燂紝
+     * 鍚﹀垯缂撳瓨姘歌繙涓嶅懡涓紝姣忔璇锋眰閮借閲嶇畻涓�娆¤仛鍚堛��
+     */
+    private List<ServiceSubtask> selectServiceSubtaskPage(ServiceSubtaskEntity serviceSubtaskEntity) {
+        List<Long> pageIds = serviceSubtaskMapper.selectServiceSubtaskIdsPage(serviceSubtaskEntity);
+        if (CollectionUtils.isEmpty(pageIds)) {
+            return new ArrayList<>();
+        }
+        Integer pageNum = serviceSubtaskEntity.getPageNum();
+        Integer pageSize = serviceSubtaskEntity.getPageSize();
+        List<Long> originSubIdList = serviceSubtaskEntity.getSubIdList();
+        serviceSubtaskEntity.setPageNum(null);
+        serviceSubtaskEntity.setPageSize(null);
+        serviceSubtaskEntity.setSubIdList(pageIds);
+        List<ServiceSubtask> rows;
+        try {
+            rows = serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtaskEntity);
+        } finally {
+            serviceSubtaskEntity.setPageNum(pageNum);
+            serviceSubtaskEntity.setPageSize(pageSize);
+            serviceSubtaskEntity.setSubIdList(originSubIdList);
+        }
+        if (CollectionUtils.isEmpty(rows)) {
+            return new ArrayList<>();
+        }
+        // 浠ョ涓�闃舵鐨� id 椤哄簭涓哄噯閲嶆帓锛氱浜岄樁娈电殑 order by 鍙繚璇併�屽悓涓�椤靛唴銆嶆湁搴忥紝
+        // 閬囧埌鎺掑簭瀛楁鍊肩浉鍚岀殑琛屾椂鐩稿椤哄簭涓嶄竴瀹氫笌绗竴闃舵涓�鑷淬��
+        Map<Long, ServiceSubtask> byId = new HashMap<>(Math.max(16, rows.size() * 2));
+        for (ServiceSubtask row : rows) {
+            if (row.getId() != null) {
+                byId.put(row.getId(), row);
+            }
+        }
+        List<ServiceSubtask> ordered = new ArrayList<>(pageIds.size());
+        for (Long id : pageIds) {
+            ServiceSubtask row = byId.get(id);
+            if (row != null) {
+                ordered.add(row);
+            }
+        }
+        return ordered;
     }
 
     @Override
@@ -1164,8 +1255,8 @@
                     serviceSubtask.setInhospid(patTaskRelevance.getHospid());
                     //鏂板缓瀹屾垚灏辨槸寰呭彂閫佺姸鎬�
                     serviceSubtask.setSendstate(2L);
-                    serviceSubtask.setDeptcode(StringUtils.isNotEmpty(patTaskRelevance.getDeptcode()) ? patTaskRelevance.getDeptcode() : serviceTaskVO.getDeptcode());
-                    serviceSubtask.setDeptname(StringUtils.isNotEmpty(patTaskRelevance.getDeptName()) ? patTaskRelevance.getDeptName() : serviceTaskVO.getDeptname());
+                    serviceSubtask.setLeaveldeptcode(StringUtils.isNotEmpty(patTaskRelevance.getDeptcode()) ? patTaskRelevance.getDeptcode() : serviceTaskVO.getDeptcode());
+                    serviceSubtask.setLeaveldeptname(StringUtils.isNotEmpty(patTaskRelevance.getDeptName()) ? patTaskRelevance.getDeptName() : serviceTaskVO.getDeptname());
                     serviceSubtask.setLeavehospitaldistrictcode(patTaskRelevance.getLeavehospitaldistrictcode());
                     serviceSubtask.setLeavehospitaldistrictname(patTaskRelevance.getLeavehospitaldistrictname());
                     serviceSubtask.setType(serviceTaskVO.getType());
@@ -1530,10 +1621,10 @@
                     serviceSubtask.setAddr(patTaskRelevance.getAddr());
                     serviceSubtask.setPatid(patTaskRelevance.getPatid());
                     serviceSubtask.setOpenid(patTaskRelevance.getOpenid());
-                    serviceSubtask.setDeptcode(patTaskRelevance.getDeptcode());
+                    serviceSubtask.setLeaveldeptcode(patTaskRelevance.getDeptcode());
                     serviceSubtask.setLeavehospitaldistrictname(patTaskRelevance.getLeavehospitaldistrictname());
                     serviceSubtask.setLeavehospitaldistrictcode(patTaskRelevance.getLeavehospitaldistrictcode());
-                    serviceSubtask.setDeptname(patTaskRelevance.getDeptName());
+                    serviceSubtask.setLeaveldeptname(patTaskRelevance.getDeptName());
                     serviceSubtask.setType(serviceTaskVO.getType());
                     serviceSubtask.setCreateTime(DateUtils.getNowDate());
                     serviceSubtask.setDrname(patTaskRelevance.getDrname());
@@ -1787,7 +1878,7 @@
                 collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getManagementDoctorCode()).orElse("Unknown")));
                 break;
             case "deptcode":
-                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDeptcode()).orElse("Unknown")));
+                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getLeaveldeptcode()).orElse("Unknown")));
                 break;
             case "leavehospitaldistrictcode":
                 collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getLeavehospitaldistrictcode()).orElse("Unknown")));
@@ -1852,6 +1943,21 @@
      * @return
      */
     public Map<String, Map<String, Object>> getSsRateForSfStatistics(ServiceSubtaskCountReq serviceSubtaskCountReq, Map<String, List<ServiceSubtask>> collect) {
+        if (ObjectUtils.isEmpty(serviceSubtaskCountReq) || ObjectUtils.isEmpty(collect)) {
+            return null;
+        }
+        return getSsRateForSfStatistics(serviceSubtaskCountReq, new ArrayList<>(collect.keySet()));
+    }
+
+    /**
+     * 闅忚缁熻-鍙婃椂鐜囩粺璁★紙鍒嗙粍閿洿鎺ヤ紶鍊肩殑閲嶈浇锛�
+     * <p>
+     * 缁熻涓嬫帹鍒� SQL 鐨� {@code getSfStatisticsScript} 涓嶅啀鎶婃槑缁嗚鎹炲洖鍐呭瓨锛屾嬁涓嶅埌
+     * {@code Map<鍒嗙粍, List<鏄庣粏>>}锛屽洜姝ょ洿鎺ヤ紶鍒嗙粍閿泦鍚堬紱鏌ヨ璇彞涓庡師鏉ュ畬鍏ㄥ悓涓�涓��
+     *
+     * @param groupKeyList 鍒嗙粍閿泦鍚堬紙drcode / leaveldeptcode / leavehospitaldistrictcode 鐨勫疄闄呭彇鍊硷級
+     */
+    public Map<String, Map<String, Object>> getSsRateForSfStatistics(ServiceSubtaskCountReq serviceSubtaskCountReq, List<String> groupKeyList) {
         if (ObjectUtils.isEmpty(serviceSubtaskCountReq)) {
             return null;
         }
@@ -1859,7 +1965,6 @@
         if (StringUtils.isEmpty(groupKey)) {
             return null;
         }
-        List<String> groupKeyList = new ArrayList<>(collect.keySet());
         if (ObjectUtils.isEmpty(groupKeyList)) {
             return null;
         }
@@ -1878,11 +1983,21 @@
         ssRate.setGroupKey(groupKey);
         ssRate.setGroupKeyList(groupKeyList);
         ssRate.setRateDay(serviceSubtaskCountReq.getRateDay());
-        Map<String, Map<String, Object>> jsRates = new HashMap<>();
-        if (!collect.isEmpty()) {
-            jsRates = serviceSubtaskMapper.selectTimelyRateBatch(ssRate);
-        }
-        return jsRates;
+        return serviceSubtaskMapper.selectTimelyRateBatch(ssRate);
+    }
+
+    /**
+     * 绌哄�煎厹搴曪細SUM(CASE ...) 鐞嗚涓婁笉浼氭槸 null锛岃繖閲屽彧鍋氶槻寰★紝閬垮厤鎷嗙 NPE銆�
+     */
+    private long nvlLong(Long value) {
+        return value == null ? 0L : value;
+    }
+
+    /**
+     * 鎶婃暟鎹簱鑱氬悎鍊硷紙BigDecimal / Long / Integer 绛夛級杞垚 int銆�
+     */
+    private int toIntValue(Object value) {
+        return value instanceof Number ? ((Number) value).intValue() : 0;
     }
 
     public List<ServiceSubtaskStatistic> getSfStatisticsExport(ServiceSubtaskCountReq serviceSubtaskCountReq) {
@@ -1930,7 +2045,7 @@
             if (serviceSubtaskCountReq.getDrcode() != null && !serviceSubtaskCountReq.getDrcode().isEmpty()) {
                 collect = serviceSubtaskMapper.getSfStatistics(serviceSubtaskCountReq).stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDrname()).orElse("Unknown")));
             } else {
-                collect = serviceSubtaskMapper.getSfStatistics(serviceSubtaskCountReq).stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDeptname()).orElse("Unknown")));
+                collect = serviceSubtaskMapper.getSfStatistics(serviceSubtaskCountReq).stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getLeaveldeptname()).orElse("Unknown")));
             }
         }
         List<ServiceSubtaskCount> joySubCount = serviceSubtaskMapper.getSfStatisticsJoy(serviceSubtaskCountReq);
@@ -1951,7 +2066,7 @@
                 if (CollectionUtils.isNotEmpty(serviceSubtaskCountReq.getLeavehospitaldistrictcodes())) {
                     ss.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode());
                 } else if (CollectionUtils.isNotEmpty(serviceSubtaskCountReq.getDeptcodes())) {
-                    ss.setDeptcode(serviceSubtaskList.get(0).getDeptcode());
+                    ss.setLeaveldeptcode(serviceSubtaskList.get(0).getLeaveldeptcode());
                 }
             }
 
@@ -2000,8 +2115,8 @@
         } else {
             //鏍煎紡鍖栦负涓や綅灏忔暟鐨勭櫨鍒嗘瘮
             DecimalFormat percentFormat = new DecimalFormat("##.##%");
-            serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getDeptname());
-            serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getDeptcode());
+            serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getLeaveldeptname());
+            serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getLeaveldeptcode());
             serviceSubtaskStatistic.setLeavehospitaldistrictname(serviceSubtaskList.get(0).getLeavehospitaldistrictname());
             serviceSubtaskStatistic.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode());
             serviceSubtaskStatistic.setDrcode(serviceSubtaskList.get(0).getDrcode());
@@ -2292,8 +2407,8 @@
         ServiceSubtaskStatistic serviceSubtaskStatistic = new ServiceSubtaskStatistic();
         //鏍煎紡鍖栦负涓や綅灏忔暟鐨勭櫨鍒嗘瘮
         DecimalFormat percentFormat = new DecimalFormat("##.##%");
-        serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getDeptname());
-        serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getDeptcode());
+        serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getLeaveldeptname());
+        serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getLeaveldeptcode());
         serviceSubtaskStatistic.setLeavehospitaldistrictname(serviceSubtaskList.get(0).getLeavehospitaldistrictname());
         serviceSubtaskStatistic.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode());
         serviceSubtaskStatistic.setDrcode(serviceSubtaskList.get(0).getDrcode());
@@ -2462,8 +2577,8 @@
         ServiceSubtaskStatistic serviceSubtaskStatistic = new ServiceSubtaskStatistic();
         //鏍煎紡鍖栦负涓や綅灏忔暟鐨勭櫨鍒嗘瘮
         DecimalFormat percentFormat = new DecimalFormat("##.##%");
-        serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getDeptname());
-        serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getDeptcode());
+        serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getLeaveldeptname());
+        serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getLeaveldeptcode());
         serviceSubtaskStatistic.setLeavehospitaldistrictname(serviceSubtaskList.get(0).getLeavehospitaldistrictname());
         serviceSubtaskStatistic.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode());
         serviceSubtaskStatistic.setDrcode(serviceSubtaskList.get(0).getDrcode());
@@ -2624,8 +2739,8 @@
         ServiceSubtaskStatistic serviceSubtaskStatistic = new ServiceSubtaskStatistic();
         //鏍煎紡鍖栦负涓や綅灏忔暟鐨勭櫨鍒嗘瘮
         DecimalFormat percentFormat = new DecimalFormat("##.##%");
-        serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getDeptname());
-        serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getDeptcode());
+        serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getLeaveldeptname());
+        serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getLeaveldeptcode());
         serviceSubtaskStatistic.setLeavehospitaldistrictname(serviceSubtaskList.get(0).getLeavehospitaldistrictname());
         serviceSubtaskStatistic.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode());
         serviceSubtaskStatistic.setDrcode(serviceSubtaskList.get(0).getDrcode());
@@ -2729,8 +2844,8 @@
         ServiceSubtaskStatistic serviceSubtaskStatistic = new ServiceSubtaskStatistic();
         //鏍煎紡鍖栦负涓や綅灏忔暟鐨勭櫨鍒嗘瘮
         DecimalFormat percentFormat = new DecimalFormat("##.##%");
-        serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getDeptname());
-        serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getDeptcode());
+        serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getLeaveldeptname());
+        serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getLeaveldeptcode());
         serviceSubtaskStatistic.setLeavehospitaldistrictname(serviceSubtaskList.get(0).getLeavehospitaldistrictname());
         serviceSubtaskStatistic.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode());
         serviceSubtaskStatistic.setDrcode(serviceSubtaskList.get(0).getDrcode());
@@ -3074,67 +3189,111 @@
         log.info("getSfStatisticsScript鐨勫叆鍙備负锛歿}", serviceSubtaskCountReq);
         List<ServiceSubtaskStatistic> serviceSubtaskStatistics = new ArrayList<>();
 
-        // 鏍规嵁鏉′欢杩涜鍒嗙粍
-        Map<String, List<ServiceSubtask>> collect = new HashMap<>();
+        // 鏍规嵁鏉′欢鍐冲畾鍒嗙粍缁村害锛氱闄㈢淮搴︽寜 leaveldeptcode / leavehospitaldistrictcode锛堝惈鍘嗗彶 deptcodes 鍏ュ弬锛夛紝
+        // 鍦ㄩ櫌缁村害鎸� deptcode / hospitaldistrictcode
         String groupKey = "drcode";
+        boolean hasDrcode = serviceSubtaskCountReq.getDrcode() != null && !serviceSubtaskCountReq.getDrcode().isEmpty();
         if (serviceSubtaskCountReq.getLeavehospitaldistrictcodes() != null && !serviceSubtaskCountReq.getLeavehospitaldistrictcodes().isEmpty()) {
-            if (serviceSubtaskCountReq.getDrcode() != null && !serviceSubtaskCountReq.getDrcode().isEmpty()) {
-                groupKey = "drcode";
-            } else {
-                groupKey = "leavehospitaldistrictcode";
-            }
+            groupKey = hasDrcode ? "drcode" : "leavehospitaldistrictcode";
+        } else if (serviceSubtaskCountReq.getLeaveldeptcodes() != null && !serviceSubtaskCountReq.getLeaveldeptcodes().isEmpty()) {
+            groupKey = hasDrcode ? "drcode" : "leaveldeptcode";
+        } else if (serviceSubtaskCountReq.getHospitaldistrictcodes() != null && !serviceSubtaskCountReq.getHospitaldistrictcodes().isEmpty()) {
+            // 鍦ㄩ櫌婊℃剰搴︼細鎸夊湪闄㈢梾鍖哄垎缁勶紙hospitaldistrictcode锛�
+            groupKey = hasDrcode ? "drcode" : "hospitaldistrictcode";
+        } else if (serviceSubtaskCountReq.getHospitaldeptcodes() != null && !serviceSubtaskCountReq.getHospitaldeptcodes().isEmpty()) {
+            // 鍦ㄩ櫌婊℃剰搴︼細鎸夊湪闄㈢瀹ゅ垎缁勶紙deptcode锛�
+            groupKey = hasDrcode ? "drcode" : "deptcode";
         } else if (serviceSubtaskCountReq.getDeptcodes() != null && !serviceSubtaskCountReq.getDeptcodes().isEmpty()) {
-            if (serviceSubtaskCountReq.getDrcode() != null && !serviceSubtaskCountReq.getDrcode().isEmpty()) {
-                groupKey = "drcode";
-            } else {
-                groupKey = "deptcode";
-            }
+            // 鍘嗗彶鍏ュ弬 deptcodes 琛ㄧず绂婚櫌绉戝
+            groupKey = hasDrcode ? "drcode" : "leaveldeptcode";
         }
         serviceSubtaskCountReq.setGroupKey(groupKey);
+        // 鍒嗙粍鍒椾笌杩囨护鍒椾繚鎸佷竴鑷达細绂婚櫌绉戝 leaveldeptcode銆佸湪闄㈢瀹� deptcode
+        serviceSubtaskCountReq.setGroupColumn(groupKey);
+        //鍒嗙粍閿泦鍚堬細杩欎竴姝ヤ繚鎸佷笉鍙橈紙鍒嗛〉鍙傛暟鐓ф棫浣滅敤鍦ㄨ鏌ヨ涓婏級锛屼繚璇佲�滃弬涓庣粺璁$殑鍒嗙粍鈥濅笌鏀归�犲墠涓�鑷�
         List<String> groupKeyList = serviceSubtaskMapper.getSfStatisticsGroupKey(serviceSubtaskCountReq);
+        /*
+         * 鍒嗙粍鍒楀彲鑳戒负 NULL锛氭弧鎰忓害瀛愪换鍔★紙service_type 6/14/15/16锛夌殑 leavehospitaldistrictcode
+         * 澶ч噺涓� NULL锛実etSfStatisticsGroupKey 浼氭妸 NULL 鍘熸牱甯﹀洖鏉ワ紝
+         * 鎷艰繘 SQL 灏卞彉鎴� `AND xxx IN (null)`锛堟亽涓嶆垚绔嬶級锛屾暣寮犵粺璁¤〃鐩存帴绌恒��
+         * 杩欓噷缁熶竴鎴� 'Unknown'锛屼笌鑱氬悎 SQL 鐨� GROUP BY IFNULL(鍒�,'Unknown') 瀵归綈銆�
+         */
+        if (groupKeyList != null) {
+            groupKeyList = groupKeyList.stream()
+                    .map(key -> key == null ? "Unknown" : key)
+                    .distinct()
+                    .collect(Collectors.toList());
+        }
         serviceSubtaskCountReq.setGroupKeyList(groupKeyList);
-        List<ServiceSubtask> rawData = serviceSubtaskMapper.getSfStatistics(serviceSubtaskCountReq);
-        switch (groupKey) {
-            case "deptcode":
-                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDeptcode()).orElse("Unknown")));
-                break;
-            case "drcode":
-                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDrcode()).orElse("Unknown")));
-                break;
-            case "leavehospitaldistrictcode":
-                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getLeavehospitaldistrictcode()).orElse("Unknown")));
-                break;
-            default:
-                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDrcode()).orElse("Unknown")));
-                break;
+
+        /*
+         * 缁熻涓嬫帹鍒版暟鎹簱锛氫竴娆� GROUP BY 鍙繑鍥炩�滃垎缁勬暟鈥濊銆�
+         * 鏀归�犲墠鏄� serviceSubtaskMapper.getSfStatistics() 鎶婂懡涓殑鍏ㄩ儴鏄庣粏琛岋紙39 涓瓧娈碉紝
+         * 鍚� continue_content 绛夊ぇ瀛楁锛夋崬鍥� JVM 鍚庨�愯绱姞锛屽嚑鍗冭鏃朵紶杈撳拰閬嶅巻閮藉緢鎱€��
+         * 杩欓噷鐨勮仛鍚堝彛寰勪笌鍘� getStatisticCategory 閫愭潯瀵归綈锛堣 Mapper 涓� getSfStatisticsScriptSum 鐨勬敞閲婏級銆�
+         */
+        List<ServiceSubtaskStatistic> sumStatistics = serviceSubtaskMapper.getSfStatisticsScriptSum(serviceSubtaskCountReq);
+        if (CollectionUtils.isEmpty(sumStatistics)) {
+            return serviceSubtaskStatistics;
         }
-        //鑾峰彇鍙婃椂鐜囩粺璁″悎闆�
-        Map<String, Map<String, Object>> jsRates = getSsRateForSfStatistics(serviceSubtaskCountReq, collect);
-        //涓�娆℃�ф煡璇㈡墍鏈夊垎缁勭殑棰樼洰缁熻锛岄伩鍏嶆瘡涓垎缁勪竴娆QL锛圢+1锛�
-        List<Long> allSubTaskIds = rawData.stream().map(ServiceSubtask::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
-        List<ServiceSubtaskCount> subCounts = new ArrayList<>();
-        if (CollectionUtils.isNotEmpty(allSubTaskIds)) {
-            serviceSubtaskCountReq.setSubTaskIds(allSubTaskIds);
-            subCounts = serviceSubtaskMapper.getSfStatisticsCategory(serviceSubtaskCountReq);
-        }
-        for (String collectKey : collect.keySet()) {
-            List<ServiceSubtask> serviceSubtaskList = collect.get(collectKey);
-            if (CollectionUtils.isEmpty(serviceSubtaskList)) {
-                continue;
-            }
-            ServiceSubtaskStatistic statistic = getStatisticCategory(serviceSubtaskList, serviceSubtaskCountReq, subCounts);
-            if (ObjectUtils.isNotEmpty(jsRates)) {
-                Map<String, Object> jsRateMap = jsRates.get(collectKey);
-                BigDecimal jsRate = new BigDecimal("0");
-                if (ObjectUtils.isNotEmpty(jsRateMap) && ObjectUtils.isNotEmpty(jsRateMap.get("rate"))) {
-                    jsRate = new BigDecimal(jsRateMap.get("rate").toString());
+
+        /*
+         * 婊℃剰搴﹂鐩噺锛氫篃鏀规垚鎸夊垎缁勫湪搴撻噷鑱氬悎銆�
+         * 鏀归�犲墠鏄厛鎶婃湰娆″懡涓殑鍏ㄩ儴瀛愪换鍔� id 鐏岃繘 getSfStatisticsCategory 鐨� IN 鍒楄〃鏌ヤ竴閬嶏紝
+         * 鍐嶅湪鍐呭瓨閲屽姣忎釜瀛愪换鍔″仛涓�娆� subCounts.stream().filter(...)锛圢*M 娆℃瘮杈冿級銆�
+         */
+        Map<String, Integer> joyCountMap = new HashMap<>();
+        Map<String, Integer> joyAllCountMap = new HashMap<>();
+        if (StringUtils.isNotEmpty(serviceSubtaskCountReq.getConfigValue())) {
+            List<Map<String, Object>> joySums = serviceSubtaskMapper.getSfStatisticsScriptJoySum(serviceSubtaskCountReq);
+            if (CollectionUtils.isNotEmpty(joySums)) {
+                for (Map<String, Object> joySum : joySums) {
+                    String joyGroupCode = joySum.get("groupCode") == null ? "Unknown" : joySum.get("groupCode").toString();
+                    joyCountMap.put(joyGroupCode, toIntValue(joySum.get("joyCount")));
+                    joyAllCountMap.put(joyGroupCode, toIntValue(joySum.get("joyAllCount")));
                 }
-                Double jsRateDouble = (jsRate.setScale(4, RoundingMode.HALF_UP)).doubleValue();
-                statistic.setRate(jsRateDouble);
             }
-            if (ObjectUtils.isNotEmpty(statistic)) {
-                serviceSubtaskStatistics.add(statistic);
+        }
+
+        //闅忚鐜囷細鍙e緞涓庡師 getStatisticCategory 涓�鑷达紙棣栨鐜囩殑鍒ゆ柇娌跨敤鍘熸潵鐨� needFollowUp銆佸啀娆$巼娌跨敤鍘熸潵鐨勫垎姣嶏級
+        DecimalFormat percentFormat = new DecimalFormat("##.##%");
+        List<String> statisticsGroupKeys = new ArrayList<>();
+        for (ServiceSubtaskStatistic statistic : sumStatistics) {
+            String statisticGroupCode = statistic.getGroupCode() == null ? "Unknown" : statistic.getGroupCode();
+            statistic.setJoyCount(joyCountMap.getOrDefault(statisticGroupCode, 0));
+            statistic.setJoyAllCount(joyAllCountMap.getOrDefault(statisticGroupCode, 0));
+            //棣栨闅忚鐜囷細鍙湁璇ュ垎缁勫瓨鍦ㄩ娆¢殢璁胯褰曟椂鎵嶄細琚祴鍊硷紙涓嶅瓨鍦ㄥ垯鏄� null锛屼笌鏀归�犲墠涓�鑷达級
+            if (statistic.getFirstVisitCount() != null && statistic.getFirstVisitCount() > 0) {
+                if (statistic.getNeedFollowUp() != null && statistic.getNeedFollowUp() > 0) {
+                    double rate = (double) (nvlLong(statistic.getFollowUpSuccess()) + nvlLong(statistic.getFollowUpFail())) / statistic.getNeedFollowUp();
+                    statistic.setFollowUpRate(percentFormat.format(rate));
+                } else {
+                    statistic.setFollowUpRate("0.00%");
+                }
             }
+            //鍐嶆闅忚鐜囷細鍒ゆ柇鏉′欢涓庡師瀹炵幇涓�鑷达紙鍘熸潵鍒ゆ柇鐨勬槸 needFollowUp锛岃繖閲岀収鎼互鍏嶅彛寰勫彉鍖栵級
+            if (statistic.getAgainVisitCount() != null && statistic.getAgainVisitCount() > 0) {
+                if (statistic.getNeedFollowUp() != null && statistic.getNeedFollowUp() > 0) {
+                    double rateAgain = (double) (nvlLong(statistic.getFollowUpSuccessAgain()) + nvlLong(statistic.getFollowUpFailAgain())) / nvlLong(statistic.getNeedFollowUpAgain());
+                    statistic.setFollowUpRateAgain(percentFormat.format(rateAgain));
+                } else {
+                    statistic.setFollowUpRateAgain("0.00%");
+                }
+            }
+            statisticsGroupKeys.add(statisticGroupCode);
+            serviceSubtaskStatistics.add(statistic);
+        }
+
+        //鑾峰彇鍙婃椂鐜囩粺璁″悎闆嗭紙涓�娆℃壒閲忔煡璇紝涓嶆寜鍒嗙粍寰幆鏌ワ級
+        Map<String, Map<String, Object>> jsRates = getSsRateForSfStatistics(serviceSubtaskCountReq, statisticsGroupKeys);
+        for (ServiceSubtaskStatistic statistic : serviceSubtaskStatistics) {
+            String statisticGroupCode = statistic.getGroupCode() == null ? "Unknown" : statistic.getGroupCode();
+            Map<String, Object> jsRateMap = jsRates == null ? null : jsRates.get(statisticGroupCode);
+            BigDecimal jsRate = new BigDecimal("0");
+            if (ObjectUtils.isNotEmpty(jsRateMap) && ObjectUtils.isNotEmpty(jsRateMap.get("rate"))) {
+                jsRate = new BigDecimal(jsRateMap.get("rate").toString());
+            }
+            statistic.setRate((jsRate.setScale(4, RoundingMode.HALF_UP)).doubleValue());
         }
 
         //缁熻闅忚棰樼洰鍒嗙被
@@ -3401,7 +3560,7 @@
             diagname.setPhone(subtask.getPhone());
             diagname.setNurseName(subtask.getNurseName());
             diagname.setDrname(subtask.getDrname());
-            diagname.setDeptname(subtask.getDeptname());
+            diagname.setDeptname(subtask.getLeaveldeptname());
             diagname.setLeavehospitaldistrictname(subtask.getLeavehospitaldistrictname());
             diagname.setTemplatename(subtask.getTemplatename());
             diagname.setPreachform(subtask.getPreachform());
@@ -3508,7 +3667,6 @@
         //3.濡傛灉鏌ュ嚭鏉ョ殑闆嗗悎涓嶄负绌猴紝鍒欒繘琛屽惊鐜�
         for (ServiceSubtask serviceSubtask : serviceSubtasks) {
             Integer preachformSize = 0;
-            Boolean flag = false;
             ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform();
             serviceSubtaskPreachform.setSubid(serviceSubtask.getId());
             List<ServiceSubtaskPreachform> serviceSubtaskPreachforms = taskPreachformPort.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
@@ -3516,31 +3674,100 @@
                 preachformSize = serviceSubtaskPreachforms.size();
             if (serviceSubtask.getUpdateTime() != null && DateUtils.differentDaysByMillisecond(new Date(), serviceSubtask.getUpdateTime()) >= failDay) {
                 //3.1 鍒ゆ柇褰撳墠serviceSubtask鐨剈pdateTime鏄笉鏄负绌猴紝濡傛灉涓嶄负绌猴紝鍒欏垽鏂綋鍓嶆椂闂存槸涓嶆槸涓巙pdateTime宸窛澶т簬绛変簬failDay
-                flag = saveServiceSubtaskDetail(serviceSubtask);
+                log.debug("銆愬け璐ヤ换鍔¢粯璁ゅ�笺�戝瓙浠诲姟 {} 杈惧埌澶辫触澶╂暟(updateTime)", serviceSubtask.getId());
             } else if (serviceSubtask.getVisitTime() != null && DateUtils.differentDaysByMillisecond(new Date(), serviceSubtask.getVisitTime()) >= failDay + preachformSize) {
                 //3.2 濡傛灉褰撳墠serviceSubtask鐨剈pdateTime涓虹┖锛屾牴鎹綋鍓峴erviceSubtask鐨剆ubid鍘绘煡service_subtask_preachform寰楀埌size锛堝鏋渟ize涓虹┖锛屽垯榛樿0锛夛紝鍒欐牴鎹綋鍓嶆椂闂存槸涓嶆槸涓庡綋鍓峴erviceSubtask鐨剉isitTime宸窛澶т簬绛変簬failDay + size
-                flag = saveServiceSubtaskDetail(serviceSubtask);
+                log.debug("銆愬け璐ヤ换鍔¢粯璁ゅ�笺�戝瓙浠诲姟 {} 杈惧埌澶辫触澶╂暟(visitTime+preachformSize)", serviceSubtask.getId());
             } else {
                 //3.3 濡傛灉2.1涓�2.2閮戒负false锛屽垯continue
                 continue;
             }
 
-            //4.濡傛灉flag涓簍rue锛屽垯鏇存柊service_subtask琛ㄤ腑鐨剆endstate涓�6锛宲reachform涓�1
-            if (flag) {
-                serviceSubtask.setSendstate(6L);
-                serviceSubtask.setPreachform("1");
-                serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
+            //4. 鈿狅笍 2026-10-21 鍔犲浐锛氬厛"绠楀畬"鍐�"钀藉簱"锛屽交搴曞幓鎺�"鍏堟彃鍏ャ�佸け璐ュ啀鍒犻櫎"鐨勫啓娉曘��
+            //   鏃ч�昏緫鏄竟鎻掕竟鍒ゆ柇锛屽彧瑕佹湁涓�棰樻病閰嶉粯璁ゅ�硷紝灏辨妸杩欎釜 sub_id 涓�**鎵�鏈�**鏄庣粏锛堝惈鎮h�呯湡瀹炰綔绛斻��
+            //   鐢氳嚦鍒氭彃杩涘幓鐨勯偅鎵癸級缁熺粺缃� del_flag='1' 鈥斺�� nhfy 2026-09-08 閭� 10 浣嶆偅鑰呯殑婊℃剰搴︿綔绛�
+            //   灏辨槸杩欐牱琚垹鎺夈�佸鑷村鍑恒�岄棶棰樿鎯呭崰姣斻��370 鑰屻�岄殢璁夸俊鎭〃鍗曘��380 鐨勩��
+            //   鐜板湪锛氣憼 娓呭崟涓虹┖锛�=鏈夐娌¢厤榛樿鍊硷級鈫� 鏁翠唤璺宠繃锛屼笉鍐欎篃涓嶅垹锛�
+            //         鈶� 娓呭崟榻愬叏 鈫� 缁熶竴钀藉簱锛堝瓨鍦ㄥ垯鏇存柊骞跺娲伙紝涓嶅瓨鍦ㄥ垯鎻掑叆锛夈��
+            List<ServiceSubtaskDetail> defaultDetails = buildDefaultDetails(serviceSubtask);
+            if (CollectionUtils.isEmpty(defaultDetails)) {
+                log.info("銆愬け璐ヤ换鍔¢粯璁ゅ�笺�戜换鍔� {} 瀛愪换鍔� {} 鏈夐鐩湭閰嶇疆榛樿鍊硷紝鏁翠唤璺宠繃锛堜笉鎻掑叆銆佷笉鍒犻櫎浠讳綍鏄庣粏锛�",
+                        serviceSubtask.getTaskid(), serviceSubtask.getId());
+                continue;
+            }
+            persistDefaultDetails(defaultDetails);
+
+            //5.鍏ㄩ儴钀藉簱鎴愬姛鍚庡啀鎶婁换鍔$疆涓哄凡瀹屾垚
+            serviceSubtask.setSendstate(6L);
+            serviceSubtask.setPreachform("1");
+            serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
+        }
+    }
+
+    /**
+     * 鎸夋ā鏉挎瀯閫�"榛樿鍊兼槑缁�"娓呭崟锛�<b>鍙绠椼�佷笉钀藉簱</b>锛�
+     * <p>
+     * 2026-10-21 鏂板锛氭妸鍘熸潵鐨� {@code saveServiceSubtaskDetail}锛堣竟绠楄竟鎻掋�佸け璐ュ啀鍒狅級鎷嗘垚
+     * 銆宐uild锛堟湰鏂规硶锛夈��+銆宲ersist锛坽@link #persistDefaultDetails}锛夈�嶄袱姝ワ紝
+     * 淇濊瘉"榛樿鍊间笉鍏�"鏃�**涓�涓瓧鑺傞兘涓嶄細鍐欍�佹洿涓嶄細鍒�**銆�
+     *
+     * @param serviceSubtask 瀛愪换鍔�
+     * @return 鏄庣粏娓呭崟锛涗换涓�棰樻病閰嶉粯璁ゅ�硷紙鎴栨ā鏉夸负绌猴級鏃惰繑鍥� {@code null}锛岃〃绀烘暣浠戒笉澶勭悊
+     */
+    private List<ServiceSubtaskDetail> buildDefaultDetails(ServiceSubtask serviceSubtask) {
+        if (serviceSubtask.getType() == null) {
+            return null;
+        }
+        List<ServiceSubtaskDetail> details = new ArrayList<>();
+        if (serviceSubtask.getType().equals("1")) {
+            //3.3.1 濡傛灉type鏄� 1锛屽垯鐢ㄥ綋鍓峴erviceSubtask鐨則emplateid鍘籭vr_task_temaplate_script涓幏鍙栭棶棰樺拰閫夐」
+            IvrTaskTemplateScript ivrTaskTemplateScript = new IvrTaskTemplateScript();
+            ivrTaskTemplateScript.setTemplateID(serviceSubtask.getTemplateid());
+            List<IvrTaskTemplateScript> ivrTaskTemplateScripts = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptList(ivrTaskTemplateScript);
+            if (CollectionUtils.isEmpty(ivrTaskTemplateScripts)) return null;
+            for (IvrTaskTemplateScript its : ivrTaskTemplateScripts) {
+                IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO = DtoConversionUtils.sourceToTarget(its, IvrTaskTemplateScriptVO.class);
+                IvrTaskTemplateTargetoption ivrTaskTemplateTargetoption = new IvrTaskTemplateTargetoption();
+                ivrTaskTemplateTargetoption.setScriptid(ivrTaskTemplateScriptVO.getId());
+                List<IvrTaskTemplateTargetoption> ivrTaskTemplateTargetoptions = iIvrTaskTemplateTargetoptionService.selectIvrTaskTemplateTargetoptionList(ivrTaskTemplateTargetoption);
+                ivrTaskTemplateScriptVO.setIvrTaskScriptTargetoptionList(ivrTaskTemplateTargetoptions);
+                ServiceSubtaskDetail detail = buildSFDetail(ivrTaskTemplateScriptVO, serviceSubtask);
+                if (detail == null) return null;
+                details.add(detail);
+            }
+        } else if (serviceSubtask.getType().equals("2")) {
+            //3.3.2 濡傛灉type鏄� 2锛屽垯鐢ㄥ綋鍓峴erviceSubtask鐨則emplateid鍘籹vy_task_temaplate_script涓幏鍙栭棶棰樺拰閫夐」
+            SvyTaskTemplateScript svyTaskTemplateScript = new SvyTaskTemplateScript();
+            svyTaskTemplateScript.setTemplateID(serviceSubtask.getTemplateid());
+            List<SvyTaskTemplateScript> svyTaskTemplateScripts = svyTaskTemplateScriptService.selectSvyTaskTemplateScriptList(svyTaskTemplateScript);
+            if (CollectionUtils.isEmpty(svyTaskTemplateScripts)) return null;
+            for (SvyTaskTemplateScript taskTemplateScript : svyTaskTemplateScripts) {
+                SvyTaskTemplateScriptVO svyTaskTemplateScriptVO = DtoConversionUtils.sourceToTarget(taskTemplateScript, SvyTaskTemplateScriptVO.class);
+                SvyTaskTemplateScriptVO svyTaskTemplateScriptVO1 = svyTaskTemplateScriptService.selectInfoByCondition(svyTaskTemplateScriptVO);
+                ServiceSubtaskDetail detail = buildWJDetail(svyTaskTemplateScriptVO1, serviceSubtask);
+                if (detail == null) return null;
+                details.add(detail);
+            }
+        } else {
+            return null;
+        }
+        return details;
+    }
+
+    /**
+     * 钀藉簱"榛樿鍊兼槑缁�"锛氬瓨鍦ㄥ垯鏇存柊骞跺娲伙紝涓嶅瓨鍦ㄥ垯鎻掑叆锛�<b>鍙涓嶅垹</b>锛�
+     */
+    private void persistDefaultDetails(List<ServiceSubtaskDetail> details) {
+        for (ServiceSubtaskDetail detail : details) {
+            ServiceSubtaskDetailDTO exist = serviceSubtaskDetailMapper.isExistServiceSubtaskDetail(detail.getSubId(), detail.getScriptid());
+            if (ObjectUtils.isNotEmpty(exist)) {
+                detail.setId(exist.getId());
+                detail.setUpdateTime(new Date());
+                serviceSubtaskDetailMapper.updateServiceSubtaskDetail(detail);
+                //鍛戒腑鍘嗗彶琚垹鍓湰鏃剁疆鍥� del_flag='0'锛岄伩鍏嶅啀鎻掍竴浠芥柊鍓湰
+                serviceSubtaskDetailMapper.reviveServiceSubtaskDetail(exist.getId());
             } else {
-                //鍒犻櫎璇柊澧瀌etail閲岀殑鏁版嵁
-                ServiceSubtaskDetail serviceSubtaskDetail = new ServiceSubtaskDetail();
-                serviceSubtaskDetail.setSubId(serviceSubtask.getId());
-                List<ServiceSubtaskDetail> serviceSubtaskDetails = serviceSubtaskDetailMapper.selectServiceSubtaskDetailList(serviceSubtaskDetail);
-                if (CollectionUtils.isNotEmpty(serviceSubtaskDetails)) {
-                    for (ServiceSubtaskDetail serviceSubtaskDetail1 : serviceSubtaskDetails) {
-                        serviceSubtaskDetail1.setDelFlag("1");
-                        serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail1);
-                    }
-                }
+                serviceSubtaskDetailMapper.insertServiceSubtaskDetail(detail);
             }
         }
     }
@@ -3740,44 +3967,30 @@
         return resultMap;
     }
 
-    private Boolean saveServiceSubtaskDetail(ServiceSubtask serviceSubtask) {
-        Boolean result = true;
-        //3.4 濡傛灉3.1鎴�3.2涓簍rue鐨勮瘽锛屾牴鎹畉ype鍒ゆ柇浠�涔堢被鍨�
-        if (serviceSubtask.getType().equals("1")) {
-            //3.3.1    濡傛灉type鏄� 1 锛屽垯鐢ㄥ綋鍓峴erviceSubtask鐨則emplateid鍘籭vr_task_temaplate_script涓幏鍙栭棶棰樺拰閫夐」锛屽皢闂鍜岄�夐」鐨勯粯璁ゅ�兼斁鍒皊ervice_detail涓�
-            IvrTaskTemplateScript ivrTaskTemplateScript = new IvrTaskTemplateScript();
-            ivrTaskTemplateScript.setTemplateID(serviceSubtask.getTemplateid());
-            List<IvrTaskTemplateScript> ivrTaskTemplateScripts = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptList(ivrTaskTemplateScript);
-            for (IvrTaskTemplateScript its : ivrTaskTemplateScripts) {
-                IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO = DtoConversionUtils.sourceToTarget(its, IvrTaskTemplateScriptVO.class);
-                IvrTaskTemplateTargetoption ivrTaskTemplateTargetoption = new IvrTaskTemplateTargetoption();
-                ivrTaskTemplateTargetoption.setScriptid(ivrTaskTemplateScriptVO.getId());
-                List<IvrTaskTemplateTargetoption> ivrTaskTemplateTargetoptions = iIvrTaskTemplateTargetoptionService.selectIvrTaskTemplateTargetoptionList(ivrTaskTemplateTargetoption);
-                ivrTaskTemplateScriptVO.setIvrTaskScriptTargetoptionList(ivrTaskTemplateTargetoptions);
-                Integer integer = setSFDetailInfo(ivrTaskTemplateScriptVO, serviceSubtask);
-                if (Objects.isNull(integer) || integer == 0) result = false;
-            }
+    /*
+     * 2026-10-21 宸插垹闄� saveServiceSubtaskDetail(...)銆�
+     * 瀹冨師鏉ョ殑璇箟鏄�"杈圭畻榛樿鍊艰竟钀藉簱锛屾渶鍚庤繑鍥炲竷灏斿��"锛岃皟鐢ㄦ柟鍦ㄨ繑鍥� false 鏃舵妸璇� sub_id 涓嬬殑
+     * 鍏ㄩ儴鏄庣粏缃� del_flag='1'锛堣繛鎮h�呯湡瀹炰綔绛斾竴璧峰垹锛夈��
+     * 鐜板湪鎷嗘垚 buildDefaultDetails(...)锛堝彧绠椾笉鍐欙級 + persistDefaultDetails(...)锛堝彧澧炰笉鍒狅級锛�
+     * 浠讳綍涓�棰樼己榛樿鍊煎氨鏁翠唤璺宠繃锛屼笉浼氬啀浜х敓"鍒犻櫎"鍔ㄤ綔銆�
+     */
 
-        } else if (serviceSubtask.getType().equals("2")) {
-            //3.3.2    濡傛灉type鏄� 2,鍒欑敤褰撳墠serviceSubtask鐨則emplateid鍘籹vy_task_temaplate_script涓幏鍙栭棶棰樺拰閫夐」锛屽皢闂鍜岄�夐」鐨勯粯璁ゅ�兼斁鍒皊ervice_detail涓�
-            SvyTaskTemplateScript svyTaskTemplateScript = new SvyTaskTemplateScript();
-            svyTaskTemplateScript.setTemplateID(serviceSubtask.getTemplateid());
-            List<SvyTaskTemplateScript> svyTaskTemplateScripts = svyTaskTemplateScriptService.selectSvyTaskTemplateScriptList(svyTaskTemplateScript);
-            for (SvyTaskTemplateScript taskTemplateScript : svyTaskTemplateScripts) {
-                SvyTaskTemplateScriptVO svyTaskTemplateScriptVO = DtoConversionUtils.sourceToTarget(taskTemplateScript, SvyTaskTemplateScriptVO.class);
-                SvyTaskTemplateScriptVO svyTaskTemplateScriptVO1 = svyTaskTemplateScriptService.selectInfoByCondition(svyTaskTemplateScriptVO);
-                Integer integer = setWJDetailInfo(svyTaskTemplateScriptVO1, serviceSubtask);
-                if (Objects.isNull(integer) || integer == 0) result = false;
-            }
+    /**
+     * 鎸夈�岄棶鍗锋ā鏉裤�嶆瀯閫犱竴鏉�"榛樿鍊兼槑缁�"锛�<b>鍙绠椼�佷笉钀藉簱</b>锛�
+     * <p>
+     * 2026-10-21 鐢� {@code setWJDetailInfo}锛堢畻瀹屽氨鐩存帴 insert/update锛屽け璐ヨ繑鍥� 0锛夋敼閫犺�屾潵锛�
+     * 鐜板湪鍙礋璐f妸瀹炰綋鎷煎嚭鏉ワ紝鐢� {@link #persistDefaultDetails} 缁熶竴钀藉簱銆�
+     *
+     * @return 鏄庣粏锛涜棰樻病閰嶉粯璁ゅ�硷紙鍗�/澶氶�夐涓�涓粯璁ら�夐」閮芥病鏈夛級鏃惰繑鍥� {@code null}锛岃〃绀烘暣浠介棶鍗蜂笉澶勭悊
+     */
+    private ServiceSubtaskDetail buildWJDetail(SvyTaskTemplateScriptVO svyTaskTemplateScriptVO, ServiceSubtask serviceSubtask) {
+        if (svyTaskTemplateScriptVO == null) {
+            return null;
         }
-        return result;
-    }
-
-    private Integer setWJDetailInfo(SvyTaskTemplateScriptVO svyTaskTemplateScriptVO, ServiceSubtask serviceSubtask) {
-        log.info("-----setWJDetailInfo鐨勫叆鍙備负锛歿}", svyTaskTemplateScriptVO);
+        log.info("-----buildWJDetail鐨勫叆鍙備负锛歿}", svyTaskTemplateScriptVO);
 
         ServiceSubtaskDetailVO serviceSubtaskDetailVO = new ServiceSubtaskDetailVO();
-        if (svyTaskTemplateScriptVO.getScriptType().equals("1") || svyTaskTemplateScriptVO.getScriptType().equals("2")) {
+        if ("1".equals(svyTaskTemplateScriptVO.getScriptType()) || "2".equals(svyTaskTemplateScriptVO.getScriptType())) {
             //1銆�2涓哄崟閫夋垨澶氶��
             for (SvyTaskTemplateTargetoption svyTaskTemplateTargetoption : svyTaskTemplateScriptVO.getSvyTaskTemplateTargetoptions()) {
                 //灏嗛棶棰橀�夐」璁板綍涓嬫潵
@@ -3792,9 +4005,9 @@
                 }
 
             }
-            //濡傛灉asrtext鍜宮atchedtext閮戒负绌猴紝鍒欐病鏈夐粯璁ゅ�硷紝鍒欎笉杩涜澶勭悊
+            //濡傛灉asrtext鍜宮atchedtext閮戒负绌猴紝鍒欐病鏈夐粯璁ゅ�硷紝鍒欎笉杩涜澶勭悊锛堣繑鍥� null = 鏁翠唤闂嵎璺宠繃锛�
             if (StringUtils.isEmpty(serviceSubtaskDetailVO.getAsrtext()) && StringUtils.isEmpty(serviceSubtaskDetailVO.getMatchedtext())) {
-                return 0;
+                return null;
             }
         }
         ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
@@ -3817,21 +4030,16 @@
         }
         serviceSubtaskDetailVO.setSubId(serviceSubtask.getId());
         serviceSubtaskDetailVO.setTemplatequestionnum(svyTaskTemplateScriptVO.getId());
-        ServiceSubtaskDetail serviceSubtaskDetail = DtoConversionUtils.sourceToTarget(serviceSubtaskDetailVO, ServiceSubtaskDetail.class);
-
-        //鍏堢敤subid鍜宻criptid鏌ヨ涓�涓嬫槸鍚﹀瓨鍦紝濡傛灉瀛樺湪鍒欐洿鏂帮紝涓嶅瓨鍦ㄥ垯鎻掑叆
-        ServiceSubtaskDetailDTO existServiceSubtaskDetail = serviceSubtaskDetailMapper.isExistServiceSubtaskDetail(serviceSubtaskDetailVO.getSubId(), serviceSubtaskDetailVO.getScriptid());
-        if (ObjectUtils.isNotEmpty(existServiceSubtaskDetail)) {
-            serviceSubtaskDetail.setId(existServiceSubtaskDetail.getId());
-            serviceSubtaskDetail.setUpdateTime(new Date());
-            return serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail);
-        } else {
-            return serviceSubtaskDetailMapper.insertServiceSubtaskDetail(serviceSubtaskDetail);
-        }
+        return DtoConversionUtils.sourceToTarget(serviceSubtaskDetailVO, ServiceSubtaskDetail.class);
     }
 
-    private Integer setSFDetailInfo(IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO, ServiceSubtask serviceSubtask) {
-
+    /**
+     * 鎸夈�岀數璇濇ā鏉裤�嶆瀯閫犱竴鏉�"榛樿鍊兼槑缁�"锛�<b>鍙绠椼�佷笉钀藉簱</b>锛夛紝璇箟鍚� {@link #buildWJDetail}
+     */
+    private ServiceSubtaskDetail buildSFDetail(IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO, ServiceSubtask serviceSubtask) {
+        if (ivrTaskTemplateScriptVO == null) {
+            return null;
+        }
         ServiceSubtaskDetailVO serviceSubtaskDetailVO = new ServiceSubtaskDetailVO();
         if (ivrTaskTemplateScriptVO.getScriptType() != null && (ivrTaskTemplateScriptVO.getScriptType().equals("1") || ivrTaskTemplateScriptVO.getScriptType().equals("2"))) {
             //1銆�2涓哄崟閫夋垨澶氶��
@@ -3848,10 +4056,12 @@
                     serviceSubtaskDetailVO.setMatchedtext(StringUtils.isEmpty(serviceSubtaskDetailVO.getMatchedtext()) ? ivrTaskTemplateTargetoption.getTargetvalue() : serviceSubtaskDetailVO.getMatchedtext() + "&" + ivrTaskTemplateTargetoption.getTargetvalue());
                 }
             }
-            //濡傛灉asrtext鍜宮atchedtext閮戒负绌猴紝鍒欐病鏈夐粯璁ゅ�硷紝涓嶈繘琛屽鐞�
+            //濡傛灉asrtext鍜宮atchedtext閮戒负绌猴紝鍒欐病鏈夐粯璁ゅ�硷紝涓嶈繘琛屽鐞嗭紙杩斿洖 null = 鏁翠唤闂嵎璺宠繃锛�
             if (StringUtils.isEmpty(serviceSubtaskDetailVO.getAsrtext()) && StringUtils.isEmpty(serviceSubtaskDetailVO.getMatchedtext())) {
-                return 0;
+                return null;
             }
+        } else if (ivrTaskTemplateScriptVO.getScriptType() == null) {
+            return null;
         }
 
         serviceSubtaskDetailVO.setTargetid(ivrTaskTemplateScriptVO.getTargetid() != null ? ivrTaskTemplateScriptVO.getTargetid().intValue() : null);
@@ -3871,17 +4081,9 @@
         serviceSubtaskDetailVO.setTemplateType(1);
         serviceSubtaskDetailVO.setTemplateid(ivrTaskTemplateScriptVO.getTemplateID() == null ? null : ivrTaskTemplateScriptVO.getTemplateID().toString());
         serviceSubtaskDetailVO.setLibTemplateid(serviceSubtask.getLibtemplateid() != null ? serviceSubtask.getLibtemplateid().intValue() : null);
-        ServiceSubtaskDetail serviceSubtaskDetail = DtoConversionUtils.sourceToTarget(serviceSubtaskDetailVO, ServiceSubtaskDetail.class);
-        //鍏堢敤subid鍜宻criptid鏌ヨ涓�涓嬫槸鍚﹀瓨鍦紝濡傛灉瀛樺湪鍒欐洿鏂帮紝涓嶅瓨鍦ㄥ垯鎻掑叆
-        ServiceSubtaskDetailDTO existServiceSubtaskDetail = serviceSubtaskDetailMapper.isExistServiceSubtaskDetail(serviceSubtaskDetailVO.getSubId(), serviceSubtaskDetailVO.getScriptid());
-        if (ObjectUtils.isNotEmpty(existServiceSubtaskDetail)) {
-            serviceSubtaskDetail.setId(existServiceSubtaskDetail.getId());
-            serviceSubtaskDetail.setUpdateTime(new Date());
-            return serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail);
-        } else {
-            return serviceSubtaskDetailMapper.insertServiceSubtaskDetail(serviceSubtaskDetail);
-        }
+        return DtoConversionUtils.sourceToTarget(serviceSubtaskDetailVO, ServiceSubtaskDetail.class);
     }
+
 
     public String scanGenerateSubtask(ServiceTask serviceTaskVo) {
         String content = "";
@@ -3953,8 +4155,8 @@
 //        serviceSubtask.setDrcode(patMedInhosp1.getDrcode());
 //        serviceSubtask.setDrname(patMedInhosp1.getDrname());
         if (StringUtils.isNotEmpty(serviceTaskdept.getDeptType()) && serviceTaskdept.getDeptType().equals("1")) {
-            serviceSubtask.setDeptcode(serviceTaskdept.getDeptCode());
-            serviceSubtask.setDeptname(serviceTaskdept.getDeptName());
+            serviceSubtask.setLeaveldeptcode(serviceTaskdept.getDeptCode());
+            serviceSubtask.setLeaveldeptname(serviceTaskdept.getDeptName());
         } else {
             serviceSubtask.setLeavehospitaldistrictcode(serviceTaskdept.getDeptCode());
             serviceSubtask.setLeavehospitaldistrictname(serviceTaskdept.getDeptName());
@@ -3990,7 +4192,7 @@
         // 杩欓噷鐢ㄤ换鍔¢厤缃殑鐥呭尯锛堝叾娆$瀹わ級鍙嶆煡 sys_dept.campusid 钀藉簱锛屼繚璇侀棶鍗风粺璁¤兘鎸夐櫌鍖哄彇鍒般��
         String campusIdByDept = queryCampusIdByDeptCode(serviceSubtask.getLeavehospitaldistrictcode(), serviceTask.getOrgid());
         if (StringUtils.isEmpty(campusIdByDept)) {
-            campusIdByDept = queryCampusIdByDeptCode(serviceSubtask.getDeptcode(), serviceTask.getOrgid());
+            campusIdByDept = queryCampusIdByDeptCode(serviceSubtask.getLeaveldeptcode(), serviceTask.getOrgid());
         }
         if (StringUtils.isNotEmpty(campusIdByDept)) {
             serviceSubtask.setCampusid(campusIdByDept);
@@ -3999,7 +4201,7 @@
         if (StringUtils.isEmpty(serviceSubtask.getLeavehospitaldistrictcode())
                 && ("6".equals(serviceSubtask.getServiceType()) || "14".equals(serviceSubtask.getServiceType()))) {
             log.warn("銆愭壂鐮佺敓鎴愪换鍔°�戞弧鎰忓害瀛愪换鍔℃病鏈夌梾鍖猴紝鎸夌梾鍖虹瓫閫夌殑鎶ヨ〃灏嗙粺璁′笉鍒拌绛斿嵎锛歵askid={}, deptcode={}, campusid={}",
-                    serviceSubtask.getTaskid(), serviceSubtask.getDeptcode(), serviceSubtask.getCampusid());
+                    serviceSubtask.getTaskid(), serviceSubtask.getLeaveldeptcode(), serviceSubtask.getCampusid());
         }
         return serviceSubtask;
     }
diff --git a/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskDetailMapper.xml b/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskDetailMapper.xml
index 3b8bb91..89fa87a 100644
--- a/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskDetailMapper.xml
+++ b/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskDetailMapper.xml
@@ -219,8 +219,8 @@
             ssd.targetid,
             ssd.template_type,
             ssd.lib_templateid,
-            sd.deptcode,
-            sd.deptname,
+            sd.leaveldeptcode AS deptcode,
+            sd.leaveldeptname AS deptname,
             sd.leavehospitaldistrictcode,
             sd.leavehospitaldistrictname
         from service_subtask_detail ssd
@@ -247,7 +247,7 @@
             </foreach>
         </if>
         <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
-            and sd.deptcode in
+            and sd.leaveldeptcode in
             <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," close=")">
                 #{leaveldeptcode}
             </foreach>
@@ -283,12 +283,22 @@
         <if test="questiontext != null">and questiontext = #{questiontext}</if>
     </select>
 
-                <select id="isExistServiceSubtaskDetail" resultType="com.ruoyi.task.domain.DTO.ServiceSubtaskDetailDTO">
+    <!--
+        鈿狅笍 鍙e緞鍙樻洿锛�2026-10-21锛夛細杩欓噷**涓嶅啀杩囨护 del_flag**锛屾敼涓哄彇璇� (sub_id, scriptid) 鏈�鏂扮殑涓�琛屻��
+
+        鍘熷洜锛氬師鏉ュ彧璁� del_flag=0锛屾槑缁嗕竴鏃﹁閫昏緫鍒犻櫎灏辨煡涓嶅埌锛屼笅涓�娆′繚瀛樺繀鐒� INSERT 涓�鏉℃柊鍓湰锛�
+        瀵艰嚧鍚屼竴浣嶆偅鑰呭悓涓�閬撻鍫嗗嚭 2~6 鏉¢噸澶嶆槑缁嗭紙瑙� nhfy 2026-09-08 鐨勪簨鏁咃級銆�
+        鏀逛负銆屽拷鐣ュ垹闄ゆ爣璁般�佸彇鏈�鏂颁竴琛屻�嶅悗锛屼繚瀛樿蛋 UPDATE锛堢敱璋冪敤鏂瑰啀璋� reviveServiceSubtaskDetail 澶嶆椿锛夛紝
+        鍓湰涓嶄細鍐嶇疮绉��
+    -->
+    <select id="isExistServiceSubtaskDetail" resultType="com.ruoyi.task.domain.DTO.ServiceSubtaskDetailDTO">
         select id, questiontext, matchedtext, score
         from service_subtask_detail
-        where del_flag = 0
+        where 1 = 1
         <if test="subid != null ">and sub_id = #{subid}</if>
         <if test="scriptid != null">and scriptid = #{scriptid}</if>
+        order by id desc
+        limit 1
     </select>
 
     <insert id="insertServiceSubtaskDetail" parameterType="com.ruoyi.task.domain.ServiceSubtaskDetail"
@@ -453,7 +463,6 @@
             <if test="uploadTime != null">upload_time = #{uploadTime},</if>
             <if test="orgid != null">orgid = #{orgid},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
-            <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
@@ -512,7 +521,6 @@
             <if test="uploadTime != null">upload_time = #{uploadTime},</if>
             <if test="orgid != null">orgid = #{orgid},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
-            <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
@@ -533,6 +541,39 @@
         where patid = #{patid} and scriptid = #{scriptid} and sub_id = #{subId}
     </update>
 
+    <!-- ======================================================================
+         閫昏緫鍒犻櫎 / 澶嶆椿锛�2026-10-21 鏀跺彛锛�
+         ======================================================================
+         鑳屾櫙锛氫笂闈袱鏉¢�氱敤 UPDATE锛坲pdateServiceSubtaskDetail銆乽pdateSSDByCondition锛夊師鏈兘甯�
+               if test="delFlag != null" 灏卞幓 SET del_flag = 瀹㈡埛绔紶鐨勫�硷紝
+               绛変簬鎶� del_flag 鐨勫啓鏉冮檺浜ょ粰浜嗗鎴风锛氬墠绔竴涓� {"subId":x,"delFlag":"1"}
+               灏辫兘鎶婃暣鍗风瓟鍗锋倓鎮�"鍒犻櫎"锛坣hfy 2026-09-08 灏辫繖鏍蜂涪浜� 10 浣嶆偅鑰呯殑婊℃剰搴︿綔绛旓紝
+               鑰� patItemExport 鐨勩�岄棶棰樿鎯呭崰姣斻�嶅張鍙 del_flag=0锛屼簬鏄� 380 琛屽彧鍓� 370 浜猴級銆�
+         鐜板湪杩欎袱鏉¢�氱敤 UPDATE 宸茬Щ闄� del_flag 瀛楁锛岄�昏緫鍒犻櫎鍙兘璧颁笅闈袱鏉′笓鐢ㄨ鍙ワ紝
+         澶嶆椿鍙厑璁哥疆鍥� '0'锛坮eviveServiceSubtaskDetail锛夈��
+         ====================================================================== -->
+    <update id="softDeleteServiceSubtaskDetailBySubId">
+        update service_subtask_detail
+        set del_flag = '1', update_time = now()
+        where sub_id = #{subId}
+          and del_flag = '0'
+    </update>
+
+    <update id="softDeleteServiceSubtaskDetailById">
+        update service_subtask_detail
+        set del_flag = '1', update_time = now()
+        where id = #{id}
+          and del_flag = '0'
+    </update>
+
+    <!-- 澶嶆椿涓�琛屾槑缁嗭細淇濆瓨绛旀鏃跺懡涓巻鍙茶鍒犲壇鏈� -> 鏇存柊鍐呭鍚庡啀缃洖 del_flag='0'锛岄伩鍏嶆柊澧炲壇鏈� -->
+    <update id="reviveServiceSubtaskDetail">
+        update service_subtask_detail
+        set del_flag = '0'
+        where id = #{id}
+          and del_flag &lt;&gt; '0'
+    </update>
+
     <delete id="deleteServiceSubtaskDetailByCalldetailid" parameterType="String">
         delete
         from service_subtask_detail
diff --git a/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml b/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml
index c478704..da3b3a7 100644
--- a/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml
+++ b/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml
@@ -26,7 +26,7 @@
         <result property="recordid" column="recordid"/>
         <result property="exrecallcount" column="exrecallcount"/>
         <result property="pulltime" column="pulltime"/>
-        <result property="deptcode" column="deptcode"/>
+        <result property="leaveldeptcode" column="leaveldeptcode"/>
         <result property="labelstatus" column="labelstatus"/>
         <result property="delFlag" column="del_flag"/>
         <result property="updateBy" column="update_by"/>
@@ -53,6 +53,11 @@
         <result property="leaveicd10code" column="leaveicd10code"/>
         <result property="leavediagname" column="leavediagname"/>
         <result property="diagname" column="diagname"/>
+        <result property="leaveldeptname" column="leaveldeptname"/>
+        <!-- 2026-11锛氬師 sendlimit* 鍥涗釜绌洪棽鍒楀鐢ㄤ负銆屽湪闄㈢淮搴︺�嶏紙hospitaldistrict* = 鍦ㄩ櫌鐥呭尯锛宒eptcode/name = 鍦ㄩ櫌绉戝锛� -->
+        <result property="hospitaldistrictcode" column="hospitaldistrictcode"/>
+        <result property="hospitaldistrictname" column="hospitaldistrictname"/>
+        <result property="deptcode" column="deptcode"/>
         <result property="deptname" column="deptname"/>
         <result property="admindate" column="admindate"/>
         <result property="roomno" column="roomno"/>
@@ -205,7 +210,7 @@
                recordid,
                exrecallcount,
                pulltime,
-               deptcode,
+               leaveldeptcode,
                labelstatus,
                del_flag,
                update_by,
@@ -228,6 +233,10 @@
                sendname,
                roomno,
                admindate,
+               leaveldeptname,
+               hospitaldistrictcode,
+               hospitaldistrictname,
+               deptcode,
                deptname,
                stop_state,
                leavehospitaldistrictcode,
@@ -291,9 +300,111 @@
         <if test="continueTimeNext != null ">and continue_time_next = #{continueTimeNext}</if>
     </select>
 
-    <select id="selectServiceSubtaskList" parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity"
-            resultMap="ServiceSubtaskResult">
-        <include refid="selectServiceSubtaskVo"/>
+    <!-- ======================================================================
+         绉戝 / 鐥呭尯绛涢�夛紙2026-11 淇鐗堬級
+         涓ょ粍鏉′欢銆愬悇鑷嫭绔嬨�戯紝浜掍笉鐗佃繛锛堝湪闄㈢梾鍖轰笌绂婚櫌鐥呭尯涓嶄細鍚屾椂瀛樺湪锛夛細
+           绂婚櫌缁勶細leavehospitaldistrictcodes 鈫� leavehospitaldistrictcode
+                   leaveldeptcodes            鈫� leaveldeptcode
+           鍦ㄩ櫌缁勶細hospitaldistrictcodes      鈫� hospitaldistrictcode锛堝湪闄㈢梾鍖猴級
+                   deptcodes                  鈫� deptcode锛堝湪闄㈢瀹わ級
+         缁勫唴缁勫悎鏂瑰紡鐢� deptOrDistrict 鍐冲畾锛�'1' = AND锛�'2' = OR銆�
+         锛�'3'/'4' 鏄�岀闄㈢梾鍖� + 闅忚绉戝 visit_dept_code銆嶉偅濂楋紝鍗曠嫭鍒嗘敮锛屼笉璧拌繖閲岋級
+         涓ょ粍涔嬮棿鏄� AND锛氬彧浼犱竴缁勬椂鍙︿竴缁勮嚜鍔ㄤ笉鎷笺��
+         绌烘暟缁� [] 涓�寰嬭涓�"娌′紶"锛屼笉浼氭嫾鍑� IN ()銆�
+         ====================================================================== -->
+    <sql id="filterLeaveDimAnd">
+        /* f-v3 */
+        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
+            AND leavehospitaldistrictcode IN
+            <foreach collection="leavehospitaldistrictcodes" item="lvWardCodeItem" open="(" separator="," close=")">
+                #{lvWardCodeItem}
+            </foreach>
+        </if>
+        <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+            AND leaveldeptcode IN
+            <foreach collection="leaveldeptcodes" item="lvDeptCodeItem" open="(" separator="," close=")">
+                #{lvDeptCodeItem}
+            </foreach>
+        </if>
+    </sql>
+
+    <sql id="filterLeaveDimOr">
+        /* f-v3 */
+        <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0)
+                  or (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+            AND (
+            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
+                leavehospitaldistrictcode IN
+                <foreach collection="leavehospitaldistrictcodes" item="lvWardCodeItem" open="(" separator="," close=")">
+                    #{lvWardCodeItem}
+                </foreach>
+            </if>
+            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0)
+                      and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
+                OR
+            </if>
+            <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+                leaveldeptcode IN
+                <foreach collection="leaveldeptcodes" item="lvDeptCodeItem" open="(" separator="," close=")">
+                    #{lvDeptCodeItem}
+                </foreach>
+            </if>
+            )
+        </if>
+    </sql>
+
+    <sql id="filterInhospDimAnd">
+        /* f-v3 */
+        <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
+            AND hospitaldistrictcode IN
+            <foreach collection="hospitaldistrictcodes" item="inWardCodeItem" open="(" separator="," close=")">
+                #{inWardCodeItem}
+            </foreach>
+        </if>
+        <if test="deptcodes != null and deptcodes.size() > 0">
+            AND deptcode IN
+            <foreach collection="deptcodes" item="inDeptCodeItem" open="(" separator="," close=")">
+                #{inDeptCodeItem}
+            </foreach>
+        </if>
+    </sql>
+
+    <sql id="filterInhospDimOr">
+        /* f-v3 */
+        <if test="(hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0)
+                  or (deptcodes != null and deptcodes.size() > 0)">
+            AND (
+            <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
+                hospitaldistrictcode IN
+                <foreach collection="hospitaldistrictcodes" item="inWardCodeItem" open="(" separator="," close=")">
+                    #{inWardCodeItem}
+                </foreach>
+            </if>
+            <if test="(hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0)
+                      and (deptcodes != null and deptcodes.size() > 0)">
+                OR
+            </if>
+            <if test="deptcodes != null and deptcodes.size() > 0">
+                deptcode IN
+                <foreach collection="deptcodes" item="inDeptCodeItem" open="(" separator="," close=")">
+                    #{inDeptCodeItem}
+                </foreach>
+            </if>
+            )
+        </if>
+    </sql>
+
+    <!-- ==================================================================
+         service_subtask 鍒楄〃鏌ヨ鐨勫叕鍏� where 鐗囨
+         ==================================================================
+         patItem 璧般�屼袱闃舵鍒嗛〉銆嶏細
+           鈶� selectServiceSubtaskIdsPage 鈥斺�� 鍙煡 id锛岃蛋瑕嗙洊绱㈠紩锛屼笉涓鸿 offset
+              璺宠繃鐨勬瘡涓�琛屽洖琛ㄨ 100 鍒楋紱
+           鈶� selectServiceSubtaskList + subIdList 鈥斺�� 鎸� id 鍥炶〃锛屽彧璇讳竴椤电殑閲忋��
+         涓ゆ潯璇彞鐨� where 蹇呴』銆愰�愬瓧涓�鑷淬�戯紝鍚﹀垯绗憽姝ヤ細鎶婄鈶犳閫夊嚭鐨勮杩囨护鎺夛紝
+         瀵艰嚧涓�椤佃繑鍥炰笉瓒� pageSize 鏉°�傛墍浠ユ敹鎴愬叕鍏辩墖娈碉紝鏉滅粷涓や唤鍙e緞婕傜Щ銆�
+         ================================================================== -->
+    <sql id="serviceSubtaskWhere">
         where del_flag = 0
         <if test="subId != null ">and id = #{subId}</if>
         <if test="continueFlag != null ">and continue_flag = #{continueFlag}</if>
@@ -367,63 +478,43 @@
             '%')
         </if>
         <if test="startOutHospTime != null">
-            AND date_format(endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
+            AND endtime &gt;= DATE(#{startOutHospTime})
         </if>
         <if test="endOutHospTime != null">
-            AND date_format(endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
+            AND endtime &lt; DATE_ADD(DATE(#{endOutHospTime}), INTERVAL 1 DAY)
         </if>
         <if test="startSendDateTime != null">
-            AND date_format(visit_time,'%y%m%d') &gt;= date_format(#{startSendDateTime},'%y%m%d')
+            AND visit_time &gt;= DATE(#{startSendDateTime})
         </if>
         <if test="endSendDateTime != null">
-            AND date_format(visit_time,'%y%m%d') &lt;= date_format(#{endSendDateTime},'%y%m%d')
+            AND visit_time &lt; DATE_ADD(DATE(#{endSendDateTime}), INTERVAL 1 DAY)
         </if>
         <if test="finishtimeStart != null">
-            AND date_format(finishtime,'%y%m%d') &gt;= date_format(#{finishtimeStart},'%y%m%d')
+            AND finishtime &gt;= DATE(#{finishtimeStart})
         </if>
         <if test="finishtimeEnd != null">
-            AND date_format(finishtime,'%y%m%d') &lt;= date_format(#{finishtimeEnd},'%y%m%d')
+            AND finishtime &lt; DATE_ADD(DATE(#{finishtimeEnd}), INTERVAL 1 DAY)
         </if>
         <if test="longSendTime != null">
-            AND date_format(long_send_time,'%y%m%d') &lt;= date_format(#{longSendTime},'%y%m%d')
+            AND long_send_time &lt; DATE_ADD(DATE(#{longSendTime}), INTERVAL 1 DAY)
         </if>
-        <if test="deptOrDistrict==1">
-            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-                AND leavehospitaldistrictcode IN
-                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
-                         separator=","
-                         close=")">
-                    #{leavehospitaldistrictcode}
-                </foreach>
-            </if>
-            <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
-                AND deptcode IN
-                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
-                         close=")">
-                    #{leaveldeptcode}
-                </foreach>
-            </if>
+        <!--
+            绉戝/鐥呭尯绛涢�夛紙2026-11 淇锛夛細
+              绂婚櫌缁勶紙leaveldeptcodes / leavehospitaldistrictcodes锛変繚鎸佸師閫昏緫锛�
+              鍦ㄩ櫌缁勶紙deptcodes / hospitaldistrictcodes 鈫� deptcode / hospitaldistrictcode锛夋槸鏂板鐨勪竴缁勶紱
+              缁勫唴鎸� deptOrDistrict 鍙� AND('1') / OR('2')锛屼袱缁勪箣闂� AND锛堝彧浼犱竴缁勬椂鍙︿竴缁勪笉鎷硷級銆�
+        -->
+        <if test='deptOrDistrict == "1"'>
+            <include refid="filterLeaveDimAnd"/>
+            <include refid="filterInhospDimAnd"/>
         </if>
-        <if test="deptOrDistrict==2">
-            AND (1=1
-            <if test="leavehospitaldistrictcodes != null">
-                AND leavehospitaldistrictcode IN
-                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
-                         separator=","
-                         close=")">
-                    #{leavehospitaldistrictcode}
-                </foreach>
-            </if>
-            <if test=" leaveldeptcodes != null">
-                OR deptcode IN
-                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
-                         close=")">
-                    #{leaveldeptcode}
-                </foreach>
-            </if>
-            )
+        <if test='deptOrDistrict == "2"'>
+            <include refid="filterLeaveDimOr"/>
+            <include refid="filterInhospDimOr"/>
         </if>
-        <if test="deptOrDistrict==3">
+        <!-- 鈿狅笍 deptOrDistrict 鏄� String锛歄GNL 閲� '1'锛堝崟寮曞彿鍗曞瓧绗︼級鏄� char锛孲tring != char 鎭� false锛�
+             蹇呴』鍐欐垚鍙屽紩鍙峰瓧绗︿覆锛圶ML 灞炴�х敤鍗曞紩鍙峰寘浣忥級锛屾垨鐩存帴鍜屾暟瀛楁瘮锛圤GNL 浼氬仛 String鈫扤umber 杞崲锛夈�� -->
+        <if test='deptOrDistrict == "3"'>
             AND (1=1
             <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
                 AND leavehospitaldistrictcode IN
@@ -442,7 +533,7 @@
             </if>
             )
         </if>
-        <if test="deptOrDistrict==4">
+        <if test='deptOrDistrict == "4"'>
             AND (1=1
             <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
                 AND leavehospitaldistrictcode IN
@@ -462,7 +553,8 @@
             )
         </if>
         <if test="visitTime != null">
-            AND date_format(visit_time,'%y%m%d') = date_format(#{visitTime},'%y%m%d')
+            AND visit_time &gt;= DATE(#{visitTime})
+            AND visit_time &lt; DATE_ADD(DATE(#{visitTime}), INTERVAL 1 DAY)
         </if>
         <if test="senddate != null ">and senddate = #{senddate}</if>
         <if test="senduuid != null  and senduuid != ''">and senduuid = #{senduuid}</if>
@@ -471,8 +563,8 @@
         <if test="recordid != null ">and recordid = #{recordid}</if>
         <if test="exrecallcount != null ">and exrecallcount = #{exrecallcount}</if>
         <if test="pulltime != null ">and pulltime = #{pulltime}</if>
-        <if test="deptcode != null  and deptcode != ''">and deptcode = #{deptcode}</if>
-        <if test="deptname != null  and deptname != ''">and deptname = #{deptname}</if>
+        <if test="leaveldeptcode != null  and leaveldeptcode != ''">and leaveldeptcode = #{leaveldeptcode}</if>
+        <if test="leaveldeptname != null  and leaveldeptname != ''">and leaveldeptname = #{leaveldeptname}</if>
         <if test="labelstatus != null ">and labelstatus = #{labelstatus}</if>
         <if test="isupload != null ">and isupload = #{isupload}</if>
         <if test="uploadTime != null ">and upload_time = #{uploadTime}</if>
@@ -524,6 +616,11 @@
                 #{visitDeptCode}
             </foreach>
         </if>
+    </sql>
+
+    <!-- 鎺掑簭鐗囨锛氫繚鎸佸師璇箟锛屽彧鍦ㄨ皟鐢ㄦ柟鏄惧紡浼� sort 鏃舵墠鎷� order by
+         锛堝鍑虹瓑涓嶅垎椤电殑璋冪敤鏂硅涓哄畬鍏ㄤ笉鍙橈級 -->
+    <sql id="serviceSubtaskOrderBy">
         <if test="sort != null  and sort==0">order by endtime asc</if>
         <if test="sort != null  and sort==1">order by endtime desc</if>
         <if test="sort != null  and sort==2">order by visit_time asc</if>
@@ -533,7 +630,37 @@
         <if test="sort != null  and sort==7">order by visit_time asc</if>
         <if test="sort != null  and sort==8">order by visit_time desc</if>
         <if test="sort != null  and sort==9">order by sendname asc</if>
+    </sql>
+
+    <!-- 鍒嗛〉鍦烘櫙涓撶敤鎺掑簭锛歴ort 涓虹┖鏃跺厹搴� order by id desc銆�
+         鍘熸潵 sort 涓虹┖鏃舵暣鏉� SQL 娌℃湁 order by锛宭imit/offset 鍙栧埌鐨勬槸銆屼笉纭畾椤哄簭銆嶏紝
+         缈婚〉浼氶噸澶嶆垨婕忚锛涜繖閲岀粰涓�涓ǔ瀹氶『搴忥紙鎯虫敼鎴� id asc 鍙敼杩欎竴琛岋級銆� -->
+    <sql id="serviceSubtaskOrderByPaged">
+        <include refid="serviceSubtaskOrderBy"/>
+        <if test="sort == null">order by id desc</if>
+    </sql>
+
+    <select id="selectServiceSubtaskList" parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity"
+            resultMap="ServiceSubtaskResult">
+        <include refid="selectServiceSubtaskVo"/>
+        <include refid="serviceSubtaskWhere"/>
+        <include refid="serviceSubtaskOrderBy"/>
         <if test="pageSize != null  and pageNum != null">limit ${pageSize} OFFSET ${pageNum}</if>
+    </select>
+
+    <!--
+        涓ら樁娈靛垎椤电 1 姝ワ細鍙彇 id銆�
+        select 鍒楄〃鍙湁 id锛寃here/order 娑夊強鐨勫垪閮藉湪 idx_ss_org_cam_del_* 涓婏紝
+        鍥犳鑳借蛋銆岃鐩栫储寮� + 鎻愬墠鎴柇銆嶏紱琚� offset 璺宠繃鐨勯偅鍑犲崈琛屼笉鍐嶅洖琛ㄨ 100 鍒椼��
+        绗� 2 姝ョ敱璋冪敤鏂圭敤 subIdList 鍥炶〃鍙栨暣琛岋紙瑙� ServiceSubtaskServiceImpl#selectServiceSubtaskPage锛夈��
+    -->
+    <select id="selectServiceSubtaskIdsPage" parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity"
+            resultType="java.lang.Long">
+        select id
+        from service_subtask
+        <include refid="serviceSubtaskWhere"/>
+        <include refid="serviceSubtaskOrderByPaged"/>
+        limit ${pageSize} OFFSET ${pageNum}
     </select>
 
             <select id="getCompensateServiceSubtaskList" parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity"
@@ -615,8 +742,8 @@
         <if test="recordid != null ">and recordid = #{recordid}</if>
         <if test="exrecallcount != null ">and exrecallcount = #{exrecallcount}</if>
         <if test="pulltime != null ">and pulltime = #{pulltime}</if>
-        <if test="deptcode != null  and deptcode != ''">and deptcode = #{deptcode}</if>
-        <if test="deptname != null  and deptname != ''">and deptname = #{deptname}</if>
+        <if test="leaveldeptcode != null  and leaveldeptcode != ''">and leaveldeptcode = #{leaveldeptcode}</if>
+        <if test="leaveldeptname != null  and leaveldeptname != ''">and leaveldeptname = #{leaveldeptname}</if>
         <if test="labelstatus != null ">and labelstatus = #{labelstatus}</if>
         <if test="isupload != null ">and isupload = #{isupload}</if>
         <if test="uploadTime != null ">and upload_time = #{uploadTime}</if>
@@ -691,8 +818,8 @@
         <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
         <if test="serviceType != null and serviceType != ''">and service_type = #{serviceType}</if>
         <if test="serviceTypes != null and serviceTypes != ''">and service_type IN (#{serviceTypes})</if>
-        <if test="deptcode != null  and deptcode != ''">and deptcode = #{deptcode}</if>
-        <if test="deptname != null  and deptname != ''">and deptname = #{deptname}</if>
+        <if test="leaveldeptcode != null  and leaveldeptcode != ''">and leaveldeptcode = #{leaveldeptcode}</if>
+        <if test="leaveldeptname != null  and leaveldeptname != ''">and leaveldeptname = #{leaveldeptname}</if>
         <if test="isabnormal != null">and isabnormal = #{isabnormal}</if>
         <if test="leavehospitaldistrictcode != null  and leavehospitaldistrictcode != ''">and
             leavehospitaldistrictcode = #{leavehospitaldistrictcode}
@@ -703,10 +830,10 @@
         <if test="managementDoctorCode != null">and management_doctor_code = #{managementDoctorCode}</if>
         <if test="managementDoctor != null">and management_doctor like concat('%',#{managementDoctor}, '%')</if>
         <if test="startOutHospTime != null">
-            AND date_format(endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
+            AND endtime &gt;= DATE(#{startOutHospTime})
         </if>
         <if test="endOutHospTime != null">
-            AND date_format(endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
+            AND endtime &lt; DATE_ADD(DATE(#{endOutHospTime}), INTERVAL 1 DAY)
         </if>
         ) a
     </select>
@@ -750,8 +877,8 @@
         </if>
         <if test="orgid != null and orgid != ''">AND ss.orgid = #{orgid}</if>
         <if test="campusid != null and campusid != ''">and ss.campusid = #{campusid}</if>
-        <if test="deptcode != null  and deptcode != ''">and ss.deptcode = #{deptcode}</if>
-        <if test="deptname != null  and deptname != ''">and ss.deptname = #{deptname}</if>
+        <if test="leaveldeptcode != null  and leaveldeptcode != ''">and ss.leaveldeptcode = #{leaveldeptcode}</if>
+        <if test="leaveldeptname != null  and leaveldeptname != ''">and ss.leaveldeptname = #{leaveldeptname}</if>
         <if test="isabnormal != null">and ss.isabnormal = #{isabnormal}</if>
         <if test="leavehospitaldistrictcode != null  and leavehospitaldistrictcode != ''">and
             ss.leavehospitaldistrictcode = #{leavehospitaldistrictcode}
@@ -781,7 +908,7 @@
             AND date_format(ss.endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
         </if>
         <if test="groupKey != null and groupKey != ''">
-            AND ss.${groupKey} IN
+            AND IFNULL(ss.${groupKey}, 'Unknown') IN
             <foreach collection="groupKeyList" item="key" open="(" separator=","
                      close=")">
                 #{key}
@@ -812,8 +939,8 @@
         <if test="serviceType != null and serviceType != ''">and service_type = #{serviceType}</if>
         <if test="serviceTypes != null and serviceTypes != ''">and service_type IN (#{serviceTypes})</if>
         <if test="isabnormal != null ">and isabnormal = #{isabnormal}</if>
-        <if test="deptcode != null  and deptcode != ''">and deptcode = #{deptcode}</if>
-        <if test="deptname != null  and deptname != ''">and deptname = #{deptname}</if>
+        <if test="leaveldeptcode != null  and leaveldeptcode != ''">and leaveldeptcode = #{leaveldeptcode}</if>
+        <if test="leaveldeptname != null  and leaveldeptname != ''">and leaveldeptname = #{leaveldeptname}</if>
         <if test="leavehospitaldistrictcode != null  and leavehospitaldistrictcode != ''">and
             leavehospitaldistrictcode = #{leavehospitaldistrictcode}
         </if>
@@ -846,10 +973,10 @@
         <if test="continueCount != null ">and continue_count = #{continueCount}</if>
         <if test="continueTimeNext != null ">and continue_time_next = #{continueTimeNext}</if>
         <if test="startOutHospTime != null">
-            AND date_format(endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
+            AND endtime &gt;= DATE(#{startOutHospTime})
         </if>
         <if test="endOutHospTime != null">
-            AND date_format(endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
+            AND endtime &lt; DATE_ADD(DATE(#{endOutHospTime}), INTERVAL 1 DAY)
         </if>
         GROUP BY sendname,sendstate,starttime,endtime,nurse_name,phone,sex,task_name,leavediagname,visit_time
         ORDER BY sendname,visit_time
@@ -878,7 +1005,12 @@
             <if test="recordid != null">recordid,</if>
             <if test="exrecallcount != null">exrecallcount,</if>
             <if test="pulltime != null">pulltime,</if>
-            <if test="deptcode != null">deptcode,</if>
+            <if test="leaveldeptcode != null">leaveldeptcode,</if>
+            <!-- 2026-11锛氬師 sendlimit* 澶嶇敤鍒楋紙鍦ㄩ櫌缁村害锛氬湪闄㈢梾鍖�/鍦ㄩ櫌绉戝锛夛紝浠呭嚭闄㈤殢璁夸細濉�� -->
+            <if test="hospitaldistrictcode != null  and hospitaldistrictcode != ''">hospitaldistrictcode,</if>
+            <if test="hospitaldistrictname != null  and hospitaldistrictname != ''">hospitaldistrictname,</if>
+            <if test="deptcode != null  and deptcode != ''">deptcode,</if>
+            <if test="deptname != null  and deptname != ''">deptname,</if>
             <if test="labelstatus != null">labelstatus,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateTime != null">update_time,</if>
@@ -903,7 +1035,7 @@
             <if test="wechat != null  and wechat != ''">wechat,</if>
             <if test="roomno != null  and roomno != ''">roomno,</if>
             <if test="admindate != null">admindate,</if>
-            <if test="deptname != null  and deptname != ''">deptname,</if>
+            <if test="leaveldeptname != null  and leaveldeptname != ''">leaveldeptname,</if>
             <if test="leaveicd10code != null  and leaveicd10code != ''">leaveicd10code,</if>
             <if test="leavediagname != null  and leavediagname != ''">leavediagname,</if>
             <!-- diagname锛氬叆闄㈣瘖鏂悕绉般�傚師 insert 婕忎簡杩欎竴鍒楋紝鑰屽嚭闄㈤摼璺殑
@@ -980,7 +1112,12 @@
             <if test="recordid != null">#{recordid},</if>
             <if test="exrecallcount != null">#{exrecallcount},</if>
             <if test="pulltime != null">#{pulltime},</if>
-            <if test="deptcode != null">#{deptcode},</if>
+            <if test="leaveldeptcode != null">#{leaveldeptcode},</if>
+            <!-- 2026-11锛氬師 sendlimit* 澶嶇敤鍒楋紙鍏ラ櫌/鍦ㄩ櫌缁村害锛夛紝浠呭嚭闄㈤殢璁夸細濉�� -->
+            <if test="hospitaldistrictcode != null  and hospitaldistrictcode != ''">#{hospitaldistrictcode},</if>
+            <if test="hospitaldistrictname != null  and hospitaldistrictname != ''">#{hospitaldistrictname},</if>
+            <if test="deptcode != null  and deptcode != ''">#{deptcode},</if>
+            <if test="deptname != null  and deptname != ''">#{deptname},</if>
             <if test="labelstatus != null">#{labelstatus},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateTime != null">#{updateTime},</if>
@@ -1005,7 +1142,7 @@
             <if test="wechat != null  and wechat != ''">#{wechat},</if>
             <if test="roomno != null  and roomno != ''">#{roomno},</if>
             <if test="admindate != null ">#{admindate},</if>
-            <if test="deptname != null  and deptname != ''">#{deptname},</if>
+            <if test="leaveldeptname != null  and leaveldeptname != ''">#{leaveldeptname},</if>
             <if test="leaveicd10code != null  and leaveicd10code != ''">#{leaveicd10code},</if>
             <if test="leavediagname != null  and leavediagname != ''">#{leavediagname},</if>
             <if test="diagname != null  and diagname != ''">#{diagname},</if>
@@ -1084,7 +1221,7 @@
             <if test="recordid != null">recordid = #{recordid},</if>
             <if test="exrecallcount != null">exrecallcount = #{exrecallcount},</if>
             <if test="pulltime != null">pulltime = #{pulltime},</if>
-            <if test="deptcode != null">deptcode = #{deptcode},</if>
+            <if test="leaveldeptcode != null">leaveldeptcode = #{leaveldeptcode},</if>
             <if test="labelstatus != null">labelstatus = #{labelstatus},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
@@ -1109,7 +1246,7 @@
             <if test="wechat != null  and wechat != ''">wechat = #{wechat},</if>
             <if test="roomno != null  and roomno != ''">roomno = #{roomno},</if>
             <if test="admindate != null ">admindate = #{admindate},</if>
-            <if test="deptname != null  and deptname != ''">deptname = #{deptname},</if>
+            <if test="leaveldeptname != null  and leaveldeptname != ''">leaveldeptname = #{leaveldeptname},</if>
             <if test="leaveicd10code != null  and leaveicd10code != ''">leaveicd10code = #{leaveicd10code},</if>
             <if test="leavediagname != null  and leavediagname != ''">leavediagname = #{leavediagname},</if>
             <if test="libtemplateid != null ">libtemplateid = #{libtemplateid},</if>
@@ -1188,7 +1325,7 @@
             <if test="recordid != null">recordid = #{recordid},</if>
             <if test="exrecallcount != null">exrecallcount = #{exrecallcount},</if>
             <if test="pulltime != null">pulltime = #{pulltime},</if>
-            <if test="deptcode != null">deptcode = #{deptcode},</if>
+            <if test="leaveldeptcode != null">leaveldeptcode = #{leaveldeptcode},</if>
             <if test="labelstatus != null">labelstatus = #{labelstatus},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
@@ -1213,7 +1350,7 @@
             <if test="wechat != null  and wechat != ''">wechat = #{wechat},</if>
             <if test="roomno != null  and roomno != ''">roomno = #{roomno},</if>
             <if test="admindate != null">admindate = #{admindate},</if>
-            <if test="deptname != null  and deptname != ''">deptname = #{deptname},</if>
+            <if test="leaveldeptname != null  and leaveldeptname != ''">leaveldeptname = #{leaveldeptname},</if>
             <if test="leaveicd10code != null  and leaveicd10code != ''">leaveicd10code = #{leaveicd10code},</if>
             <if test="leavediagname != null  and leavediagname != ''">leavediagname = #{leavediagname},</if>
             <if test="libtemplateid != null ">libtemplateid = #{libtemplateid},</if>
@@ -1293,7 +1430,7 @@
             <if test="recordid != null">recordid = #{recordid},</if>
             <if test="exrecallcount != null">exrecallcount = #{exrecallcount},</if>
             <if test="pulltime != null">pulltime = #{pulltime},</if>
-            <if test="deptcode != null">deptcode = #{deptcode},</if>
+            <if test="leaveldeptcode != null">leaveldeptcode = #{leaveldeptcode},</if>
             <if test="labelstatus != null">labelstatus = #{labelstatus},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
@@ -1320,7 +1457,7 @@
             <if test="wechat != null  and wechat != ''">wechat = #{wechat},</if>
             <if test="roomno != null  and roomno != ''">roomno = #{roomno},</if>
             <if test="admindate != null">admindate = #{admindate},</if>
-            <if test="deptname != null  and deptname != ''">deptname = #{deptname},</if>
+            <if test="leaveldeptname != null  and leaveldeptname != ''">leaveldeptname = #{leaveldeptname},</if>
             <if test="leaveicd10code != null  and leaveicd10code != ''">leaveicd10code = #{leaveicd10code},</if>
             <if test="leavediagname != null  and leavediagname != ''">leavediagname = #{leavediagname},</if>
             <if test="libtemplateid != null ">libtemplateid = #{libtemplateid},</if>
@@ -1404,7 +1541,7 @@
             <if test="recordid != null">recordid = #{recordid},</if>
             <if test="exrecallcount != null">exrecallcount = #{exrecallcount},</if>
             <if test="pulltime != null">pulltime = #{pulltime},</if>
-            <if test="deptcode != null">deptcode = #{deptcode},</if>
+            <if test="leaveldeptcode != null">leaveldeptcode = #{leaveldeptcode},</if>
             <if test="labelstatus != null">labelstatus = #{labelstatus},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
@@ -1431,7 +1568,7 @@
             <if test="admindate != null ">admindate = #{admindate},</if>
             <if test="visitCount != null ">visit_count = #{visitCount},</if>
             <if test="isVisitAgain != null ">is_visit_again = #{isVisitAgain},</if>
-            <if test="deptname != null  and deptname != ''">deptname = #{deptname},</if>
+            <if test="leaveldeptname != null  and leaveldeptname != ''">leaveldeptname = #{leaveldeptname},</if>
             <if test="leaveicd10code != null  and leaveicd10code != ''">leaveicd10code = #{leaveicd10code},</if>
             <if test="leavediagname != null  and leavediagname != ''">leavediagname = #{leavediagname},</if>
             <if test="libtemplateid != null ">libtemplateid = #{libtemplateid},</if>
@@ -1509,8 +1646,8 @@
         management_doctor,
         leavehospitaldistrictcode,
         leavehospitaldistrictname,
-        deptcode,
-        deptname,
+        leaveldeptcode,
+        leaveldeptname,
         sendstate,
         preachform,
         current_preachform,
@@ -1547,15 +1684,20 @@
         <if test="campusid != null and campusid != ''">
             and campusid = #{campusid}
         </if>
+        <!-- 2026-10-21锛氱梾鍖轰负绌烘椂瑙嗕负"涓嶉檺"
+             鍗楀崕婊℃剰搴﹀瓙浠诲姟鐨� leavehospitaldistrictcode 鏈� 83%锛�3236/3811锛変负 NULL锛�
+             鍘熸潵銆岀瀹� AND 鐥呭尯銆嶄袱涓潯浠舵案杩滀笉鍙兘鍚屾椂鎴愮珛 鈫� 鏁村紶缁熻琛ㄧ┖銆�
+             鍒ょ┖鏀捐鍙奖鍝嶇梾鍖轰负绌虹殑璁板綍锛屾湁鐥呭尯鐨勬暟鎹涓轰笉鍙樸�� -->
         <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-            AND leavehospitaldistrictcode IN
+            AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN
             <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
                      close=")">
                 #{leavehospitaldistrictcode}
             </foreach>
+            )
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
@@ -1568,9 +1710,10 @@
                 #{serviceType}
             </foreach>
         </if>
+        <!-- 2026-10-21锛歷isit_time 涓虹┖锛堝崡鍗庢弧鎰忓害 3811/3811 鍏ㄤ负 NULL锛夋椂鎸夊畬鎴�/鍒涘缓鏃堕棿鍏滃簳 -->
         <if test="startTime != null and endTime!=null">
-            AND visit_time >= DATE(#{startTime})
-            AND visit_time &lt; DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY)
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) >= DATE(#{startTime})
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) &lt; DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY)
         </if>
         <if test="hospitalStartTime != null and hospitalEndTime!=null">
             AND endtime >= DATE(#{hospitalStartTime})
@@ -1594,7 +1737,7 @@
             AND visit_count > 1
         </if>
         <if test="groupKey != null and groupKey != '' and groupKeyList != null and groupKeyList.size>0">
-            AND ${groupKey} IN
+            AND IFNULL(${groupKey}, 'Unknown') IN
             <foreach collection="groupKeyList" item="key" open="(" separator=","
                      close=")">
                 #{key}
@@ -1673,7 +1816,7 @@
             </foreach>
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND b.deptcode IN
+            AND b.leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
@@ -1730,18 +1873,45 @@
         <if test="campusid != null and campusid != ''">
             and campusid = #{campusid}
         </if>
+        <!-- 2026-10-21锛氱梾鍖轰负绌烘椂瑙嗕负"涓嶉檺"
+             鍗楀崕婊℃剰搴﹀瓙浠诲姟鐨� leavehospitaldistrictcode 鏈� 83%锛�3236/3811锛変负 NULL锛�
+             鍘熸潵銆岀瀹� AND 鐥呭尯銆嶄袱涓潯浠舵案杩滀笉鍙兘鍚屾椂鎴愮珛 鈫� 鏁村紶缁熻琛ㄧ┖銆�
+             鍒ょ┖鏀捐鍙奖鍝嶇梾鍖轰负绌虹殑璁板綍锛屾湁鐥呭尯鐨勬暟鎹涓轰笉鍙樸�� -->
         <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-            AND leavehospitaldistrictcode IN
+            AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN
             <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
                      close=")">
                 #{leavehospitaldistrictcode}
             </foreach>
+            )
+        </if>
+        <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+            AND leaveldeptcode IN
+            <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
+                     close=")">
+                #{leaveldeptcode}
+            </foreach>
+        </if>
+        <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
+            AND (hospitaldistrictcode IS NULL OR hospitaldistrictcode IN
+            <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator=","
+                     close=")">
+                #{hospitaldistrictcode}
+            </foreach>
+            )
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
+            </foreach>
+        </if>
+        <if test="hospitaldeptcodes != null and hospitaldeptcodes.size() > 0">
+            AND deptcode IN
+            <foreach collection="hospitaldeptcodes" item="hospitaldeptcode" open="(" separator=","
+                     close=")">
+                #{hospitaldeptcode}
             </foreach>
         </if>
         <if test="serviceType != null and serviceType.size() > 0">
@@ -1751,9 +1921,10 @@
                 #{serviceType}
             </foreach>
         </if>
+        <!-- 2026-10-21锛歷isit_time 涓虹┖锛堝崡鍗庢弧鎰忓害 3811/3811 鍏ㄤ负 NULL锛夋椂鎸夊畬鎴�/鍒涘缓鏃堕棿鍏滃簳 -->
         <if test="startTime != null and endTime!=null">
-            AND visit_time >= DATE(#{startTime})
-            AND visit_time &lt; DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY)
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) >= DATE(#{startTime})
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) &lt; DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY)
         </if>
         <if test="hospitalStartTime != null and hospitalEndTime!=null">
             AND endtime >= DATE(#{hospitalStartTime})
@@ -1784,6 +1955,300 @@
         </if>
     </select>
 
+    <!--
+        ==================================================================
+        闅忚鍒嗙被缁熻锛�/smartor/serviceSubtask/getSfStatisticsCount锛夋�ц兘浼樺寲
+        ==================================================================
+        鏀归�犲墠锛歡etSfStatisticsScript 鍏堟妸 service_subtask 鍛戒腑鐨�**鍏ㄩ儴鏄庣粏琛�**
+        锛坓etSfStatistics 鍏� select 39 涓瓧娈碉紝鍚� continue_content / result / suggest 绛夊ぇ瀛楁锛�
+        鎹炲洖 JVM锛屽啀鍦ㄥ唴瀛橀噷鎸� drcode/绉戝/鐥呭尯 閫愯 if 绱姞锛涙澶栬繕瑕佹妸杩欐鍛戒腑鐨�
+        **鍏ㄩ儴瀛愪换鍔� id** 鐏岃繘 getSfStatisticsCategory 鐨� IN 鍒楄〃鍐嶆煡涓�閬嶃��
+        鍛戒腑鍑犲崈琛屾椂锛岀綉缁滀紶杈擄紙杩滅鐨勫簱灏ゅ叾鏄庢樉锛�+ 鍐呭瓨閬嶅巻 + 瓒呭ぇ IN 鍒楄〃灏辨槸鎺ュ彛鎱㈢殑涓诲洜銆�
+
+        鏀归�犲悗锛氱疮鍔犱笅鎺ㄥ埌鏁版嵁搴擄紝涓�娆� GROUP BY 鍙繑鍥炩�滃垎缁勬暟鈥濓紙閫氬父鍑犲崄琛岋級鐨勭粺璁$粨鏋滐紱
+        婊℃剰搴﹂鐩噺涔熷悓鏍锋寜鍒嗙粍鍦ㄥ簱閲岃仛鍚堛�傜粺璁″彛寰勪笌鍘熸潵鐨� getStatisticCategory 閫愭潯瀵归綈銆�
+        杩欎袱涓鍙ョ殑 where 鏉′欢涓� getSfStatistics 淇濇寔涓�鑷达紝淇濊瘉缁撴灉闆嗕笉鍙樸��
+
+        鍒嗙粍鍒楋紙2026-10 璧凤級锛�
+          绂婚櫌缁村害 鈥斺�� groupKey = leaveldeptcode / leavehospitaldistrictcode锛�
+          鍦ㄩ櫌缁村害 鈥斺�� groupKey = deptcode / hospitaldistrictcode锛�
+          杩囨护涓庡垎缁勪娇鐢ㄥ悓涓�鍒楋紙groupColumn = groupKey锛夛紝閬垮厤鍒嗙粍閿笌鑱氬悎琛屽彛寰勪笉涓�鑷淬��
+        ==================================================================
+    -->
+    <resultMap type="com.ruoyi.task.domain.ServiceSubtaskStatistic" id="ServiceSubtaskScriptStatisticResult">
+        <result property="groupCode" column="group_code"/>
+        <result property="firstVisitCount" column="first_visit_count"/>
+        <result property="againVisitCount" column="again_visit_count"/>
+        <result property="drcode" column="drcode"/>
+        <result property="drname" column="drname"/>
+        <result property="deptcode" column="deptcode"/>
+        <result property="deptname" column="deptname"/>
+        <result property="leavehospitaldistrictcode" column="leavehospitaldistrictcode"/>
+        <result property="leavehospitaldistrictname" column="leavehospitaldistrictname"/>
+        <result property="hospitaldistrictcode" column="hospitaldistrictcode"/>
+        <result property="hospitaldistrictname" column="hospitaldistrictname"/>
+        <result property="hospitaldeptcode" column="hospitaldeptcode"/>
+        <result property="hospitaldeptname" column="hospitaldeptname"/>
+        <result property="nonFollowUp" column="non_follow_up"/>
+        <result property="followUpNeeded" column="follow_up_needed"/>
+        <result property="needFollowUp" column="need_follow_up"/>
+        <result property="pendingFollowUp" column="pending_follow_up"/>
+        <result property="followUpSuccess" column="follow_up_success"/>
+        <result property="followUpFail" column="follow_up_fail"/>
+        <result property="manual" column="manual"/>
+        <result property="voice" column="voice"/>
+        <result property="sms" column="sms"/>
+        <result property="weChat" column="we_chat"/>
+        <result property="abnormal" column="abnormal"/>
+        <result property="needFollowUpAgain" column="need_follow_up_again"/>
+        <result property="pendingFollowUpAgain" column="pending_follow_up_again"/>
+        <result property="followUpSuccessAgain" column="follow_up_success_again"/>
+        <result property="followUpFailAgain" column="follow_up_fail_again"/>
+        <result property="manualAgain" column="manual_again"/>
+        <result property="voiceAgain" column="voice_again"/>
+        <result property="smsAgain" column="sms_again"/>
+        <result property="weChatAgain" column="we_chat_again"/>
+        <result property="abnormalAgain" column="abnormal_again"/>
+    </resultMap>
+
+    <!--
+        鎸夊垎缁勮仛鍚堥殢璁跨粺璁★紙鏇夸唬鈥滃叏閲忔槑缁嗗洖鍐呭瓨鍐嶇疮鍔犫�濓級銆�
+        鍙e緞璇存槑锛堜笌鍘� ServiceSubtaskServiceImpl.getStatisticCategory 瀹屽叏涓�鑷达級锛�
+          * 鏃犻渶闅忚锛歴endstate = 4
+          * 搴旈殢璁匡細sendstate 闈炵┖涓� != 4
+          * 棣栨(visit_count = 1) / 鍐嶆(visit_count > 1) 涓や釜鍒嗘敮浜掓枼锛屼笌鍘熸潵鐨� if / else if 涓�鑷�
+          * 浜哄伐/璇煶/鐭俊/寰俊锛氶娆″垎鏀�**涓�**鎺掗櫎 sendstate = 4锛堝師浠g爜濡傛锛夛紝鍐嶆鍒嗘敮鍚屾牱
+          * 寮傚父锛歟xcep = '1' 涓� sendstate 闈炵┖
+          * 棣栨闅忚鐜� / 鍐嶆闅忚鐜囧湪 Java 閲屾寜鍘熷叕寮忥紙鍚師鏉ョ殑鍒嗘瘝鍒ゆ柇锛夎绠�
+    -->
+    <select id="getSfStatisticsScriptSum" parameterType="com.ruoyi.task.domain.ServiceSubtaskCountReq"
+            resultMap="ServiceSubtaskScriptStatisticResult">
+        select
+        IFNULL(${groupColumn}, 'Unknown') as group_code,
+        MAX(drcode) as drcode,
+        MAX(drname) as drname,
+        MAX(leaveldeptcode) as deptcode,
+        MAX(leaveldeptname) as deptname,
+        MAX(leavehospitaldistrictcode) as leavehospitaldistrictcode,
+        MAX(leavehospitaldistrictname) as leavehospitaldistrictname,
+        MAX(hospitaldistrictcode) as hospitaldistrictcode,
+        MAX(hospitaldistrictname) as hospitaldistrictname,
+        MAX(deptcode) as hospitaldeptcode,
+        MAX(deptname) as hospitaldeptname,
+        SUM(CASE WHEN visit_count = 1 THEN 1 ELSE 0 END) as first_visit_count,
+        SUM(CASE WHEN visit_count > 1 THEN 1 ELSE 0 END) as again_visit_count,
+        SUM(CASE WHEN sendstate = 4 THEN 1 ELSE 0 END) as non_follow_up,
+        SUM(CASE WHEN sendstate is not null and sendstate != 4 THEN 1 ELSE 0 END) as follow_up_needed,
+        SUM(CASE WHEN visit_count = 1 and sendstate is not null and sendstate != 4 THEN 1 ELSE 0 END) as need_follow_up,
+        SUM(CASE WHEN visit_count = 1 and sendstate = 2 THEN 1 ELSE 0 END) as pending_follow_up,
+        SUM(CASE WHEN visit_count = 1 and sendstate = 6 THEN 1 ELSE 0 END) as follow_up_success,
+        SUM(CASE WHEN visit_count = 1 and (sendstate = 5 or sendstate = 7) THEN 1 ELSE 0 END) as follow_up_fail,
+        SUM(CASE WHEN visit_count = 1 and sendstate is not null and current_preachform = '1' THEN 1 ELSE 0 END) as manual,
+        SUM(CASE WHEN visit_count = 1 and sendstate is not null and current_preachform = '3' THEN 1 ELSE 0 END) as voice,
+        SUM(CASE WHEN visit_count = 1 and sendstate is not null and current_preachform = '4' THEN 1 ELSE 0 END) as sms,
+        SUM(CASE WHEN visit_count = 1 and sendstate is not null and current_preachform = '5' THEN 1 ELSE 0 END) as we_chat,
+        SUM(CASE WHEN visit_count = 1 and sendstate is not null and excep = '1' THEN 1 ELSE 0 END) as abnormal,
+        SUM(CASE WHEN visit_count > 1 and sendstate is not null and sendstate != 4 THEN 1 ELSE 0 END) as need_follow_up_again,
+        SUM(CASE WHEN visit_count > 1 and sendstate = 2 THEN 1 ELSE 0 END) as pending_follow_up_again,
+        SUM(CASE WHEN visit_count > 1 and (sendstate = 1 or sendstate = 3 or sendstate = 6) THEN 1 ELSE 0 END) as follow_up_success_again,
+        SUM(CASE WHEN visit_count > 1 and sendstate = 5 THEN 1 ELSE 0 END) as follow_up_fail_again,
+        SUM(CASE WHEN visit_count > 1 and sendstate is not null and current_preachform = '1' THEN 1 ELSE 0 END) as manual_again,
+        SUM(CASE WHEN visit_count > 1 and sendstate is not null and current_preachform = '3' THEN 1 ELSE 0 END) as voice_again,
+        SUM(CASE WHEN visit_count > 1 and sendstate is not null and current_preachform = '4' THEN 1 ELSE 0 END) as sms_again,
+        SUM(CASE WHEN visit_count > 1 and sendstate is not null and current_preachform = '5' THEN 1 ELSE 0 END) as we_chat_again,
+        SUM(CASE WHEN visit_count > 1 and sendstate is not null and excep = '1' THEN 1 ELSE 0 END) as abnormal_again
+        from service_subtask
+        where 1=1
+        and del_flag = 0
+        <if test="orgid != null and orgid != ''">
+            and orgid = #{orgid}
+        </if>
+        <if test="campusid != null and campusid != ''">
+            and campusid = #{campusid}
+        </if>
+        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
+            AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN
+            <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
+                     close=")">
+                #{leavehospitaldistrictcode}
+            </foreach>
+            )
+        </if>
+        <if test="deptcodes != null and deptcodes.size() > 0">
+            AND leaveldeptcode IN
+            <foreach collection="deptcodes" item="deptcode" open="(" separator=","
+                     close=")">
+                #{deptcode}
+            </foreach>
+        </if>
+        <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+            AND leaveldeptcode IN
+            <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
+                     close=")">
+                #{leaveldeptcode}
+            </foreach>
+        </if>
+        <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
+            AND (hospitaldistrictcode IS NULL OR hospitaldistrictcode IN
+            <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator=","
+                     close=")">
+                #{hospitaldistrictcode}
+            </foreach>
+            )
+        </if>
+        <if test="hospitaldeptcodes != null and hospitaldeptcodes.size() > 0">
+            AND deptcode IN
+            <foreach collection="hospitaldeptcodes" item="hospitaldeptcode" open="(" separator=","
+                     close=")">
+                #{hospitaldeptcode}
+            </foreach>
+        </if>
+        <if test="serviceType != null and serviceType.size() > 0">
+            AND service_type IN
+            <foreach collection="serviceType" item="serviceType" open="(" separator=","
+                     close=")">
+                #{serviceType}
+            </foreach>
+        </if>
+        <if test="startTime != null and endTime!=null">
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) >= DATE(#{startTime})
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) &lt; DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY)
+        </if>
+        <if test="hospitalStartTime != null and hospitalEndTime!=null">
+            AND endtime >= DATE(#{hospitalStartTime})
+            AND endtime &lt; DATE_ADD(DATE(#{hospitalEndTime}), INTERVAL 1 DAY)
+        </if>
+        <if test="visitDeptCode != null">and visit_dept_code = #{visitDeptCode}</if>
+        <if test="visitDeptName != null">and visit_dept_name = #{visitDeptName}</if>
+        <if test="isabnormal != null">and isabnormal = #{isabnormal}</if>
+        <if test="continueFlag != null ">and continue_flag = #{continueFlag}</if>
+        <if test="continueTimeNow != null ">and continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if>
+        <if test="continueCount != null ">and continue_count = #{continueCount}</if>
+        <if test="continueTimeNext != null ">and continue_time_next = #{continueTimeNext,jdbcType=TIMESTAMP}</if>
+        <if test="type != null">
+            and type = #{type}
+        </if>
+        <if test="visitCount != null and visitCount == 1">
+            AND visit_count = 1
+        </if>
+        <if test="visitCount != null and visitCount > 1">
+            AND visit_count > 1
+        </if>
+        <if test="groupKey != null and groupKey != '' and groupKeyList != null and groupKeyList.size>0">
+            AND IFNULL(${groupKey}, 'Unknown') IN
+            <foreach collection="groupKeyList" item="key" open="(" separator=","
+                     close=")">
+                #{key}
+            </foreach>
+        </if>
+        group by IFNULL(${groupColumn}, 'Unknown')
+    </select>
+
+    <!--
+        鎸夊垎缁勮仛鍚堟弧鎰忓害棰樼洰閲忥紙鏇夸唬 getSfStatisticsCategory 鐨勨�滈�愬瓙浠诲姟 IN 鏌ヨ + 鍐呭瓨 N*M 杩囨护鈥濓級銆�
+        where 鏉′欢 = 涓婇潰鑱氬悎鏌ヨ鐨勬潯浠� + 鍘� getSfStatisticsCategory 鐨勬槑缁嗘潯浠讹紝
+        鍥犳鍛戒腑鐨勬槑缁嗛泦鍚堜笌鏀归�犲墠锛坓etSfStatisticsCategory 缁撴灉鍐嶆寜瀛愪换鍔′笌鍒嗙粍姹備氦锛夊畬鍏ㄤ竴鑷淬��
+        configValue 涓虹┖鏃朵笉璋冪敤鏈鍙ワ紙鍘熷疄鐜板湪杩欑鍦烘櫙涓嬮鐩噺涓�寰嬩负 0锛夈��
+    -->
+    <select id="getSfStatisticsScriptJoySum" parameterType="com.ruoyi.task.domain.ServiceSubtaskCountReq"
+            resultType="map">
+        select
+        IFNULL(t.${groupColumn}, 'Unknown') as groupCode,
+        SUM(CASE WHEN a.categoryid IN(${configValue})
+        THEN 1 ELSE 0 END) as joyAllCount,
+        SUM(CASE WHEN a.categoryid IN(${configValue})
+        AND IFNULL(a.matchedtext,a.asrtext) is not null
+        AND IFNULL(a.matchedtext,a.asrtext) != ''
+        THEN 1 ELSE 0 END) as joyCount
+        from service_subtask_detail a
+        INNER JOIN service_subtask t on a.sub_id = t.id
+        where 1=1
+        and a.del_flag = 0
+        and t.del_flag = 0
+        <if test="orgid != null and orgid != ''">
+            and t.orgid = #{orgid}
+        </if>
+        <if test="campusid != null and campusid != ''">
+            and t.campusid = #{campusid}
+        </if>
+        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
+            AND (t.leavehospitaldistrictcode IS NULL OR t.leavehospitaldistrictcode IN
+            <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
+                     close=")">
+                #{leavehospitaldistrictcode}
+            </foreach>
+            )
+        </if>
+        <if test="deptcodes != null and deptcodes.size() > 0">
+            AND t.leaveldeptcode IN
+            <foreach collection="deptcodes" item="deptcode" open="(" separator=","
+                     close=")">
+                #{deptcode}
+            </foreach>
+        </if>
+        <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+            AND t.leaveldeptcode IN
+            <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
+                     close=")">
+                #{leaveldeptcode}
+            </foreach>
+        </if>
+        <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
+            AND (t.hospitaldistrictcode IS NULL OR t.hospitaldistrictcode IN
+            <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator=","
+                     close=")">
+                #{hospitaldistrictcode}
+            </foreach>
+            )
+        </if>
+        <if test="hospitaldeptcodes != null and hospitaldeptcodes.size() > 0">
+            AND t.deptcode IN
+            <foreach collection="hospitaldeptcodes" item="hospitaldeptcode" open="(" separator=","
+                     close=")">
+                #{hospitaldeptcode}
+            </foreach>
+        </if>
+        <if test="serviceType != null and serviceType.size() > 0">
+            AND t.service_type IN
+            <foreach collection="serviceType" item="serviceType" open="(" separator=","
+                     close=")">
+                #{serviceType}
+            </foreach>
+        </if>
+        <if test="startTime != null and endTime!=null">
+            AND IFNULL(t.visit_time, IFNULL(t.finishtime, t.create_time)) >= DATE(#{startTime})
+            AND IFNULL(t.visit_time, IFNULL(t.finishtime, t.create_time)) &lt; DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY)
+        </if>
+        <if test="hospitalStartTime != null and hospitalEndTime!=null">
+            AND t.endtime >= DATE(#{hospitalStartTime})
+            AND t.endtime &lt; DATE_ADD(DATE(#{hospitalEndTime}), INTERVAL 1 DAY)
+        </if>
+        <if test="visitDeptCode != null">and t.visit_dept_code = #{visitDeptCode}</if>
+        <if test="visitDeptName != null">and t.visit_dept_name = #{visitDeptName}</if>
+        <if test="isabnormal != null">and t.isabnormal = #{isabnormal}</if>
+        <if test="continueFlag != null ">and t.continue_flag = #{continueFlag}</if>
+        <if test="continueTimeNow != null ">and t.continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if>
+        <if test="continueCount != null ">and t.continue_count = #{continueCount}</if>
+        <if test="continueTimeNext != null ">and t.continue_time_next = #{continueTimeNext,jdbcType=TIMESTAMP}</if>
+        <if test="type != null">
+            and t.type = #{type}
+        </if>
+        <if test="visitCount != null and visitCount == 1">
+            AND t.visit_count = 1
+        </if>
+        <if test="visitCount != null and visitCount > 1">
+            AND t.visit_count > 1
+        </if>
+        <if test="groupKey != null and groupKey != '' and groupKeyList != null and groupKeyList.size>0">
+            AND IFNULL(t.${groupKey}, 'Unknown') IN
+            <foreach collection="groupKeyList" item="key" open="(" separator=","
+                     close=")">
+                #{key}
+            </foreach>
+        </if>
+        group by IFNULL(t.${groupColumn}, 'Unknown')
+    </select>
+
     <select id="getSfStatisticsHyperlink" parameterType="com.ruoyi.task.domain.ServiceSubtaskCountReq"
             resultMap="ServiceSubtaskResult">
         select id,
@@ -1795,8 +2260,8 @@
         drname,
         leavehospitaldistrictcode,
         leavehospitaldistrictname,
-        deptcode,
-        deptname,
+        leaveldeptcode,
+        leaveldeptname,
         sendstate,
         preachform,
         current_preachform,
@@ -1834,15 +2299,17 @@
         <if test="campusid != null and campusid != ''">
             and campusid = #{campusid}
         </if>
+        <!-- 2026-10-21锛氱梾鍖轰负绌烘椂瑙嗕负"涓嶉檺"锛堝崡鍗庢弧鎰忓害 83% 瀛愪换鍔℃棤鐥呭尯锛夛紝鏈夌梾鍖虹殑鏁版嵁琛屼负涓嶅彉 -->
         <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-            AND leavehospitaldistrictcode IN
+            AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN
             <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
                      close=")">
                 #{leavehospitaldistrictcode}
             </foreach>
+            )
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
@@ -1855,9 +2322,10 @@
                 #{serviceType}
             </foreach>
         </if>
+        <!-- 2026-10-21锛歷isit_time 涓虹┖鏃舵寜瀹屾垚/鍒涘缓鏃堕棿鍏滃簳 -->
         <if test="startTime != null and endTime!=null">
-            AND visit_time >= DATE(#{startTime})
-            AND visit_time &lt; DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY)
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) >= DATE(#{startTime})
+            AND IFNULL(visit_time, IFNULL(finishtime, create_time)) &lt; DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY)
         </if>
         <if test="visitDeptCode != null">and visit_dept_code = #{visitDeptCode}</if>
         <if test="visitDeptName != null">and visit_dept_name = #{visitDeptName}</if>
@@ -1877,7 +2345,7 @@
             AND visit_count > 1
         </if>
         <if test="groupKey != null and groupKey != '' and groupKeyList != null and groupKeyList.size>0">
-            AND ${groupKey} IN
+            AND IFNULL(${groupKey}, 'Unknown') IN
             <foreach collection="groupKeyList" item="key" open="(" separator=","
                      close=")">
                 #{key}
@@ -1909,7 +2377,7 @@
             AND leavehospitaldistrictcode = #{leavehospitaldistrictcode}
         </if>
         <if test="deptcode != null and deptcode != ''">
-            AND deptcode = #{deptcode}
+            AND leaveldeptcode = #{deptcode}
         </if>
         order by endtime desc
         <if test="pageSize != null  and pageNum != null">
@@ -1932,15 +2400,17 @@
         <if test="campusid != null and campusid != ''">
             and campusid = #{campusid}
         </if>
+        <!-- 2026-10-21锛氱梾鍖轰负绌烘椂瑙嗕负"涓嶉檺"锛堝崡鍗庢弧鎰忓害 83% 瀛愪换鍔℃棤鐥呭尯锛夛紝鏈夌梾鍖虹殑鏁版嵁琛屼负涓嶅彉 -->
         <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-            AND leavehospitaldistrictcode IN
+            AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN
             <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
                      close=")">
                 #{leavehospitaldistrictcode}
             </foreach>
+            )
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
@@ -1954,8 +2424,8 @@
             </foreach>
         </if>
         <if test="startTime != null and endTime!=null">
-            AND date_format(visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d')
-            AND date_format(visit_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
+            AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d')
+            AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
         </if>
         <if test="visitDeptCode != null">and visit_dept_code = #{visitDeptCode}</if>
         <if test="visitDeptName != null">and visit_dept_name = #{visitDeptName}</if>
@@ -1979,15 +2449,17 @@
         <if test="campusid != null and campusid != ''">
             and campusid = #{campusid}
         </if>
+        <!-- 2026-10-21锛氱梾鍖轰负绌烘椂瑙嗕负"涓嶉檺"锛堝崡鍗庢弧鎰忓害 83% 瀛愪换鍔℃棤鐥呭尯锛夛紝鏈夌梾鍖虹殑鏁版嵁琛屼负涓嶅彉 -->
         <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-            AND leavehospitaldistrictcode IN
+            AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN
             <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
                      close=")">
                 #{leavehospitaldistrictcode}
             </foreach>
+            )
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
@@ -2001,8 +2473,8 @@
             </foreach>
         </if>
         <if test="startTime != null and endTime!=null">
-            AND date_format(visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d')
-            AND date_format(visit_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
+            AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d')
+            AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
         </if>
         ) AND targetid=a.id) joyCount , (SELECT COUNT(*) from (select sub_id FROM service_subtask_detail
         WHERE sub_id IN(SELECT id FROM service_subtask t
@@ -2023,7 +2495,7 @@
             </foreach>
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
@@ -2037,8 +2509,8 @@
             </foreach>
         </if>
         <if test="startTime != null and endTime!=null">
-            AND date_format(visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d')
-            AND date_format(visit_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
+            AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d')
+            AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
         </if>
         GROUP BY sub_id ) ) ta ) joyAllCount
         FROM ivr_liba_target a
@@ -2072,15 +2544,20 @@
         <if test="campusid != null and campusid != ''">
             and t.campusid = #{campusid}
         </if>
+        <!-- 2026-10-21锛氱梾鍖轰负绌烘椂瑙嗕负"涓嶉檺"
+             鍗楀崕婊℃剰搴﹀瓙浠诲姟鐨� leavehospitaldistrictcode 鏈� 83%锛�3236/3811锛変负 NULL锛�
+             鍘熸潵銆岀瀹� AND 鐥呭尯銆嶄袱涓潯浠舵案杩滀笉鍙兘鍚屾椂鎴愮珛 鈫� 鏁村紶缁熻琛ㄧ┖銆�
+             鍒ょ┖鏀捐鍙奖鍝嶇梾鍖轰负绌虹殑璁板綍锛屾湁鐥呭尯鐨勬暟鎹涓轰笉鍙樸�� -->
         <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-            AND t.leavehospitaldistrictcode IN
+            AND (t.leavehospitaldistrictcode IS NULL OR t.leavehospitaldistrictcode IN
             <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
                      close=")">
                 #{leavehospitaldistrictcode}
             </foreach>
+            )
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND t.deptcode IN
+            AND t.leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
@@ -2100,9 +2577,10 @@
                 #{serviceType}
             </foreach>
         </if>
+        <!-- 2026-10-21锛歷isit_time 涓虹┖鏃舵寜瀹屾垚/鍒涘缓鏃堕棿鍏滃簳 -->
         <if test="startTime != null and endTime!=null">
-            AND date_format(t.visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d')
-            AND date_format(t.visit_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
+            AND date_format(IFNULL(t.visit_time, IFNULL(t.finishtime, t.create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d')
+            AND date_format(IFNULL(t.visit_time, IFNULL(t.finishtime, t.create_time)),'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
         </if>
         <if test="visitDeptCode != null">
             and t.visit_dept_code = #{visitDeptCode}
@@ -2166,10 +2644,31 @@
             </foreach>
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND ss.deptcode IN
+            AND ss.leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
+            </foreach>
+        </if>
+        <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+            AND ss.leaveldeptcode IN
+            <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
+                     close=")">
+                #{leaveldeptcode}
+            </foreach>
+        </if>
+        <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
+            AND ss.hospitaldistrictcode IN
+            <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator=","
+                     close=")">
+                #{hospitaldistrictcode}
+            </foreach>
+        </if>
+        <if test="hospitaldeptcodes != null and hospitaldeptcodes.size() > 0">
+            AND ss.deptcode IN
+            <foreach collection="hospitaldeptcodes" item="hospitaldeptcode" open="(" separator=","
+                     close=")">
+                #{hospitaldeptcode}
             </foreach>
         </if>
         <if test="serviceType != null and serviceType.size() > 0">
@@ -2179,9 +2678,10 @@
                 #{serviceType}
             </foreach>
         </if>
+        <!-- 2026-10-21锛歷isit_time 涓虹┖锛堝崡鍗庢弧鎰忓害 3811/3811 鍏ㄤ负 NULL锛夋椂鎸夊畬鎴�/鍒涘缓鏃堕棿鍏滃簳 -->
         <if test="startTime != null and endTime!=null">
-            AND date_format(ss.visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d')
-            AND date_format(ss.visit_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
+            AND date_format(IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d')
+            AND date_format(IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)),'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
         </if>
         <!-- 鐩墠鍙粺璁¤闊冲拰闂嵎 -->
         <if test="type != null">
@@ -2226,10 +2726,31 @@
             </foreach>
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND ss.deptcode IN
+            AND ss.leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
+            </foreach>
+        </if>
+        <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
+            AND ss.leaveldeptcode IN
+            <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
+                     close=")">
+                #{leaveldeptcode}
+            </foreach>
+        </if>
+        <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
+            AND ss.hospitaldistrictcode IN
+            <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator=","
+                     close=")">
+                #{hospitaldistrictcode}
+            </foreach>
+        </if>
+        <if test="hospitaldeptcodes != null and hospitaldeptcodes.size() > 0">
+            AND ss.deptcode IN
+            <foreach collection="hospitaldeptcodes" item="hospitaldeptcode" open="(" separator=","
+                     close=")">
+                #{hospitaldeptcode}
             </foreach>
         </if>
         <if test="serviceType != null and serviceType.size() > 0">
@@ -2239,9 +2760,10 @@
                 #{serviceType}
             </foreach>
         </if>
+        <!-- 2026-10-21锛歷isit_time 涓虹┖锛堝崡鍗庢弧鎰忓害 3811/3811 鍏ㄤ负 NULL锛夋椂鎸夊畬鎴�/鍒涘缓鏃堕棿鍏滃簳 -->
         <if test="startTime != null and endTime!=null">
-            AND date_format(ss.visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d')
-            AND date_format(ss.visit_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
+            AND date_format(IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d')
+            AND date_format(IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)),'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
         </if>
         <!-- 鐩墠鍙粺璁¤闊冲拰闂嵎 -->
         <if test="type != null">
@@ -2279,7 +2801,7 @@
                recordid,
                exrecallcount,
                pulltime,
-               deptcode,
+               leaveldeptcode,
                labelstatus,
                del_flag,
                upid,
@@ -2309,7 +2831,7 @@
                admindate,
                patid,
                service_type,
-               deptname,
+               leaveldeptname,
                score,
                drname,
                drcode,
@@ -2368,7 +2890,7 @@
     </select>
 
     <select id="getDeptRanking" parameterType="com.ruoyi.common.core.service.dto.PatMedReq" resultType="com.ruoyi.common.core.service.dto.PatMedRes">
-        SELECT deptname,
+        SELECT leaveldeptname AS deptname,
         count(1) AS rc
         FROM service_subtask
         WHERE DATE_FORMAT(visit_time, '%Y-%m-%d') >= #{startDate}
@@ -2381,7 +2903,7 @@
         <if test="campusid != null and campusid != ''">
             AND campusid = #{campusid}
         </if>
-        GROUP BY deptname
+        GROUP BY leaveldeptname
     </select>
 
     <!-- 鏈嶅姟缁熻鏌ヨ - 鎸夋椂闂寸淮搴︾粺璁″嚭闄�/闂ㄨ瘖闅忚鏁版嵁 -->
@@ -2432,7 +2954,7 @@
             AND campusid = #{campusid}
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
                 #{deptcode}
             </foreach>
@@ -2581,46 +3103,24 @@
             AND phone = #{phone}
         </if>
         <if test="finishtimeStart != null">
-            AND date_format(finishtime,'%y%m%d') &gt;= date_format(#{finishtimeStart},'%y%m%d')
+            AND finishtime &gt;= DATE(#{finishtimeStart})
         </if>
         <if test="finishtimeEnd != null">
-            AND date_format(finishtime,'%y%m%d') &lt;= date_format(#{finishtimeEnd},'%y%m%d')
+            AND finishtime &lt; DATE_ADD(DATE(#{finishtimeEnd}), INTERVAL 1 DAY)
         </if>
-        <if test="deptOrDistrict==1">
-            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-                AND leavehospitaldistrictcode IN
-                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
-                         separator=","
-                         close=")">
-                    #{leavehospitaldistrictcode}
-                </foreach>
-            </if>
-            <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
-                AND deptcode IN
-                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
-                         close=")">
-                    #{leaveldeptcode}
-                </foreach>
-            </if>
+        <!--
+            绉戝/鐥呭尯绛涢�夛紙2026-11 淇锛夛細
+              绂婚櫌缁勶紙leaveldeptcodes / leavehospitaldistrictcodes锛変繚鎸佸師閫昏緫锛�
+              鍦ㄩ櫌缁勶紙deptcodes / hospitaldistrictcodes 鈫� deptcode / hospitaldistrictcode锛夋槸鏂板鐨勪竴缁勶紱
+              缁勫唴鎸� deptOrDistrict 鍙� AND('1') / OR('2')锛屼袱缁勪箣闂� AND锛堝彧浼犱竴缁勬椂鍙︿竴缁勪笉鎷硷級銆�
+        -->
+        <if test='deptOrDistrict == "1"'>
+            <include refid="filterLeaveDimAnd"/>
+            <include refid="filterInhospDimAnd"/>
         </if>
-        <if test="deptOrDistrict==2">
-            AND (1=1
-            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-                AND leavehospitaldistrictcode IN
-                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
-                         separator=","
-                         close=")">
-                    #{leavehospitaldistrictcode}
-                </foreach>
-            </if>
-            <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
-                OR deptcode IN
-                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
-                         close=")">
-                    #{leaveldeptcode}
-                </foreach>
-            </if>
-            )
+        <if test='deptOrDistrict == "2"'>
+            <include refid="filterLeaveDimOr"/>
+            <include refid="filterInhospDimOr"/>
         </if>
         <if test="visitCount != null and visitCount > 1 and visitDeptCodes != null and visitDeptCodes.size() > 0">
             AND visit_dept_code IN
@@ -2694,37 +3194,24 @@
             AND templatename LIKE CONCAT('%', #{templatename}, '%')
         </if>
         <if test="startOutHospTime != null">
-            AND DATE_FORMAT(endtime,'%y%m%d') &gt;= DATE_FORMAT(#{startOutHospTime},'%y%m%d')
+            AND endtime &gt;= DATE(#{startOutHospTime})
         </if>
         <if test="endOutHospTime != null">
-            AND DATE_FORMAT(endtime,'%y%m%d') &lt;= DATE_FORMAT(#{endOutHospTime},'%y%m%d')
+            AND endtime &lt; DATE_ADD(DATE(#{endOutHospTime}), INTERVAL 1 DAY)
         </if>
         <if test="startSendDateTime != null">
-            AND DATE_FORMAT(visit_time,'%y%m%d') &gt;= DATE_FORMAT(#{startSendDateTime},'%y%m%d')
+            AND visit_time &gt;= DATE(#{startSendDateTime})
         </if>
         <if test="endSendDateTime != null">
-            AND DATE_FORMAT(visit_time,'%y%m%d') &lt;= DATE_FORMAT(#{endSendDateTime},'%y%m%d')
+            AND visit_time &lt; DATE_ADD(DATE(#{endSendDateTime}), INTERVAL 1 DAY)
         </if>
         <if test="longSendTime != null">
-            AND DATE_FORMAT(long_send_time,'%y%m%d') &lt;= DATE_FORMAT(#{longSendTime},'%y%m%d')
+            AND long_send_time &lt; DATE_ADD(DATE(#{longSendTime}), INTERVAL 1 DAY)
         </if>
-        <if test="deptOrDistrict == 1">
-            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
-                AND leavehospitaldistrictcode IN
-                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
-                         separator="," close=")">
-                    #{leavehospitaldistrictcode}
-                </foreach>
-            </if>
-            <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
-                AND deptcode IN
-                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," close=")">
-                    #{leaveldeptcode}
-                </foreach>
-            </if>
-        </if>
-        <if test="deptcode != null and deptcode != ''">
-            AND deptcode = #{deptcode}
+        <!-- 2026-11锛氳繖閲屽師鏈繕鏈変竴浠戒笌涓婃柟 deptOrDistrict==1 瀹屽叏閲嶅鐨勭梾鍖�/绉戝鏉′欢锛�
+             宸插垹闄わ紙鏉′欢鏀圭敤 filterSubtaskWardDim / filterSubtaskDeptDim 鐗囨锛岄伩鍏嶄袱浠藉彛寰勪笉涓�鑷达級 -->
+        <if test="leaveldeptcode != null and leaveldeptcode != ''">
+            AND leaveldeptcode = #{leaveldeptcode}
         </if>
         <if test="sendstate != null">
             AND sendstate = #{sendstate}
@@ -2784,7 +3271,7 @@
             AND date_format( visit_time, '%y%m%d' ) &lt;= date_format(#{endDate},'%y%m%d')
         </if>
         <if test="deptcodeList != null and deptcodeList.size()>0">
-            and deptcode in
+            and leaveldeptcode in
             <foreach collection="deptcodeList" item="deptcode" open="(" separator="," close=")">
                 #{deptcode}
             </foreach>
@@ -2819,7 +3306,7 @@
             </foreach>
         </if>
         <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                      close=")">
                 #{leaveldeptcode}
@@ -2867,14 +3354,14 @@
             parameterType="com.ruoyi.task.domain.VO.ServiceSubtaskCotinueCountVO"
             resultType="java.util.Map">
         SELECT
-        deptcode AS groupCode,
-        deptname AS groupName,
+        leaveldeptcode AS groupCode,
+        leaveldeptname AS groupName,
         SUM(CASE WHEN continue_flag = 1 THEN 1 ELSE 0 END) AS noContinueCnt,
         SUM(CASE WHEN continue_flag = 2 THEN 1 ELSE 0 END) AS continueCnt
         FROM service_subtask
         WHERE del_flag = 0
         AND continue_flag IN (1, 2)
-        AND deptcode IS NOT NULL AND deptcode != ''
+        AND leaveldeptcode IS NOT NULL AND leaveldeptcode != ''
         <if test="orgid != null and orgid != ''">
             AND orgid = #{orgid}
         </if>
@@ -2882,12 +3369,12 @@
             AND campusid = #{campusid}
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="deptcodes" item="code" open="(" separator="," close=")">
                 #{code}
             </foreach>
         </if>
-        GROUP BY deptcode, deptname
+        GROUP BY leaveldeptcode, leaveldeptname
         ORDER BY groupCode
     </select>
 
@@ -2900,8 +3387,8 @@
                 leavehospitaldistrictname AS groupName,
             </when>
             <otherwise>
-                deptcode AS groupCode,
-                deptname AS groupName,
+                leaveldeptcode AS groupCode,
+                leaveldeptname AS groupName,
             </otherwise>
         </choose>
         COUNT(*) AS totalCount,
@@ -2938,12 +3425,12 @@
             </when>
             <otherwise>
                 <if test="deptcodes != null and deptcodes.size() > 0">
-                    AND deptcode IN
+                    AND leaveldeptcode IN
                     <foreach collection="deptcodes" item="code" open="(" separator="," close=")">
                         #{code}
                     </foreach>
                 </if>
-                GROUP BY deptcode, deptname
+                GROUP BY leaveldeptcode, leaveldeptname
                 ORDER BY groupCode
             </otherwise>
         </choose>
@@ -2979,8 +3466,8 @@
         drname,
         leavehospitaldistrictcode,
         leavehospitaldistrictname,
-        deptcode,
-        deptname,
+        leaveldeptcode,
+        leaveldeptname,
         sendstate,
         preachform,
         current_preachform,
@@ -3033,7 +3520,7 @@
             </foreach>
         </if>
         <if test="deptcodes != null and deptcodes.size() > 0">
-            AND deptcode IN
+            AND leaveldeptcode IN
             <foreach collection="deptcodes" item="deptcode" open="(" separator=","
                      close=")">
                 #{deptcode}
diff --git a/smartor/src/main/java/com/smartor/domain/ServiceSubtaskExportVO.java b/smartor/src/main/java/com/smartor/domain/ServiceSubtaskExportVO.java
index fe869d2..15eff92 100644
--- a/smartor/src/main/java/com/smartor/domain/ServiceSubtaskExportVO.java
+++ b/smartor/src/main/java/com/smartor/domain/ServiceSubtaskExportVO.java
@@ -173,32 +173,32 @@
     private Date senddate;
 
     /**
-     * 涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌鐥呭尯缂栫爜锛堝師 sendlimitabegin 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓婂崍寮�濮嬪彂閫佹椂闂撮檺鍒�")
-    private String sendlimitabegin;
+    @Excel(name = " 鍦ㄩ櫌鐥呭尯缂栫爜 ")
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯缂栫爜")
+    private String hospitaldistrictcode;
 
     /**
-     * 涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌鐥呭尯鍚嶇О锛堝師 sendlimitaend 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓婂崍缁撴潫鍙戦�佹椂闂撮檺鍒�")
-    private String sendlimitaend;
+    @Excel(name = " 鍦ㄩ櫌鐥呭尯鍚嶇О ")
+    @ApiModelProperty(value = "鍦ㄩ櫌鐥呭尯鍚嶇О")
+    private String hospitaldistrictname;
 
     /**
-     * 涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌绉戝缂栫爜锛堝師 sendlimitpbegin 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓嬪崍寮�濮嬪彂閫佹椂闂撮檺鍒�")
-    private String sendlimitpbegin;
+    @Excel(name = " 鍦ㄩ櫌绉戝缂栫爜 ")
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝缂栫爜")
+    private String deptcode;
 
     /**
-     * 涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒�
+     * 鍦ㄩ櫌绉戝鍚嶇О锛堝師 sendlimitpend 鍒楀鐢ㄨ�屾潵锛�
      */
-    @Excel(name = " 涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒� ")
-    @ApiModelProperty(value = "涓嬪崍缁撴潫鍙戦�佹椂闂撮檺鍒�")
-    private String sendlimitpend;
+    @Excel(name = " 鍦ㄩ櫌绉戝鍚嶇О ")
+    @ApiModelProperty(value = "鍦ㄩ櫌绉戝鍚嶇О")
+    private String deptname;
 
     /**
      * 鏅氫笂寮�濮嬪彂閫佹椂闂撮檺鍒�
@@ -272,11 +272,11 @@
     private Date pulltime;
 
     /**
-     * 閮ㄩ棬code
+     * 鍑洪櫌绉戝缂栫爜锛堝師 deptcode 鍒楋紝宸叉敼鍚� leaveldeptcode锛�
      */
-    @Excel(name = "  閮ㄩ棬code")
-    @ApiModelProperty(value = "閮ㄩ棬code")
-    private String deptcode;
+    @Excel(name = "  鍑洪櫌绉戝缂栫爜")
+    @ApiModelProperty(value = "鍑洪櫌绉戝缂栫爜")
+    private String leaveldeptcode;
 
     /**
      * 鍖荤敓缂栫爜
@@ -435,11 +435,11 @@
     private Long patid;
 
     /**
-     * 绉戝鍚嶇О
+     * 鍑洪櫌绉戝鍚嶇О锛堝師 deptname 鍒楋紝宸叉敼鍚� leaveldeptname锛�
      */
-    @Excel(name = "绉戝鍚嶇О")
-    @ApiModelProperty(value = "绉戝鍚嶇О")
-    private String deptname;
+    @Excel(name = "鍑洪櫌绉戝鍚嶇О")
+    @ApiModelProperty(value = "鍑洪櫌绉戝鍚嶇О")
+    private String leaveldeptname;
 
     /**
      * 灏辫瘖鏃ユ湡
diff --git a/smartor/src/main/java/com/smartor/service/impl/PatMedInhospServiceImpl.java b/smartor/src/main/java/com/smartor/service/impl/PatMedInhospServiceImpl.java
index e299c66..3aa700e 100644
--- a/smartor/src/main/java/com/smartor/service/impl/PatMedInhospServiceImpl.java
+++ b/smartor/src/main/java/com/smartor/service/impl/PatMedInhospServiceImpl.java
@@ -1139,14 +1139,14 @@
         serviceSubtask.setInhospid(patMedInhosp1.getInhospid());
         serviceSubtask.setDrcode(patMedInhosp1.getDrcode());
         serviceSubtask.setDrname(patMedInhosp1.getDrname());
-        serviceSubtask.setDeptcode(patMedInhosp1.getLeaveldeptcode());
-        serviceSubtask.setDeptname(patMedInhosp1.getLeaveldeptname());
+        serviceSubtask.setLeaveldeptcode(patMedInhosp1.getLeaveldeptcode());
+        serviceSubtask.setLeaveldeptname(patMedInhosp1.getLeaveldeptname());
         serviceSubtask.setLeavehospitaldistrictcode(patMedInhosp1.getLeavehospitaldistrictcode());
         serviceSubtask.setLeavehospitaldistrictname(patMedInhosp1.getLeavehospitaldistrictname());
         if (type == 4 || type == 5) {
             //璁剧疆鍏ラ櫌鐨�
-            serviceSubtask.setDeptcode(patMedInhosp1.getDeptcode());
-            serviceSubtask.setDeptname(patMedInhosp1.getDeptname());
+            serviceSubtask.setLeaveldeptcode(patMedInhosp1.getDeptcode());
+            serviceSubtask.setLeaveldeptname(patMedInhosp1.getDeptname());
             serviceSubtask.setLeavehospitaldistrictcode(patMedInhosp1.getHospitaldistrictcode());
             serviceSubtask.setLeavehospitaldistrictname(patMedInhosp1.getHospitaldistrictname());
         }
@@ -1252,8 +1252,8 @@
         serviceSubtask.setInhospid(patMedInhosp1.getInhospid());
         serviceSubtask.setDrcode(patMedInhosp1.getDrcode());
         serviceSubtask.setDrname(patMedInhosp1.getDrname());
-        serviceSubtask.setDeptcode(patMedInhosp1.getLeaveldeptcode());
-        serviceSubtask.setDeptname(patMedInhosp1.getLeaveldeptname());
+        serviceSubtask.setLeaveldeptcode(patMedInhosp1.getLeaveldeptcode());
+        serviceSubtask.setLeaveldeptname(patMedInhosp1.getLeaveldeptname());
         serviceSubtask.setLeavehospitaldistrictcode(patMedInhosp1.getLeavehospitaldistrictcode());
         serviceSubtask.setLeavehospitaldistrictname(patMedInhosp1.getLeavehospitaldistrictname());
 
diff --git a/smartor/src/main/java/com/smartor/service/impl/ServiceSLTDHealthcareRecordServiceImpl.java b/smartor/src/main/java/com/smartor/service/impl/ServiceSLTDHealthcareRecordServiceImpl.java
index 11638b2..6fc6d50 100644
--- a/smartor/src/main/java/com/smartor/service/impl/ServiceSLTDHealthcareRecordServiceImpl.java
+++ b/smartor/src/main/java/com/smartor/service/impl/ServiceSLTDHealthcareRecordServiceImpl.java
@@ -572,6 +572,11 @@
         try {
             List<Map<String, Object>> dataList = getDataList(result, cry.equals("4") ? 2 : 1);
             log.info("銆恜arseResponseData銆戞垚鍔熻В鏋恉ataList:{}鏉″仴搴疯褰曟暟鎹�", dataList.size());
+            if (dataList.size() >= 1500) {
+                // 鏉ユ湭鏉ユ帴鍙e崟娆′笂闄� 1500 鏉★細鍒拌繖閲岃鏄庢湰椤靛緢鍙兘宸茶鎴柇銆�
+                // 閲囬泦缂栨帓浼氭寜杩斿洖鏉℃暟浜屽垎閲嶉噰锛岃繖閲岀暀涓�鏉� error 渚夸簬浜嬪悗鏍稿
+                log.error("銆恜arseResponseData銆戞帴鍙e崟娆¤繑鍥炲凡杈� 1500 鏉′笂闄愶紝鏁版嵁鍙兘琚埅鏂細cry={}锛宼ypes={}", cry, types);
+            }
             List<ServiceSLTDInhospResDTO> resultList = new ArrayList<>();
             for (Map<String, Object> dataItem : dataList) {
                 try {
diff --git a/smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskAnswerServiceImpl.java b/smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskAnswerServiceImpl.java
index aa89ed0..19130e6 100644
--- a/smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskAnswerServiceImpl.java
+++ b/smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskAnswerServiceImpl.java
@@ -276,6 +276,8 @@
     public Integer saveQuestionAnswer(ServiceSubTaskAnswerReq serviceSubTaskAnswerReq, Long flag) {
         String threadName = Thread.currentThread().getName();
         log.info("[{}] 寮�濮嬪紓姝ュ鐞嗕繚瀛橀棶鍗风瓟妗�", threadName);
+        // 骞傜瓑鍗犱綅閿細澶辫触鏃惰閲婃斁锛屽厑璁告偅鑰呴噸璇�
+        String idemKey = null;
         try {
             //鍙傛暟瑙e瘑
             Long tid = null;
@@ -299,6 +301,17 @@
             //鏍规嵁 PID銆乀ID銆丼UBID 鏋勫缓闇�瑕佸鐞嗙殑 cache key
             String scriptCacheKeyPrefix = pid + "-" + tid + "-" + subid;
             Set<String> targetKeys = new HashSet<>();
+
+            // ---------------- 骞傜瓑锛氬悓涓�浠介棶鍗� 60 绉掑唴鍙鐞嗕竴娆� ----------------
+            // 鏈柟娉曟槸 @Async 寮傛鎵ц锛屾偅鑰呯閲嶅鐐瑰嚮/缃戠粶閲嶈瘯浼氳瀹冨苟鍙戣窇澶氭锛�
+            // 姣忔閮戒細 upsert 涓�閬嶆槑缁嗭紱骞跺彂鏃跺郊姝ょ湅涓嶅埌瀵规柟杩樻病鎻愪氦鐨勮 -> 鎻掑叆閲嶅鍓湰
+            // 锛坣hfy 2026-09-08 灏辨槸杩欐牱鍫嗗嚭 2~6 浠斤紝骞朵笖鎶� del_flag 涓�璧峰啓鍧忥級銆�
+            idemKey = "subtaskAnswer:submit:" + scriptCacheKeyPrefix + ":"
+                    + (serviceSubTaskAnswerReq == null || serviceSubTaskAnswerReq.getType() == null ? "all" : serviceSubTaskAnswerReq.getType());
+            if (!redisCache.setCacheObjectIfAbsent(idemKey, "1", 60, TimeUnit.SECONDS)) {
+                log.warn("[{}] 妫�娴嬪埌閲嶅鎻愪氦锛屾湰娆″拷鐣ワ細{}", threadName, idemKey);
+                return 0;
+            }
 
             if (serviceSubTaskAnswerReq != null && serviceSubTaskAnswerReq.getType() != null) {
                 if (serviceSubTaskAnswerReq.getType() == 2) {
@@ -491,6 +504,14 @@
             return 1;
         } catch (Exception e) {
             log.error("[{}] 寮傛澶勭悊淇濆瓨闂嵎绛旀鍙戠敓寮傚父 : {},璇锋眰鐨勫璞′负锛歿}", Thread.currentThread().getName(), e.getMessage(), e, serviceSubTaskAnswerReq);
+            // 澶勭悊澶辫触鏃堕噴鏀惧箓绛夐敭锛屽厑璁告偅鑰呴噸鏂版彁浜�
+            if (idemKey != null) {
+                try {
+                    redisCache.deleteObject(idemKey);
+                } catch (Exception ignore) {
+                    log.warn("[{}] 閲婃斁骞傜瓑閿け璐ワ細{}", Thread.currentThread().getName(), idemKey);
+                }
+            }
             throw new RuntimeException("淇濆瓨闂嵎绛旀澶辫触", e);
         }
     }
@@ -728,8 +749,8 @@
                 serviceSubtask.setLibtemplateid(Long.valueOf(serviceTask.getLibtemplateid()));
                 if (CollectionUtils.isNotEmpty(patMedInhospList)) {
                     serviceSubtask.setHospType("2");
-                    serviceSubtask.setDeptname(patMedInhospList.get(0).getDeptname());
-                    serviceSubtask.setDeptcode(patMedInhospList.get(0).getDeptcode());
+                    serviceSubtask.setLeaveldeptname(patMedInhospList.get(0).getDeptname());
+                    serviceSubtask.setLeaveldeptcode(patMedInhospList.get(0).getDeptcode());
                     serviceSubtask.setLeavehospitaldistrictcode(patMedInhospList.get(0).getLeavehospitaldistrictcode());
                     serviceSubtask.setLeavehospitaldistrictname(patMedInhospList.get(0).getLeavehospitaldistrictname());
                     serviceSubtask.setDrname(patMedInhospList.get(0).getDrname());
@@ -743,8 +764,8 @@
                     serviceSubtask.setHospType("1");
                     serviceSubtask.setAdmindate(patMedOuthosps.get(0).getAdmitdate());
                     serviceSubtask.setHospno(patMedOuthosps.get(0).getOuthospno());
-                    serviceSubtask.setDeptname(patMedOuthosps.get(0).getDeptname());
-                    serviceSubtask.setDeptcode(patMedOuthosps.get(0).getDeptcode());
+                    serviceSubtask.setLeaveldeptname(patMedOuthosps.get(0).getDeptname());
+                    serviceSubtask.setLeaveldeptcode(patMedOuthosps.get(0).getDeptcode());
                     serviceSubtask.setDrname(patMedOuthosps.get(0).getDrname());
                     serviceSubtask.setDrcode(patMedOuthosps.get(0).getDrcode());
                     serviceSubtask.setCampusid(patMedOuthosps.get(0).getCampusid());
@@ -766,7 +787,7 @@
                 }
                 if (StringUtils.isNotEmpty(dealDept)) {
                     //鎶曡瘔寤鸿鐨勫鐞嗛儴闂�
-                    serviceSubtask.setDeptcode(dealDept);
+                    serviceSubtask.setLeaveldeptcode(dealDept);
                     serviceSubtask.setServiceType("15");
                 }
                 serviceSubtask.setSubmit(1L);
@@ -1025,6 +1046,11 @@
 
     /**
      * 鎵归噺鏌ヨ宸插瓨鍦ㄧ殑鏄庣粏璁板綍ID锛屾寜scriptid鍒嗙粍锛堥伩鍏嶅惊鐜腑閫愭潯鏌ヨ锛�
+     * <p>
+     * 鈿狅笍 2026-10-21锛�<b>涓嶅啀杩囨护 del_flag</b>锛屽悓涓� scriptid 鍙� id 鏈�澶э紙鏈�鏂帮級鐨勯偅涓�琛屻��
+     * 鍘熸潵鍙 del_flag=0锛屾槑缁嗚閫昏緫鍒犻櫎鍚庡氨鏌ヤ笉鍒� 鈫� 涓嬩竴娆′繚瀛樺繀鐒� INSERT 鏂板壇鏈紝
+     * 鍚屼竴鎮h�呭悓涓�棰樹細鍫嗗嚭 2~6 鏉¢噸澶嶆槑缁嗭紙nhfy 2026-09-08锛夈��
+     * 鍛戒腑琚垹鍓湰鏃剁敱璋冪敤鏂瑰啀璋� {@code reviveServiceSubtaskDetail} 缃洖 '0'銆�
      */
     private Map<Long, Long> getExistingDetailIdMap(Long subid) {
         if (subid == null) return Collections.emptyMap();
@@ -1034,7 +1060,9 @@
         if (CollectionUtils.isEmpty(details)) return Collections.emptyMap();
         Map<Long, Long> map = new HashMap<>();
         for (ServiceSubtaskDetail d : details) {
-            if ((d.getDelFlag() == null || "0".equals(d.getDelFlag())) && d.getScriptid() != null && !map.containsKey(d.getScriptid())) {
+            if (d.getScriptid() == null || d.getId() == null) continue;
+            Long existId = map.get(d.getScriptid());
+            if (existId == null || d.getId() > existId) {
                 map.put(d.getScriptid(), d.getId());
             }
         }
@@ -1131,6 +1159,8 @@
             serviceSubtaskDetail.setId(existDetailId);
             serviceSubtaskDetail.setUpdateTime(new Date());
             serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail);
+            //鍛戒腑鍘嗗彶琚�昏緫鍒犻櫎鐨勫壇鏈椂缃洖 del_flag='0'锛堝惁鍒欑瓟妗堝啓杩涘幓浜嗗嵈鏌ヤ笉鍒帮紝涓斾笅娆″張浼氭柊澧炲壇鏈級
+            serviceSubtaskDetailMapper.reviveServiceSubtaskDetail(existDetailId);
         } else {
             serviceSubtaskDetailMapper.insertServiceSubtaskDetail(serviceSubtaskDetail);
         }
@@ -1430,6 +1460,8 @@
             serviceSubtaskDetail.setId(existServiceSubtaskDetail.getId());
             serviceSubtaskDetail.setUpdateTime(new Date());
             serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail);
+            //鍛戒腑鍘嗗彶琚�昏緫鍒犻櫎鐨勫壇鏈椂缃洖 del_flag='0'锛岄伩鍏嶉噸澶嶅壇鏈�
+            serviceSubtaskDetailMapper.reviveServiceSubtaskDetail(existServiceSubtaskDetail.getId());
         } else {
             serviceSubtaskDetailMapper.insertServiceSubtaskDetail(serviceSubtaskDetail);
         }
diff --git a/smartor/src/main/java/com/smartor/service/impl/SvyTaskSingleServiceImpl.java b/smartor/src/main/java/com/smartor/service/impl/SvyTaskSingleServiceImpl.java
index ccb8e75..bfd0b92 100644
--- a/smartor/src/main/java/com/smartor/service/impl/SvyTaskSingleServiceImpl.java
+++ b/smartor/src/main/java/com/smartor/service/impl/SvyTaskSingleServiceImpl.java
@@ -216,7 +216,7 @@
                 patTaskRelevance.setSfzh(serviceSubtask1.getSfzh());
                 patTaskRelevance.setPhone(serviceSubtask1.getPhone());
                 patTaskRelevance.setAddr(serviceSubtask1.getAddr());
-                patTaskRelevance.setDeptName(serviceSubtask1.getDeptname());
+                patTaskRelevance.setDeptName(serviceSubtask1.getLeaveldeptname());
                 patTaskRelevance.setBedNo(serviceSubtask1.getBedNo());
                 patTaskRelevance.setDiagname(serviceSubtask1.getLeavediagname());
                 patTaskRelevance.setPatid(serviceSubtask1.getPatid());
@@ -286,8 +286,8 @@
         serviceSubtask.setAdmindate(serviceTaskVO.getVisittime());
         serviceSubtask.setRoomno(serviceTaskVO.getRoomno());
         serviceSubtask.setBedNo(serviceTaskVO.getBedno());
-        serviceSubtask.setDeptname(serviceTaskVO.getDeptname());
-        serviceSubtask.setDeptcode(serviceTaskVO.getDeptcode());
+        serviceSubtask.setLeaveldeptname(serviceTaskVO.getDeptname());
+        serviceSubtask.setLeaveldeptcode(serviceTaskVO.getDeptcode());
         serviceSubtask.setSendstate(6L);
         serviceSubtask.setVisitTime(serviceTaskVO.getVisittime());
         serviceSubtask.setCreateTime(new Date());

--
Gitblit v1.9.3