Bläddra i källkod

合并master 修复冲突

chenlei1231 5 månader sedan
förälder
incheckning
6bd42ff265
58 ändrade filer med 1112 tillägg och 901 borttagningar
  1. 7 11
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/constant/NumConstant.java
  2. 20 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/CommonUtil.java
  3. 40 106
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/DateUtil.java
  4. 3 6
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/EnglishAnalyzer.java
  5. 18 17
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/GeoIpUtil.java
  6. 0 172
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/ListUtil.java
  7. 50 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/controller/GTMController.java
  8. 2 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/analytics/CreatePropertyRequestDTO.java
  9. 5 1
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/analytics/GAAccountDTO.java
  10. 5 1
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/analytics/GAPropertyDTO.java
  11. 2 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/gtm/CreateContainerRequestDTO.java
  12. 5 1
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/gtm/GTMAccountDTO.java
  13. 9 2
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/gtm/GTMContainerDTO.java
  14. 40 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/gtm/GTMTagDTO.java
  15. 4 4
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/entity/GACountryReport.java
  16. 4 4
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/entity/GAPagePathReport.java
  17. 4 4
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/entity/GASourceMediumReport.java
  18. 4 4
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/entity/GoogleGTM.java
  19. 35 20
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/service/google/GAReportService.java
  20. 224 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/service/google/GTMAdminService.java
  21. 3 3
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/controller/AdwebEnquiryBlacklistController.java
  22. 10 10
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/controller/AdwebEnquiryController.java
  23. 0 7
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/controller/EnquiryController.java
  24. 5 12
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/AdwebOpenApiService.java
  25. 67 66
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/impl/AdwebEnquiryServiceImpl.java
  26. 9 7
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/impl/AdwebPublicEnquiryRuleServiceImpl.java
  27. 12 10
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/impl/AdwebSiteBlackEmailServiceImpl.java
  28. 6 4
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/impl/AdwebSiteBlackIpServiceImpl.java
  29. 11 14
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/impl/EnquiryEmailMessageServiceImpl.java
  30. 4 6
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/controller/SeoKeywordsController.java
  31. 3 6
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/controller/SeoKeywordsRankController.java
  32. 18 14
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/entity/ComprehensiveStatistics.java
  33. 0 26
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/ISearchKeywordsService.java
  34. 17 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/ISeoKeywordsRankService.java
  35. 11 20
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/dataforseo/DataForSEOService.java
  36. 0 259
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/impl/SearchKeywordsServiceImpl.java
  37. 282 12
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/impl/SeoKeywordsRankServiceImpl.java
  38. 4 5
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/impl/SeoKeywordsSerpServiceImpl.java
  39. 2 2
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/impl/SeoKeywordsServiceImpl.java
  40. 6 2
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/site/controller/AdwebSiteController.java
  41. 13 6
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/site/entity/AdwebSite.java
  42. 5 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/site/service/IAdwebSiteService.java
  43. 16 5
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/site/service/impl/AdwebSiteServiceImpl.java
  44. 6 5
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/site/service/impl/SiteUserPermissionServiceImpl.java
  45. 6 3
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/system/service/impl/MasterSubAccountRelationServiceImpl.java
  46. 7 4
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/system/service/impl/SysAdwebApiImpl.java
  47. 9 9
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/userCountry/controller/AdwebUserCountryController.java
  48. 3 3
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/userCountry/service/impl/AdwebUserCountryServiceImpl.java
  49. 11 7
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysBaseApiImpl.java
  50. 26 17
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/xxl/DataForSEOJob.java
  51. 9 2
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/xxl/GAReportJob.java
  52. 4 0
      jeecg-module-system/jeecg-system-biz/src/main/resources/google/gtm/body-snippet.tmpl
  53. 7 0
      jeecg-module-system/jeecg-system-biz/src/main/resources/google/gtm/head-snippet.tmpl
  54. 4 0
      jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml
  55. 4 0
      jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml
  56. 4 0
      jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml
  57. 25 0
      jeecg-module-system/jeecg-system-start/src/test/java/org/jeecg/modules/adweb/dmp/service/google/GoogleServiceTest.java
  58. 2 2
      jeecg-module-system/jeecg-system-start/src/test/java/org/jeecg/modules/adweb/seo/service/DataForSEOTest.java

+ 7 - 11
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/constant/NumConstant.java

@@ -28,7 +28,7 @@ public class NumConstant {
 
     public static final Integer ELEVEN = 11;
 
-    public static final Integer TWELF = 12;
+    public static final Integer TWELVE = 12;
 
     public static final Integer THIRTEEN = 13;
 
@@ -40,21 +40,17 @@ public class NumConstant {
 
     public static final Integer TWENTY = 20;
 
-    public static final Integer THRITY = 30;
+    public static final Integer THIRTY = 30;
 
-    public static final Integer CONS_50 = 50;
+    public static final Integer FIFTY = 50;
 
-    public static final Integer CONS_80 = 80;
+    public static final Integer EIGHTY = 80;
 
-    public static final Integer CONS_100 = 100;
-
-    public static final Integer CONS_443 = 443;
+    public static final Integer ONE_HUNDRED = 100;
 
     public static final Integer SIXTY = 60;
 
-    public static final Integer ONEHUNDREDTWENTY = 120;
-
-    public static final Integer HUGE = 99999;
+    public static final Integer ONE_HUNDRED_TWENTY = 120;
 
-    public static final Integer MILLION = 1000000;
+    public static final Integer ONE_MILLION = 1_000_000;
 }

+ 20 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/CommonUtil.java

@@ -1,11 +1,16 @@
 package org.jeecg.modules.adweb.common.util;
 
+import static java.util.function.Predicate.*;
+
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
 import com.google.common.net.InternetDomainName;
 
 import lombok.extern.slf4j.Slf4j;
 
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.List;
 
 /**
  * 常用工具类
@@ -31,4 +36,19 @@ public class CommonUtil {
             return InternetDomainName.from(host).topPrivateDomain().toString();
         }
     }
+
+    /**
+     * 对一个字符串进行split and trim,过滤空串,返回{@link List}
+     *
+     * @param str
+     * @param separator
+     * @return
+     */
+    public static List<String> splitAndTrim(String str, final String separator) {
+        return Splitter.on(separator)
+                .splitToStream(str)
+                .map(String::trim)
+                .filter(not(Strings::isNullOrEmpty))
+                .toList();
+    }
 }

+ 40 - 106
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/DateUtil.java

@@ -1,6 +1,6 @@
 package org.jeecg.modules.adweb.common.util;
 
-import com.xkcoding.http.util.StringUtil;
+import com.google.common.collect.ImmutableMap;
 
 import lombok.extern.slf4j.Slf4j;
 
@@ -21,65 +21,56 @@ import java.util.*;
 @Slf4j
 public class DateUtil {
 
-    /** 时间格式(yyyy-MM-dd) */
-    public static final String DATE_PATTERN = "yyyy-MM-dd";
+    /** 标准日期格式(yyyy-MM-dd) */
+    public static final String DATE_FORMAT = "yyyy-MM-dd";
 
-    /** 时间格式(yyyy-MM-dd HH:mm:ss) */
-    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+    /** 标准时间格式(yyyy-MM-dd HH:mm:ss) */
+    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
 
     /** 带时区的时间格式(yyyy-MM-dd HH:mm:ss +00:00) */
-    public static final String ZONED_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss X";
+    public static final String ZONED_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss X";
 
-    public static final String SUBJECT_DATE = "yyyy/MM/dd";
+    /** 时间格式(yyyy/MM/dd) */
+    public static final String SUBJECT_DATE_FORMAT = "yyyy/MM/dd";
 
-    public static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("Asia/Shanghai");
-
-    /** yyyy-MM-dd HH:mm:ss. */
-    public static final String DATE_FORMAT_FIVE = "yyyy-MM-dd HH:mm:ss";
-
-    /** yyyyMMdd. */
-    public static final String DATE_FORMAT_THREE = "yyyyMMdd";
+    /** 时间格式(yyyyMMdd) */
+    public static final String COMPACT_DATE_FORMAT = "yyyyMMdd";
 
-    /** yyyyMMddHHmm */
-    public static final String DATE_FORMAT = "yyyyMMddHHmmss";
-
-    public static Date plusDays(Date date, int daysToAdd) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(date);
+    /** 时间格式(yyyyMMddHHmmss) */
+    public static final String COMPACT_DATE_TIME_FORMAT = "yyyyMMddHHmmss";
 
-        calendar.add(Calendar.DAY_OF_MONTH, daysToAdd);
-        return calendar.getTime();
-    }
+    public static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("Asia/Shanghai");
 
     /**
-     * 特殊时间数据处理
+     * 根据日期类型返回日期区间
      *
-     * @param dateType 时间
+     * @param dateType 日期类型
      */
-    public static Map<String, Date> dealDateType(String dateType) {
+    public static Map<String, Date> getDateRangeByType(String dateType) {
         Date now = new Date();
         Date start = null;
         Date end = null;
-        if ("yesterday".equals(dateType)) {
-            start = getTodayZeroTime(DateUtil.addDays(now, -1));
-            end = getTodayZeroTime(now);
-        }
-        if ("today".equals(dateType)) {
-            start = getTodayZeroTime(now);
-            end = getTmrZeroTime(now);
-        }
-        if ("sevenDay".equals(dateType)) {
-            end = getTmrZeroTime(now);
-            start = addDays(end, -7);
-        }
-        if ("thirtyDay".equals(dateType)) {
-            end = getTmrZeroTime(now);
-            start = addDays(end, -30);
+
+        switch (dateType) {
+            case "yesterday":
+                start = getTodayZeroTime(DateUtil.addDays(now, -1));
+                end = getTodayZeroTime(now);
+                break;
+            case "today":
+                start = getTodayZeroTime(now);
+                end = getTmrZeroTime(now);
+                break;
+            case "sevenDay":
+                end = getTmrZeroTime(now);
+                start = addDays(end, -7);
+                break;
+            case "thirtyDay":
+                end = getTmrZeroTime(now);
+                start = addDays(end, -30);
+                break;
         }
-        Map<String, Date> map = new HashMap<>();
-        map.put("start", start);
-        map.put("end", end);
-        return map;
+
+        return ImmutableMap.of("start", start, "end", end);
     }
 
     /**
@@ -119,74 +110,17 @@ public class DateUtil {
      * 在当前日期上追加N天
      *
      * @param date 当前日期
-     * @param num 添加天数
+     * @param daysToAdd 添加天数
      * @return 日期字符串形式
      */
-    public static Date addDays(Date date, int num) {
+    public static Date addDays(Date date, int daysToAdd) {
         Calendar c = Calendar.getInstance();
         c.setTime(date);
-        c.add(Calendar.DAY_OF_MONTH, num);
+        c.add(Calendar.DAY_OF_MONTH, daysToAdd);
         return c.getTime();
     }
 
     /**
-     * 按指定格式转化字符串为Date
-     *
-     * @param strDate String
-     * @param strFormat String
-     * @return FormatDate
-     * @throws ParseException ParseException
-     */
-    public static Date getFormatDate(String strDate, String strFormat) throws ParseException {
-        if (StringUtil.isEmpty(strDate) || StringUtil.isEmpty(strFormat)) {
-            return null;
-        }
-
-        SimpleDateFormat df = new SimpleDateFormat(strFormat);
-        df.setLenient(false);
-        return df.parse(strDate);
-    }
-
-    /**
-     * 按指定格式转化Date为字符串
-     *
-     * @param date Date
-     * @param toFormat String
-     * @return FormatDate String
-     */
-    public static String dateToString(Date date, String toFormat) {
-
-        if (date == null) {
-            return "";
-        }
-
-        SimpleDateFormat df = new SimpleDateFormat(toFormat);
-        df.setLenient(false);
-        return df.format(date);
-    }
-
-    /**
-     * 转换为指定格式Date
-     *
-     * @param date String
-     * @param strFormat String
-     * @return FormatDate
-     * @throws ParseException ParseException
-     */
-    public static Date formatDate(Date date, String strFormat) {
-        if (date == null) {
-            return null;
-        }
-        Date reDate = null;
-        try {
-            reDate = getFormatDate(dateToString(date, strFormat), strFormat);
-        } catch (ParseException e) {
-            date = null;
-        }
-        return reDate;
-    }
-
-    /**
      * 计算两个Date的日期差
      *
      * @param start
@@ -207,7 +141,7 @@ public class DateUtil {
      * @param format
      * @return
      */
-    public static String formatDateStr(Date date, String format) {
+    public static String formatDate(Date date, String format) {
         SimpleDateFormat dateFormat = new SimpleDateFormat(format);
         dateFormat.setLenient(false);
         return dateFormat.format(date);

+ 3 - 6
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/EnglishAnalyzer.java

@@ -1,6 +1,6 @@
 package org.jeecg.modules.adweb.common.util;
 
-
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.TokenStream;
@@ -11,9 +11,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
-/**
- * 英文分词器
- */
+/** 英文分词器 */
 public class EnglishAnalyzer {
 
     public static List<String> analyze(String text, Analyzer analyzer) throws IOException {
@@ -39,11 +37,10 @@ public class EnglishAnalyzer {
             return 0;
         }
 
-        if(ListUtil.isEmpty(result)){
+        if (CollectionUtils.isEmpty(result)) {
             return 0;
         }
 
         return result.stream().mapToInt(String::length).max().getAsInt();
     }
-
 }

+ 18 - 17
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/GeoIpUtil.java

@@ -1,6 +1,5 @@
 package org.jeecg.modules.adweb.common.util;
 
-
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.maxmind.db.CHMCache;
 import com.maxmind.geoip2.DatabaseReader;
@@ -9,11 +8,12 @@ import com.maxmind.geoip2.model.CityResponse;
 import com.maxmind.geoip2.record.Country;
 import com.maxmind.geoip2.record.Location;
 import com.maxmind.geoip2.record.Subdivision;
+
 import org.jeecg.modules.adweb.common.dto.CountryAreaApiDto;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
+import org.springframework.stereotype.Component;
 
 import java.io.File;
 import java.io.IOException;
@@ -27,11 +27,11 @@ import java.util.TimeZone;
  * @author: Cyan
  * @time: 2019/12/16 10:33
  */
-@Service
+@Component
 public class GeoIpUtil {
 
     private static final Logger log = LoggerFactory.getLogger(GeoIpUtil.class);
-    //GEOIp数据库实例
+    // GEOIp数据库实例
     private static DatabaseReader reader = null;
 
     @Value("${geoip.static.city.mmdb}")
@@ -67,12 +67,12 @@ public class GeoIpUtil {
         CountryAreaApiDto dto = new CountryAreaApiDto();
         try {
             DatabaseReader reader = getDatabaseReader(geoipCityMmdb);
-            if(reader == null){
+            if (reader == null) {
                 return dto;
             }
             InetAddress ipAddress = InetAddress.getByName(ip);
             CityResponse response = reader.city(ipAddress);
-            //国家
+            // 国家
             Country country = response.getCountry();
             dto.setCountryZhCN(country.getNames().get("zh-CN"));
             if ("香港".equals(country.getNames().get("zh-CN"))) {
@@ -85,7 +85,7 @@ public class GeoIpUtil {
                 dto.setCountryZhCN("中国澳门");
             }
             dto.setCountryIsoCode(country.getIsoCode());
-            //省份
+            // 省份
             Subdivision subdivision = response.getMostSpecificSubdivision();
             dto.setSubdivisionIsoCode(subdivision.getIsoCode());
             dto.setSubdivisionZhCN(subdivision.getNames().get("zh-CN"));
@@ -104,6 +104,7 @@ public class GeoIpUtil {
 
     /**
      * 根据ip获取时区
+     *
      * @param ip
      * @return 时区
      * @author Cyan -- 2020/3/9 10:58
@@ -125,26 +126,26 @@ public class GeoIpUtil {
 
     /**
      * 根据ip获取当地时区时间
+     *
      * @param ip
      * @return
      * @author Cyan -- 2020/3/9 11:06
      */
-    public Date getLocalhostTime(String ip,Date date) {
-        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DATE_FORMAT_FIVE);
+    public Date getLocalhostTime(String ip, Date date) {
+        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT);
         String timeZone = getTimeZone(ip);
-        if(StringUtils.isEmpty(timeZone)){
-            timeZone = "Asia/Shanghai";
-        }
-        sdf.setTimeZone(TimeZone.getTimeZone(timeZone));
+        sdf.setTimeZone(
+                StringUtils.isNotEmpty(timeZone)
+                        ? TimeZone.getTimeZone(timeZone)
+                        : TimeZone.getTimeZone(DateUtil.DEFAULT_ZONE_ID));
+
         String dateStr = sdf.format(date);
         Date res = new Date();
         try {
-            res = DateUtil.getFormatDate(dateStr,DateUtil.DATE_FORMAT_FIVE);
-        }catch (Exception e){
+            res = DateUtil.parseDate(dateStr, DateUtil.DATE_TIME_FORMAT);
+        } catch (Exception e) {
             log.error("获取ip时区时间失败", e);
         }
         return res;
     }
-
-
 }

+ 0 - 172
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/ListUtil.java

@@ -1,172 +0,0 @@
-package org.jeecg.modules.adweb.common.util;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import org.apache.commons.lang3.StringUtils;
-import org.jeecg.modules.adweb.common.constant.NumConstant;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-
-public final class ListUtil {
-
-    /**
-     * 判断集合是否为空
-     *
-     * @param list
-     * @return
-     */
-    public static boolean isEmpty(List list) {
-        if (list != null && list.size() != 0) {
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    /**
-     * 判断集合是否不为空
-     *
-     * @param list
-     * @return
-     */
-    public static boolean notEmpty(List list) {
-        if (list != null && list.size() != 0) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * 返回集合大小
-     *
-     * @param list
-     * @return
-     */
-    public static int returnSize(List list) {
-        if (notEmpty(list)) {
-            return list.size();
-        } else {
-            return NumConstant.ZERO;
-        }
-    }
-
-    /**
-     * @param list 原集合
-     * @param str  符号
-     * @return java.lang.String
-     * @author 汤星鹏
-     * @Description 集合转字符串
-     * @date 2019/8/26 11:50
-     */
-    public static String listToString(List list, String str) {
-        if (ListUtil.notEmpty(list)) {
-            return list.stream().map(l->l.toString()).collect(Collectors.joining(str)).toString();
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * 将String类型的结合转Long类型
-     *
-     * @param list
-     * @return
-     */
-    public static List<Long> stringToLong(List<String> list) {
-
-        if (ListUtil.notEmpty(list)) {
-            List<Long> longList = new ArrayList<>();
-            list.forEach(l -> {
-                if (StringUtils.isNotBlank(l)) {
-                    longList.add(Long.parseLong(l));
-                }
-            });
-            return longList;
-        } else {
-            return new ArrayList<>();
-        }
-    }
-
-    /**
-     * @param list  集合
-     * @param index 下标
-     * @return java.lang.Object
-     * @author 汤星鹏
-     * @Description 获取对应下标对象
-     * @date 2019/11/5 9:31
-     */
-    public static <T> T listGetIndex(List<T> list, Integer index) {
-        if (ListUtil.notEmpty(list)) {
-            return list.get(index);
-        }
-        return null;
-    }
-
-    /**
-     * @param list 集合
-     * @return java.lang.Object
-     * @author 汤星鹏
-     * @Description 获取下标为o对应对象
-     * @date 2019/11/5 9:33
-     */
-    public static <T> T listGetZero(List<T> list) {
-        return listGetIndex(list, NumConstant.ZERO);
-    }
-
-    /**
-     * @param list
-     * @return java.util.List<T>
-     * @author 汤星鹏
-     * @Description 集合去重
-     * @date 2019/11/11 14:47
-     */
-    public static <T> List<T> distinct(List<T> list) {
-        if (notEmpty(list)) {
-            return list.stream().distinct().collect(Collectors.toList());
-        }
-        return null;
-    }
-
-    /**
-     * 分页函数
-     * @author pochettino
-     * @param currentPage   当前页数
-     * @param pageSize  每一页的数据条数
-     * @param list  要进行分页的数据列表
-     * @return  当前页要展示的数据
-     */
-    public static Page getPages(Integer currentPage, Integer pageSize, List list) {
-        Page page = new Page();
-        if(list==null){
-            return  null;
-        }
-        int size = list.size();
-
-        if(pageSize > size) {
-            pageSize = size;
-        }
-        if (pageSize!=0){
-            // 求出最大页数,防止currentPage越界
-            int maxPage = size % pageSize == 0 ? size / pageSize : size / pageSize + 1;
-
-            if(currentPage > maxPage) {
-                currentPage = maxPage;
-            }
-        }
-        // 当前页第一条数据的下标
-        int curIdx = currentPage > 1 ? (currentPage - 1) * pageSize : 0;
-
-        List pageList = new ArrayList();
-
-        // 将当前页的数据放进pageList
-        for(int i = 0; i < pageSize && curIdx + i < size; i++) {
-            pageList.add(list.get(curIdx + i));
-        }
-
-        page.setCurrent(currentPage).setSize(pageSize).setTotal(list.size()).setRecords(pageList);
-        return page;
-    }
-}

+ 50 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/controller/GTMController.java

@@ -0,0 +1,50 @@
+package org.jeecg.modules.adweb.dmp.controller;
+
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.modules.adweb.dmp.entity.GoogleGTM;
+import org.jeecg.modules.adweb.dmp.service.google.GTMAdminService;
+import org.jeecg.modules.adweb.site.entity.AdwebSite;
+import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Objects;
+
+/**
+ * GTM容器和标签管理
+ *
+ * @author wfansh
+ */
+@Tag(name = "Google Tag Manager")
+@RestController
+@RequestMapping("/gtm")
+@Slf4j
+public class GTMController {
+
+    @Autowired private IAdwebSiteService adwebSiteService;
+
+    @Autowired private GTMAdminService gtmAdminService;
+
+    @RequestMapping(value = "/add", method = RequestMethod.POST)
+    @ResponseBody
+    public Result<Pair<String, String>> addContainer(String siteId) {
+        AdwebSite adwebSite = adwebSiteService.getById(siteId);
+        if (Objects.isNull(adwebSite)) {
+            return Result.error("站点未找到" + siteId);
+        }
+
+        // 如果GoogleGTM表中已存在,不再创建,返回现有记录
+        GoogleGTM googleGTM =
+                gtmAdminService.createContainer(
+                        adwebSite.getCode(), adwebSite.getDomain(), adwebSite.getName());
+        return Result.ok(gtmAdminService.getSnippets(googleGTM.getGtmTagId()));
+    }
+}

+ 2 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/analytics/CreatePropertyRequestDTO.java

@@ -1,11 +1,13 @@
 package org.jeecg.modules.adweb.dmp.dto.google.analytics;
 
+import lombok.Builder;
 import lombok.Data;
 
 /**
  * @author wfansh
  */
 @Data
+@Builder
 public class CreatePropertyRequestDTO {
 
     private String accountResourceName;

+ 5 - 1
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/analytics/GAAccountDTO.java

@@ -1,5 +1,7 @@
 package org.jeecg.modules.adweb.dmp.dto.google.analytics;
 
+import com.google.common.base.Joiner;
+
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
@@ -24,6 +26,8 @@ public class GAAccountDTO extends ResourceDTO {
     private long updateTime;
 
     public static String toResourceName(String id) {
-        return StringUtils.isNumeric(id) ? "accounts" + RESOURCE_NAME_SPLITTER + id : id;
+        return StringUtils.isNumeric(id)
+                ? Joiner.on(RESOURCE_NAME_SPLITTER).join("accounts", id)
+                : id;
     }
 }

+ 5 - 1
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/analytics/GAPropertyDTO.java

@@ -1,5 +1,7 @@
 package org.jeecg.modules.adweb.dmp.dto.google.analytics;
 
+import com.google.common.base.Joiner;
+
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
@@ -42,6 +44,8 @@ public class GAPropertyDTO extends ResourceDTO {
     private List<GADataStreamDTO> dataStreams;
 
     public static String toResourceName(String id) {
-        return StringUtils.isNumeric(id) ? "properties" + RESOURCE_NAME_SPLITTER + id : id;
+        return StringUtils.isNumeric(id)
+                ? Joiner.on(RESOURCE_NAME_SPLITTER).join("properties", id)
+                : id;
     }
 }

+ 2 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/gtm/CreateContainerRequestDTO.java

@@ -1,11 +1,13 @@
 package org.jeecg.modules.adweb.dmp.dto.google.gtm;
 
+import lombok.Builder;
 import lombok.Data;
 
 /**
  * @author wfansh
  */
 @Data
+@Builder
 public class CreateContainerRequestDTO {
 
     private String accountResourceName;

+ 5 - 1
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/gtm/GTMAccountDTO.java

@@ -1,5 +1,7 @@
 package org.jeecg.modules.adweb.dmp.dto.google.gtm;
 
+import com.google.common.base.Joiner;
+
 import lombok.*;
 import lombok.experimental.SuperBuilder;
 
@@ -21,6 +23,8 @@ public class GTMAccountDTO extends ResourceDTO {
     private boolean supportMultipleContainers;
 
     public static String toResourceName(String id) {
-        return StringUtils.isNumeric(id) ? "accounts" + RESOURCE_NAME_SPLITTER + id : id;
+        return StringUtils.isNumeric(id)
+                ? Joiner.on(RESOURCE_NAME_SPLITTER).join("accounts", id)
+                : id;
     }
 }

+ 9 - 2
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/gtm/GTMContainerDTO.java

@@ -1,5 +1,7 @@
 package org.jeecg.modules.adweb.dmp.dto.google.gtm;
 
+import com.google.common.base.Joiner;
+
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
@@ -39,7 +41,12 @@ public class GTMContainerDTO extends ResourceDTO {
 
     private String fingerprint;
 
-    public static String toResourceName(String id) {
-        return StringUtils.isNumeric(id) ? "accounts" + RESOURCE_NAME_SPLITTER + id : id;
+    private List<GTMTagDTO> tags;
+
+    public static String toResourceName(String accountId, String containerId) {
+        return StringUtils.isNumeric(accountId) && StringUtils.isNumeric(containerId)
+                ? Joiner.on(RESOURCE_NAME_SPLITTER)
+                        .join("accounts", accountId, "containers", containerId)
+                : containerId;
     }
 }

+ 40 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/dto/google/gtm/GTMTagDTO.java

@@ -0,0 +1,40 @@
+package org.jeecg.modules.adweb.dmp.dto.google.gtm;
+
+import lombok.*;
+import lombok.experimental.SuperBuilder;
+
+import org.jeecg.modules.adweb.dmp.dto.google.ResourceDTO;
+
+import java.util.List;
+
+/**
+ * @author wfansh
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = true)
+public class GTMTagDTO extends ResourceDTO {
+
+    private String accountId;
+
+    private String containerId;
+
+    private String workspaceId;
+
+    private String type;
+
+    private List<TagParameter> parameters;
+
+    private List<String> firingTriggerIds;
+
+    @Data
+    public static class TagParameter {
+        private String type;
+
+        private String key;
+
+        private String value;
+    }
+}

+ 4 - 4
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/entity/GACountryReport.java

@@ -35,10 +35,10 @@ public class GACountryReport implements Serializable {
 	@TableId(type = IdType.AUTO)
     @Schema(description = "id")
     private Long id;
-	/**站点id*/
-	@Excel(name = "站点id", width = 15)
-    @Schema(description = "站点id")
-    private Integer siteId;
+    /**站点code*/
+    @Excel(name = "站点code", width = 15)
+    @Schema(description = "站点code")
+    private String siteCode;
 	/**统计时间*/
 	@Excel(name = "统计时间", width = 15, format = "yyyy-MM-dd")
 	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")

+ 4 - 4
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/entity/GAPagePathReport.java

@@ -35,10 +35,10 @@ public class GAPagePathReport implements Serializable {
 	@TableId(type = IdType.AUTO)
     @Schema(description = "id")
     private Long id;
-	/**站点id*/
-	@Excel(name = "站点id", width = 15)
-    @Schema(description = "站点id")
-    private Integer siteId;
+    /**站点code*/
+    @Excel(name = "站点code", width = 15)
+    @Schema(description = "站点code")
+    private String siteCode;
 	/**统计时间*/
 	@Excel(name = "统计时间", width = 15, format = "yyyy-MM-dd")
 	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")

+ 4 - 4
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/entity/GASourceMediumReport.java

@@ -35,10 +35,10 @@ public class GASourceMediumReport implements Serializable {
 	@TableId(type = IdType.AUTO)
     @Schema(description = "id")
     private Long id;
-	/**站点id*/
-	@Excel(name = "站点id", width = 15)
-    @Schema(description = "站点id")
-    private Integer siteId;
+    /**站点code*/
+    @Excel(name = "站点code", width = 15)
+    @Schema(description = "站点code")
+    private String siteCode;
 	/**统计时间*/
 	@Excel(name = "统计时间", width = 15, format = "yyyy-MM-dd")
 	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")

+ 4 - 4
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/entity/GoogleGTM.java

@@ -35,10 +35,10 @@ public class GoogleGTM implements Serializable {
 	@TableId(type = IdType.AUTO)
     @Schema(description = "id")
     private Integer id;
-	/**siteId*/
-	@Excel(name = "siteId", width = 15)
-    @Schema(description = "siteId")
-    private Integer siteId;
+	/**站点code*/
+	@Excel(name = "站点code", width = 15)
+    @Schema(description = "站点code")
+    private String siteCode;
 	/**uid*/
 	@Excel(name = "uid", width = 15)
     @Schema(description = "uid")

+ 35 - 20
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/service/google/GAReportService.java

@@ -3,6 +3,7 @@ package org.jeecg.modules.adweb.dmp.service.google;
 import static org.jeecg.modules.adweb.dmp.dto.google.analytics.report.ReportConstant.*;
 
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.google.common.annotations.VisibleForTesting;
 
@@ -10,6 +11,7 @@ import jakarta.annotation.PostConstruct;
 
 import lombok.extern.slf4j.Slf4j;
 
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.compress.utils.Lists;
 import org.apache.commons.lang3.reflect.TypeUtils;
 import org.jeecg.common.util.DateUtils;
@@ -34,6 +36,7 @@ import org.jeecg.modules.adweb.dmp.service.IGACountryReportService;
 import org.jeecg.modules.adweb.dmp.service.IGAPagePathReportService;
 import org.jeecg.modules.adweb.dmp.service.IGASourceMediumReportService;
 import org.jeecg.modules.adweb.dmp.service.IGoogleGTMService;
+import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.core.ParameterizedTypeReference;
@@ -70,8 +73,8 @@ public class GAReportService {
     @Value("${data-bridge.api.token}")
     private String dataBridgeApiToken;
 
+    @Autowired private IAdwebSiteService adwebSiteService;
     @Autowired private IGoogleGTMService googleGTMService;
-
     @Autowired private IGACountryReportService gaCountryReportService;
     @Autowired private IGASourceMediumReportService gaSourceMediumReportService;
     @Autowired private IGAPagePathReportService gaPagePathReportService;
@@ -85,19 +88,28 @@ public class GAReportService {
         this.restTemplate = RestTemplateUtil.getRestTemplate(60, 60, dataBridgeApiToken);
     }
 
-    /** 拉取并同步Google Analytics报表 */
-    public void syncGAReport() {
-        // TODO: 判断网站状态
-        List<GoogleGTM> googleGTMS = googleGTMService.list();
+    /**
+     * 拉取并同步Google Analytics报表
+     *
+     * @param siteCodes 待执行的网站codes,为空时执行所有网站
+     */
+    public void syncGAReport(List<String> siteCodes) {
+        if (CollectionUtils.isEmpty(siteCodes)) {
+            siteCodes = adwebSiteService.getAllActiveSiteCodes();
+        }
+
+        List<GoogleGTM> googleGTMs =
+                googleGTMService.list(
+                        new LambdaQueryWrapper<GoogleGTM>().in(GoogleGTM::getSiteCode, siteCodes));
 
-        for (GoogleGTM googleGTM : googleGTMS) {
+        for (GoogleGTM googleGTM : googleGTMs) {
             // 每个帐号同步更新三张报表
             try {
                 this.syncGACountryReport(googleGTM);
                 this.syncGASourceMediumReport(googleGTM);
                 this.syncGAPagePathReport(googleGTM);
             } catch (RuntimeException e) {
-                log.warn("同步GA报表异常, siteId = {], error = {}", googleGTM.getSiteId(), e);
+                log.warn("同步GA报表异常, siteCode = {], error = {}", googleGTM.getSiteCode(), e);
             }
         }
     }
@@ -109,7 +121,7 @@ public class GAReportService {
      */
     private void syncGACountryReport(GoogleGTM googleGTM) {
         // 1. 报表时间区间
-        Date startDate = this.getReportStartDate(TABLE_GA_COUNTRY_REPORT, googleGTM.getSiteId());
+        Date startDate = this.getReportStartDate(TABLE_GA_COUNTRY_REPORT, googleGTM.getSiteCode());
         Date endDate = new Date();
 
         // 2. 构建GA报表请求参数
@@ -132,7 +144,7 @@ public class GAReportService {
         List<GACountryReport> countryReport = Lists.newArrayList();
         for (CustomReportData reportData : reportDataList) {
             GACountryReport reportRow = new GACountryReport();
-            reportRow.setSiteId(googleGTM.getSiteId());
+            reportRow.setSiteCode(googleGTM.getSiteCode());
             reportRow.setDate(
                     DateUtils.str2Date(
                             reportData.get(ReportConstant.DIMENSION_DATE),
@@ -147,7 +159,7 @@ public class GAReportService {
         // 3. 更新数据库 - 删除旧数据,插入新数据
         gaCountryReportService.remove(
                 this.getRemoveQueryWrapper(
-                        GACountryReport.class, googleGTM.getSiteId(), startDate, endDate));
+                        GACountryReport.class, googleGTM.getSiteCode(), startDate, endDate));
 
         gaCountryReportService.saveBatch(countryReport, countryReport.size());
     }
@@ -160,7 +172,7 @@ public class GAReportService {
     private void syncGASourceMediumReport(GoogleGTM googleGTM) {
         // 1. 报表时间区间
         Date startDate =
-                this.getReportStartDate(TABLE_GA_SOURCE_MEDIUM_REPORT, googleGTM.getSiteId());
+                this.getReportStartDate(TABLE_GA_SOURCE_MEDIUM_REPORT, googleGTM.getSiteCode());
         Date endDate = new Date();
 
         // 2. 构建GA报表请求参数
@@ -192,7 +204,7 @@ public class GAReportService {
         List<GASourceMediumReport> sourceMediumReport = Lists.newArrayList();
         for (CustomReportData reportData : reportDataList) {
             GASourceMediumReport reportRow = new GASourceMediumReport();
-            reportRow.setSiteId(googleGTM.getSiteId());
+            reportRow.setSiteCode(googleGTM.getSiteCode());
             reportRow.setDate(
                     DateUtils.str2Date(
                             reportData.get(ReportConstant.DIMENSION_DATE),
@@ -217,7 +229,7 @@ public class GAReportService {
         // 3. 更新数据库 - 删除旧数据,插入新数据
         gaSourceMediumReportService.remove(
                 this.getRemoveQueryWrapper(
-                        GASourceMediumReport.class, googleGTM.getSiteId(), startDate, endDate));
+                        GASourceMediumReport.class, googleGTM.getSiteCode(), startDate, endDate));
 
         gaSourceMediumReportService.saveBatch(sourceMediumReport, sourceMediumReport.size());
     }
@@ -229,7 +241,8 @@ public class GAReportService {
      */
     private void syncGAPagePathReport(GoogleGTM googleGTM) {
         // 1. 报表时间区间
-        Date startDate = this.getReportStartDate(TABLE_GA_PAGE_PATH_REPORT, googleGTM.getSiteId());
+        Date startDate =
+                this.getReportStartDate(TABLE_GA_PAGE_PATH_REPORT, googleGTM.getSiteCode());
         Date endDate = new Date();
 
         // 2. 构建GA报表请求参数
@@ -256,7 +269,7 @@ public class GAReportService {
         List<GAPagePathReport> pagePathReport = Lists.newArrayList();
         for (CustomReportData reportData : reportDataList) {
             GAPagePathReport reportRow = new GAPagePathReport();
-            reportRow.setSiteId(googleGTM.getSiteId());
+            reportRow.setSiteCode(googleGTM.getSiteCode());
             reportRow.setDate(
                     DateUtils.str2Date(
                             reportData.get(ReportConstant.DIMENSION_DATE),
@@ -276,7 +289,7 @@ public class GAReportService {
         // 3. 更新数据库 - 删除旧数据,插入新数据
         gaPagePathReportService.remove(
                 this.getRemoveQueryWrapper(
-                        GAPagePathReport.class, googleGTM.getSiteId(), startDate, endDate));
+                        GAPagePathReport.class, googleGTM.getSiteCode(), startDate, endDate));
 
         gaPagePathReportService.saveBatch(pagePathReport, pagePathReport.size());
     }
@@ -325,8 +338,10 @@ public class GAReportService {
      *
      * <p>2. 表中最大时间减一天 - 如10月10号凌晨2点执行,最大时间可能是10号;同时9号数据GA侧有可能更新
      */
-    private Date getReportStartDate(String tableName, int siteId) {
-        Date maxDate = commonMapper.getMaxDate(tableName, "date", "site_id = " + siteId);
+    private Date getReportStartDate(String tableName, String siteCode) {
+        Date maxDate =
+                commonMapper.getMaxDate(
+                        tableName, "date", String.format("site_code = '%s'", siteCode));
         if (Objects.isNull(maxDate)) {
             // 1. 一年前
             return DateUtil.addDays(new Date(), -365);
@@ -337,9 +352,9 @@ public class GAReportService {
 
     /** 生成{@link QueryWrapper}, 删除GA报表历史数据 */
     private <T> QueryWrapper<T> getRemoveQueryWrapper(
-            Class<T> entityClass, int siteId, Date startDate, Date endDate) {
+            Class<T> entityClass, String siteCode, Date startDate, Date endDate) {
         QueryWrapper<T> queryWrapper = new QueryWrapper<>(entityClass);
-        queryWrapper.eq("site_id", siteId);
+        queryWrapper.eq("site_code", siteCode);
         queryWrapper.ge("date", startDate);
         queryWrapper.le("date", endDate);
         return queryWrapper;

+ 224 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/dmp/service/google/GTMAdminService.java

@@ -0,0 +1,224 @@
+package org.jeecg.modules.adweb.dmp.service.google;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.io.Resources;
+
+import jakarta.annotation.PostConstruct;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.jeecg.common.util.FastJsonUtil;
+import org.jeecg.modules.adweb.common.util.RestTemplateUtil;
+import org.jeecg.modules.adweb.dmp.dto.OpenAPIRequest;
+import org.jeecg.modules.adweb.dmp.dto.OpenAPIResponse;
+import org.jeecg.modules.adweb.dmp.dto.google.analytics.CreatePropertyRequestDTO;
+import org.jeecg.modules.adweb.dmp.dto.google.analytics.GAAccountDTO;
+import org.jeecg.modules.adweb.dmp.dto.google.analytics.GAPropertyDTO;
+import org.jeecg.modules.adweb.dmp.dto.google.gtm.CreateContainerRequestDTO;
+import org.jeecg.modules.adweb.dmp.dto.google.gtm.GTMAccountDTO;
+import org.jeecg.modules.adweb.dmp.dto.google.gtm.GTMContainerDTO;
+import org.jeecg.modules.adweb.dmp.entity.GoogleGTM;
+import org.jeecg.modules.adweb.dmp.service.IGoogleGTMService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * Google Tag Manager + Google Analytics帐号及标签管理
+ *
+ * <p>http://data-bridge.v3.adwebcloud.com:9002/swagger-ui/index.html
+ *
+ * @author wfansh
+ */
+@Slf4j
+@Service
+public class GTMAdminService {
+
+    private static final String GA_CREATE_PROPERTY_API_PATH = "/api/google/ga/properties/create";
+    private static final String GA_DELETE_PROPERTY_API_PATH = "/api/google/ga/properties/delete";
+    private static final String GTM_CREATE_CONTAINER_API_PATH = "/api/google/gtm/containers/create";
+    private static final String GTM_DELETE_CONTAINER_API_PATH = "/api/google/gtm/containers/delete";
+
+    @Value("${data-bridge.api.host}")
+    private String dataBridgeApiHost;
+
+    @Value("${data-bridge.api.token}")
+    private String dataBridgeApiToken;
+
+    @Value("${data-bridge.gtm.account-id}")
+    private String gtmAccountId;
+
+    @Value("${data-bridge.ga.account-id}")
+    private String gaAccountId;
+
+    @Autowired private IGoogleGTMService googleGTMService;
+
+    private RestTemplate restTemplate;
+
+    private String headSnippetTemplate;
+
+    private String bodySnippetTemplate;
+
+    @PostConstruct
+    private void init() throws IOException {
+        this.restTemplate = RestTemplateUtil.getRestTemplate(60, 60, dataBridgeApiToken);
+
+        headSnippetTemplate =
+                Resources.toString(
+                        this.getClass()
+                                .getClassLoader()
+                                .getResource("google/gtm/head-snippet.tmpl"),
+                        StandardCharsets.UTF_8);
+        bodySnippetTemplate =
+                Resources.toString(
+                        this.getClass()
+                                .getClassLoader()
+                                .getResource("google/gtm/body-snippet.tmpl"),
+                        StandardCharsets.UTF_8);
+    }
+
+    /**
+     *
+     * <li>1. 创建GTM container + GA property
+     * <li>2. 更新{@link GoogleGTM}表
+     */
+    public GoogleGTM createContainer(String siteCode, String siteUrl, String siteName) {
+        List<GoogleGTM> googleGTMs =
+                googleGTMService.list(
+                        new LambdaQueryWrapper<GoogleGTM>().eq(GoogleGTM::getSiteCode, siteCode));
+        if (CollectionUtils.isNotEmpty(googleGTMs)) {
+            log.info("站点 {} 对应的GoogleGTM已存在,ID = {}", siteCode, googleGTMs.get(0).getId());
+            return googleGTMs.get(0);
+        }
+
+        // 1. 创建GA property - 通过data-bridge API
+        OpenAPIRequest<CreatePropertyRequestDTO> createGAPropertyRequest = new OpenAPIRequest<>();
+        createGAPropertyRequest.setRequestServer(this.getClass().getSimpleName());
+        createGAPropertyRequest.setRequestTime(System.currentTimeMillis());
+        createGAPropertyRequest.setData(
+                CreatePropertyRequestDTO.builder()
+                        .accountResourceName(GAAccountDTO.toResourceName(gaAccountId))
+                        .displayName(siteName)
+                        .url(siteUrl)
+                        .build());
+        GAPropertyDTO gaProperty =
+                RestTemplateUtil.postForObject(
+                                restTemplate,
+                                dataBridgeApiHost + GA_CREATE_PROPERTY_API_PATH,
+                                createGAPropertyRequest,
+                                new ParameterizedTypeReference<OpenAPIResponse<GAPropertyDTO>>() {})
+                        .getData();
+        log.info("为站点 {} 创建GA property: {}", siteCode, FastJsonUtil.toJSONString(gaProperty));
+
+        // 2. 创建GTM container - 通过data-bridge API
+        OpenAPIRequest<CreateContainerRequestDTO> createGTMContainerRequest =
+                new OpenAPIRequest<>();
+        createGTMContainerRequest.setRequestServer(this.getClass().getSimpleName());
+        createGTMContainerRequest.setRequestTime(System.currentTimeMillis());
+        createGTMContainerRequest.setData(
+                CreateContainerRequestDTO.builder()
+                        .accountResourceName(GTMAccountDTO.toResourceName(gtmAccountId))
+                        .displayName(siteName)
+                        .googleTagId(gaProperty.getDataStreams().get(0).getStreamMeasurementId())
+                        .build());
+        GTMContainerDTO gtmContainer =
+                RestTemplateUtil.postForObject(
+                                restTemplate,
+                                dataBridgeApiHost + GTM_CREATE_CONTAINER_API_PATH,
+                                createGTMContainerRequest,
+                                new ParameterizedTypeReference<
+                                        OpenAPIResponse<GTMContainerDTO>>() {})
+                        .getData();
+        log.info("为站点 {} 创建GTM container: {}", siteCode, FastJsonUtil.toJSONString(gtmContainer));
+
+        // 3. 更新数据库
+        GoogleGTM googleGTM = new GoogleGTM();
+        googleGTM.setSiteCode(siteCode);
+        googleGTM.setUid(null); // TODO
+        googleGTM.setGtmAccountId(gtmAccountId);
+        googleGTM.setGtmContainerId(gtmContainer.getId());
+        googleGTM.setGtmTagId(gtmContainer.getPublicId());
+        googleGTM.setGaAccountId(gaAccountId);
+        googleGTM.setGaPropertyId(gaProperty.getId());
+        googleGTM.setGaVersion("V4"); // GA4 https://support.google.com/analytics/answer/10089681
+        googleGTM.setGaSiteUrl(siteUrl);
+        googleGTM.setGaTagId(gaProperty.getDataStreams().get(0).getStreamMeasurementId());
+        googleGTMService.save(googleGTM);
+
+        return googleGTM;
+    }
+
+    /**
+     * 返回GTM container的head + body snippet代码
+     *
+     * @param gtmTagId
+     * @return
+     */
+    public Pair<String, String> getSnippets(String gtmTagId) {
+        return Pair.of(
+                String.format(headSnippetTemplate, gtmTagId),
+                String.format(bodySnippetTemplate, gtmTagId));
+    }
+
+    /**
+     * 测试专用 - 删除相关资源
+     * <li>1. 删除GTM container + GA property
+     * <li>2. 删除{@link GoogleGTM}表
+     */
+    @VisibleForTesting
+    boolean deleteContainer(String siteCode) {
+        List<GoogleGTM> googleGTMs =
+                googleGTMService.list(
+                        new LambdaQueryWrapper<GoogleGTM>().eq(GoogleGTM::getSiteCode, siteCode));
+        if (CollectionUtils.isEmpty(googleGTMs)) {
+            log.info("站点 {} 对应的GoogleGTM不存在", siteCode);
+            return false;
+        }
+
+        GoogleGTM googleGTM = googleGTMs.get(0);
+
+        // 1. 删除GA property - 通过data-bridge API
+        OpenAPIRequest<String> deleteGAPropertyRequest = new OpenAPIRequest<>();
+        deleteGAPropertyRequest.setRequestServer(this.getClass().getSimpleName());
+        deleteGAPropertyRequest.setRequestTime(System.currentTimeMillis());
+        deleteGAPropertyRequest.setData(GAPropertyDTO.toResourceName(googleGTM.getGaPropertyId()));
+        String gaPropertyResourceName =
+                RestTemplateUtil.postForObject(
+                                restTemplate,
+                                dataBridgeApiHost + GA_DELETE_PROPERTY_API_PATH,
+                                deleteGAPropertyRequest,
+                                new ParameterizedTypeReference<OpenAPIResponse<String>>() {})
+                        .getData();
+        log.info("为站点 {} 删除GA property: {}", siteCode, gaPropertyResourceName);
+
+        // 2. 删除GTM container - 通过data-bridge API
+        OpenAPIRequest<String> deleteGTMContainerRequest = new OpenAPIRequest<>();
+        deleteGTMContainerRequest.setRequestServer(this.getClass().getSimpleName());
+        deleteGTMContainerRequest.setRequestTime(System.currentTimeMillis());
+        deleteGTMContainerRequest.setData(
+                GTMContainerDTO.toResourceName(
+                        googleGTM.getGtmAccountId(), googleGTM.getGtmContainerId()));
+        String gtmContainerResourceName =
+                RestTemplateUtil.postForObject(
+                                restTemplate,
+                                dataBridgeApiHost + GTM_DELETE_CONTAINER_API_PATH,
+                                deleteGTMContainerRequest,
+                                new ParameterizedTypeReference<OpenAPIResponse<String>>() {})
+                        .getData();
+        log.info("为站点 {} 删除GTM container: {}", siteCode, gtmContainerResourceName);
+
+        // 3. 更新数据库
+        googleGTMService.removeById(googleGTM.getId());
+
+        return true;
+    }
+}

+ 3 - 3
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/controller/AdwebEnquiryBlacklistController.java

@@ -3,6 +3,7 @@ package org.jeecg.modules.adweb.enquiry.controller;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 
@@ -19,7 +20,6 @@ import org.jeecg.common.system.api.ISysBaseAPI;
 import org.jeecg.common.system.base.controller.JeecgController;
 import org.jeecg.common.system.vo.LoginUser;
 
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.enquiry.constant.EnquiryDistributeTypeConstant;
 import org.jeecg.modules.adweb.enquiry.dto.result.EnquiryListDto;
 import org.jeecg.modules.adweb.enquiry.entity.AdwebEnquiry;
@@ -125,7 +125,7 @@ public class AdwebEnquiryBlacklistController extends JeecgController<AdwebEnquir
             }
             if (EnquiryDistributeTypeConstant.REGION.equals(distributeType)) {
                 List<String> countryCodes = adwebUserCountryService.getCountryCodesBySubId(loginUser.getId(), siteId);
-                if (ListUtil.isEmpty(countryCodes)) {
+                if (CollectionUtils.isEmpty(countryCodes)) {
                     return Result.OK(new Page<>(pageNo, pageSize));
                 }
                 queryWrapper.in("country_code", countryCodes);
@@ -172,7 +172,7 @@ public class AdwebEnquiryBlacklistController extends JeecgController<AdwebEnquir
         enquirySiteBlackEmailQueryWrapper.eq("email", adwebEnquiry.getFromEmail());
         List<AdwebSiteBlackEmail> enquirySiteBlackEmailList = enquirySiteBlackEmailService.list(enquirySiteBlackEmailQueryWrapper);
 
-        if (ListUtil.notEmpty(enquirySiteBlackEmailList)) {
+        if (CollectionUtils.isNotEmpty(enquirySiteBlackEmailList)) {
             Integer blackOrWhite = enquirySiteBlackEmailList.get(0).getBlackOrWhite();
             String blackOrWhiteStr = "";
             if (blackOrWhite == 0) {

+ 10 - 10
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/controller/AdwebEnquiryController.java

@@ -11,6 +11,7 @@ import jakarta.annotation.Resource;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.ibatis.annotations.Param;
 import org.apache.shiro.SecurityUtils;
@@ -24,7 +25,6 @@ import org.jeecg.common.util.FastJsonUtil;
 import org.jeecg.modules.adweb.common.constant.AdwebConstant;
 import org.jeecg.modules.adweb.common.util.AwsTranslateUtils;
 import org.jeecg.modules.adweb.common.util.DateUtil;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.enquiry.constant.EnquirySendStatus;
 import org.jeecg.modules.adweb.enquiry.dto.param.EnquirySearchDto;
 import org.jeecg.modules.adweb.enquiry.dto.param.EffectiveEnquiryParamDto;
@@ -135,7 +135,7 @@ public class AdwebEnquiryController extends JeecgController<AdwebEnquiry, IAdweb
             uidList.add(sysUser.getId());
         }
         List<String> siteCodeList = null;
-        if (ListUtil.notEmpty(uidList)) {
+        if (CollectionUtils.isNotEmpty(uidList)) {
             siteCodeList = siteUserPermissionService.getSiteCodeListByUids(uidList);
         }
 
@@ -157,7 +157,7 @@ public class AdwebEnquiryController extends JeecgController<AdwebEnquiry, IAdweb
 		Date start = searchDto.getStart();
 		Date end = searchDto.getEnd();
 		if (StringUtils.isNotBlank(dateType)) {
-			Map<String, Date> map = DateUtil.dealDateType(dateType);
+			Map<String, Date> map = DateUtil.getDateRangeByType(dateType);
 			start = map.get("start");
 			end = map.get("end");
 		} else {
@@ -165,7 +165,7 @@ public class AdwebEnquiryController extends JeecgController<AdwebEnquiry, IAdweb
 				end = DateUtil.addDays(end, 1);
 			}
 		}
-		if(ListUtil.isEmpty(codeList)){
+		if(CollectionUtils.isEmpty(codeList)){
 			return Result.OK(page);
 		}
 
@@ -180,7 +180,7 @@ public class AdwebEnquiryController extends JeecgController<AdwebEnquiry, IAdweb
         IPage<EnquiryListDto> pageList = adwebEnquiryMapper.selectAdmpEnquiryList(page, codeList, userEfftecive, searchDto.getWasteEnquiryType(),
                 searchDto.getSearchText(), searchDto.getSearchContent(), start, end, searchDto.getWhatsApp(), searchDto.getReadStatus(), principalUid, selfPrincipalUid);
 
-        if (ListUtil.notEmpty(pageList.getRecords())) {
+        if (CollectionUtils.isNotEmpty(pageList.getRecords())) {
             dealInfo(pageList.getRecords());
         }
         return Result.OK(pageList);
@@ -191,7 +191,7 @@ public class AdwebEnquiryController extends JeecgController<AdwebEnquiry, IAdweb
      * @param enquiryList
      */
     private void dealInfo(List<EnquiryListDto> enquiryList) {
-        if (ListUtil.isEmpty(enquiryList)) {
+        if (CollectionUtils.isEmpty(enquiryList)) {
             return;
         }
         LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
@@ -220,7 +220,7 @@ public class AdwebEnquiryController extends JeecgController<AdwebEnquiry, IAdweb
             }
 
             /**********************字典数据处理***********************/
-            if (ListUtil.notEmpty(userEffectiveDict)) {
+            if (CollectionUtils.isNotEmpty(userEffectiveDict)) {
                 userEffectiveDict.forEach(dict -> {
                     if (dict.getValue().equals(enquiry.getUserEffective() + "")) {
                         enquiry.setUserEffectiveStr(dict.getLabel());
@@ -355,7 +355,7 @@ public class AdwebEnquiryController extends JeecgController<AdwebEnquiry, IAdweb
     @GetMapping("/getTurnInquiryCode")
     public Result<?> getTurnInquiryCode() {
         List<DictPropertyModel> siteRes = sysAdwebApi.queryDictInfoByDictCode("turn_inquiry_site_code");
-        if (ListUtil.notEmpty(siteRes)){
+        if (CollectionUtils.isNotEmpty(siteRes)){
             return Result.OK(siteRes);
         }
         return null;
@@ -625,7 +625,7 @@ public class AdwebEnquiryController extends JeecgController<AdwebEnquiry, IAdweb
         }
 
         List<String> siteCodeList = null;
-        if(ListUtil.notEmpty(uidList)){
+        if(CollectionUtils.isNotEmpty(uidList)){
             siteCodeList = siteUserPermissionService.getSiteCodeListByUids(uidList);
         }
 
@@ -643,7 +643,7 @@ public class AdwebEnquiryController extends JeecgController<AdwebEnquiry, IAdweb
         }
         enquiryType = "(" + enquiryType + ")";
         IPage<EnquiryListDto> pageList = adwebEnquiryMapper.queryWasteEnquiryList(page, codeList, "", enquiryType, searchText, null, null, null, principalUid);
-        if (ListUtil.isEmpty(pageList.getRecords())) {
+        if (CollectionUtils.isNotEmpty(pageList.getRecords())) {
             dealInfo(pageList.getRecords());
             return Result.OK(pageList);
         }

+ 0 - 7
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/controller/EnquiryController.java

@@ -1,7 +0,0 @@
-package org.jeecg.modules.adweb.enquiry.controller;
-
-/**
- * @author wfansh
- */
-public class EnquiryController {
-}

+ 5 - 12
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/AdwebOpenApiService.java

@@ -1,24 +1,17 @@
 package org.jeecg.modules.adweb.enquiry.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+
 import jakarta.annotation.Resource;
+
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.StringUtils;
-import org.jeecg.common.util.FastJsonUtil;
-import org.jeecg.modules.adweb.common.constant.NumConstant;
-import org.jeecg.modules.adweb.common.util.DateUtil;
-import org.jeecg.modules.adweb.common.util.ListUtil;
-import org.jeecg.modules.adweb.common.util.SnowflakeIdUtil;
-import org.jeecg.modules.adweb.enquiry.constant.EnquiryConstants;
-import org.jeecg.modules.adweb.enquiry.dto.IndependentEnquiryDto;
-import org.jeecg.modules.adweb.enquiry.entity.AdwebEnquiry;
-import org.jeecg.modules.adweb.enquiry.entity.AdwebEnquiryForm;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.jeecg.modules.adweb.site.entity.AdwebSite;
 import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
-import java.util.Date;
 import java.util.List;
 
 /**
@@ -55,7 +48,7 @@ public class AdwebOpenApiService {
     public String loadNo(String siteCode) {
         int code = 0;
         List<AdwebSite> adwebSites = selectBySiteCode(siteCode);
-        if (ListUtil.notEmpty(adwebSites)) {
+        if (CollectionUtils.isNotEmpty(adwebSites)) {
             AdwebSite adwebSite = adwebSites.get(0);
             if(adwebSite.getDayEnquiryCount()!= null){
                 code = adwebSite.getDayEnquiryCount() + 1;

+ 67 - 66
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/impl/AdwebEnquiryServiceImpl.java

@@ -9,8 +9,12 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.xkcoding.http.util.StringUtil;
+
 import jakarta.annotation.Resource;
+
 import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.jeecg.common.constant.CacheConstant;
 import org.jeecg.common.system.vo.DictModel;
@@ -79,9 +83,6 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
     private IAdwebPublicEnquiryRuleService AdwebPublicEnquiryRuleService;
 
     @Resource
-    private GeoIpUtil geoIpService;
-
-    @Resource
     private ISysDictService dictService;
 
     @Resource
@@ -187,7 +188,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                     .eq(AdwebPublicEnquiryRule::getIsEnable, 1)
                     .eq(AdwebPublicEnquiryRule::getBlackOrWhiteList, blackOrWhite)
                     .eq(AdwebPublicEnquiryRule::getUseStatus, useStatus));
-            if (ListUtil.notEmpty(AdwebPublicEnquiryRuleList)) {
+            if (CollectionUtils.isNotEmpty(AdwebPublicEnquiryRuleList)) {
                 blackWordList = AdwebPublicEnquiryRuleList.stream().map(AdwebPublicEnquiryRule::getWord).toList();
             }
         } catch (Exception e) {
@@ -214,10 +215,10 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         Map<String, String> principalEmailMap = new HashMap<>();
         List<String> subAccountIdList = masterSubAccountRelationService.getSubAccountIdByMaster(String.valueOf(adwebSite.getUid()));
         log.info("获取的子账户id:{}", FastJsonUtil.toJSONString(subAccountIdList));
-        if (ListUtil.notEmpty(subAccountIdList)) {
+        if (CollectionUtils.isNotEmpty(subAccountIdList)) {
             subAccountIdList.add(String.valueOf(adwebSite.getUid()));
             List<SysUser> principalEmailList = sysUserService.list(new QueryWrapper<SysUser>().in("id", subAccountIdList).eq("del_flag", 0).isNotNull("email").ne("email", "").select("id", "email"));
-            if (ListUtil.notEmpty(principalEmailList)) {
+            if (CollectionUtils.isNotEmpty(principalEmailList)) {
                 principalEmailMap = principalEmailList.stream().collect(Collectors.toMap(SysUser::getId, SysUser::getEmail));
 
             }
@@ -275,7 +276,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
      * @param principalEmailMap
      */
     private void sendValidateEmail(List<AdwebEnquiry> enquiryList, AdwebSite adwebSite, Map<String, String> principalEmailMap) {
-        if (ListUtil.isEmpty(enquiryList)) {
+        if (CollectionUtils.isEmpty(enquiryList)) {
             log.info("未获取到需要发送邮件的询盘");
             return;
         }
@@ -283,7 +284,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
 
         //特殊站点发送邮件
         List<DictPropertyModel> siteRes = sysAdwebApiImpl.queryDictInfoByDictCode("turn_inquiry_site_code");
-        if (ListUtil.notEmpty(siteRes) && siteRes.get(0).getValue().equals(adwebSite.getCode())) {
+        if (CollectionUtils.isNotEmpty(siteRes) && siteRes.get(0).getValue().equals(adwebSite.getCode())) {
             specialSendEmail(enquiryList, adwebSite);
         } else {
             String emailStr = adwebSite.getEnquiryEmailList();
@@ -295,7 +296,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             log.info("发送询盘邮件--子账户邮箱:{}", FastJsonUtil.toJSONString(principalEmailMap));
 
             List<String> emailList = JSON.parseArray(emailStr, String.class);
-            if (ListUtil.isEmpty(emailList)) {
+            if (CollectionUtils.isEmpty(emailList)) {
                 return;
             }
 
@@ -462,12 +463,12 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             log.info("=======发送询盘邮件======");
             enquiryEmailMessageList.forEach(e -> System.out.println(e.getEmail()));
             log.info("需要添加的询盘邮件:{}", FastJsonUtil.toJSONString(enquiryEmailMessageList));
-            if (ListUtil.notEmpty(enquiryEmailMessageList)) {
+            if (CollectionUtils.isNotEmpty(enquiryEmailMessageList)) {
                 QueryWrapper<EnquiryEmailMessage> enquiryEmailMessageQueryWrapper = new QueryWrapper<>();
                 enquiryEmailMessageQueryWrapper.eq("site_code", adwebSite.getCode());
                 List<EnquiryEmailMessage> enquiryEmailMessages = enquiryEmailMessageService.list(enquiryEmailMessageQueryWrapper);
                 List<EnquiryEmailMessage> sameEnquiryEmailMessageList = new ArrayList<>();
-                if (ListUtil.notEmpty(enquiryEmailMessages)) {
+                if (CollectionUtils.isNotEmpty(enquiryEmailMessages)) {
                     for (EnquiryEmailMessage enquiryEmailMessage : enquiryEmailMessages) {
                         for (EnquiryEmailMessage enquiryEmailMessage1 : enquiryEmailMessageList) {
                             if (enquiryEmailMessage.getEnquiryId().equals(enquiryEmailMessage1.getEnquiryId()) && enquiryEmailMessage.getEmail().equals(enquiryEmailMessage1.getEmail())) {
@@ -506,7 +507,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
         sysUserQueryWrapper.eq("is_inquiry", 2);
         sysUserQueryWrapper.eq("status", 1);
-        if (ListUtil.notEmpty(idList)) {
+        if (CollectionUtils.isNotEmpty(idList)) {
             sysUserQueryWrapper.in("id", idList);
         }
         List<SysUser> sysUsers = sysUserService.list(sysUserQueryWrapper);
@@ -519,7 +520,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                 SysUser sysUser = new SysUser();
 
                 //如果没有子账号,则只给主账号发送邮件
-                if (ListUtil.isEmpty(sysUsers)) {
+                if (CollectionUtils.isEmpty(sysUsers)) {
                     //获取主账号
                     SysUser mainUser = sysUserService.getById(adwebSite.getUid());
                     //主账号邮件信息添加
@@ -531,12 +532,12 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                 enquiryEmailMessageList.forEach(e -> System.out.println(e.getEmail()));
 
                 log.info("需要添加的询盘邮件:{}", FastJsonUtil.toJSONString(enquiryEmailMessageList));
-                if (ListUtil.notEmpty(enquiryEmailMessageList)) {
+                if (CollectionUtils.isNotEmpty(enquiryEmailMessageList)) {
                     QueryWrapper<EnquiryEmailMessage> enquiryEmailMessageQueryWrapper = new QueryWrapper<>();
                     enquiryEmailMessageQueryWrapper.eq("site_code", adwebSite.getCode());
                     List<EnquiryEmailMessage> enquiryEmailMessages = enquiryEmailMessageService.list(enquiryEmailMessageQueryWrapper);
                     List<EnquiryEmailMessage> sameEnquiryEmailMessageList = new ArrayList<>();
-                    if (ListUtil.notEmpty(enquiryEmailMessages)) {
+                    if (CollectionUtils.isNotEmpty(enquiryEmailMessages)) {
                         for (EnquiryEmailMessage enquiryEmailMessage : enquiryEmailMessages) {
                             for (EnquiryEmailMessage enquiryEmailMessage1 : enquiryEmailMessageList) {
                                 if (enquiryEmailMessage.getEnquiryId().equals(enquiryEmailMessage1.getEnquiryId()) && enquiryEmailMessage.getEmail().equals(enquiryEmailMessage1.getEmail())) {
@@ -635,14 +636,14 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         adwebEnquiry.setFromEmail(enquiryDto.getFromEmail());
         adwebEnquiry.setPluginName(enquiryDto.getPluginName());
         adwebEnquiry.setRecordId(enquiryDto.getRecordId());
-        adwebEnquiry.setModifyRecordCtime(geoIpService.getLocalhostTime(enquiryDto.getFromIp(), enquiryDto.getRecordCtime()));
+        adwebEnquiry.setModifyRecordCtime(geoIpUtil.getLocalhostTime(enquiryDto.getFromIp(), enquiryDto.getRecordCtime()));
         adwebEnquiry.setRecordCtime(enquiryDto.getRecordCtime());
         adwebEnquiry.setSiteCode(adwebSite.getCode());
         adwebEnquiry.setModular(enquiryDto.getPluginName());
         adwebEnquiry.setSysEffective(NumConstant.ONE);
         adwebEnquiry.setUserEffective(NumConstant.TWO);
         adwebEnquiry.setSiteHost(enquiryDto.getSiteHost());
-        adwebEnquiry.setNo("xp" + DateUtil.dateToString(new Date(), DateUtil.DATE_FORMAT) + adwebOpenApiService.loadNo(adwebSite.getCode()));
+        adwebEnquiry.setNo("xp" + DateUtil.formatDate(new Date(), DateUtil.DATE_FORMAT) + adwebOpenApiService.loadNo(adwebSite.getCode()));
 
         // 外部编号暂无作用,且多查询一次数据库,暂时注释
 //        adwebEnquiry.setNoOut(DateUtil.dateToString(new Date(), DateUtil.DATE_FORMAT_THREE) + adwebOpenApiService.loadOutNoByUser(adwebSite.getUid()));
@@ -689,7 +690,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         Map<String, JSONObject> formObj = FastJsonUtil.parseObject(form, Map.class);
         if (formObj == null || formObj.size() == 0) {
             List<JSONObject> formList = FastJsonUtil.parseObject(form, List.class);
-            if (ListUtil.notEmpty(formList)) {
+            if (CollectionUtils.isNotEmpty(formList)) {
                 formItems = formList;
             }
         } else {
@@ -784,7 +785,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
     }
 
     private boolean contains(List<String> keys, String key) {
-        if (ListUtil.isEmpty(keys) || StringUtil.isEmpty(key)) {
+        if (CollectionUtils.isEmpty(keys) || StringUtil.isEmpty(key)) {
             return false;
         }
         key = key.replace(":", "").replace(":", "").replaceAll(" {2,}", " ").toLowerCase().trim();
@@ -806,7 +807,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         }
         List<SysDictItem> dictItems = sysAdwebApiImpl.selectItemsByDictCode(dictCode);
         List<String> keys = new ArrayList<>();
-        if (ListUtil.notEmpty(dictItems)) {
+        if (CollectionUtils.isNotEmpty(dictItems)) {
             for (SysDictItem item : dictItems) {
                 String value = item.getItemValue();
                 if (StringUtil.isEmpty(value)) {
@@ -835,17 +836,17 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         //邮箱 黑名单
         //先获取对应站点的邮箱黑名单
         List<String> siteBlackEmailList = (List<String>) adwebRedisUtil.get(SiteBlackEmailKey + "::" + adwebSite.getId());
-        if (ListUtil.isEmpty(siteBlackEmailList)) {
+        if (CollectionUtils.isEmpty(siteBlackEmailList)) {
             enquirySiteBlackEmailService.saveRedisSiteBlackEmailBySiteId(adwebSite.getId(), 0);
             siteBlackEmailList = (List<String>) adwebRedisUtil.get(SiteBlackEmailKey + "::" + adwebSite.getId());
-            if (ListUtil.isEmpty(siteBlackEmailList)) {
+            if (CollectionUtils.isEmpty(siteBlackEmailList)) {
                 siteBlackEmailList = new ArrayList<>();
             }
         }
 
         //邮箱 公共黑名单
         List<String> publicBlackEmailList = (List<String>) adwebRedisUtil.get(BlackEmailKey);
-        if (ListUtil.isEmpty(publicBlackEmailList)) {
+        if (CollectionUtils.isEmpty(publicBlackEmailList)) {
             List<AdwebPublicBlackEmail> enquiryPublicBlackEmailList = adwebPublicBlackEmailService
                     .list(new LambdaQueryWrapper<AdwebPublicBlackEmail>()
                             .ne(AdwebPublicBlackEmail::getStatus, 0)
@@ -853,7 +854,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                             .isNotNull(AdwebPublicBlackEmail::getEmail)
                             .select(AdwebPublicBlackEmail::getEmail));
 
-            if (ListUtil.notEmpty(enquiryPublicBlackEmailList)) {
+            if (CollectionUtils.isNotEmpty(enquiryPublicBlackEmailList)) {
                 publicBlackEmailList = enquiryPublicBlackEmailList.stream().map(AdwebPublicBlackEmail::getEmail).filter(StringUtil::isNotEmpty).collect(Collectors.toList());
                 adwebRedisUtil.set(BlackEmailKey, publicBlackEmailList, 60 * 60 * 24);
             } else {
@@ -863,12 +864,12 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             publicBlackEmailList = publicBlackEmailList.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
         }
         List<String> allBlackEmailList = new ArrayList<>();
-        if (ListUtil.notEmpty(siteBlackEmailList)) {
+        if (CollectionUtils.isNotEmpty(siteBlackEmailList)) {
             allBlackEmailList = new ArrayList<>(siteBlackEmailList);
         }
         allBlackEmailList.addAll(publicBlackEmailList);
         List<String> blackEmailList = new ArrayList<>();
-        if (ListUtil.notEmpty(allBlackEmailList)) {
+        if (CollectionUtils.isNotEmpty(allBlackEmailList)) {
             HashSet<String> blackEmailHashSet = new HashSet<String>(allBlackEmailList);
             blackEmailList = new ArrayList<>(blackEmailHashSet);
         }
@@ -878,13 +879,13 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         //邮箱 白名单
         //先获取对应站点的邮箱白名单
         List<String> siteWhiteEmailList = (List<String>) adwebRedisUtil.get(SiteWhiteEmailListKey + "::" + adwebSite.getId());
-        if (ListUtil.isEmpty(siteWhiteEmailList)) {
+        if (CollectionUtils.isEmpty(siteWhiteEmailList)) {
             enquirySiteBlackEmailService.saveRedisSiteBlackEmailBySiteId(adwebSite.getId(), 1);
             siteWhiteEmailList = (List<String>) adwebRedisUtil.get(SiteWhiteEmailListKey + "::" + adwebSite.getId());
         }
         //公共邮箱白名单数据
         List<String> publicWhiteEmailList = (List<String>) adwebRedisUtil.get(WhiteEmailListKey);
-        if (ListUtil.isEmpty(publicWhiteEmailList)) {
+        if (CollectionUtils.isEmpty(publicWhiteEmailList)) {
             List<AdwebPublicBlackEmail> enquiryPublicWhiteEmailList = adwebPublicBlackEmailService
                     .list(new LambdaQueryWrapper<AdwebPublicBlackEmail>()
                             .ne(AdwebPublicBlackEmail::getStatus, 0)
@@ -892,7 +893,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                             .isNotNull(AdwebPublicBlackEmail::getEmail)
                             .select(AdwebPublicBlackEmail::getEmail));
 
-            if (ListUtil.notEmpty(enquiryPublicWhiteEmailList)) {
+            if (CollectionUtils.isNotEmpty(enquiryPublicWhiteEmailList)) {
                 publicWhiteEmailList = enquiryPublicWhiteEmailList.stream().map(AdwebPublicBlackEmail::getEmail).filter(StringUtil::isNotEmpty).collect(Collectors.toList());
                 adwebRedisUtil.set(WhiteEmailListKey, publicWhiteEmailList, 60 * 60 * 24);
             } else {
@@ -902,12 +903,12 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             publicWhiteEmailList = publicWhiteEmailList.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
         }
         List<String> allWhiteEmailList = new ArrayList<>();
-        if (ListUtil.notEmpty(siteWhiteEmailList)) {
+        if (CollectionUtils.isNotEmpty(siteWhiteEmailList)) {
             allWhiteEmailList = new ArrayList<>(siteWhiteEmailList);
         }
         allWhiteEmailList.addAll(publicWhiteEmailList);
         List<String> whiteEmailList = new ArrayList<>();
-        if (ListUtil.notEmpty(allWhiteEmailList)) {
+        if (CollectionUtils.isNotEmpty(allWhiteEmailList)) {
             HashSet<String> whiteEmailHashSet = new HashSet<String>(allWhiteEmailList);
             whiteEmailList = new ArrayList<>(whiteEmailHashSet);
         }
@@ -918,13 +919,13 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         //Ip黑名单
         //公共ip黑名单
         List<String> publicBlackIpList = (List<String>) adwebRedisUtil.get(BlackIpKey);
-        if (ListUtil.isEmpty(publicBlackIpList)) {
+        if (CollectionUtils.isEmpty(publicBlackIpList)) {
             List<AdwebPublicBlackIp> enquiryPublicBlackIpList = adwebPublicBlackIpService
                     .list(new LambdaQueryWrapper<AdwebPublicBlackIp>()
                             .ne(AdwebPublicBlackIp::getStatus, 0)
                             .eq(AdwebPublicBlackIp::getBlackOrWhite, 0)
                             .select(AdwebPublicBlackIp::getIp));
-            if (ListUtil.notEmpty(enquiryPublicBlackIpList)) {
+            if (CollectionUtils.isNotEmpty(enquiryPublicBlackIpList)) {
                 publicBlackIpList = enquiryPublicBlackIpList.stream().map(AdwebPublicBlackIp::getIp).collect(Collectors.toList());
                 adwebRedisUtil.set(BlackIpKey, publicBlackIpList, 60 * 60 * 24);
             } else {
@@ -933,14 +934,14 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         }
         //站点ip黑名单
         List<String> siteBlackIpList = (List<String>) adwebRedisUtil.get(SiteBlackIpKey + "::" + adwebSite.getId());
-        if (ListUtil.isEmpty(siteBlackIpList)) {
+        if (CollectionUtils.isEmpty(siteBlackIpList)) {
             List<AdwebSiteBlackIp> enquirySiteBlackIpList = adwebSiteBlackIpService
                     .list(new LambdaQueryWrapper<AdwebSiteBlackIp>()
                             .ne(AdwebSiteBlackIp::getStatus, 0)
                             .eq(AdwebSiteBlackIp::getBlackOrWhite, 0)
                             .eq(AdwebSiteBlackIp::getSiteId, adwebSite.getId())
                             .select(AdwebSiteBlackIp::getIp));
-            if (ListUtil.notEmpty(enquirySiteBlackIpList)) {
+            if (CollectionUtils.isNotEmpty(enquirySiteBlackIpList)) {
                 siteBlackIpList = enquirySiteBlackIpList.stream().map(AdwebSiteBlackIp::getIp).collect(Collectors.toList());
                 adwebRedisUtil.set(SiteBlackIpKey + "::" + adwebSite.getId(), siteBlackIpList, 60 * 60 * 24);
             } else {
@@ -948,12 +949,12 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             }
         }
         List<String> allBlackIpList = new ArrayList<>();
-        if (ListUtil.notEmpty(siteBlackIpList)) {
+        if (CollectionUtils.isNotEmpty(siteBlackIpList)) {
             allBlackIpList = new ArrayList<>(siteBlackIpList);
         }
         allBlackIpList.addAll(publicBlackIpList);
         List<String> blackIpList = new ArrayList<>();
-        if (ListUtil.notEmpty(allBlackIpList)) {
+        if (CollectionUtils.isNotEmpty(allBlackIpList)) {
             HashSet<String> blackIpHashSet = new HashSet<String>(allBlackIpList);
             blackIpList = new ArrayList<>(blackIpHashSet);
         }
@@ -970,7 +971,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                             .ne(AdwebPublicBlackIp::getStatus, 0)
                             .eq(AdwebPublicBlackIp::getBlackOrWhite, 1)
                             .select(AdwebPublicBlackIp::getIp));
-            if (ListUtil.notEmpty(enquiryPublicWhiteIpList)) {
+            if (CollectionUtils.isNotEmpty(enquiryPublicWhiteIpList)) {
                 publicWhiteIpList = enquiryPublicWhiteIpList.stream().map(AdwebPublicBlackIp::getIp).collect(Collectors.toList());
                 adwebRedisUtil.set(WhiteIpListKey, publicWhiteIpList, 60 * 60 * 24);
             } else {
@@ -979,14 +980,14 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         }
         //站点Ip白名单, 基于站点查询
         List<String> siteWhiteIpList = (List<String>) adwebRedisUtil.get(SiteWhiteIpListKey + "::" + adwebSite.getId());
-        if (ListUtil.isEmpty(siteWhiteIpList)) {
+        if (CollectionUtils.isEmpty(siteWhiteIpList)) {
             List<AdwebSiteBlackIp> enquirySiteWhiteIpList = adwebSiteBlackIpService
                     .list(new LambdaQueryWrapper<AdwebSiteBlackIp>()
                             .ne(AdwebSiteBlackIp::getStatus, 0)
                             .eq(AdwebSiteBlackIp::getBlackOrWhite, 1)
                             .eq(AdwebSiteBlackIp::getSiteId, adwebSite.getId())
                             .select(AdwebSiteBlackIp::getIp));
-            if (ListUtil.notEmpty(enquirySiteWhiteIpList)) {
+            if (CollectionUtils.isNotEmpty(enquirySiteWhiteIpList)) {
                 siteWhiteIpList = enquirySiteWhiteIpList.stream().map(AdwebSiteBlackIp::getIp).collect(Collectors.toList());
                 adwebRedisUtil.set(SiteWhiteIpListKey + "::" + adwebSite.getId(), siteWhiteIpList, 60 * 60 * 24);
             } else {
@@ -994,12 +995,12 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             }
         }
         List<String> allWhiteIpList = new ArrayList<>();
-        if (ListUtil.notEmpty(siteWhiteIpList)) {
+        if (CollectionUtils.isNotEmpty(siteWhiteIpList)) {
             allWhiteIpList = new ArrayList<>(siteWhiteIpList);
         }
         allWhiteIpList.addAll(publicWhiteIpList);
         List<String> whiteIpList = new ArrayList<>();
-        if (ListUtil.notEmpty(allWhiteIpList)) {
+        if (CollectionUtils.isNotEmpty(allWhiteIpList)) {
             HashSet<String> whiteIpHashSet = new HashSet<String>(allWhiteIpList);
             whiteIpList = new ArrayList<>(whiteIpHashSet);
         }
@@ -1035,7 +1036,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             isJudgeWasteEnquiry = adwebEnquiry;
 
             // 判断 询盘邮箱黑名单
-            if (ListUtil.notEmpty(blackEmailList) || StringUtils.isNotBlank(adwebEnquiry.getEmail())) {
+            if (CollectionUtils.isNotEmpty(blackEmailList) || StringUtils.isNotBlank(adwebEnquiry.getEmail())) {
 
                 String email = adwebEnquiry.getEmail().toLowerCase();
 
@@ -1058,7 +1059,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                 //黑名单
                 String containPublicBlackStr = "";
                 boolean isContainPublicBlack = false;
-                if (ListUtil.notEmpty(publicBlackEmailList)) {
+                if (CollectionUtils.isNotEmpty(publicBlackEmailList)) {
                     for (String blackEmail : publicBlackEmailList) {
                         String allBlackEmail = blackEmail;
                         if (allBlackEmail.contains("*")) {
@@ -1084,7 +1085,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                 boolean isSiteAllContain = true;
                 String containSiteWhiteStr = "";
                 //白名单
-                if (ListUtil.notEmpty(siteWhiteEmailList)) {
+                if (CollectionUtils.isNotEmpty(siteWhiteEmailList)) {
                     for (String whiteEmail : siteWhiteEmailList) {
                         String compareWhiteEmail = whiteEmail;
                         if (compareWhiteEmail.contains("*")) {
@@ -1112,7 +1113,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                 //黑名单
                 boolean isContainSiteBlack = false;
                 String containSiteBlackStr = "";
-                if (ListUtil.notEmpty(siteBlackEmailList)) {
+                if (CollectionUtils.isNotEmpty(siteBlackEmailList)) {
                     for (String blackEmail : siteBlackEmailList) {
                         String allBlackEmail = blackEmail;
                         if (allBlackEmail.contains("*")) {
@@ -1179,7 +1180,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             // @see http://52.83.154.198:8082/browse/ADWEBV2-12
             // 垃圾询盘过滤时IP按照客户IP去使用黑名单过滤而不再使用来源IP
             // 判断是否为ip黑名单
-            if (ListUtil.notEmpty(blackIpList) || StringUtils.isNotBlank(adwebEnquiry.getCustomerIp())) {
+            if (CollectionUtils.isNotEmpty(blackIpList) || StringUtils.isNotBlank(adwebEnquiry.getCustomerIp())) {
                 String ip = adwebEnquiry.getCustomerIp();
                 //公共ip黑名单
                 boolean isPublicIp = false;
@@ -1233,7 +1234,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                     }
                 }
             } else {
-                if (ListUtil.notEmpty(urlList)) {
+                if (CollectionUtils.isNotEmpty(urlList)) {
                     adwebEnquiry.setWasteEnquiry(1);
                     adwebEnquiry.setUserEffective(0);
                     adwebEnquiry.setWasteEnquiryType("other");
@@ -1247,7 +1248,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             // 判断询盘是否包含关键词
             String message = adwebEnquiry.getMessage().replaceAll("[\\n\\t]",
                     " ").replaceAll(" {2,}", " ").toLowerCase();
-            if (ListUtil.notEmpty(blackWordList) || ListUtil.notEmpty(siteBlackRuleList)) {
+            if (CollectionUtils.isNotEmpty(blackWordList) || CollectionUtils.isNotEmpty(siteBlackRuleList)) {
                 //公共关键词黑名单
                 boolean isPublicWord = false;
                 String isBlackWord = "";
@@ -1328,29 +1329,29 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
 
         //更新redis
         //站点
-        if (ListUtil.notEmpty(siteBlackEmailList)) {
+        if (CollectionUtils.isNotEmpty(siteBlackEmailList)) {
             adwebRedisUtil.set(SiteBlackEmailKey + "::" + adwebSite.getId(), siteBlackEmailList, 86400);
         }
-        if (ListUtil.notEmpty(siteBlackIpList)) {
+        if (CollectionUtils.isNotEmpty(siteBlackIpList)) {
             adwebRedisUtil.set(SiteBlackIpKey + "::" + adwebSite.getId(), siteBlackIpList, 86400);
         }
-        if (ListUtil.notEmpty(siteWhiteEmailList)) {
+        if (CollectionUtils.isNotEmpty(siteWhiteEmailList)) {
             adwebRedisUtil.set(SiteWhiteEmailListKey + "::" + adwebSite.getId(), siteWhiteEmailList, 86400);
         }
-        if (ListUtil.notEmpty(siteWhiteIpList)) {
+        if (CollectionUtils.isNotEmpty(siteWhiteIpList)) {
             adwebRedisUtil.set(SiteWhiteIpListKey + "::" + adwebSite.getId(), siteWhiteIpList, 86400);
         }
         //公共
-        if (ListUtil.notEmpty(publicBlackEmailList)) {
+        if (CollectionUtils.isNotEmpty(publicBlackEmailList)) {
             adwebRedisUtil.set(BlackEmailKey, publicBlackEmailList, 86400);
         }
-        if (ListUtil.notEmpty(publicBlackIpList)) {
+        if (CollectionUtils.isNotEmpty(publicBlackIpList)) {
             adwebRedisUtil.set(BlackIpKey, publicBlackIpList, 86400);
         }
-        if (ListUtil.notEmpty(publicWhiteEmailList)) {
+        if (CollectionUtils.isNotEmpty(publicWhiteEmailList)) {
             adwebRedisUtil.set(WhiteEmailListKey, publicWhiteEmailList, 86400);
         }
-        if (ListUtil.notEmpty(publicWhiteIpList)) {
+        if (CollectionUtils.isNotEmpty(publicWhiteIpList)) {
             adwebRedisUtil.set(WhiteIpListKey, publicWhiteIpList, 86400);
         }
     }
@@ -1375,7 +1376,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         Pattern pattern1 = Pattern.compile("(https?|ftp|file)://([-a-zA-Z0-9]+\\.)+[a-zA-Z0-9]+");
         List<String> domainPatterns = getFormKeys("enquiry_domain_pattern");
         String domainPattern = "";
-        if (ListUtil.notEmpty(domainPatterns)) {
+        if (CollectionUtils.isNotEmpty(domainPatterns)) {
             domainPattern = domainPatterns.get(0);
         }
         if (StringUtil.isEmpty(domainPattern)) {
@@ -1419,7 +1420,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         }
 
         // 如果邮箱和 URL 都存在,并且 URL 中不包含 http 和 https,则从 URL 中删除邮箱
-        if (ListUtil.notEmpty(emailList)) {
+        if (CollectionUtils.isNotEmpty(emailList)) {
             Set<String> urlSet = new HashSet<>(urls);
             urlSet.removeAll(emailList.stream()
                     .filter(email -> urlSet.contains(email) && !email.contains("http") && !email.contains("https"))
@@ -1439,7 +1440,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             log.info("上一封邮件为垃圾询盘,处理中...");
             boolean emailFlag = false;
             String isJudgeWasteEnquiryEmail = isJudgeWasteEnquiry.getEmail().toLowerCase();
-            if (StringUtils.isNotBlank(isJudgeWasteEnquiryEmail) && ListUtil.notEmpty(blackEmailList)) {
+            if (StringUtils.isNotBlank(isJudgeWasteEnquiryEmail) && CollectionUtils.isNotEmpty(blackEmailList)) {
                 for (String blackEmail : blackEmailList) {
                     if (isJudgeWasteEnquiry.getEmail().equals(blackEmail)) {
                         emailFlag = false;
@@ -1511,7 +1512,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
             log.info("上一封邮件为垃圾询盘,处理中...");
             boolean emailFlag = false;
             String isJudgeWasteEnquiryEmail = isJudgeWasteEnquiry.getEmail().toLowerCase();
-            if (StringUtils.isNotBlank(isJudgeWasteEnquiryEmail) && ListUtil.notEmpty(siteBlackEmailList)) {
+            if (StringUtils.isNotBlank(isJudgeWasteEnquiryEmail) && CollectionUtils.isNotEmpty(siteBlackEmailList)) {
                 for (String blackEmail : siteBlackEmailList) {
                     if (isJudgeWasteEnquiry.getEmail().equals(blackEmail)) {
                         emailFlag = false;
@@ -1784,7 +1785,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         }
 
         List<String> idList = Arrays.asList(id.split(","));
-        if (ListUtil.isEmpty(idList)) {
+        if (CollectionUtils.isEmpty(idList)) {
             return false;
         }
 
@@ -1829,7 +1830,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
         // 有效询盘发送邮件
         try {
             List<AdwebEnquiry> enquiryList = this.list(new LambdaQueryWrapper<AdwebEnquiry>().in(AdwebEnquiry::getId, idList));
-            if (ListUtil.notEmpty(enquiryList)) {
+            if (CollectionUtils.isNotEmpty(enquiryList)) {
                 AdwebSite adwebSite = adwebSiteService.getOne(new QueryWrapper<AdwebSite>().eq("code", enquiryList.get(0).getSiteCode()));
                 if (adwebSite != null) {
 
@@ -1845,7 +1846,7 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                     // 判断是否为联系我们询盘
                     for (AdwebEnquiry adwebEnquiry : enquiryList) {
                         List<DictModel> contactEnquiryWebsites = dictService.queryDictItemsByCode("send_contact_enquiry_website");
-                        List<String> contactEnquiryCodes = contactEnquiryWebsites.stream().map(DictModel::getValue).collect(Collectors.toList());
+                        List<String> contactEnquiryCodes = contactEnquiryWebsites.stream().map(DictModel::getValue).toList();
                         if (contactEnquiryCodes.contains(adwebSite.getCode())) {
                             if (StringUtils.isNotBlank(adwebEnquiry.getFromPage()) && adwebEnquiry.getFromPage().contains("contact")) {
                                 adwebEnquiry.setExistContactEnquiry(1);
@@ -1856,10 +1857,10 @@ public class AdwebEnquiryServiceImpl extends ServiceImpl<AdwebEnquiryMapper, Adw
                     //获取子账户
                     List<String> subAccountIdList = masterSubAccountRelationService.getSubAccountIdByMaster(String.valueOf(adwebSite.getUid()));
                     log.info("获取的子账户id:{}", FastJsonUtil.toJSONString(subAccountIdList));
-                    if (ListUtil.notEmpty(subAccountIdList)) {
+                    if (CollectionUtils.isNotEmpty(subAccountIdList)) {
                         subAccountIdList.add(String.valueOf(adwebSite.getUid()));
                         List<SysUser> principalEmailList = sysUserService.list(new QueryWrapper<SysUser>().in("id", subAccountIdList).eq("del_flag", 0).isNotNull("email").ne("email","").select("id", "email"));
-                        if (ListUtil.notEmpty(principalEmailList)) {
+                        if (CollectionUtils.isNotEmpty(principalEmailList)) {
                             principalEmailMap = principalEmailList.stream().collect(Collectors.toMap(SysUser::getId, SysUser::getEmail));
 
                         }

+ 9 - 7
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/impl/AdwebPublicEnquiryRuleServiceImpl.java

@@ -1,17 +1,19 @@
 package org.jeecg.modules.adweb.enquiry.service.impl;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.jeecg.modules.adweb.common.util.ListUtil;
+
+import jakarta.annotation.Resource;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.jeecg.modules.adweb.enquiry.entity.AdwebPublicEnquiryRule;
 import org.jeecg.modules.adweb.enquiry.mapper.AdwebPublicEnquiryRuleMapper;
 import org.jeecg.modules.adweb.enquiry.service.IAdwebPublicEnquiryRuleService;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.springframework.stereotype.Service;
 
-import jakarta.annotation.Resource;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -39,7 +41,7 @@ public class AdwebPublicEnquiryRuleServiceImpl extends ServiceImpl<AdwebPublicEn
                 .eq("use_status", 1)
                 .eq("is_enable", 1)
                 .eq("black_or_white_list", 0));
-        if (ListUtil.isEmpty(list)) {
+        if (CollectionUtils.isEmpty(list)) {
             return null;
         }
         return list.stream().map(AdwebPublicEnquiryRule::getWord).collect(Collectors.toList());
@@ -52,7 +54,7 @@ public class AdwebPublicEnquiryRuleServiceImpl extends ServiceImpl<AdwebPublicEn
                 .eq("use_status", 0)
                 .eq("is_enable", 1)
                 .eq("black_or_white_list", 0));
-        if (ListUtil.isEmpty(list)) {
+        if (CollectionUtils.isEmpty(list)) {
             return null;
         }
         return list.stream().map(AdwebPublicEnquiryRule::getWord).collect(Collectors.toList());

+ 12 - 10
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/impl/AdwebSiteBlackEmailServiceImpl.java

@@ -4,9 +4,11 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
 import jakarta.annotation.Resource;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.jeecg.common.util.RedisUtil;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.enquiry.dto.param.EffectiveEnquiryParamDto;
 import org.jeecg.modules.adweb.enquiry.entity.AdwebSiteBlackEmail;
 import org.jeecg.modules.adweb.enquiry.mapper.AdwebSiteBlackEmailMapper;
@@ -45,12 +47,12 @@ public class AdwebSiteBlackEmailServiceImpl extends ServiceImpl<AdwebSiteBlackEm
         siteAllEmailQueryWrapper.eq("site_id", siteId);
         siteAllEmailQueryWrapper.eq("black_or_white", blackOrWhite);
         List<AdwebSiteBlackEmail> allEmailList = list(siteAllEmailQueryWrapper);
-        if(ListUtil.isEmpty(allEmailList)){
+        if(CollectionUtils.isEmpty(allEmailList)){
             log.warn("未获取到对应站点的名单数据");
         }
 
         List<String> emailList = new ArrayList<>();
-        if(ListUtil.notEmpty(allEmailList)){
+        if(CollectionUtils.isNotEmpty(allEmailList)){
             for (AdwebSiteBlackEmail enquirySiteBlackEmail1 : allEmailList){
                 if(enquirySiteBlackEmail1.getType().equals("0")){
                     emailList.add("*" + enquirySiteBlackEmail1.getEmail() + "*");
@@ -61,13 +63,13 @@ public class AdwebSiteBlackEmailServiceImpl extends ServiceImpl<AdwebSiteBlackEm
         }
         //处理对应站点的黑名单
         if(blackOrWhite == 0){
-            if (ListUtil.notEmpty(emailList)) {
+            if (CollectionUtils.isNotEmpty(emailList)) {
                 redisUtil.set(SiteBlackEmailKey + "::" + siteId, emailList, 60 * 60 * 24);
             }else {
                 redisUtil.del(SiteBlackEmailKey + "::" + siteId);
             }
         }else{
-            if (ListUtil.notEmpty(emailList)) {
+            if (CollectionUtils.isNotEmpty(emailList)) {
                 redisUtil.set(SiteWhiteEmailListKey + "::" + siteId, emailList, 60 * 60 * 24);
             }else {
                 redisUtil.del(SiteWhiteEmailListKey + "::" + siteId);
@@ -85,13 +87,13 @@ public class AdwebSiteBlackEmailServiceImpl extends ServiceImpl<AdwebSiteBlackEm
         siteAllEmailQueryWrapper.ne("status", 0);
         siteAllEmailQueryWrapper.eq("site_id", siteId);
         List<AdwebSiteBlackEmail> allEmailList = list(siteAllEmailQueryWrapper);
-        if(ListUtil.isEmpty(allEmailList)){
+        if(CollectionUtils.isEmpty(allEmailList)){
             log.warn("未获取到对应站点的黑白名单数据");
         }
 
         List<String> emailList = new ArrayList<>();
         List<String> whiteEmailList = new ArrayList<>();
-        if(ListUtil.notEmpty(allEmailList)){
+        if(CollectionUtils.isNotEmpty(allEmailList)){
             for (AdwebSiteBlackEmail enquirySiteBlackEmail1 : allEmailList){
                 if(enquirySiteBlackEmail1.getBlackOrWhite() == 0){
                     if(enquirySiteBlackEmail1.getType().equals("0")){
@@ -140,7 +142,7 @@ public class AdwebSiteBlackEmailServiceImpl extends ServiceImpl<AdwebSiteBlackEm
         enquirySiteBlackEmailQueryWrapper.eq("site_code", effectiveEnquiryParamDto.getSiteCode());
         enquirySiteBlackEmailQueryWrapper.eq("status", 1);
         List<AdwebSiteBlackEmail> enquirySiteBlackEmailList = list(enquirySiteBlackEmailQueryWrapper);
-        if(ListUtil.notEmpty(enquirySiteBlackEmailList)){
+        if(CollectionUtils.isNotEmpty(enquirySiteBlackEmailList)){
             //如果有白名单 先删除原数据,后添加新的黑名单数据
             for(AdwebSiteBlackEmail enquirySiteBlackEmail : enquirySiteBlackEmailList){
                 if(enquirySiteBlackEmail.getBlackOrWhite() == 1){
@@ -179,14 +181,14 @@ public class AdwebSiteBlackEmailServiceImpl extends ServiceImpl<AdwebSiteBlackEm
         List<String> whiteEmailList = enquirySiteBlackEmailListMap.get("white");
 
         //处理对应站点的黑名单
-        if (ListUtil.notEmpty(emailList)) {
+        if (CollectionUtils.isNotEmpty(emailList)) {
             redisUtil.set(SiteBlackEmailKey + "::" + effectiveEnquiryParamDto.getSiteId(), emailList, 60 * 60 * 24);
         }else {
             redisUtil.del(SiteBlackEmailKey + "::" + effectiveEnquiryParamDto.getSiteId());
         }
 
         //处理对应站点的白名单
-        if (ListUtil.notEmpty(whiteEmailList)) {
+        if (CollectionUtils.isNotEmpty(whiteEmailList)) {
             redisUtil.set(SiteWhiteEmailListKey + "::" + effectiveEnquiryParamDto.getSiteId(), whiteEmailList, 60 * 60 * 24);
         }else {
             redisUtil.del(SiteWhiteEmailListKey + "::" + effectiveEnquiryParamDto.getSiteId());

+ 6 - 4
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/impl/AdwebSiteBlackIpServiceImpl.java

@@ -5,9 +5,11 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
 import jakarta.annotation.Resource;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.jeecg.common.util.RedisUtil;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.enquiry.dto.param.EffectiveEnquiryParamDto;
 import org.jeecg.modules.adweb.enquiry.entity.AdwebSiteBlackIp;
 import org.jeecg.modules.adweb.enquiry.mapper.AdwebSiteBlackIpMapper;
@@ -89,16 +91,16 @@ public class AdwebSiteBlackIpServiceImpl extends ServiceImpl<AdwebSiteBlackIpMap
             redisUtil.del(SiteBlackIpKey + "::" + effectiveEnquiryParamDto.getSiteId());
             redisUtil.del(SiteWhiteIpListKey + "::" + effectiveEnquiryParamDto.getSiteId());
         }
-        if(ListUtil.notEmpty(redisList)){
+        if(CollectionUtils.isNotEmpty(redisList)){
             List<String> blackIpList = redisList.stream().filter(siteBlackIp -> siteBlackIp.getBlackOrWhite().equals(0)).map(AdwebSiteBlackIp::getIp).collect(Collectors.toList());
-            if(ListUtil.notEmpty(blackIpList)){
+            if(CollectionUtils.isNotEmpty(blackIpList)){
                 redisUtil.set(SiteBlackIpKey + "::" + effectiveEnquiryParamDto.getSiteId(), blackIpList, 60 * 60 * 24);
             } else{
                 redisUtil.del(SiteBlackIpKey + "::" + effectiveEnquiryParamDto.getSiteId());
             }
 
             List<String> whiteIpList = redisList.stream().filter(siteBlackIp -> siteBlackIp.getBlackOrWhite().equals(1)).map(AdwebSiteBlackIp::getIp).collect(Collectors.toList());
-            if(ListUtil.notEmpty(whiteIpList)){
+            if(CollectionUtils.isNotEmpty(whiteIpList)){
                 redisUtil.set(SiteWhiteIpListKey + "::" + effectiveEnquiryParamDto.getSiteId(), whiteIpList, 60 * 60 * 24);
             } else{
                 redisUtil.del(SiteWhiteIpListKey + "::" + effectiveEnquiryParamDto.getSiteId());

+ 11 - 14
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/service/impl/EnquiryEmailMessageServiceImpl.java

@@ -7,17 +7,19 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fasterxml.jackson.databind.ObjectMapper;
+
+import jakarta.annotation.Resource;
+
 import lombok.Data;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.system.vo.DictModel;
 import org.jeecg.common.util.FastJsonUtil;
-
-
 import org.jeecg.modules.adweb.common.service.FeishuService;
-import org.jeecg.modules.adweb.common.util.JedisUtil;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.common.util.AdwebRedisUtil;
+import org.jeecg.modules.adweb.common.util.JedisUtil;
 import org.jeecg.modules.adweb.enquiry.constant.EnquiryConstants;
 import org.jeecg.modules.adweb.enquiry.constant.EnquirySendStatus;
 import org.jeecg.modules.adweb.enquiry.entity.AdwebEnquiry;
@@ -25,10 +27,7 @@ import org.jeecg.modules.adweb.enquiry.entity.AdwebEnquiryForm;
 import org.jeecg.modules.adweb.enquiry.entity.EnquiryEmailMessage;
 import org.jeecg.modules.adweb.enquiry.mapper.EnquiryEmailMessageMapper;
 import org.jeecg.modules.adweb.enquiry.service.IAdwebEnquiryFormService;
-import org.jeecg.modules.adweb.enquiry.service.IAdwebEnquiryService;
 import org.jeecg.modules.adweb.enquiry.service.IEnquiryEmailMessageService;
-
-
 import org.jeecg.modules.adweb.site.entity.AdwebSite;
 import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
 import org.jeecg.modules.adweb.system.entity.SysException;
@@ -36,7 +35,6 @@ import org.jeecg.modules.adweb.system.service.IMasterSubAccountRelationService;
 import org.jeecg.modules.adweb.system.service.ISysExceptionService;
 import org.jeecg.modules.message.handle.enums.SendMsgTypeEnum;
 import org.jeecg.modules.message.handle.impl.EmailSendMsgHandle;
-
 import org.jeecg.modules.system.entity.SysUser;
 import org.jeecg.modules.system.service.ISysDictService;
 import org.jeecg.modules.system.service.ISysUserService;
@@ -44,7 +42,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
-import jakarta.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -263,7 +260,7 @@ public class EnquiryEmailMessageServiceImpl extends ServiceImpl<EnquiryEmailMess
             List<String> subAccountIdList = masterSubAccountRelationService.getSubAccountIdByMaster(String.valueOf(adwebEnquiry.getUid()));
             if (!subAccountIdList.isEmpty()) {
                 List<SysUser> principalEmailList = sysUserService.list(new QueryWrapper<SysUser>().in("id", subAccountIdList).eq("del_flag", 0).isNotNull("email").ne("email","").select("id", "email"));
-                if (ListUtil.notEmpty(principalEmailList)) {
+                if (CollectionUtils.isNotEmpty(principalEmailList)) {
                     emailList = principalEmailList.stream().map(SysUser::getEmail).collect(Collectors.toList());
                 }
             }
@@ -274,14 +271,14 @@ public class EnquiryEmailMessageServiceImpl extends ServiceImpl<EnquiryEmailMess
             }
         }
 
-        if(ListUtil.notEmpty(emailList)){
+        if(CollectionUtils.isNotEmpty(emailList)){
             QueryWrapper<EnquiryEmailMessage> enquiryEmailMessageQueryWrapper = new QueryWrapper<>();
             enquiryEmailMessageQueryWrapper.eq("enquiry_id", adwebEnquiry.getId());
             enquiryEmailMessageQueryWrapper.eq("site_code", adwebEnquiry.getSiteCode());
             enquiryEmailMessageQueryWrapper.in("email",emailList);
             List<EnquiryEmailMessage> enquiryEmailMessageList = list(enquiryEmailMessageQueryWrapper);
 
-            if(ListUtil.notEmpty(enquiryEmailMessageList)){
+            if(CollectionUtils.isNotEmpty(enquiryEmailMessageList)){
                 List<String> oldEmailList = enquiryEmailMessageList.stream().map(EnquiryEmailMessage::getEmail).collect(Collectors.toList());
                 List<String> noNeedEmailList = new ArrayList<>();
                 for(String email : emailList){
@@ -289,12 +286,12 @@ public class EnquiryEmailMessageServiceImpl extends ServiceImpl<EnquiryEmailMess
                         noNeedEmailList.add(email);
                     }
                 }
-                if(ListUtil.notEmpty(noNeedEmailList)){
+                if(CollectionUtils.isNotEmpty(noNeedEmailList)){
                     emailList.removeAll(noNeedEmailList);
                 }
             }
 
-            if(ListUtil.notEmpty(emailList)){
+            if(CollectionUtils.isNotEmpty(emailList)){
                 List<EnquiryEmailMessage> enquiryEmailMessageList1 = new ArrayList<>();
                 for (String email : emailList){
                     EnquiryEmailMessage enquiryEmailMessage = new EnquiryEmailMessage();

+ 4 - 6
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/controller/SeoKeywordsController.java

@@ -26,7 +26,6 @@ import org.jeecg.common.system.base.controller.JeecgController;
 import org.jeecg.common.system.query.QueryGenerator;
 import org.jeecg.modules.adweb.seo.dto.AvesApiSearchKeywordsDTO;
 import org.jeecg.modules.adweb.seo.entity.SeoKeywords;
-import org.jeecg.modules.adweb.seo.service.ISearchKeywordsService;
 import org.jeecg.modules.adweb.seo.service.ISeoKeywordsService;
 import org.jeecg.modules.adweb.seo.service.ISeoKeywordsRankService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -52,11 +51,10 @@ public class SeoKeywordsController extends JeecgController<SeoKeywords, ISeoKeyw
 	@Autowired
 	private ISeoKeywordsService seoKeywordsService;
 
-	@Autowired
-	ISeoKeywordsRankService seoKpiStatisticsService;
+	@Autowired ISeoKeywordsRankService seoKeywordsRankService;
 
 	@Autowired
-	ISearchKeywordsService searchKeywordsService;
+	ISeoKeywordsRankService seoKpiStatisticsService;
 
 	@Autowired
 	private ISysBaseAPI sysBaseAPI;
@@ -234,7 +232,7 @@ public class SeoKeywordsController extends JeecgController<SeoKeywords, ISeoKeyw
 		 if(pageList == null){
 			 return Result.error("未获取到关键词数据");
 		 }
-		 searchKeywordsService.addRankInfoByIntervalTimeByType(pageList.getRecords(), avesApiSearchKeywordsDTO.getKeywordType(),siteCode,subscriptionId,dateList);
+		 seoKeywordsRankService.addRankInfoByIntervalTimeByType(pageList.getRecords(), avesApiSearchKeywordsDTO.getKeywordType(),siteCode,subscriptionId,dateList);
 		 log.info(pageList.toString());
 		 return Result.OK(pageList);
 	 }
@@ -308,7 +306,7 @@ public class SeoKeywordsController extends JeecgController<SeoKeywords, ISeoKeyw
 			response.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName + ".xlsx").getBytes(), StandardCharsets.ISO_8859_1));
 			out = response.getOutputStream();
 			writer.write(list, true);
-			searchKeywordsService.setSizeColumn(sheet, list.get(0).size());
+			seoKeywordsRankService.setSizeColumn(sheet, list.get(0).size());
 			// 写出到文件
 			writer.flush(out, true);
 			// 关闭writer,释放内存

+ 3 - 6
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/controller/SeoKeywordsRankController.java

@@ -6,7 +6,6 @@ import lombok.extern.slf4j.Slf4j;
 
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.modules.adweb.seo.entity.ComprehensiveStatistics;
-import org.jeecg.modules.adweb.seo.service.ISearchKeywordsService;
 import org.jeecg.modules.adweb.seo.service.ISeoKeywordsRankService;
 import org.jeecg.modules.adweb.site.entity.AdwebSite;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -26,8 +25,6 @@ import java.util.Map;
 public class SeoKeywordsRankController {
     @Autowired private ISeoKeywordsRankService seoKeywordsRankService;
 
-    @Autowired private ISearchKeywordsService searchKeywordsService;
-
     /** 获取当前用户管理的 父 站点信息 @CopyFrom: getAllSites */
     @GetMapping("/getAllSites")
     public Result<List<AdwebSite>> getAllSites() {
@@ -39,8 +36,8 @@ public class SeoKeywordsRankController {
      * 获得综合统计信息
      */
     @GetMapping(value = "/comprehensiveInfo")
-    public Result<?> getComprehensiveInfo(@RequestParam String siteCode, @RequestParam String subscriptionId) throws ParseException {
-        ComprehensiveStatistics statistics = searchKeywordsService.getComprehensiveInfo(siteCode, subscriptionId);
+    public Result<?> getComprehensiveInfo(@RequestParam String siteCode, @RequestParam String planId) throws ParseException {
+        ComprehensiveStatistics statistics = seoKeywordsRankService.getComprehensiveInfo(siteCode, planId);
         return Result.OK(statistics);
     }
 
@@ -49,7 +46,7 @@ public class SeoKeywordsRankController {
      */
     @GetMapping(value = "/getRankInfo")
     public Result<?> getRankInfo(@RequestParam("siteCode") String siteCode, @RequestParam("subscriptionId") String subscriptionId) throws ParseException {
-        Map map = searchKeywordsService.getRankInfo(siteCode, subscriptionId);
+        Map map = seoKeywordsRankService.getRankInfo(siteCode, subscriptionId);
         return Result.OK(map);
     }
 }

+ 18 - 14
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/entity/ComprehensiveStatistics.java

@@ -10,37 +10,41 @@ import lombok.Data;
 @Data
 public class ComprehensiveStatistics {
     /**
-     * 指定词
+     * 套餐指定词
      */
-    private String appointKeywordNum;
+    private Integer planAppointKeywordNum;
 
     /**
-     * 长尾词
+     * 套餐长尾词
      */
-    private String longTailKeywordNum;
+    private Integer planLongTailKeywordNum;
 
     /**
-     * 外链数
+     * 套餐外链数
      */
-    private String outerLinkNum;
+    private Integer planOuterLinkNum;
 
     /**
-     * 文章数
+     * 套餐文章数
+     */
+    private Integer planArticleNum;
+    /**
+     * 指定词
      */
-    private String articleNum;
+    private Integer appointKeywordNum;
 
     /**
-     * 询盘数
+     * 长尾词
      */
-    private String enquiryNum;
+    private Integer longTailKeywordNum;
 
     /**
-     * 访问量(UV)
+     * 外链数
      */
-    private String uvNum;
+    private Integer outerLinkNum;
 
     /**
-     * 是否展示访问量
+     * 文章数
      */
-    private boolean showUvNum;
+    private Integer articleNum;
 }

+ 0 - 26
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/ISearchKeywordsService.java

@@ -1,26 +0,0 @@
-package org.jeecg.modules.adweb.seo.service;
-
-import org.apache.poi.ss.usermodel.Sheet;
-import org.jeecg.modules.adweb.seo.entity.ComprehensiveStatistics;
-import org.jeecg.modules.adweb.seo.entity.SeoKeywords;
-import org.jeecg.modules.adweb.seo.vo.SeoRankInfoVO;
-
-import java.text.ParseException;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Zenas
- */
-public interface ISearchKeywordsService {
-
-    ComprehensiveStatistics getComprehensiveInfo(String siteCode, String historyId) throws ParseException;
-
-    Map getRankInfo(String siteCode, String historyId) throws ParseException;
-
-    List<SeoRankInfoVO> getSeoRankInfo(String siteCode, String historyId) throws ParseException;
-
-    void addRankInfoByIntervalTimeByType(List<SeoKeywords> keywordList, Integer keywordType, String siteCode, String historyId, List<String> dateList) throws Exception;
-
-    void setSizeColumn(Sheet sheet, int size);
-}

+ 17 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/ISeoKeywordsRankService.java

@@ -1,8 +1,14 @@
 package org.jeecg.modules.adweb.seo.service;
 
+import org.apache.poi.ss.usermodel.Sheet;
+import org.jeecg.modules.adweb.seo.entity.ComprehensiveStatistics;
+import org.jeecg.modules.adweb.seo.entity.SeoKeywords;
+import org.jeecg.modules.adweb.seo.vo.SeoRankInfoVO;
 import org.jeecg.modules.adweb.site.entity.AdwebSite;
 
+import java.text.ParseException;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @Description: seo_kpi_statistics
@@ -13,4 +19,15 @@ import java.util.List;
 public interface ISeoKeywordsRankService {
 
     List<AdwebSite> getAllSites();
+
+    ComprehensiveStatistics getComprehensiveInfo(String siteCode, String subscriptionId);
+
+    Map getRankInfo(String siteCode, String historyId) throws ParseException;
+
+    List<SeoRankInfoVO> getSeoRankInfo(String siteCode, String historyId)
+            throws ParseException;
+
+    void addRankInfoByIntervalTimeByType(List<SeoKeywords> keywordList, Integer keywordType, String siteCode, String historyId, List<String> dateList) throws Exception;
+
+    void setSizeColumn(Sheet sheet, int size);
 }

+ 11 - 20
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/dataforseo/DataForSEOService.java

@@ -1,7 +1,6 @@
 package org.jeecg.modules.adweb.seo.service.dataforseo;
 
 import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.json.JSONUtil;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -17,17 +16,17 @@ import jakarta.annotation.PostConstruct;
 
 import lombok.extern.slf4j.Slf4j;
 
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.jeecg.common.util.FastJsonUtil;
 import org.jeecg.modules.adweb.common.util.AdwebRedisUtil;
 import org.jeecg.modules.adweb.common.util.CommonUtil;
 import org.jeecg.modules.adweb.common.util.DateUtil;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.seo.entity.SeoKeywords;
 import org.jeecg.modules.adweb.seo.entity.SeoKeywordsSerp;
 import org.jeecg.modules.adweb.seo.mapper.SeoKeywordsMapper;
 import org.jeecg.modules.adweb.seo.service.ISeoKeywordsSerpService;
 import org.jeecg.modules.adweb.seo.service.ISeoKeywordsService;
-import org.jeecg.modules.adweb.site.entity.AdwebSite;
 import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -95,26 +94,19 @@ public class DataForSEOService {
     /**
      * 全局查询更新DataForSEO keywords Serp数据 - 启动Serp任务并保存到Redis
      *
+     * @param siteCodes 待执行的网站codes,为空时执行所有网站
      * @param keywordType 1 - 指定词; 2 - 长尾词
      * @param limit 最大查询条数
      */
     public void runKeywordsSerpTasks(List<String> siteCodes, int keywordType, int limit) {
-        if (ListUtil.isEmpty(siteCodes)) {
-            siteCodes =
-                    adwebSiteService
-                            .list(
-                                    new LambdaQueryWrapper<AdwebSite>()
-                                            .eq(AdwebSite::getStatus, 1)
-                                            .eq(AdwebSite::getRunStatus, 1))
-                            .stream()
-                            .map(AdwebSite::getCode)
-                            .toList();
+        if (CollectionUtil.isEmpty(siteCodes)) {
+            siteCodes = adwebSiteService.getAllActiveSiteCodes();
         }
 
         List<SeoKeywords> seoKeywords =
                 seoKeywordsMapper.getKeywordsToSerp(siteCodes, keywordType, limit);
 
-        if (ListUtil.isEmpty(seoKeywords)) {
+        if (CollectionUtils.isEmpty(seoKeywords)) {
             log.info("暂无需要Serp查询的关键词");
         } else {
             // DataForSEO - each POST call containing no more than 100 tasks
@@ -167,7 +159,7 @@ public class DataForSEOService {
                     serpApi.googleOrganicTaskPost(serpTaskRequestInfoList);
             log.info(
                     "创建DataForSEO Serp任务,response = {}",
-                    JSONUtil.toJsonStr(serpTaskPostResponseInfo));
+                    FastJsonUtil.toJSONString(serpTaskPostResponseInfo));
             if (serpTaskPostResponseInfo.getStatusCode() != SERP_STATUS_CODE_SUCCESS) {
                 throw new ApiException(serpTaskPostResponseInfo.getStatusMessage());
             }
@@ -223,7 +215,7 @@ public class DataForSEOService {
             String taskId = redisUtil.getString(serpTaskRedisKey);
             SerpGoogleOrganicTaskGetRegularTaskInfo serpTask =
                     serpApi.googleOrganicTaskGetRegular(taskId).getTasks().get(0);
-            log.info("获取DataForSEO Serp任务,response = {}", JSONUtil.toJsonStr(serpTask));
+            log.info("获取DataForSEO Serp任务,response = {}", FastJsonUtil.toJSONString(serpTask));
             if (serpTask.getStatusCode() != SERP_STATUS_CODE_SUCCESS) {
                 log.info(
                         "DataForSEO Serp任务 {} 状态为 {} {}",
@@ -261,7 +253,7 @@ public class DataForSEOService {
 
             // 读取Serp相关数据
             Date seDatetime =
-                    DateUtil.parseDate(serpResult.getDatetime(), DateUtil.ZONED_DATE_TIME_PATTERN);
+                    DateUtil.parseDate(serpResult.getDatetime(), DateUtil.ZONED_DATE_TIME_FORMAT);
             String positionUrl =
                     Objects.nonNull(serpItem)
                             ? StringUtils.removeEnd(serpItem.getUrl(), "/")
@@ -290,8 +282,7 @@ public class DataForSEOService {
                                             .eq(SeoKeywordsSerp::getKeywordsId, keywordId)
                                             .eq(
                                                     SeoKeywordsSerp::getSeDate,
-                                                    DateUtil.formatDate(
-                                                            seDatetime, DateUtil.DATE_PATTERN)))
+                                                    DateUtil.getTodayZeroTime(seDatetime)))
                             .stream()
                             .findFirst()
                             .orElse(new SeoKeywordsSerp());
@@ -304,7 +295,7 @@ public class DataForSEOService {
             keywordSerp.setPageNumber(rankGroup > 0 ? rankGroup / GOOGLE_SEARCH_PAGE_SIZE + 1 : 0);
             keywordSerp.setRankGroup(rankGroup);
             keywordSerp.setRankAbsolute(rankAbsolute);
-            keywordSerp.setSeDate(DateUtil.formatDateStr(seDatetime, DateUtil.DATE_PATTERN));
+            keywordSerp.setSeDate(DateUtil.formatDate(seDatetime, DateUtil.DATE_FORMAT));
             keywordSerp.setSeDatetime(seDatetime);
             seoKeywordsSerpService.save(keywordSerp);
 

+ 0 - 259
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/impl/SearchKeywordsServiceImpl.java

@@ -1,259 +0,0 @@
-package org.jeecg.modules.adweb.seo.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.xkcoding.http.util.StringUtil;
-
-import jakarta.annotation.Resource;
-
-import lombok.extern.slf4j.Slf4j;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.jeecg.modules.adweb.common.util.ListUtil;
-import org.jeecg.modules.adweb.seo.entity.*;
-import org.jeecg.modules.adweb.seo.mapper.SeoKeywordsMapper;
-import org.jeecg.modules.adweb.seo.service.*;
-import org.jeecg.modules.adweb.seo.vo.RankInfoVO;
-import org.jeecg.modules.adweb.seo.vo.SeoRankInfoVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.text.ParseException;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * @author Zenas
- */
-@Slf4j
-@Service
-public class SearchKeywordsServiceImpl implements ISearchKeywordsService {
-
-    @Resource private SeoKeywordsMapper seoKeywordsMapper;
-
-    @Autowired private ISeoKeywordsService seoKeywordsService;
-
-    @Autowired private ISeoKeywordsSerpService seoKeywordsSerpService;
-
-    /**
-     * 获得综合统计的数据
-     *
-     * @param siteCode 站点code
-     * @param subscriptionId 订阅表id
-     * @return 综合统计的数据
-     */
-    @Override
-    public ComprehensiveStatistics getComprehensiveInfo(String siteCode, String subscriptionId) {
-        ComprehensiveStatistics comprehensiveStatistics = new ComprehensiveStatistics();
-
-        return comprehensiveStatistics;
-    }
-
-    @Override
-    public Map getRankInfo(String siteCode, String historyId) throws ParseException {
-        List<SeoRankInfoVO> seoRankInfos = this.getSeoRankInfo(siteCode, historyId);
-
-        Map map = new HashMap<>();
-        map.put("appointKeyword", seoRankInfos.get(0));
-        map.put("longTailKeyword", seoRankInfos.get(1));
-        return map;
-    }
-
-    /**
-     * 获取一个站点的关键词排名数量
-     *
-     * @param siteCode 站点code
-     * @return 关键词排名数量
-     */
-    @Override
-    public List<SeoRankInfoVO> getSeoRankInfo(String siteCode, String historyId)
-            throws ParseException {
-        // 排名信息
-        SeoRankInfoVO appointRankInfo = new SeoRankInfoVO();
-        SeoRankInfoVO longTailRankInfo = new SeoRankInfoVO();
-        // 1-10
-        Map<String, Integer> first = dealKeywordsRankData(siteCode, historyId, 1, 10);
-        if (first.containsKey("appoint")) {
-            appointRankInfo.setFirstNum(first.get("appoint"));
-        }
-        if (first.containsKey("longTail")) {
-            longTailRankInfo.setFirstNum(first.get("longTail"));
-        }
-
-        // 11-30
-        Map<String, Integer> second = dealKeywordsRankData(siteCode, historyId, 11, 30);
-        if (second.containsKey("appoint")) {
-            appointRankInfo.setSecondNum(second.get("appoint"));
-        }
-        if (second.containsKey("longTail")) {
-            longTailRankInfo.setSecondNum(second.get("longTail"));
-        }
-        // 31-100
-        Map<String, Integer> third = dealKeywordsRankData(siteCode, historyId, 31, 100);
-        if (third.containsKey("appoint")) {
-            appointRankInfo.setThirdType(third.get("appoint"));
-        }
-        if (third.containsKey("longTail")) {
-            longTailRankInfo.setThirdType(third.get("longTail"));
-        }
-        List<SeoRankInfoVO> list = new ArrayList<>();
-        list.add(appointRankInfo);
-        list.add(longTailRankInfo);
-        return list;
-    }
-
-    private Map<String, Integer> dealKeywordsRankData(
-            String siteCode, String historyId, Integer rankStart, Integer rankEnd) {
-        Map<String, Integer> KeywordsRankMap = new HashMap<>();
-
-        // 指定词
-        List<String> appointDateList =
-                seoKeywordsService.getKeywordsLastSevenDays(siteCode, 1, historyId);
-        String appointDatesStr = "";
-        if (ListUtil.notEmpty(appointDateList)) {
-            for (int i = 0; i < appointDateList.size(); i++) {
-                if (i == appointDateList.size() - 1) {
-                    appointDatesStr += "'" + appointDateList.get(i) + "'";
-                } else {
-                    appointDatesStr += "'" + appointDateList.get(i) + "'" + ",";
-                }
-            }
-            appointDatesStr = "(" + appointDatesStr + ")";
-
-            // 指定词
-            RankInfoVO appointRankInfo =
-                    seoKeywordsMapper.queryKeywordNumByRankRange(
-                            siteCode, historyId, rankStart, rankEnd, appointDatesStr, "1");
-            if (appointRankInfo != null) {
-                KeywordsRankMap.put("appoint", appointRankInfo.getKeywordNum());
-            }
-        }
-
-        // 长尾词
-        List<String> dateList = seoKeywordsService.getKeywordsLastSevenDays(siteCode, 2, historyId);
-        String dateStr = "";
-        if (ListUtil.notEmpty(dateList)) {
-            for (int i = 0; i < dateList.size(); i++) {
-                if (i == dateList.size() - 1) {
-                    dateStr += "'" + dateList.get(i) + "'";
-                } else {
-                    dateStr += "'" + dateList.get(i) + "'" + ",";
-                }
-            }
-            dateStr = "(" + dateStr + ")";
-            RankInfoVO longRankInfo =
-                    seoKeywordsMapper.queryKeywordNumByRankRange(
-                            siteCode, historyId, rankStart, rankEnd, dateStr, "2");
-            if (longRankInfo != null) {
-                KeywordsRankMap.put("longTail", longRankInfo.getKeywordNum());
-            }
-        }
-        return KeywordsRankMap;
-    }
-
-    /**
-     * 给列表中的关键字增加排名信息
-     * 根据关键词类型
-     * @param keywordList 关键词列表
-     *
-     */
-    @Override
-    public void addRankInfoByIntervalTimeByType(List<SeoKeywords> keywordList, Integer keywordType, String siteCode, String historyId, List<String> dateList) throws Exception {
-        if (ListUtil.isEmpty(keywordList)) {
-            return;
-        }
-
-        String datesStr = "";
-        if(ListUtil.isEmpty(dateList)){
-            return;
-        }else{
-            for(int i = 0; i < dateList.size(); i++){
-                if(i == dateList.size() - 1){
-                    datesStr +=  "'" + dateList.get(i) + "'";
-                }else{
-                    datesStr +=  "'" + dateList.get(i) + "'" + ",";
-                }
-            }
-            datesStr = "(" + datesStr + ")";
-        }
-        List<Integer> keywordIds = keywordList.stream().map(SeoKeywords::getId).collect(Collectors.toList());
-        List<SeoKeywordsSerp> serpList = seoKeywordsSerpService.list(new LambdaQueryWrapper<SeoKeywordsSerp>()
-                .in(SeoKeywordsSerp::getKeywordsId, keywordIds)
-                .in(SeoKeywordsSerp::getSeDate, dateList));
-        List<SeoKeywordsSerp> noRepeatSerpList = new ArrayList<>();
-        Map<String, Integer> serpMap = new HashMap<>();
-        if(ListUtil.notEmpty(serpList)){
-            for (SeoKeywordsSerp seoKeywordsSerp : serpList) {
-                seoKeywordsSerp.setKey(seoKeywordsSerp.getKeywordsId() + "_" + seoKeywordsSerp.getSeDate());
-                if(ListUtil.notEmpty(noRepeatSerpList)){
-                    List<SeoKeywordsSerp> have = noRepeatSerpList.stream().filter(o -> o.getKey().equals(seoKeywordsSerp.getKey())).collect(Collectors.toList());
-                    if(ListUtil.isEmpty(have)){
-                        serpMap.put(seoKeywordsSerp.getKey(),seoKeywordsSerp.getRankAbsolute());
-                        noRepeatSerpList.add(seoKeywordsSerp);
-                    }else{
-                        log.info("重复的数据:" + seoKeywordsSerp.getKey());
-                    }
-                }else {
-                    serpMap.put(seoKeywordsSerp.getKey(),seoKeywordsSerp.getRankAbsolute());
-                    noRepeatSerpList.add(seoKeywordsSerp);
-                }
-            }
-        }
-
-        for (SeoKeywords keyword : keywordList) {
-            Map<String, String> rankInfo = new LinkedHashMap<>();
-            for (String date : dateList) {
-
-                // 从Map中获取那天的排名信息
-                Integer rankAbsolute = serpMap.get(keyword.getId() + "_" + date);
-
-                if(rankAbsolute == null){
-                    rankAbsolute = 0;
-                }
-                rankInfo.put(date, rankAbsolute + "");
-            }
-
-            keyword.setRankInfo(rankInfo);
-            keyword.setIpAddress("223.112.18.226");
-
-            keyword.setDateList(dateList);
-            if(StringUtil.isEmpty(keyword.getSearchUrl())){
-                keyword.setSearchUrl("https://www.google.com/");
-            }
-        }
-    }
-
-    /**
-     * 自适应宽度(中文支持)
-     * @param sheet
-     * @param size 因为for循环从0开始,size值为 列数-1
-     */
-    @Override
-    public void setSizeColumn(Sheet sheet, int size) {
-        for (int columnNum = 0; columnNum <= size; columnNum++) {
-            int columnWidth = sheet.getColumnWidth(columnNum) / 256;
-            for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
-                Row currentRow;
-                //当前行未被使用过
-                if (sheet.getRow(rowNum) == null) {
-                    currentRow = sheet.createRow(rowNum);
-                } else {
-                    currentRow = sheet.getRow(rowNum);
-                }
-
-                if (currentRow.getCell(columnNum) != null) {
-                    Cell currentCell = currentRow.getCell(columnNum);
-                    if (currentCell.getCellType() == CellType.STRING) {
-                        int length = currentCell.getStringCellValue().getBytes().length;
-                        if (columnWidth < length) {
-                            columnWidth = length;
-                        }
-                    }
-                }
-            }
-            sheet.setColumnWidth(columnNum, columnWidth * 256);
-        }
-    }
-}

+ 282 - 12
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/impl/SeoKeywordsRankServiceImpl.java

@@ -1,25 +1,44 @@
 package org.jeecg.modules.adweb.seo.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.xkcoding.http.util.StringUtil;
+
+import jakarta.annotation.Resource;
 
 import lombok.extern.slf4j.Slf4j;
 
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.system.api.ISysBaseAPI;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.modules.adweb.common.constant.AdwebConstant;
-import org.jeecg.modules.adweb.common.util.ListUtil;
+import org.jeecg.modules.adweb.seo.entity.ComprehensiveStatistics;
+import org.jeecg.modules.adweb.seo.entity.SeoKeywords;
+import org.jeecg.modules.adweb.seo.entity.SeoKeywordsSerp;
 import org.jeecg.modules.adweb.seo.entity.SeoPlanSubscription;
+import org.jeecg.modules.adweb.seo.mapper.SeoKeywordsMapper;
 import org.jeecg.modules.adweb.seo.service.ISeoKeywordsRankService;
+import org.jeecg.modules.adweb.seo.service.ISeoKeywordsSerpService;
+import org.jeecg.modules.adweb.seo.service.ISeoKeywordsService;
 import org.jeecg.modules.adweb.seo.service.ISeoPlanSubscriptionService;
+import org.jeecg.modules.adweb.seo.vo.RankInfoVO;
+import org.jeecg.modules.adweb.seo.vo.SeoRankInfoVO;
 import org.jeecg.modules.adweb.site.entity.AdwebSite;
 import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
 import org.jeecg.modules.adweb.site.service.ISiteUserPermissionService;
+import org.jeecg.modules.adweb.subscribePlan.entity.SubscribePlan;
+import org.jeecg.modules.adweb.subscribePlan.mapper.SubscribePlanMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.text.ParseException;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @Description: seo_kpi_statistics @Author: jeecg-boot @Date: 2024-10-09 @Version: V1.0
@@ -36,6 +55,14 @@ public class SeoKeywordsRankServiceImpl implements ISeoKeywordsRankService {
 
     @Autowired private ISeoPlanSubscriptionService seoPlanSubscriptionService;
 
+    @Autowired private ISeoKeywordsService seoKeywordsService;
+
+    @Resource private SeoKeywordsMapper seoKeywordsMapper;
+
+    @Autowired private ISeoKeywordsSerpService seoKeywordsSerpService;
+
+    @Resource private SubscribePlanMapper subscribePlanMapper;
+
     @Override
     public List<AdwebSite> getAllSites() {
         log.info("获取当前用户管理的 父 站点信息");
@@ -61,7 +88,7 @@ public class SeoKeywordsRankServiceImpl implements ISeoKeywordsRankService {
 
     /** 放入营销方案名称 */
     private void setPlanName(List<AdwebSite> siteList) {
-        if (ListUtil.isEmpty(siteList)) {
+        if (CollectionUtils.isEmpty(siteList)) {
             return;
         }
 
@@ -74,20 +101,263 @@ public class SeoKeywordsRankServiceImpl implements ISeoKeywordsRankService {
         historyQueryWrapper.select("id", "plan_id", "site_id", "plan_name", "plan_type");
         historyQueryWrapper.in("site_id", siteIds);
         historyQueryWrapper.eq("status", 1);
-        List<SeoPlanSubscription> histories = seoPlanSubscriptionService.list(historyQueryWrapper);
-        if (ListUtil.isEmpty(histories)) {
+        List<SeoPlanSubscription> seoPlanSubscriptions = seoPlanSubscriptionService.list(historyQueryWrapper);
+        if (CollectionUtils.isEmpty(seoPlanSubscriptions)) {
             return;
         }
 
         for (AdwebSite site : siteList) {
-            for (SeoPlanSubscription history : histories) {
-                if (history.getSiteId().equals(site.getId() + "")) {
-                    site.setPlanId(history.getPlanId());
-                    site.setPlanName(history.getPlanName());
-                    site.setHistoryId(history.getId());
-                    site.setPlanType(history.getPlanType());
+            for (SeoPlanSubscription seoPlanSubscription : seoPlanSubscriptions) {
+                if (seoPlanSubscription.getSiteId().equals(site.getId() + "")) {
+                    site.setPlanId(seoPlanSubscription.getPlanId());
+                    site.setPlanName(seoPlanSubscription.getPlanName());
+                    site.setSubscriptionId(seoPlanSubscription.getId());
+                    site.setPlanType(seoPlanSubscription.getPlanType());
+                }
+            }
+        }
+    }
+
+    /**
+     * 获得综合统计的数据
+     *
+     * @param siteCode 站点code
+     * @param planId 套餐表id
+     * @return 综合统计的数据
+     */
+    @Override
+    public ComprehensiveStatistics getComprehensiveInfo(String siteCode, String planId) {
+        ComprehensiveStatistics comprehensiveStatistics = new ComprehensiveStatistics();
+        SubscribePlan subscribePlan = subscribePlanMapper.selectById(planId);
+        log.info("planId:{}, subscribePlan:{}", planId, subscribePlan.toString());
+        if (subscribePlan != null) {
+            // 添加套餐数据
+            comprehensiveStatistics.setPlanAppointKeywordNum(subscribePlan.getSpecifyKeyword());
+            comprehensiveStatistics.setPlanLongTailKeywordNum(subscribePlan.getLongTailKeyword());
+            comprehensiveStatistics.setPlanOuterLinkNum(subscribePlan.getExternalLinks());
+            comprehensiveStatistics.setPlanArticleNum(subscribePlan.getArticle());
+        }
+        // 添加站点数据
+        // 1.获取站点指定词数量
+        QueryWrapper<SeoKeywords> seoKeywordsQueryWrapper = new QueryWrapper<>();
+        seoKeywordsQueryWrapper.eq("site_code", siteCode);
+        seoKeywordsQueryWrapper.eq("status", 1);
+        seoKeywordsQueryWrapper.eq("keyword_type", 1);
+        Long appointKeywordNum = seoKeywordsMapper.selectCount(seoKeywordsQueryWrapper);
+        // 2.获取站点关键词数量
+        QueryWrapper<SeoKeywords> seoKeywordsQueryWrapper1 = new QueryWrapper<>();
+        seoKeywordsQueryWrapper1.eq("site_code", siteCode);
+        seoKeywordsQueryWrapper1.eq("status", 1);
+        seoKeywordsQueryWrapper1.eq("keyword_type", 2);
+        Long longTailKeywordNum = seoKeywordsMapper.selectCount(seoKeywordsQueryWrapper1);
+        comprehensiveStatistics.setAppointKeywordNum(Math.toIntExact(appointKeywordNum));
+        comprehensiveStatistics.setLongTailKeywordNum(Math.toIntExact(longTailKeywordNum));
+        return comprehensiveStatistics;
+    }
+
+    @Override
+    public Map getRankInfo(String siteCode, String subscriptionId) throws ParseException {
+        List<SeoRankInfoVO> seoRankInfos = this.getSeoRankInfo(siteCode, subscriptionId);
+
+        Map map = new HashMap<>();
+        map.put("appointKeyword", seoRankInfos.get(0));
+        map.put("longTailKeyword", seoRankInfos.get(1));
+        return map;
+    }
+
+    /**
+     * 获取一个站点的关键词排名数量
+     *
+     * @param siteCode 站点code
+     * @return 关键词排名数量
+     */
+    @Override
+    public List<SeoRankInfoVO> getSeoRankInfo(String siteCode, String subscriptionId)
+            throws ParseException {
+        // 排名信息
+        SeoRankInfoVO appointRankInfo = new SeoRankInfoVO();
+        SeoRankInfoVO longTailRankInfo = new SeoRankInfoVO();
+        // 1-10
+        Map<String, Integer> first = dealKeywordsRankData(siteCode, subscriptionId, 1, 10);
+        if (first.containsKey("appoint")) {
+            appointRankInfo.setFirstNum(first.get("appoint"));
+        }
+        if (first.containsKey("longTail")) {
+            longTailRankInfo.setFirstNum(first.get("longTail"));
+        }
+
+        // 11-30
+        Map<String, Integer> second = dealKeywordsRankData(siteCode, subscriptionId, 11, 30);
+        if (second.containsKey("appoint")) {
+            appointRankInfo.setSecondNum(second.get("appoint"));
+        }
+        if (second.containsKey("longTail")) {
+            longTailRankInfo.setSecondNum(second.get("longTail"));
+        }
+        // 31-100
+        Map<String, Integer> third = dealKeywordsRankData(siteCode, subscriptionId, 31, 100);
+        if (third.containsKey("appoint")) {
+            appointRankInfo.setThirdType(third.get("appoint"));
+        }
+        if (third.containsKey("longTail")) {
+            longTailRankInfo.setThirdType(third.get("longTail"));
+        }
+        List<SeoRankInfoVO> list = new ArrayList<>();
+        list.add(appointRankInfo);
+        list.add(longTailRankInfo);
+        return list;
+    }
+
+    private Map<String, Integer> dealKeywordsRankData(
+            String siteCode, String subscriptionId, Integer rankStart, Integer rankEnd) {
+        Map<String, Integer> KeywordsRankMap = new HashMap<>();
+
+        // 指定词
+        List<String> appointDateList =
+                seoKeywordsService.getKeywordsLastSevenDays(siteCode, 1, subscriptionId);
+        String appointDatesStr = "";
+        if (CollectionUtils.isNotEmpty(appointDateList)) {
+            for (int i = 0; i < appointDateList.size(); i++) {
+                if (i == appointDateList.size() - 1) {
+                    appointDatesStr += "'" + appointDateList.get(i) + "'";
+                } else {
+                    appointDatesStr += "'" + appointDateList.get(i) + "'" + ",";
+                }
+            }
+            appointDatesStr = "(" + appointDatesStr + ")";
+
+            // 指定词
+            RankInfoVO appointRankInfo =
+                    seoKeywordsMapper.queryKeywordNumByRankRange(
+                            siteCode, subscriptionId, rankStart, rankEnd, appointDatesStr, "1");
+            if (appointRankInfo != null) {
+                KeywordsRankMap.put("appoint", appointRankInfo.getKeywordNum());
+            }
+        }
+
+        // 长尾词
+        List<String> dateList = seoKeywordsService.getKeywordsLastSevenDays(siteCode, 2, subscriptionId);
+        String dateStr = "";
+        if (CollectionUtils.isNotEmpty(dateList)) {
+            for (int i = 0; i < dateList.size(); i++) {
+                if (i == dateList.size() - 1) {
+                    dateStr += "'" + dateList.get(i) + "'";
+                } else {
+                    dateStr += "'" + dateList.get(i) + "'" + ",";
+                }
+            }
+            dateStr = "(" + dateStr + ")";
+            RankInfoVO longRankInfo =
+                    seoKeywordsMapper.queryKeywordNumByRankRange(
+                            siteCode, subscriptionId, rankStart, rankEnd, dateStr, "2");
+            if (longRankInfo != null) {
+                KeywordsRankMap.put("longTail", longRankInfo.getKeywordNum());
+            }
+        }
+        return KeywordsRankMap;
+    }
+
+    /**
+     * 给列表中的关键字增加排名信息
+     * 根据关键词类型
+     * @param keywordList 关键词列表
+     *
+     */
+    @Override
+    public void addRankInfoByIntervalTimeByType(List<SeoKeywords> keywordList, Integer keywordType, String siteCode, String subscriptionId, List<String> dateList) throws Exception {
+        if (CollectionUtils.isEmpty(keywordList)) {
+            return;
+        }
+
+        String datesStr = "";
+        if(CollectionUtils.isEmpty(dateList)){
+            return;
+        }else{
+            for(int i = 0; i < dateList.size(); i++){
+                if(i == dateList.size() - 1){
+                    datesStr +=  "'" + dateList.get(i) + "'";
+                }else{
+                    datesStr +=  "'" + dateList.get(i) + "'" + ",";
+                }
+            }
+            datesStr = "(" + datesStr + ")";
+        }
+        List<Integer> keywordIds = keywordList.stream().map(SeoKeywords::getId).collect(Collectors.toList());
+        List<SeoKeywordsSerp> serpList = seoKeywordsSerpService.list(new LambdaQueryWrapper<SeoKeywordsSerp>()
+                .in(SeoKeywordsSerp::getKeywordsId, keywordIds)
+                .in(SeoKeywordsSerp::getSeDate, dateList));
+        List<SeoKeywordsSerp> noRepeatSerpList = new ArrayList<>();
+        Map<String, Integer> serpMap = new HashMap<>();
+        if(CollectionUtils.isNotEmpty(serpList)){
+            for (SeoKeywordsSerp seoKeywordsSerp : serpList) {
+                seoKeywordsSerp.setKey(seoKeywordsSerp.getKeywordsId() + "_" + seoKeywordsSerp.getSeDate());
+                if(CollectionUtils.isNotEmpty(noRepeatSerpList)){
+                    List<SeoKeywordsSerp> have = noRepeatSerpList.stream().filter(o -> o.getKey().equals(seoKeywordsSerp.getKey())).collect(Collectors.toList());
+                    if(CollectionUtils.isEmpty(have)){
+                        serpMap.put(seoKeywordsSerp.getKey(),seoKeywordsSerp.getRankAbsolute());
+                        noRepeatSerpList.add(seoKeywordsSerp);
+                    }else{
+                        log.info("重复的数据:" + seoKeywordsSerp.getKey());
+                    }
+                }else {
+                    serpMap.put(seoKeywordsSerp.getKey(),seoKeywordsSerp.getRankAbsolute());
+                    noRepeatSerpList.add(seoKeywordsSerp);
+                }
+            }
+        }
+
+        for (SeoKeywords keyword : keywordList) {
+            Map<String, String> rankInfo = new LinkedHashMap<>();
+            for (String date : dateList) {
+
+                // 从Map中获取那天的排名信息
+                Integer rankAbsolute = serpMap.get(keyword.getId() + "_" + date);
+
+                if(rankAbsolute == null){
+                    rankAbsolute = 0;
+                }
+                rankInfo.put(date, rankAbsolute + "");
+            }
+
+            keyword.setRankInfo(rankInfo);
+            keyword.setIpAddress("223.112.18.226");
+
+            keyword.setDateList(dateList);
+            if(StringUtil.isEmpty(keyword.getSearchUrl())){
+                keyword.setSearchUrl("https://www.google.com/");
+            }
+        }
+    }
+
+    /**
+     * 自适应宽度(中文支持)
+     * @param sheet
+     * @param size 因为for循环从0开始,size值为 列数-1
+     */
+    @Override
+    public void setSizeColumn(Sheet sheet, int size) {
+        for (int columnNum = 0; columnNum <= size; columnNum++) {
+            int columnWidth = sheet.getColumnWidth(columnNum) / 256;
+            for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
+                Row currentRow;
+                //当前行未被使用过
+                if (sheet.getRow(rowNum) == null) {
+                    currentRow = sheet.createRow(rowNum);
+                } else {
+                    currentRow = sheet.getRow(rowNum);
+                }
+
+                if (currentRow.getCell(columnNum) != null) {
+                    Cell currentCell = currentRow.getCell(columnNum);
+                    if (currentCell.getCellType() == CellType.STRING) {
+                        int length = currentCell.getStringCellValue().getBytes().length;
+                        if (columnWidth < length) {
+                            columnWidth = length;
+                        }
+                    }
                 }
             }
+            sheet.setColumnWidth(columnNum, columnWidth * 256);
         }
     }
 }

+ 4 - 5
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/impl/SeoKeywordsSerpServiceImpl.java

@@ -4,9 +4,9 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 
 import lombok.extern.slf4j.Slf4j;
 
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.jeecg.modules.adweb.common.util.DateUtil;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.seo.entity.SeoKeywordsSerp;
 import org.jeecg.modules.adweb.seo.mapper.SeoKeywordsSerpMapper;
 import org.jeecg.modules.adweb.seo.service.ISeoKeywordsSerpService;
@@ -44,7 +44,7 @@ public class SeoKeywordsSerpServiceImpl extends ServiceImpl<SeoKeywordsSerpMappe
         // Serp最后更新时间 + 一天
         Date startDate =
                 DateUtil.getTmrZeroTime(
-                        DateUtil.parseDate(latestSerp.getSeDate(), DateUtil.DATE_PATTERN));
+                        DateUtil.parseDate(latestSerp.getSeDate(), DateUtil.DATE_FORMAT));
         // DateForSEO返回的SearchEngine时间
         Date endDate = DateUtil.getTodayZeroTime(seDatetime);
 
@@ -63,13 +63,12 @@ public class SeoKeywordsSerpServiceImpl extends ServiceImpl<SeoKeywordsSerpMappe
             serp.setPageNumber(latestSerp.getPageNumber());
             serp.setRankGroup(latestSerp.getRankGroup());
             serp.setRankAbsolute(latestSerp.getRankAbsolute());
-            serp.setSeDate(
-                    DateUtil.formatDateStr(currentDate, DateUtil.DATE_PATTERN)); // 复制Serp值的目标日期
+            serp.setSeDate(DateUtil.formatDate(currentDate, DateUtil.DATE_FORMAT)); // 复制Serp值的目标日期
             serp.setSeDatetime(latestSerp.getSeDatetime()); // 真实Serp返回的SearchingEngine时间
             serpsToFill.add(serp);
         }
 
-        if (ListUtil.notEmpty(serpsToFill)) {
+        if (CollectionUtils.isNotEmpty(serpsToFill)) {
             log.info("复制Serp记录,keyword ID = {}, 时间范围 = {} to {}", keywordId, startDate, endDate);
             return this.saveBatch(serpsToFill);
         }

+ 2 - 2
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/seo/service/impl/SeoKeywordsServiceImpl.java

@@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 
 import jakarta.annotation.Resource;
 
-import org.jeecg.modules.adweb.common.util.ListUtil;
+import org.apache.commons.collections4.CollectionUtils;
 import org.jeecg.modules.adweb.seo.entity.SeoKeywords;
 import org.jeecg.modules.adweb.seo.mapper.SeoKeywordsMapper;
 import org.jeecg.modules.adweb.seo.service.ISeoKeywordsService;
@@ -82,7 +82,7 @@ public class SeoKeywordsServiceImpl extends ServiceImpl<SeoKeywordsMapper, SeoKe
         boolean isCustomer = true;
 
         String datesStr = "";
-        if(ListUtil.isEmpty(dateList)){
+        if(CollectionUtils.isEmpty(dateList)){
             return null;
         }else{
             for(int i = 0; i < dateList.size(); i++){

+ 6 - 2
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/site/controller/AdwebSiteController.java

@@ -3,12 +3,17 @@ package org.jeecg.modules.adweb.site.controller;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
 import io.netty.util.internal.StringUtil;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
+
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+
 import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.aspect.annotation.AutoLog;
@@ -16,7 +21,6 @@ import org.jeecg.common.system.base.controller.JeecgController;
 import org.jeecg.common.system.query.QueryGenerator;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.modules.adweb.common.constant.AdwebConstant;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.site.entity.AdwebSite;
 import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
 import org.jeecg.modules.adweb.site.service.ISiteUserPermissionService;
@@ -199,7 +203,7 @@ public class AdwebSiteController extends JeecgController<AdwebSite, IAdwebSiteSe
         List<AdwebSite> siteList = adwebSiteService.list(queryWrapper);
 
         // 处理域名,全部改为绝对路径
-        if (ListUtil.notEmpty(siteList)) {
+        if (CollectionUtils.isNotEmpty(siteList)) {
             for (AdwebSite site : siteList) {
                 String domain = site.getDomain();
                 if (StringUtil.isNullOrEmpty(domain)) {

+ 13 - 6
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/site/entity/AdwebSite.java

@@ -7,15 +7,20 @@ import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import org.springframework.format.annotation.DateTimeFormat;
-import org.jeecgframework.poi.excel.annotation.Excel;
-import org.jeecg.common.aspect.annotation.Dict;
+
 import io.swagger.v3.oas.annotations.media.Schema;
+
+import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
+import org.jeecg.common.aspect.annotation.Dict;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+
 /**
  * @Description: adweb站点配置表单
  * @Author: jeecg-boot
@@ -102,7 +107,6 @@ public class AdwebSite implements Serializable {
     @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
     @Schema(description = "到期时间,默认为ctime+1年")
     private java.util.Date etime;
-
 	/**站点大小*/
 	@Excel(name = "站点大小", width = 15)
     @Schema(description = "站点大小")
@@ -377,6 +381,9 @@ public class AdwebSite implements Serializable {
     @TableField(exist = false)
     private String planType;
 
+    /**
+     * 订阅ID
+     */
     @TableField(exist = false)
-    private String historyId;
+    private String subscriptionId;
 }

+ 5 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/site/service/IAdwebSiteService.java

@@ -54,4 +54,9 @@ public interface IAdwebSiteService extends IService<AdwebSite> {
      * @return 站点id
      */
     List<Integer> getAllSiteIdByUid(String uid);
+
+    /**
+     * 查询全部有效的站点code
+     */
+    List<String> getAllActiveSiteCodes();
 }

+ 16 - 5
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/site/service/impl/AdwebSiteServiceImpl.java

@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.xkcoding.http.util.StringUtil;
+import jakarta.annotation.Resource;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.system.vo.LoginUser;
@@ -11,19 +13,17 @@ import org.jeecg.common.util.FastJsonUtil;
 import org.jeecg.common.util.RedisUtil;
 import org.jeecg.modules.adweb.common.constant.NumConstant;
 import org.jeecg.modules.adweb.common.constant.WordPressConstants;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.site.dto.WordPressConfig;
 import org.jeecg.modules.adweb.site.entity.AdwebSite;
 import org.jeecg.modules.adweb.site.entity.AdwebUserWpsite;
 import org.jeecg.modules.adweb.site.mapper.AdwebSiteMapper;
 import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
+import org.jeecg.modules.adweb.site.service.IAdwebUserWpsiteService;
 import org.jeecg.modules.adweb.site.service.ISiteUserPermissionService;
 import org.jeecg.modules.system.mapper.SysUserRoleMapper;
-import org.jeecg.modules.adweb.site.service.IAdwebUserWpsiteService;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import jakarta.annotation.Resource;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -113,7 +113,7 @@ public class AdwebSiteServiceImpl extends ServiceImpl<AdwebSiteMapper, AdwebSite
                     } else {
                         config.setWordpressSetting(wordpressSettingMap.get("setting").toString());
                         List<String> open = FastJsonUtil.parseList(wordpressSettingMap.get("open").toString(), String.class);
-                        if (ListUtil.notEmpty(open)) {
+                        if (CollectionUtils.isNotEmpty(open)) {
                             config.setOpenSetting(open);
                         }
                         if (wordpressSettingMap.size() > 2) {
@@ -200,7 +200,6 @@ public class AdwebSiteServiceImpl extends ServiceImpl<AdwebSiteMapper, AdwebSite
         }
         return "";
     }
-
     /**
      * 根据用户id查询所有未删除的站点
      *
@@ -224,4 +223,16 @@ public class AdwebSiteServiceImpl extends ServiceImpl<AdwebSiteMapper, AdwebSite
         }
         return siteIds;
     }
+
+    /** 查询全部有效的站点code */
+    @Override
+    public List<String> getAllActiveSiteCodes() {
+        return this.list(
+                        new LambdaQueryWrapper<AdwebSite>()
+                                .eq(AdwebSite::getStatus, 1)
+                                .eq(AdwebSite::getRunStatus, 1))
+                .stream()
+                .map(AdwebSite::getCode)
+                .toList();
+    }
 }

+ 6 - 5
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/site/service/impl/SiteUserPermissionServiceImpl.java

@@ -5,7 +5,8 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import lombok.extern.slf4j.Slf4j;
-import org.jeecg.modules.adweb.common.util.ListUtil;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.jeecg.modules.adweb.site.entity.AdwebSitePermission;
 import org.jeecg.modules.adweb.site.entity.AdwebSiteUserPermission;
 import org.jeecg.modules.adweb.site.service.ISitePermissionService;
@@ -41,7 +42,7 @@ public class SiteUserPermissionServiceImpl implements ISiteUserPermissionService
         } catch (Exception e) {
             log.error("通过uid获取站点权限失败", e);
         }
-        if (ListUtil.isEmpty(AdwebSiteUserPermissionList)) {
+        if (CollectionUtils.isEmpty(AdwebSiteUserPermissionList)) {
             codeList.add("-1");
             return codeList;
         }
@@ -55,7 +56,7 @@ public class SiteUserPermissionServiceImpl implements ISiteUserPermissionService
         } catch (Exception e) {
             log.error("通过站点权限获取站点code失败", e);
         }
-        if (ListUtil.isEmpty(codeList)) {
+        if (CollectionUtils.isEmpty(codeList)) {
             codeList.add("-1");
             return codeList;
         }
@@ -73,7 +74,7 @@ public class SiteUserPermissionServiceImpl implements ISiteUserPermissionService
         } catch (Exception e) {
             log.error("通过uid获取站点权限失败", e);
         }
-        if (ListUtil.isEmpty(AdwebSiteUserPermissionList)) {
+        if (CollectionUtils.isEmpty(AdwebSiteUserPermissionList)) {
             codeList.add("-1");
             return codeList;
         }
@@ -86,7 +87,7 @@ public class SiteUserPermissionServiceImpl implements ISiteUserPermissionService
         } catch (Exception e) {
             log.error("通过站点权限获取站点code失败", e);
         }
-        if (ListUtil.isEmpty(codeList)) {
+        if (CollectionUtils.isEmpty(codeList)) {
             codeList.add("-1");
             return codeList;
         }

+ 6 - 3
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/system/service/impl/MasterSubAccountRelationServiceImpl.java

@@ -3,10 +3,13 @@ package org.jeecg.modules.adweb.system.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
 import jakarta.annotation.Resource;
+
 import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.jeecg.common.system.api.ISysBaseAPI;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.system.entity.MasterSubAccountRelation;
 import org.jeecg.modules.adweb.system.mapper.MasterSubAccountRelationMapper;
 import org.jeecg.modules.adweb.system.service.IMasterSubAccountRelationService;
@@ -108,7 +111,7 @@ public class MasterSubAccountRelationServiceImpl extends ServiceImpl<MasterSubAc
             queryWrapper.eq("sub_id", uid);
             queryWrapper.eq("status", 1);
             List<MasterSubAccountRelation> relations = this.list(queryWrapper);
-            if (ListUtil.isEmpty(relations)) {
+            if (CollectionUtils.isEmpty(relations)) {
                 return defaultList;
             }
             masterId = relations.get(0).getMasterId();
@@ -118,7 +121,7 @@ public class MasterSubAccountRelationServiceImpl extends ServiceImpl<MasterSubAc
         queryWrapper.eq("master_id", masterId);
         queryWrapper.eq("status", 1);
         List<MasterSubAccountRelation> relations = this.list(queryWrapper);
-        if (ListUtil.isEmpty(relations)) {
+        if (CollectionUtils.isEmpty(relations)) {
             return defaultList;
         }
         List<String> uidList = relations.stream().map(MasterSubAccountRelation::getSubId).collect(Collectors.toList());

+ 7 - 4
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/system/service/impl/SysAdwebApiImpl.java

@@ -3,8 +3,12 @@ package org.jeecg.modules.adweb.system.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.xkcoding.http.util.StringUtil;
+
 import jakarta.annotation.Resource;
+
 import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.system.api.ISysBaseAPI;
 import org.jeecg.common.system.vo.DictModel;
@@ -12,7 +16,6 @@ import org.jeecg.common.system.vo.DictPropertyModel;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.modules.adweb.common.constant.AdwebConstant;
 import org.jeecg.modules.adweb.common.constant.NumConstant;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.site.entity.AdwebSite;
 import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
 import org.jeecg.modules.adweb.site.service.ISiteUserPermissionService;
@@ -100,7 +103,7 @@ public class SysAdwebApiImpl implements SysAdwebApi {
         } catch (Exception e) {
             log.error("获取当前登录渠道下客户群的uid");
         }
-        if (ListUtil.isEmpty(list)) {
+        if (CollectionUtils.isEmpty(list)) {
             list = new ArrayList<>();
             list.add("-1");
         }
@@ -132,7 +135,7 @@ public class SysAdwebApiImpl implements SysAdwebApi {
         queryWrapper.eq("id", siteId);
         queryWrapper.ne("status", NumConstant.ZERO);
         List<AdwebSite> list = adwebSiteService.list(queryWrapper);
-        if (ListUtil.notEmpty(list)) {
+        if (CollectionUtils.isNotEmpty(list)) {
             return false;
         }
         return true;
@@ -164,7 +167,7 @@ public class SysAdwebApiImpl implements SysAdwebApi {
         queryWrapper.eq("code", siteCode);
         queryWrapper.ne("status", AdwebConstant.SITE_DEL);
         List<AdwebSite> list = adwebSiteService.list(queryWrapper);
-        if (ListUtil.notEmpty(list)) {
+        if (CollectionUtils.isNotEmpty(list)) {
             return false;
         }
         return true;

+ 9 - 9
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/userCountry/controller/AdwebUserCountryController.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -19,7 +20,6 @@ import org.jeecg.common.system.api.ISysBaseAPI;
 import org.jeecg.common.system.base.controller.JeecgController;
 import org.jeecg.common.system.query.QueryGenerator;
 import org.jeecg.common.system.vo.LoginUser;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.enquiry.constant.EnquiryDistributeTypeConstant;
 import org.jeecg.modules.adweb.enquiry.entity.AdwebEnquiry;
 import org.jeecg.modules.adweb.enquiry.service.IAdwebEnquiryService;
@@ -112,7 +112,7 @@ public class AdwebUserCountryController extends JeecgController<AdwebUserCountry
         queryWrapper.eq("status", 1);
         List<AdwebUserCountry> userCountries = adwebUserCountryService.list(queryWrapper);
         List<AdwebCountry> countries = null;
-        if (ListUtil.isEmpty(userCountries)) {
+        if (CollectionUtils.isEmpty(userCountries)) {
 
         }
         return Result.OK();
@@ -175,7 +175,7 @@ public class AdwebUserCountryController extends JeecgController<AdwebUserCountry
         List<SubUser> list = adwebUserCountryMapper.getSubUserOptions(uid);
 
         // 如果子账户不为空,将主账户也加进去作为选项
-        if (ListUtil.notEmpty(list)) {
+        if (CollectionUtils.isNotEmpty(list)) {
             SysUser masterAccount = sysUserService.getById(uid);
             SubUser user = new SubUser();
             user.setId(masterAccount.getId());
@@ -196,7 +196,7 @@ public class AdwebUserCountryController extends JeecgController<AdwebUserCountry
         userCountryQueryWrapper.eq("site_id", siteId);
         userCountryQueryWrapper.eq("status", 1);
         List<AdwebUserCountry> userCountries = adwebUserCountryService.list(userCountryQueryWrapper);
-        if (ListUtil.isEmpty(userCountries)) {
+        if (CollectionUtils.isEmpty(userCountries)) {
             return Result.OK();
         }
 
@@ -208,7 +208,7 @@ public class AdwebUserCountryController extends JeecgController<AdwebUserCountry
         QueryWrapper<AdwebCountry> countryQueryWrapper = new QueryWrapper<>();
         countryQueryWrapper.in("geoname_id", countryIds);
         List<AdwebCountry> countries = admpCountryService.list(countryQueryWrapper);
-        if (ListUtil.isEmpty(countries)) {
+        if (CollectionUtils.isEmpty(countries)) {
             return Result.OK();
         }
 
@@ -254,7 +254,7 @@ public class AdwebUserCountryController extends JeecgController<AdwebUserCountry
         List<AdwebUserCountry> userCountries = adwebUserCountryService.list(userCountryQueryWrapper);
 
         List<AdwebCountry> countries;
-        if (ListUtil.isEmpty(userCountries)) {
+        if (CollectionUtils.isEmpty(userCountries)) {
             countries = admpCountryService.list();
         } else {
             List<Integer> countryIds = new ArrayList<>();
@@ -266,7 +266,7 @@ public class AdwebUserCountryController extends JeecgController<AdwebUserCountry
             countryQueryWrapper.notIn("geoname_id", countryIds);
             countries = admpCountryService.list(countryQueryWrapper);
         }
-        if (ListUtil.isEmpty(countries)) {
+        if (CollectionUtils.isEmpty(countries)) {
             return Result.OK();
         }
 
@@ -371,7 +371,7 @@ public class AdwebUserCountryController extends JeecgController<AdwebUserCountry
         UpdateWrapper<AdwebUserCountry> updateWrapper = new UpdateWrapper<>();
         updateWrapper.eq("uid", uid);
         updateWrapper.eq("site_id", param.getSiteId());
-        if (ListUtil.notEmpty(countryIdList)) {
+        if (CollectionUtils.isNotEmpty(countryIdList)) {
             updateWrapper.notIn("country_id", countryIdList);
         }
         updateWrapper.set("status", 0);
@@ -380,7 +380,7 @@ public class AdwebUserCountryController extends JeecgController<AdwebUserCountry
         // 更改相关询盘的负责人
         List<Integer> siteIds = adwebSiteService.getAllSiteIdByParentId(param.getSiteId());
         UpdateWrapper<AdwebEnquiry> enquiryUpdateWrapper = new UpdateWrapper<>();
-        if (ListUtil.notEmpty(countryIdList)) {
+        if (CollectionUtils.isNotEmpty(countryIdList)) {
             QueryWrapper<AdwebCountry> countryQueryWrapper = new QueryWrapper<>();
             countryQueryWrapper.in("geoname_id", countryIdList);
             List<AdwebCountry> countries = admpCountryService.list(countryQueryWrapper);

+ 3 - 3
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/userCountry/service/impl/AdwebUserCountryServiceImpl.java

@@ -3,7 +3,7 @@ package org.jeecg.modules.adweb.userCountry.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import jakarta.annotation.Resource;
-import org.jeecg.modules.adweb.common.util.ListUtil;
+import org.apache.commons.collections4.CollectionUtils;
 import org.jeecg.modules.adweb.userCountry.entity.AdwebCountry;
 import org.jeecg.modules.adweb.userCountry.entity.AdwebUserCountry;
 import org.jeecg.modules.adweb.userCountry.mapper.AdwebUserCountryMapper;
@@ -40,7 +40,7 @@ public class AdwebUserCountryServiceImpl extends ServiceImpl<AdwebUserCountryMap
                 .eq("uid", id)
                 .eq("status", 1);
         List<AdwebUserCountry> list = this.list(queryWrapper);
-        if (ListUtil.isEmpty(list)) {
+        if (CollectionUtils.isEmpty(list)) {
             return new ArrayList<>();
         }
         return list.stream().map(AdwebUserCountry::getCountryId).collect(Collectors.toList());
@@ -56,7 +56,7 @@ public class AdwebUserCountryServiceImpl extends ServiceImpl<AdwebUserCountryMap
     @Override
     public List<String> getCountryCodesBySubId(String id, Integer siteId) {
         List<Integer> countryIds = this.getCountryIdsBySubId(id);
-        if (ListUtil.isEmpty(countryIds)) {
+        if (CollectionUtils.isEmpty(countryIds)) {
             return new ArrayList<>();
         }
         QueryWrapper<AdwebCountry> queryWrapper = new QueryWrapper<>();

+ 11 - 7
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysBaseApiImpl.java

@@ -11,11 +11,17 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.base.Joiner;
 import com.xkcoding.http.util.StringUtil;
+
 import freemarker.core.TemplateClassResolver;
 import freemarker.template.Configuration;
 import freemarker.template.Template;
 import freemarker.template.TemplateException;
+
+import jakarta.annotation.Resource;
+
 import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.shiro.SecurityUtils;
@@ -43,7 +49,6 @@ import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
 import org.jeecg.config.security.utils.SecureUtil;
 import org.jeecg.modules.adweb.common.constant.AdwebConstant;
 import org.jeecg.modules.adweb.common.constant.NumConstant;
-import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.site.entity.AdwebSite;
 import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
 import org.jeecg.modules.adweb.site.service.ISiteUserPermissionService;
@@ -65,11 +70,8 @@ import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
 import org.springframework.util.AntPathMatcher;
-import org.springframework.util.CollectionUtils;
 import org.springframework.util.PathMatcher;
 
-import jakarta.annotation.Resource;
-import javax.sql.DataSource;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
@@ -79,6 +81,8 @@ import java.sql.SQLException;
 import java.util.*;
 import java.util.stream.Collectors;
 
+import javax.sql.DataSource;
+
 /**
  * @Description: 底层共通业务API,提供其他独立模块调用
  * @Author: scott
@@ -1929,7 +1933,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
 		} catch (Exception e) {
 			log.error("获取当前登录渠道下客户群的uid");
 		}
-		if (ListUtil.isEmpty(list)) {
+		if (CollectionUtils.isEmpty(list)) {
 			list = new ArrayList<>();
 			list.add("-1");
 		}
@@ -1956,7 +1960,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
 		queryWrapper.eq("id", siteId);
 		queryWrapper.ne("status", NumConstant.ZERO);
 		List<AdwebSite> list = adwebSiteService.list(queryWrapper);
-		if (ListUtil.notEmpty(list)) {
+		if (CollectionUtils.isEmpty(list)) {
 			return false;
 		}
 		return true;
@@ -1984,7 +1988,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
 		queryWrapper.eq("code", siteCode);
 		queryWrapper.ne("status", AdwebConstant.SITE_DEL);
 		List<AdwebSite> list = adwebSiteService.list(queryWrapper);
-		if (ListUtil.notEmpty(list)) {
+		if (CollectionUtils.isNotEmpty(list)) {
 			return false;
 		}
 		return true;

+ 26 - 17
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/xxl/DataForSEOJob.java

@@ -6,15 +6,11 @@ import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.extern.slf4j.Slf4j;
 
 import org.jeecg.modules.adweb.common.constant.AdwebConstant;
+import org.jeecg.modules.adweb.common.util.CommonUtil;
 import org.jeecg.modules.adweb.seo.service.dataforseo.DataForSEOService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
 /**
  * DataForSEO Serp查询及同步任务,{@link DataForSEOService}
  *
@@ -26,11 +22,17 @@ public class DataForSEOJob {
 
     @Autowired private DataForSEOService dataForSEOService;
 
+    /**
+     * 查询长尾关键词,Serp更新频率较低,建议三天左右执行一次
+     *
+     * @param siteCodes
+     * @return
+     */
     @XxlJob("runLongTailKeywordsSerpTasksHandler")
-    public ReturnT<String> runLongTailKeywordsSerpTasksHandler(String param) {
-        log.info("执行长尾词Serp查询..., param = {}", param);
+    public ReturnT<String> runLongTailKeywordsSerpTasksHandler(String siteCodes) {
+        log.info("执行长尾词Serp查询..., site codes = {}", siteCodes);
         dataForSEOService.runKeywordsSerpTasks(
-                this.parseSiteCodes(param),
+                CommonUtil.splitAndTrim(siteCodes, ","),
                 AdwebConstant.KEYWORD_TYPE_LONG_TAIL,
                 Integer.MAX_VALUE);
         log.info("执行长尾词Serp查询结束");
@@ -38,16 +40,29 @@ public class DataForSEOJob {
         return ReturnT.SUCCESS;
     }
 
+    /**
+     * 查询指定关键词,Serp更新频率较低,建议三天左右执行一次
+     *
+     * @param siteCodes
+     * @return
+     */
     @XxlJob("runAppointKeywordsSerpTasksHandler")
-    public ReturnT<String> runAppointKeywordsSerpTasksHandler(String param) {
-        log.info("执行指定词Serp查询..., param = {}", param);
+    public ReturnT<String> runAppointKeywordsSerpTasksHandler(String siteCodes) {
+        log.info("执行指定词Serp查询..., site codes = {}", siteCodes);
         dataForSEOService.runKeywordsSerpTasks(
-                this.parseSiteCodes(param), AdwebConstant.KEYWORD_TYPE_APPOINT, Integer.MAX_VALUE);
+                CommonUtil.splitAndTrim(siteCodes, ","),
+                AdwebConstant.KEYWORD_TYPE_APPOINT,
+                Integer.MAX_VALUE);
         log.info("执行指定词Serp查询结束");
 
         return ReturnT.SUCCESS;
     }
 
+    /**
+     * 同步Serp查询结果,基于Redis中的剩余任务 - 负载较低,建议一天执行多次
+     *
+     * @return
+     */
     @XxlJob("syncKeywordsSerpResultsHandler")
     public ReturnT<String> syncKeywordsSerpResultsHandler(String param) {
         log.info("同步关键词Serp查询结果...");
@@ -56,10 +71,4 @@ public class DataForSEOJob {
 
         return ReturnT.SUCCESS;
     }
-
-    private List<String> parseSiteCodes(String param) {
-        return Objects.nonNull(param)
-                ? Arrays.stream(param.split(",")).map(siteCode -> siteCode.trim()).toList()
-                : Collections.EMPTY_LIST;
-    }
 }

+ 9 - 2
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/xxl/GAReportJob.java

@@ -5,6 +5,7 @@ import com.xxl.job.core.handler.annotation.XxlJob;
 
 import lombok.extern.slf4j.Slf4j;
 
+import org.jeecg.modules.adweb.common.util.CommonUtil;
 import org.jeecg.modules.adweb.dmp.service.google.GAReportService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -20,10 +21,16 @@ public class GAReportJob {
 
     @Autowired private GAReportService gaReportService;
 
+    /**
+     * 查询GA数据 - 报表以为天为单位,且覆盖旧数据,建议每天执行一至三次
+     *
+     * @param siteCodes
+     * @return
+     */
     @XxlJob("syncGAReportHandler")
-    public ReturnT<String> syncGAReportHandler(String param) {
+    public ReturnT<String> syncGAReportHandler(String siteCodes) {
         log.info("同步GA报表数据...");
-        gaReportService.syncGAReport();
+        gaReportService.syncGAReport(CommonUtil.splitAndTrim(siteCodes, ","));
         log.info("同步GA报表数据结束");
 
         return ReturnT.SUCCESS;

+ 4 - 0
jeecg-module-system/jeecg-system-biz/src/main/resources/google/gtm/body-snippet.tmpl

@@ -0,0 +1,4 @@
+<!-- Google Tag Manager (noscript) -->
+<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=%s"
+height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
+<!-- End Google Tag Manager (noscript) -->

+ 7 - 0
jeecg-module-system/jeecg-system-biz/src/main/resources/google/gtm/head-snippet.tmpl

@@ -0,0 +1,7 @@
+<!-- Google Tag Manager -->
+<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
+new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
+j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
+'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
+})(window,document,'script','dataLayer','%s');</script>
+<!-- End Google Tag Manager -->

+ 4 - 0
jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml

@@ -355,6 +355,10 @@ data-bridge:
   api:
     host: http://data-bridge.v3.adwebcloud.com:9002
     token: lgoXX9APqgPLGMPECiNoxaPx
+  gtm:
+    account-id: 6000226571
+  ga:
+    account-id: 191734056
 
 ##GEOIP MMDB 静态数据库文件
 geoip:

+ 4 - 0
jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml

@@ -343,6 +343,10 @@ data-bridge:
   api:
     host: http://data-bridge.v3.adwebcloud.com:9002
     token: lgoXX9APqgPLGMPECiNoxaPx
+  gtm:
+    account-id: 6000226571
+  ga:
+    account-id: 191734056
 
 ##GEOIP MMDB 静态数据库文件
 geoip:

+ 4 - 0
jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml

@@ -340,6 +340,10 @@ data-bridge:
   api:
     host: http://data-bridge.v3.adwebcloud.com:9002
     token: lgoXX9APqgPLGMPECiNoxaPx
+  gtm:
+    account-id: 6000226571
+  ga:
+    account-id: 191734056
 
 ### dataforseo
 dataforseo:

+ 25 - 0
jeecg-module-system/jeecg-system-start/src/test/java/org/jeecg/modules/adweb/dmp/service/google/GoogleServiceTest.java

@@ -1,9 +1,12 @@
 package org.jeecg.modules.adweb.dmp.service.google;
 
+import org.apache.commons.lang3.tuple.Pair;
 import org.jeecg.common.util.FastJsonUtil;
 import org.jeecg.modules.adweb.dmp.dto.google.analytics.report.GAReportRequestDTO;
 import org.jeecg.modules.adweb.dmp.dto.google.analytics.report.ReportType;
 import org.jeecg.modules.adweb.dmp.dto.google.analytics.report.data.CountryChartData;
+import org.jeecg.modules.adweb.dmp.entity.GoogleGTM;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
@@ -17,6 +20,8 @@ public class GoogleServiceTest {
 
     @Autowired GAReportService gaReportService;
 
+    @Autowired GTMAdminService gtmAdminService;
+
     @Test
     public void testGAReport() {
         GAReportRequestDTO gaReportRequest = new GAReportRequestDTO();
@@ -30,4 +35,24 @@ public class GoogleServiceTest {
 
         System.out.println(FastJsonUtil.toJSONString(countryReport));
     }
+
+    @Test
+    @Disabled("GTM + GA帐户资源限制")
+    public void testCreateAndDeleteGTMContainer() {
+        GoogleGTM googleGTM =
+                gtmAdminService.createContainer(
+                        "230206anit40",
+                        "https://www.sourcingstone.com",
+                        "泉州索兴石业有限公司#" + this.getClass().getSimpleName());
+        System.out.println(FastJsonUtil.toJSONString(googleGTM));
+
+        gtmAdminService.deleteContainer(googleGTM.getSiteCode());
+    }
+
+    @Test
+    public void testGetGTMSnippets() {
+        Pair<String, String> snippets = gtmAdminService.getSnippets("GTM-T87NNQ4F");
+        System.out.println(snippets.getLeft());
+        System.out.println(snippets.getRight());
+    }
 }

+ 2 - 2
jeecg-module-system/jeecg-system-start/src/test/java/org/jeecg/modules/adweb/seo/service/DataForSEOTest.java

@@ -17,14 +17,14 @@ public class DataForSEOTest {
     @Autowired private DataForSEOService dataForSEOService;
 
     @Test
-    @Disabled
+    @Disabled("DataForSEO创建Serp任务收费")
     public void testRunKeywordsSerpTasks() {
         dataForSEOService.runKeywordsSerpTasks(
                 Collections.EMPTY_LIST, AdwebConstant.KEYWORD_TYPE_APPOINT, 10);
     }
 
     @Test
-    @Disabled
+    @Disabled("DataForSEO读取Serp结果免费 - 但用例影响生产数据")
     public void testSyncKeywordsSerpResults() {
         dataForSEOService.syncKeywordsSerpResults();
     }