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

---
 ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/service/impl/SatisfactionSubtaskServiceImpl.java |   71 +++++++++++++++++++++++++++++------
 1 files changed, 58 insertions(+), 13 deletions(-)

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 閫夐」椤哄簭涓嶅悓锛屽悓涓�閫夐」浼氭媶鎴愬琛岋級锛�

--
Gitblit v1.9.3