From 0b39edb68acc67ed01fbfe5d31bfa776a1b17de1 Mon Sep 17 00:00:00 2001
From: zxl <763096477@qq.com>
Date: 星期三, 25 三月 2026 09:14:53 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/show-demo' into show_demo

---
 jyz-base-start/src/main/java/com/tievd/jyz/Timer/SystemSchedule.java |  130 +++++++++++++++++++++++++++++++++++++------
 1 files changed, 111 insertions(+), 19 deletions(-)

diff --git a/jyz-base-start/src/main/java/com/tievd/jyz/Timer/SystemSchedule.java b/jyz-base-start/src/main/java/com/tievd/jyz/Timer/SystemSchedule.java
index 882d65e..46d93a7 100644
--- a/jyz-base-start/src/main/java/com/tievd/jyz/Timer/SystemSchedule.java
+++ b/jyz-base-start/src/main/java/com/tievd/jyz/Timer/SystemSchedule.java
@@ -279,7 +279,13 @@
          */
         public String infer() {
             try {
+                if (CollectionUtils.isEmpty(rules.getClientConfigs())) {
+                    return null;
+                }
                 for (ClientConfig rule : rules.getClientConfigs()) {
+                    if (rule == null || rule.getTimeValue() == null || StringUtils.isBlank(rule.getTimeUnit())) {
+                        return null;
+                    }
                     ChronoUnit unit = ChronoUnit.valueOf(rule.getTimeUnit().toUpperCase());
                     LocalDate timeLimit = LocalDate.now().minus(rule.getTimeValue(), unit);
                     switch(unit) {
@@ -288,30 +294,53 @@
                     }
                     LocalDate finalTimeLimit = timeLimit;
                     List<T> filterData = dataList.stream().filter(t -> !timeVal.apply(t).isBefore(finalTimeLimit)).collect(Collectors.toList());
-                    int limit = rule.getCountNum();
-                    int ref = rule.getCountRef();
-                    if (rule.getCountType() == 1) {
-                        int sum = filterData.size();
-                        if (Integer.compare(sum, limit) != ref) {
+                    
+                    // 鏍规嵁瑙勫垯绫诲瀷閫夋嫨鍒ゆ柇閫昏緫
+                    Byte ruleType = rule.getRuleType();
+                    if (ruleType == null) {
+                        return null;
+                    }
+                    if (ruleType == 1) {
+                        if (rule.getCountType() == null || rule.getCountRef() == null || rule.getCountNum() == null) {
                             return null;
                         }
-                    } else if((rule.getCountType() == 2)) {
-                        Map<Integer, Integer> monthCount = new HashMap<>();
-                        int nowMonth = LocalDate.now().getMonthValue();
-                        for (int month = timeLimit.getMonthValue(); month != nowMonth ; month++) {
-                            monthCount.put(month, 0);
-                        }
-                        for (T tmp : filterData) {
-                            int month = timeVal.apply(tmp).getMonthValue();
-                            if (monthCount.containsKey(month)) {
-                                monthCount.put(month, monthCount.get(month) + 1);
+                        // 鍔犳补棰戞锛堝師鏈夐�昏緫锛�
+                        int limit = rule.getCountNum();
+                        int ref = rule.getCountRef();
+                        if (rule.getCountType() == 1) {
+                            int sum = filterData.size();
+                            if (Integer.compare(sum, limit) != ref) {
+                                return null;
                             }
-                        }
-                        Collection<Integer> countNums = monthCount.values();
-                        if (countNums.stream().anyMatch(n -> Integer.compare(n, limit) != ref)) {
+                        } else if((rule.getCountType() == 2)) {
+                            Map<Integer, Integer> monthCount = new HashMap<>();
+                            int nowMonth = LocalDate.now().getMonthValue();
+                            for (int month = timeLimit.getMonthValue(); month != nowMonth ; month++) {
+                                monthCount.put(month, 0);
+                            }
+                            for (T tmp : filterData) {
+                                int month = timeVal.apply(tmp).getMonthValue();
+                                if (monthCount.containsKey(month)) {
+                                    monthCount.put(month, monthCount.get(month) + 1);
+                                }
+                            }
+                            Collection<Integer> countNums = monthCount.values();
+                            if (countNums.stream().anyMatch(n -> Integer.compare(n, limit) != ref)) {
+                                return null;
+                            }
+                        } else {
                             return null;
                         }
-                        /////////////////////////////
+                    } else if (ruleType == 2) {
+                        // 鍔犳补瓒嬪娍锛堟柊閫昏緫锛�
+                        if (rule.getCountTrend() == null || rule.getCountNum() == null || rule.getHistoryMonths() == null || rule.getRecentMonths() == null) {
+                            return null;
+                        }
+                        if (!checkTrend(rule, filterData)) {
+                            return null;
+                        }
+                    } else {
+                        return null;
                     }
                 }
             } catch (Exception e) {
@@ -321,6 +350,69 @@
             return rules.getClientName();
         }
         
+        /**
+         * 瓒嬪娍鍒ゆ柇锛堜娇鐢ㄩ厤缃殑鏈堟暟锛�
+         * @param rule 瑙勫垯
+         * @param dataList 鏁版嵁鍒楄〃
+         * @return
+         */
+        private boolean checkTrend(ClientConfig rule, List<T> dataList) {
+            if (dataList == null || dataList.isEmpty()) {
+                return false;
+            }
+            
+            Byte countTrend = rule.getCountTrend();
+            Integer countNum = rule.getCountNum();
+            Integer historyMonths = rule.getHistoryMonths();
+            Integer recentMonths = rule.getRecentMonths();
+            if (countTrend == null || countNum == null || historyMonths == null || recentMonths == null) {
+                return false;
+            }
+            if (historyMonths <= 0 || recentMonths <= 0 || countNum <= 0) {
+                return false;
+            }
+            
+            LocalDate now = LocalDate.now();
+            LocalDate currentMonth = now.withDayOfMonth(1);
+            LocalDate recentStart = currentMonth.minusMonths(recentMonths - 1L);
+            LocalDate historyStart = recentStart.minusMonths(historyMonths);
+            LocalDate historyEnd = recentStart;
+            
+            Map<LocalDate, Integer> recentMonthCount = new LinkedHashMap<>();
+            for (int i = 0; i < recentMonths; i++) {
+                LocalDate month = recentStart.plusMonths(i);
+                recentMonthCount.put(month, 0);
+            }
+
+            Map<LocalDate, Integer> historyMonthCount = new LinkedHashMap<>();
+            for (int i = 0; i < historyMonths; i++) {
+                LocalDate month = historyStart.plusMonths(i);
+                historyMonthCount.put(month, 0);
+            }
+
+            for (T tmp : dataList) {
+                LocalDate month = timeVal.apply(tmp).withDayOfMonth(1);
+                if (recentMonthCount.containsKey(month)) {
+                    recentMonthCount.put(month, recentMonthCount.get(month) + 1);
+                }
+                if (historyMonthCount.containsKey(month) && !month.isBefore(historyStart) && month.isBefore(historyEnd)) {
+                    historyMonthCount.put(month, historyMonthCount.get(month) + 1);
+                }
+            }
+            
+            if (countTrend == 1) {
+                boolean historyStable = historyMonthCount.values().stream().allMatch(n -> n >= countNum);
+                boolean recentStable = recentMonthCount.values().stream().allMatch(n -> n >= countNum);
+                return historyStable && recentStable;
+            } else if (countTrend == 2) {
+                boolean historyStable = historyMonthCount.values().stream().allMatch(n -> n >= countNum);
+                boolean recentDecrease = recentMonthCount.values().stream().allMatch(n -> n < countNum);
+                return historyStable && recentDecrease;
+            }
+            
+            return false;
+        }
+        
     }
     
 }

--
Gitblit v1.8.0