From 599beddc80e7e50b2099bacdbf7df2d89df00ef2 Mon Sep 17 00:00:00 2001
From: 陈昶聿 <chychen@nbjetron.com>
Date: 星期六, 07 十一月 2026 14:42:31 +0800
Subject: [PATCH] fix: 完成时状态与超时判断区分任务组

---
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java           |   74 ++++++++++++++++--
 ruoyi-admin/src/main/java/com/ruoyi/web/component/RedisMqReceiver.java |   74 ++++++++++++++++--
 ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml     |   73 ++++++++++-------
 3 files changed, 170 insertions(+), 51 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 5ddc7ab..e889ed6 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
@@ -44,8 +44,12 @@
 import com.ruoyi.task.domain.ServiceSubtask;
 import com.ruoyi.task.domain.ServiceSubtaskRecord;
 import com.ruoyi.task.domain.ServiceTask;
+import com.ruoyi.task.domain.ServiceTaskSchedule;
+import com.ruoyi.task.domain.ServiceTaskScheduleDetail;
 import com.ruoyi.task.mapper.ServiceSubtaskMapper;
 import com.ruoyi.task.mapper.ServiceTaskMapper;
+import com.ruoyi.task.mapper.ServiceTaskScheduleMapper;
+import com.ruoyi.task.mapper.ServiceTaskScheduleDetailMapper;
 import com.ruoyi.task.domain.ServiceOutPath;
 import com.ruoyi.task.service.IServiceOutPathService;
 import com.ruoyi.task.domain.ServiceSubtaskPreachform;
@@ -110,6 +114,12 @@
 
     @Autowired
     private ServiceSubtaskPreachformMapper serviceSubtaskPreachformMapper;
+
+    @Autowired
+    private ServiceTaskScheduleMapper serviceTaskScheduleMapper;
+
+    @Autowired
+    private ServiceTaskScheduleDetailMapper serviceTaskScheduleDetailMapper;
 
     @Autowired
     private IServiceSubtaskRecordService serviceSubtaskRecordService;
@@ -1033,21 +1043,65 @@
         if (Objects.isNull(serviceSubtask) || CollectionUtils.isEmpty(serviceSubtaskPreachforms)) {
             return false;
         }
-        // 鍩哄噯鏃跺埢锛氬嚭闄㈡椂闂� + 鍙戦�佹棩锛坰endDay 缂虹渷鎸� 1锛夛紝骞跺厹搴曢伩鍏� NPE/鑴忔暟鎹�
-        if (serviceSubtask.getEndtime() == null) {
-            log.warn("銆恑sSubtaskDeadline銆憇ubid锛歿} endtime涓虹┖锛屾棤娉曡绠楄秴鏃讹紝鎸夋湭瓒呮椂澶勭悊", serviceSubtask.getId());
-            return false;
-        }
         ServiceTask serviceTask = serviceTaskMapper.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
-        int sendDay = serviceTask != null && serviceTask.getSendDay() != null ? serviceTask.getSendDay().intValue() : 1;
-        Date deadline = DateUtils.addDays(serviceSubtask.getEndtime(), sendDay);
-        int sumCompensateTime = CollectionUtils.isEmpty(serviceSubtaskPreachforms) ? 0 : serviceSubtaskPreachforms.stream()
+        Date deadline;
+        if (serviceTask != null && "5".equals(serviceTask.getAppltype())) {
+            // 浠诲姟缁勶細鍩哄噯 = schedule_benchmark 瑙f瀽鍑虹殑鏃堕棿 + day_offset锛屼笉鍙犲姞 send_day
+            deadline = resolveTaskGroupDeadlineBase(serviceSubtask);
+            if (deadline == null) {
+                log.warn("銆恑sSubtaskDeadline銆憇ubid锛歿} 浠诲姟缁勫熀鍑嗘椂闂翠负绌猴紝鏃犳硶璁$畻瓒呮椂锛屾寜鏈秴鏃跺鐞�", serviceSubtask.getId());
+                return false;
+            }
+        } else {
+            // 闈炰换鍔$粍锛氬熀鍑� = 鍑洪櫌鏃堕棿 + 鍙戦�佹棩锛坰endDay 缂虹渷鎸� 1锛�
+            if (serviceSubtask.getEndtime() == null) {
+                log.warn("銆恑sSubtaskDeadline銆憇ubid锛歿} endtime涓虹┖锛屾棤娉曡绠楄秴鏃讹紝鎸夋湭瓒呮椂澶勭悊", serviceSubtask.getId());
+                return false;
+            }
+            int sendDay = serviceTask != null && serviceTask.getSendDay() != null ? serviceTask.getSendDay().intValue() : 1;
+            deadline = DateUtils.addDays(serviceSubtask.getEndtime(), sendDay);
+        }
+        int sumCompensateTime = serviceSubtaskPreachforms.stream()
                 .mapToInt(x -> NumberUtils.toInt(x.getCompensateTime(), 0))
                 .sum();
         sumCompensateTime = sumCompensateTime + 1;
-        // 鍙ˉ鍋挎渶鍚庝竴姝ヨ嚜韬殑琛ュ伩鏃堕棿锛堝ぉ锛夛紝鑴忓�间竴寰嬫寜 0 鍏滃簳
+        // 琛ュ伩鏃堕棿鑴忓�间竴寰嬫寜 0 鍏滃簳锛屾渶鍚庡啀鍔� 1 澶╁闄�
         deadline = DateUtils.addDays(deadline, sumCompensateTime);
-        // 鍑洪櫌(鍙戦��)鏃堕棿 + 鏈琛ュ伩鏃堕棿 灏忎簬褰撳墠鏃堕棿 -> 瓒呮椂
         return deadline.getTime() < new Date().getTime();
     }
+
+    /**
+     * 浠诲姟缁勫熀鍑嗘椂闂达細鎸� schedule_benchmark 瑙f瀽鍚庡姞 day_offset銆�
+     * 0/鍏跺畠-鑷畾涔夋椂闂� 1-鍏ラ櫌 2-鍑洪櫌 3-灏辫瘖 4-鍏ョ粍
+     */
+    private Date resolveTaskGroupDeadlineBase(ServiceSubtask serviceSubtask) {
+        if (serviceSubtask.getScheduleId() == null || serviceSubtask.getScheduleDetailId() == null) {
+            return null;
+        }
+        ServiceTaskSchedule schedule = serviceTaskScheduleMapper.selectServiceTaskScheduleById(serviceSubtask.getScheduleId());
+        ServiceTaskScheduleDetail detail = serviceTaskScheduleDetailMapper.selectServiceTaskScheduleDetailById(serviceSubtask.getScheduleDetailId());
+        if (schedule == null || detail == null || detail.getDayOffset() == null) {
+            return null;
+        }
+        Date base;
+        Integer benchmark = schedule.getScheduleBenchmark() == null ? 0 : schedule.getScheduleBenchmark();
+        switch (benchmark) {
+            case 1:
+                base = serviceSubtask.getStarttime();
+                break;
+            case 2:
+                base = serviceSubtask.getEndtime();
+                break;
+            case 3:
+                base = serviceSubtask.getAdmindate();
+                break;
+            case 4:
+                base = serviceSubtask.getCreateTime();
+                break;
+            default:
+                base = schedule.getScheduleBenchmarkCustomTime();
+                break;
+        }
+        return base == null ? null : DateUtils.addDays(base, detail.getDayOffset());
+    }
 }
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 faec1e6..c1ee902 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
@@ -69,8 +69,12 @@
 import com.ruoyi.task.domain.ServiceSubtask;
 import com.ruoyi.task.domain.ServiceSubtaskRecord;
 import com.ruoyi.task.domain.ServiceTask;
+import com.ruoyi.task.domain.ServiceTaskSchedule;
+import com.ruoyi.task.domain.ServiceTaskScheduleDetail;
 import com.ruoyi.task.mapper.ServiceSubtaskMapper;
 import com.ruoyi.task.mapper.ServiceTaskMapper;
+import com.ruoyi.task.mapper.ServiceTaskScheduleMapper;
+import com.ruoyi.task.mapper.ServiceTaskScheduleDetailMapper;
 import com.ruoyi.task.domain.ServiceSubtaskDetailTrace;
 import com.ruoyi.task.domain.VO.ServiceSubtaskDetailTraceVO;
 import com.ruoyi.task.service.IServiceSubtaskDetailTraceService;
@@ -167,6 +171,12 @@
 
     @Autowired
     private ServiceSubtaskMapper serviceSubtaskMapper;
+
+    @Autowired
+    private ServiceTaskScheduleMapper serviceTaskScheduleMapper;
+
+    @Autowired
+    private ServiceTaskScheduleDetailMapper serviceTaskScheduleDetailMapper;
 
     @Autowired
     private RedisCache redisCache;
@@ -2052,25 +2062,69 @@
         if (Objects.isNull(serviceSubtask) || CollectionUtils.isEmpty(serviceSubtaskPreachforms)) {
             return false;
         }
-        // 鍩哄噯鏃跺埢锛氬嚭闄㈡椂闂� + 鍙戦�佹棩锛坰endDay 缂虹渷鎸� 1锛夛紝骞跺厹搴曢伩鍏� NPE/鑴忔暟鎹�
-        if (serviceSubtask.getEndtime() == null) {
-            log.warn("銆恑sSubtaskDeadline銆憇ubid锛歿} endtime涓虹┖锛屾棤娉曡绠楄秴鏃讹紝鎸夋湭瓒呮椂澶勭悊", serviceSubtask.getId());
-            return false;
-        }
         ServiceTask serviceTask = serviceTaskMapper.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
-        int sendDay = serviceTask != null && serviceTask.getSendDay() != null ? serviceTask.getSendDay().intValue() : 1;
-        Date deadline = DateUtils.addDays(serviceSubtask.getEndtime(), sendDay);
-        int sumCompensateTime = CollectionUtils.isEmpty(serviceSubtaskPreachforms) ? 0 : serviceSubtaskPreachforms.stream()
+        Date deadline;
+        if (serviceTask != null && "5".equals(serviceTask.getAppltype())) {
+            // 浠诲姟缁勶細鍩哄噯 = schedule_benchmark 瑙f瀽鍑虹殑鏃堕棿 + day_offset锛屼笉鍙犲姞 send_day
+            deadline = resolveTaskGroupDeadlineBase(serviceSubtask);
+            if (deadline == null) {
+                log.warn("銆恑sSubtaskDeadline銆憇ubid锛歿} 浠诲姟缁勫熀鍑嗘椂闂翠负绌猴紝鏃犳硶璁$畻瓒呮椂锛屾寜鏈秴鏃跺鐞�", serviceSubtask.getId());
+                return false;
+            }
+        } else {
+            // 闈炰换鍔$粍锛氬熀鍑� = 鍑洪櫌鏃堕棿 + 鍙戦�佹棩锛坰endDay 缂虹渷鎸� 1锛�
+            if (serviceSubtask.getEndtime() == null) {
+                log.warn("銆恑sSubtaskDeadline銆憇ubid锛歿} endtime涓虹┖锛屾棤娉曡绠楄秴鏃讹紝鎸夋湭瓒呮椂澶勭悊", serviceSubtask.getId());
+                return false;
+            }
+            int sendDay = serviceTask != null && serviceTask.getSendDay() != null ? serviceTask.getSendDay().intValue() : 1;
+            deadline = DateUtils.addDays(serviceSubtask.getEndtime(), sendDay);
+        }
+        int sumCompensateTime = serviceSubtaskPreachforms.stream()
                 .mapToInt(x -> NumberUtils.toInt(x.getCompensateTime(), 0))
                 .sum();
         sumCompensateTime = sumCompensateTime + 1;
-        // 鍙ˉ鍋挎渶鍚庝竴姝ヨ嚜韬殑琛ュ伩鏃堕棿锛堝ぉ锛夛紝鑴忓�间竴寰嬫寜 0 鍏滃簳
+        // 琛ュ伩鏃堕棿鑴忓�间竴寰嬫寜 0 鍏滃簳锛屾渶鍚庡啀鍔� 1 澶╁闄�
         deadline = DateUtils.addDays(deadline, sumCompensateTime);
-        // 鍑洪櫌(鍙戦��)鏃堕棿 + 鏈琛ュ伩鏃堕棿 灏忎簬褰撳墠鏃堕棿 -> 瓒呮椂
         return deadline.getTime() < new Date().getTime();
     }
 
     /**
+     * 浠诲姟缁勫熀鍑嗘椂闂达細鎸� schedule_benchmark 瑙f瀽鍚庡姞 day_offset銆�
+     * 0/鍏跺畠-鑷畾涔夋椂闂� 1-鍏ラ櫌 2-鍑洪櫌 3-灏辫瘖 4-鍏ョ粍
+     */
+    private Date resolveTaskGroupDeadlineBase(ServiceSubtask serviceSubtask) {
+        if (serviceSubtask.getScheduleId() == null || serviceSubtask.getScheduleDetailId() == null) {
+            return null;
+        }
+        ServiceTaskSchedule schedule = serviceTaskScheduleMapper.selectServiceTaskScheduleById(serviceSubtask.getScheduleId());
+        ServiceTaskScheduleDetail detail = serviceTaskScheduleDetailMapper.selectServiceTaskScheduleDetailById(serviceSubtask.getScheduleDetailId());
+        if (schedule == null || detail == null || detail.getDayOffset() == null) {
+            return null;
+        }
+        Date base;
+        Integer benchmark = schedule.getScheduleBenchmark() == null ? 0 : schedule.getScheduleBenchmark();
+        switch (benchmark) {
+            case 1:
+                base = serviceSubtask.getStarttime();
+                break;
+            case 2:
+                base = serviceSubtask.getEndtime();
+                break;
+            case 3:
+                base = serviceSubtask.getAdmindate();
+                break;
+            case 4:
+                base = serviceSubtask.getCreateTime();
+                break;
+            default:
+                base = schedule.getScheduleBenchmarkCustomTime();
+                break;
+        }
+        return base == null ? null : DateUtils.addDays(base, detail.getDayOffset());
+    }
+
+    /**
      * 澶勭悊瓒呮椂闅忚浠诲姟锛堥殢璁胯秴鏃� 鈫� 鐢熸垚"鍐嶆闅忚"锛�
      * <p>
      * 鎵弿銆屽嚭闄㈡弧 deadlineDay 澶╀粛鏈畬鎴愩�嶇殑棣栨闅忚浠诲姟锛坰endstate=7 + visit_count=1锛夛紝
diff --git a/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml b/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml
index 9b29291..789a25d 100644
--- a/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml
+++ b/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml
@@ -267,50 +267,61 @@
     </sql>
 
     <!-- 瓒呮椂瀹屾垚銆佸欢鏈熷畬鎴愰�昏緫 瀹屾垚鏃剁姸鎬�(finish_state)璁$畻锛氫粎褰撴湰娆℃洿鏂版妸 sendstate 缃负 6锛堥殢璁垮畬鎴愶級鏃朵娇鐢ㄣ��
-         鍩哄噯鎴鏃堕棿 base = endtime + send_day(缂虹渷1) + (危 service_subtask_preachform.compensate_time + 1) 澶╋紝
-         涓� RyTask/RedisMqReceiver 鐨� isSubtaskDeadline 鍙e緞淇濇寔涓�鑷达紱
+         鍩哄噯鎴鏃堕棿 base锛�
+           闈炰换鍔$粍(appltype != 5)锛歟ndtime + send_day(缂虹渷1) + (危 service_subtask_preachform.compensate_time + 1) 澶╋紱
+           浠诲姟缁�(appltype = 5)锛氭寜 schedule_benchmark 瑙f瀽鍩哄噯鏃堕棿
+                                   (1-鍏ラ櫌 2-鍑洪櫌 3-灏辫瘖 4-鍏ョ粍 0/鍏跺畠-鑷畾涔夋椂闂�)
+                                   + day_offset + (危 compensate_time + 1) 澶╋紙涓嶅彔鍔� send_day锛夛紱
+         涓� RyTask/RedisMqReceiver 鐨� isSubtaskDeadline銆乻electTimelyRateBatch 鍙e緞淇濇寔涓�鑷达紱
          delay = COALESCE(service_task.delay_finish_days, 0)锛�
          finish_time = COALESCE(鍏ュ弬 finishtime, 搴撲腑 finishtime, NOW())锛�
            finish_time <= base                                    -> 1 姝e父瀹屾垚
            delay > 0 涓� finish_time <= base + delay               -> 2 寤舵湡瀹屾垚
            鍏朵綑锛堝惈 delay 涓� 0 鎴� NULL銆佹垨宸茶秴鍑哄欢鏈熺獥鍙o級          -> 3 瓒呮椂瀹屾垚
          finishtime 涓虹┖鏃剁敤 NOW() 鍏滃簳锛屼繚璇佸畬鎴愭椂涓�瀹氬啓鍏ョ姸鎬侊紱
-         浠呭綋 endtime 涓虹┖瀵艰嚧鏃犳硶璁$畻鏃舵墠淇濇寔鍘熷�间笉瑕嗙洊銆� -->
-    <sql id="finishStateExpr">
+         base 涓虹┖锛坋ndtime / schedule / day_offset 缂哄け锛夋椂淇濇寔鍘熷�间笉瑕嗙洊銆� -->
+    <sql id="finishDeadlineExpr">
+        DATE_ADD(
         CASE
-        WHEN service_subtask.endtime IS NULL THEN finish_state
+            WHEN COALESCE(st.appltype, '') = '5' THEN
+                DATE_ADD(
+                CASE sts.schedule_benchmark
+                    WHEN 1 THEN service_subtask.starttime
+                    WHEN 2 THEN service_subtask.endtime
+                    WHEN 3 THEN service_subtask.admindate
+                    WHEN 4 THEN service_subtask.create_time
+                    ELSE sts.schedule_benchmark_custom_time
+                END,
+                INTERVAL std.day_offset DAY)
+            ELSE
+                DATE_ADD(service_subtask.endtime, INTERVAL COALESCE(st.send_day, 1) DAY)
+        END,
+        INTERVAL (COALESCE((SELECT SUM(CAST(COALESCE(NULLIF(TRIM(pf.compensate_time), ''), '0') AS SIGNED))
+        FROM service_subtask_preachform pf
+        WHERE pf.subid = service_subtask.id AND pf.del_flag = 0), 0) + 1) DAY)
+    </sql>
+
+    <sql id="finishStateExpr">
+        COALESCE((
+        SELECT
+        CASE
+        WHEN <include refid="finishDeadlineExpr"/> IS NULL THEN NULL
         WHEN COALESCE(#{finishtime,jdbcType=TIMESTAMP}, service_subtask.finishtime, NOW())
-        &lt;= DATE_ADD(
-        DATE_ADD(
-        service_subtask.endtime,
-        INTERVAL COALESCE((SELECT st.send_day FROM service_task st
-        WHERE st.taskid = service_subtask.taskid AND st.del_flag = '0' LIMIT 1), 1) DAY
-        ),
-        INTERVAL (COALESCE((SELECT SUM(CAST(COALESCE(NULLIF(TRIM(pf.compensate_time), ''), '0') AS SIGNED))
-        FROM service_subtask_preachform pf
-        WHERE pf.subid = service_subtask.id AND pf.del_flag = 0), 0) + 1) DAY
-        )
+        &lt;= <include refid="finishDeadlineExpr"/>
         THEN 1
-        WHEN COALESCE((SELECT st.delay_finish_days FROM service_task st
-        WHERE st.taskid = service_subtask.taskid AND st.del_flag = '0' LIMIT 1), 0) &gt; 0
+        WHEN COALESCE(st.delay_finish_days, 0) &gt; 0
         AND COALESCE(#{finishtime,jdbcType=TIMESTAMP}, service_subtask.finishtime, NOW())
-        &lt;= DATE_ADD(
-        DATE_ADD(
-        DATE_ADD(
-        service_subtask.endtime,
-        INTERVAL COALESCE((SELECT st.send_day FROM service_task st
-        WHERE st.taskid = service_subtask.taskid AND st.del_flag = '0' LIMIT 1), 1) DAY
-        ),
-        INTERVAL (COALESCE((SELECT SUM(CAST(COALESCE(NULLIF(TRIM(pf.compensate_time), ''), '0') AS SIGNED))
-        FROM service_subtask_preachform pf
-        WHERE pf.subid = service_subtask.id AND pf.del_flag = 0), 0) + 1) DAY
-        ),
-        INTERVAL COALESCE((SELECT st.delay_finish_days FROM service_task st
-        WHERE st.taskid = service_subtask.taskid AND st.del_flag = '0' LIMIT 1), 0) DAY
-        )
+        &lt;= DATE_ADD(<include refid="finishDeadlineExpr"/>,
+        INTERVAL COALESCE(st.delay_finish_days, 0) DAY)
         THEN 2
         ELSE 3
         END
+        FROM (SELECT 1) dummy
+        LEFT JOIN service_task st ON st.taskid = service_subtask.taskid
+        LEFT JOIN service_task_schedule sts ON sts.id = service_subtask.schedule_id
+        LEFT JOIN service_task_schedule_detail std ON std.id = service_subtask.schedule_detail_id
+        LIMIT 1
+        ), finish_state)
     </sql>
 
     <!-- 褰撳墠鎵ц鏂瑰紡锛氶娆¢殢璁� current_preachform 涓虹┖鏃讹紝鍙� preachform 鐨勭涓�涓墽琛屾柟寮忓厹搴� -->

--
Gitblit v1.9.3