From 15defa991fcd30b9fa60bab17d2230b5929bf2a2 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期一, 14 九月 2026 17:20:20 +0800
Subject: [PATCH] update

---
 backend/src/main/java/com/tourguide/modules/user/service/GuideAutoDisableService.java |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/backend/src/main/java/com/tourguide/modules/user/service/GuideAutoDisableService.java b/backend/src/main/java/com/tourguide/modules/user/service/GuideAutoDisableService.java
index 3d850e7..3b6260b 100644
--- a/backend/src/main/java/com/tourguide/modules/user/service/GuideAutoDisableService.java
+++ b/backend/src/main/java/com/tourguide/modules/user/service/GuideAutoDisableService.java
@@ -18,6 +18,7 @@
 
 import java.math.BigDecimal;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 @Service
@@ -46,20 +47,51 @@
     @Scheduled(fixedDelayString = "${tourguide.guide.auto-disable-scan-delay-millis:60000}")
     @Transactional
     public void disableEligibleGuides() {
+        synchronizeGuideStatuses();
+    }
+
+    @Transactional
+    public void synchronizeGuideStatuses() {
         GuideAutoDisableConfig config = configMapper.selectById(1);
         if (!valid(config)) return;
+        restoreGuidesNoLongerEligible(config);
+
+        Long lastGuideId = null;
+        do {
+            List<GuideUser> candidates = selectCandidates(config, lastGuideId);
+            if (candidates.isEmpty()) return;
+            for (GuideUser guide : candidates) {
+                disableIfEligible(guide, config);
+            }
+            lastGuideId = candidates.get(candidates.size() - 1).getId();
+            if (candidates.size() < BATCH_SIZE) return;
+        } while (true);
+    }
+
+    /** 导游移出白名单后立即复核,避免等待下一次定时扫描。 */
+    @Transactional
+    public void disableGuideIfEligible(Long guideId) {
+        if (guideId == null) return;
+        GuideAutoDisableConfig config = configMapper.selectById(1);
+        if (!valid(config)) return;
+        GuideUser guide = guideUserMapper.selectById(guideId);
+        if (!matchesRule(guide, config)) return;
+        disableIfEligible(guide, config);
+    }
+
+    private List<GuideUser> selectCandidates(GuideAutoDisableConfig config, Long lastGuideId) {
         List<GuideUser> candidates = guideUserMapper.selectList(
                 new LambdaQueryWrapper<GuideUser>()
                         .eq(GuideUser::getStatus, GuideUserService.STATUS_ENABLED)
-                        .eq(GuideUser::getAutoDisableWhitelisted, 0)
+                        .and(wrapper -> wrapper.isNull(GuideUser::getAutoDisableWhitelisted)
+                                .or().eq(GuideUser::getAutoDisableWhitelisted, 0))
                         .ge(GuideUser::getAcceptedOrderCount, config.getOrderThreshold())
                         .gt(GuideUser::getRating, BigDecimal.ZERO)
                         .le(GuideUser::getRating, config.getRatingThreshold())
+                        .gt(lastGuideId != null, GuideUser::getId, lastGuideId)
                         .orderByAsc(GuideUser::getId)
                         .last("LIMIT " + BATCH_SIZE));
-        for (GuideUser guide : candidates) {
-            disableIfEligible(guide, config);
-        }
+        return candidates == null ? Collections.emptyList() : candidates;
     }
 
     void disableIfEligible(GuideUser guide, GuideAutoDisableConfig config) {
@@ -74,6 +106,14 @@
                 guide.getId(), guide.getAcceptedOrderCount(), guide.getRating());
     }
 
+    private void restoreGuidesNoLongerEligible(GuideAutoDisableConfig config) {
+        int restored = guideUserMapper.restoreAutoDisabledGuidesNoLongerEligible(
+                config.getOrderThreshold(), config.getRatingThreshold());
+        if (restored > 0) {
+            log.info("Restored automatically disabled guides after rule reconciliation, count={}", restored);
+        }
+    }
+
     private boolean hasActiveServiceOrder(Long guideId) {
         return orderMapper.selectCount(new LambdaQueryWrapper<TourOrder>()
                 .eq(TourOrder::getGuideId, guideId)
@@ -81,6 +121,17 @@
                         OrderStatus.PENDING_MEETING.getCode(), OrderStatus.IN_SERVICE.getCode()))) > 0;
     }
 
+    private boolean matchesRule(GuideUser guide, GuideAutoDisableConfig config) {
+        return guide != null
+                && Integer.valueOf(GuideUserService.STATUS_ENABLED).equals(guide.getStatus())
+                && !Integer.valueOf(1).equals(guide.getAutoDisableWhitelisted())
+                && guide.getAcceptedOrderCount() != null
+                && guide.getAcceptedOrderCount() >= config.getOrderThreshold()
+                && guide.getRating() != null
+                && guide.getRating().compareTo(BigDecimal.ZERO) > 0
+                && guide.getRating().compareTo(config.getRatingThreshold()) <= 0;
+    }
+
     private boolean valid(GuideAutoDisableConfig config) {
         return config != null
                 && config.getOrderThreshold() != null && config.getOrderThreshold() > 0

--
Gitblit v1.7.1