Pārlūkot izejas kodu

New: 新增营销模块、应用列表、数据统计、配置中心等功能

lwh 1 nedēļu atpakaļ
vecāks
revīzija
3e22a57208
44 mainītis faili ar 2153 papildinājumiem un 290 dzēšanām
  1. 1 1
      pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/sentinel/handle/GlobalBizExceptionHandler.java
  2. 44 3
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/BatchUpdateMarketingAppsDTO.java
  3. 57 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/MarketingAppsDomainDTO.java
  4. 76 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/MarketingAppsIpDTO.java
  5. 38 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/ModMarketingAppsDomainDTO.java
  6. 38 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/ModMarketingAppsIpDTO.java
  7. 6 11
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/SetMarketingAppsDTO.java
  8. 30 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/SetMarketingAppsStatusDTO.java
  9. 45 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/AddMarketingConfigDomainListDTO.java
  10. 67 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/AddMarketingConfigIpListDTO.java
  11. 1 1
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/MarketingGroupDomainDTO.java
  12. 1 1
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/MarketingGroupIPDTO.java
  13. 6 6
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/data/MarketingDataReportDTO.java
  14. 6 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/data/PageFirstLevelDataDTO.java
  15. 7 1
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/entity/MarketingApps.java
  16. 7 1
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/entity/MarketingAppsDomain.java
  17. 7 1
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/entity/MarketingAppsIp.java
  18. 6 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/entity/MarketingData.java
  19. 1 1
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/app/MarketingAppsDomainVO.java
  20. 1 1
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/app/MarketingAppsIpVO.java
  21. 2 2
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/app/PageMarketingAppsVO.java
  22. 53 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/config/GetMarketingConfigDomainListVO.java
  23. 69 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/config/GetMarketingConfigIpListVO.java
  24. 58 0
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/config/GetMarketingGlobalConfigVO.java
  25. 33 3
      pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/data/MarketingDataReportVO.java
  26. 5 0
      pig-marketing/pig-marketing-biz/pom.xml
  27. 65 40
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingAppsController.java
  28. 100 8
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingConfigController.java
  29. 0 1
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingDataController.java
  30. 3 0
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/mapper/MarketingAppsIpMapper.java
  31. 2 1
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/mapper/MarketingDataMapper.java
  32. 34 19
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/MarketingAppsService.java
  33. 62 7
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/MarketingConfigService.java
  34. 409 36
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingAppsServiceImpl.java
  35. 294 30
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingConfigServiceImpl.java
  36. 278 21
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingDataServiceImpl.java
  37. 25 0
      pig-marketing/pig-marketing-biz/src/main/resources/mapper/MarketingAppsDomainMapper.xml
  38. 25 0
      pig-marketing/pig-marketing-biz/src/main/resources/mapper/MarketingAppsIpMapper.xml
  39. 38 36
      pig-marketing/pig-marketing-biz/src/main/resources/mapper/MarketingDataMapper.xml
  40. 0 58
      pig-marketing/pig-marketing-biz/src/main/resources/mapper/MarketingGroupDomainMapper.xml
  41. 58 0
      pig-marketing/pig-marketing-biz/src/main/resources/mapper/MarketingGroupIpMapper.xml
  42. 33 0
      pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/dto/SysPublicParamDTO.java
  43. 20 0
      pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/RemoteParamService.java
  44. 42 0
      pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/controller/SysPublicParamController.java

+ 1 - 1
pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/sentinel/handle/GlobalBizExceptionHandler.java

@@ -106,7 +106,7 @@ public class GlobalBizExceptionHandler {
 	public R handleBodyValidException(MethodArgumentNotValidException exception) {
 	public R handleBodyValidException(MethodArgumentNotValidException exception) {
 		List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
 		List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
 		log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage());
 		log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage());
-		return R.failed(String.format("%s %s", fieldErrors.get(0).getField(), fieldErrors.get(0).getDefaultMessage()));
+		return R.failed(String.format("%s", fieldErrors.get(0).getDefaultMessage()));
 	}
 	}
 
 
 	/**
 	/**

+ 44 - 3
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/BatchUpdateMarketingAppsDTO.java

@@ -2,7 +2,6 @@ package com.pig4cloud.pig.marketing.api.dto.app;
 
 
 
 
 import com.pig4cloud.pig.marketing.api.vo.app.MarketingAppsDomainVO;
 import com.pig4cloud.pig.marketing.api.vo.app.MarketingAppsDomainVO;
-import com.pig4cloud.pig.marketing.api.vo.app.MarketingAppsIpVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.NotNull;
@@ -28,11 +27,53 @@ public class BatchUpdateMarketingAppsDTO implements Serializable {
 	@NotNull(message = "id不能为空")
 	@NotNull(message = "id不能为空")
 	private Long id;
 	private Long id;
 
 
+	/**
+	 * 域名限制
+	 */
+	@Schema(description = "域名限制")
+	private Boolean domainLimit;
+
+	/**
+	 * 营销投放
+	 */
+	@Schema(description = "营销投放")
+	private Boolean launch;
+
+	/**
+	 * 触发规则
+	 */
+	@Schema(description = "触发规则")
+	private Integer triggerRule;
+
+	/**
+	 * 触发频率
+	 */
+	@Schema(description = "触发频率")
+	private String triggerNum;
+
+	/**
+	 * 备注
+	 */
+	@Schema(description = "备注")
+	private String remark;
+
+	/**
+	 * 删除的分组IP id列表
+	 */
+	@Schema(description = "删除的分组IP id列表")
+	List<Long> delIps;
+
+	/**
+	 * 删除的分组域名id
+	 */
+	@Schema(description = "删除的分组域名id")
+	List<Long> delDomains;
+
 	@Valid
 	@Valid
 	@Schema(description = "ip列表")
 	@Schema(description = "ip列表")
-	private List<MarketingAppsIpVO> ips;
+	private List<MarketingAppsIpDTO> ips;
 
 
 	@Valid
 	@Valid
 	@Schema(description = "域名列表")
 	@Schema(description = "域名列表")
-	private List<MarketingAppsDomainVO> domains;
+	private List<MarketingAppsDomainDTO> domains;
 }
 }

+ 57 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/MarketingAppsDomainDTO.java

@@ -0,0 +1,57 @@
+package com.pig4cloud.pig.marketing.api.dto.app;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-24
+ * @description: 应用域名列表
+ */
+@Data
+@Schema(description = "应用域名列表")
+public class MarketingAppsDomainDTO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * id
+	 */
+	@Schema(description = "id")
+	private Long id;
+
+	/**
+	 * 来源类型
+	 */
+	@Schema(description = "来源类型,1-来自分组,2-具体域名")
+	private Integer sourceType;
+
+	/**
+	 * 分组ID
+	 */
+	@Schema(description = "分组ID")
+	private Long groupId;
+
+	/**
+	 * 分组名称
+	 */
+	@Schema(description = "分组名称")
+	private String groupName;
+
+	/**
+	 * 域名
+	 */
+	@Schema(description = "域名")
+	private String domain;
+
+	/**
+	 * 是否修改
+	 */
+	@Schema(description = "是否修改")
+	private Boolean modify = false;
+}

+ 76 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/MarketingAppsIpDTO.java

@@ -0,0 +1,76 @@
+package com.pig4cloud.pig.marketing.api.dto.app;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-24
+ * @description: 应用ip列表入参
+ */
+@Data
+@Schema(description = "应用ip列表入参")
+public class MarketingAppsIpDTO implements Serializable {
+
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * id
+	 */
+	@Schema(description = "id")
+	private Long id;
+
+	/**
+	 * ip类型
+	 */
+	@Schema(description = "ip类型,1-白名单,2-黑名单")
+	private Integer ipType;
+
+	/**
+	 * 来源类型
+	 */
+	@Schema(description = "来源类型,1-来自分组,2-具体IP")
+	private Integer sourceType;
+
+	/**
+	 * 分组ID
+	 */
+	@Schema(description = "分组ID")
+	private Long groupId;
+
+	/**
+	 * 分组名称
+	 */
+	@Schema(description = "分组名称")
+	private String groupName;
+
+	/**
+	 * ip模式
+	 */
+	@Schema(description = "ip模式,1-单IP,2-IP段")
+	private Integer ipMode;
+
+	/**
+	 * 起始IP
+	 */
+	@Schema(description = "起始IP")
+	private String startIp;
+
+	/**
+	 * 结束IP
+	 */
+	@Schema(description = "结束IP")
+	private String endIp;
+
+	/**
+	 * 是否修改
+	 */
+	@Schema(description = "是否修改")
+	private Boolean modify = false;
+}

+ 38 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/ModMarketingAppsDomainDTO.java

@@ -0,0 +1,38 @@
+package com.pig4cloud.pig.marketing.api.dto.app;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-27
+ * @description: 修改应用域名列表入参
+ */
+@Data
+@Schema(description = "修改应用域名列表入参")
+public class ModMarketingAppsDomainDTO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	@Schema(description = "id")
+	@NotNull(message = "id不能为空")
+	private Long id;
+
+	/**
+	 * 删除的分组域名id
+	 */
+	@Schema(description = "删除的分组域名id")
+	List<Long> delDomains;
+
+	@Valid
+	@Schema(description = "域名列表")
+	private List<MarketingAppsDomainDTO> domains;
+}

+ 38 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/ModMarketingAppsIpDTO.java

@@ -0,0 +1,38 @@
+package com.pig4cloud.pig.marketing.api.dto.app;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-27
+ * @description: 修改应用ip列表入参
+ */
+@Data
+@Schema(description = "修改应用ip列表入参")
+public class ModMarketingAppsIpDTO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	@Schema(description = "id")
+	@NotNull(message = "id不能为空")
+	private Long id;
+
+	/**
+	 * 删除的分组IP id列表
+	 */
+	@Schema(description = "删除的分组IP id列表")
+	List<Long> delIps;
+
+	@Valid
+	@Schema(description = "ip列表")
+	private List<MarketingAppsIpDTO> ips;
+}

+ 6 - 11
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/SetMarketingAppsDTO.java

@@ -11,10 +11,11 @@ import java.io.Serializable;
 /**
 /**
  * @author: lwh
  * @author: lwh
  * @date: 2025-07-22
  * @date: 2025-07-22
- * @description: TODO
+ * @description: 设置应用信息入参
  */
  */
 
 
 @Data
 @Data
+@Schema(description = "设置应用信息入参")
 public class SetMarketingAppsDTO implements Serializable {
 public class SetMarketingAppsDTO implements Serializable {
 
 
 	@Serial
 	@Serial
@@ -24,14 +25,14 @@ public class SetMarketingAppsDTO implements Serializable {
 	 * id
 	 * id
 	 */
 	 */
 	@Schema(description = "id")
 	@Schema(description = "id")
-	@NotNull(message = "id不能为空")
+	@NotNull(message = "不能为空")
 	private Long id;
 	private Long id;
 
 
 	/**
 	/**
 	 * 应用类型
 	 * 应用类型
 	 */
 	 */
-	@Schema(description = "应用类型")
-	private String domainType;
+	@Schema(description = "应用类型,0-Android,1-IOS")
+	private Integer domainType;
 
 
 	/**
 	/**
 	 * 域名限制
 	 * 域名限制
@@ -48,13 +49,7 @@ public class SetMarketingAppsDTO implements Serializable {
 	/**
 	/**
 	 * 触发规则
 	 * 触发规则
 	 */
 	 */
-	@Schema(description = "触发规则")
+	@Schema(description = "触发规则,1-仅一次,2-多次")
 	Integer triggerRule;
 	Integer triggerRule;
 
 
-	/**
-	 * 触发次数
-	 */
-	@Schema(description = "触发频率")
-	Integer triggerNum;
-
 }
 }

+ 30 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/app/SetMarketingAppsStatusDTO.java

@@ -0,0 +1,30 @@
+package com.pig4cloud.pig.marketing.api.dto.app;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-24
+ * @description: 设置应用状态入参
+ */
+@Data
+@Schema(description = "设置应用状态入参")
+public class SetMarketingAppsStatusDTO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	@Schema(description = "id")
+	@NotNull(message = "id不能为空")
+	private Long id;
+
+	@Schema(description = "状态,true-启用,false-拉黑")
+	@NotNull(message = "状态不能为空")
+	private Boolean status;
+}

+ 45 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/AddMarketingConfigDomainListDTO.java

@@ -0,0 +1,45 @@
+package com.pig4cloud.pig.marketing.api.dto.config;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-24
+ * @description: 添加域名入参
+ */
+@Data
+@Schema(description = "添加域名入参")
+public class AddMarketingConfigDomainListDTO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 来源类型
+	 */
+	@Schema(description = "来源类型,1-来自分组,2-具体域名")
+	private Integer sourceType;
+
+	/**
+	 * 分组ID
+	 */
+	@Schema(description = "分组ID")
+	private Long groupId;
+
+	/**
+	 * 分组名称
+	 */
+	@Schema(description = "分组名称")
+	private String groupName;
+
+	/**
+	 * 域名
+	 */
+	@Schema(description = "域名")
+	private String domain;
+}

+ 67 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/AddMarketingConfigIpListDTO.java

@@ -0,0 +1,67 @@
+package com.pig4cloud.pig.marketing.api.dto.config;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-24
+ * @description: 添加IP集合入参
+ */
+@Data
+@Schema(description = "添加IP集合入参")
+public class AddMarketingConfigIpListDTO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * ip类型
+	 */
+	@Schema(description = "ip类型,1-白名单,2-黑名单")
+	@NotNull(message = "ip类型不能为空")
+	private Integer ipType;
+
+	/**
+	 * 来源类型
+	 */
+	@Schema(description = "来源类型,1-来自分组,2-具体IP")
+	@NotNull(message = "来源类型不能为空")
+	private Integer sourceType;
+
+	/**
+	 * 分组ID
+	 */
+	@Schema(description = "分组ID")
+	private Long groupId;
+
+	/**
+	 * 分组名称
+	 */
+	@Schema(description = "分组名称")
+	private String groupName;
+
+	/**
+	 * ip模式
+	 */
+	@Schema(description = "ip模式,1-单IP,2-IP段")
+	private Integer ipMode;
+
+	/**
+	 * 起始IP
+	 */
+	@Schema(description = "起始IP")
+	private String startIp;
+
+	/**
+	 * 结束IP
+	 */
+	@Schema(description = "结束IP")
+	private String endIp;
+}

+ 1 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/MarketingGroupDomainDTO.java

@@ -39,5 +39,5 @@ public class MarketingGroupDomainDTO implements Serializable {
 	 * 是否修改
 	 * 是否修改
 	 */
 	 */
 	@Schema(description = "是否修改")
 	@Schema(description = "是否修改")
-	private Boolean modify;
+	private Boolean modify = false;
 }
 }

+ 1 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/MarketingGroupIPDTO.java

@@ -47,6 +47,6 @@ public class MarketingGroupIPDTO implements Serializable {
 	 * 是否修改
 	 * 是否修改
 	 */
 	 */
 	@Schema(description = "是否修改")
 	@Schema(description = "是否修改")
-	private Boolean modify;
+	private Boolean modify = false;
 	
 	
 }
 }

+ 6 - 6
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/data/MarketingDataReportDTO.java

@@ -19,12 +19,12 @@ public class MarketingDataReportDTO implements Serializable {
 
 
 	@Serial
 	@Serial
 	private static final long serialVersionUID = 1L;
 	private static final long serialVersionUID = 1L;
-
-	/**
-	 * id
-	 */
-	@Schema(description = "id")
-	private Long id;
+//
+//	/**
+//	 * id
+//	 */
+//	@Schema(description = "id")
+//	private Long id;
 
 
 	/**
 	/**
 	 * 域名
 	 * 域名

+ 6 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/data/PageFirstLevelDataDTO.java

@@ -35,4 +35,10 @@ public class PageFirstLevelDataDTO implements Serializable {
 	 */
 	 */
 	@Schema(description = "ip", example = "192.168.1.1")
 	@Schema(description = "ip", example = "192.168.1.1")
 	private String ip;
 	private String ip;
+
+	/**
+	 * appId
+	 */
+	@Schema(description = "应用ID", example = "6ZUoEdzwnu6U1b5o5y7C0h5")
+	private String appId;
 }
 }

+ 7 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/entity/MarketingApps.java

@@ -87,7 +87,13 @@ public class MarketingApps extends Model<MarketingApps> {
 	 * 触发频率
 	 * 触发频率
 	 */
 	 */
 	@Schema(description = "触发频率")
 	@Schema(description = "触发频率")
-	private Integer triggerNum;
+	private String triggerNum;
+
+	/**
+	 * 状态,false-拉黑,true-启用
+	 */
+	@Schema(description = "状态,false-拉黑,true-启用")
+	private Boolean status;
 
 
 	/**
 	/**
 	 * 备注
 	 * 备注

+ 7 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/entity/MarketingAppsDomain.java

@@ -37,7 +37,7 @@ public class MarketingAppsDomain extends Model<MarketingAppsDomain> {
 	/**
 	/**
 	 * 来源类型
 	 * 来源类型
 	 */
 	 */
-	@Schema(description = "来源类型,1-来自分组,2-具体域名,3-全局配置")
+	@Schema(description = "来源类型,1-来自分组,2-具体域名")
 	private Integer sourceType;
 	private Integer sourceType;
 
 
 	/**
 	/**
@@ -52,6 +52,12 @@ public class MarketingAppsDomain extends Model<MarketingAppsDomain> {
 	@Schema(description = "域名")
 	@Schema(description = "域名")
 	private String domain;
 	private String domain;
 
 
+	/**
+	 * 是否属于全局配置
+	 */
+	@Schema(description = "是否属于全局配置")
+	private Boolean config;
+
 	/**
 	/**
 	 * 删除标记
 	 * 删除标记
 	 */
 	 */

+ 7 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/entity/MarketingAppsIp.java

@@ -44,7 +44,7 @@ public class MarketingAppsIp extends Model<MarketingAppsIp> {
 	/**
 	/**
 	 * 所属类型
 	 * 所属类型
 	 */
 	 */
-	@Schema(description = "所属类型,1-来自分组,2-具体IP,3-全局配置")
+	@Schema(description = "所属类型,1-来自分组,2-具体IP")
 	private Integer sourceType;
 	private Integer sourceType;
 
 
 	/**
 	/**
@@ -71,6 +71,12 @@ public class MarketingAppsIp extends Model<MarketingAppsIp> {
 	@Schema(description = "结束IP")
 	@Schema(description = "结束IP")
 	private String endIp;
 	private String endIp;
 
 
+	/**
+	 * 是否属于全局配置
+	 */
+	@Schema(description = "是否属于全局配置")
+	private Boolean config;
+
 	/**
 	/**
 	 * 删除标记
 	 * 删除标记
 	 */
 	 */

+ 6 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/entity/MarketingData.java

@@ -126,6 +126,12 @@ public class MarketingData extends Model<MarketingData> {
 	@Schema(description = "操作系统版本")
 	@Schema(description = "操作系统版本")
 	private String osVersion;
 	private String osVersion;
 
 
+	/**
+	 * appId
+	 */
+	@Schema(description = "appId")
+	private String appId;
+
 	/**
 	/**
 	 * 删除标记
 	 * 删除标记
 	 */
 	 */

+ 1 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/app/MarketingAppsDomainVO.java

@@ -30,7 +30,7 @@ public class MarketingAppsDomainVO implements Serializable {
 	/**
 	/**
 	 * 来源类型
 	 * 来源类型
 	 */
 	 */
-	@Schema(description = "来源类型,1-来自分组,2-具体域名,3-全局配置")
+	@Schema(description = "来源类型,1-来自分组,2-具体域名")
 	private Integer sourceType;
 	private Integer sourceType;
 
 
 	/**
 	/**

+ 1 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/app/MarketingAppsIpVO.java

@@ -36,7 +36,7 @@ public class MarketingAppsIpVO implements Serializable {
 	/**
 	/**
 	 * 来源类型
 	 * 来源类型
 	 */
 	 */
-	@Schema(description = "来源类型,1-来自分组,2-具体IP,3-全局配置")
+	@Schema(description = "来源类型,1-来自分组,2-具体IP")
 	private Integer sourceType;
 	private Integer sourceType;
 
 
 	/**
 	/**

+ 2 - 2
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/app/PageMarketingAppsVO.java

@@ -81,10 +81,10 @@ public class PageMarketingAppsVO implements Serializable {
 	Integer triggerRule;
 	Integer triggerRule;
 
 
 	/**
 	/**
-	 * 触发次数
+	 * 触发频率
 	 */
 	 */
 	@Schema(description = "触发频率")
 	@Schema(description = "触发频率")
-	Integer triggerNum;
+	String triggerNum;
 
 
 	/**
 	/**
 	 * 备注
 	 * 备注

+ 53 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/config/GetMarketingConfigDomainListVO.java

@@ -0,0 +1,53 @@
+package com.pig4cloud.pig.marketing.api.vo.config;
+
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-24
+ * @description: 获取域名列表出参
+ */
+@Data
+@Schema(description = "获取域名列表出参")
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class GetMarketingConfigDomainListVO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * id
+	 */
+	@Schema(description = "id")
+	private Long id;
+
+	/**
+	 * 来源类型
+	 */
+	@Schema(description = "来源类型,1-来自分组,2-具体域名")
+	private Integer sourceType;
+
+	/**
+	 * 分组ID
+	 */
+	@Schema(description = "分组ID")
+	private Long groupId;
+
+	/**
+	 * 分组名称
+	 */
+	@Schema(description = "分组名称")
+	private String groupName;
+
+	/**
+	 * 域名
+	 */
+	@Schema(description = "域名")
+	private String domain;
+}

+ 69 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/config/GetMarketingConfigIpListVO.java

@@ -0,0 +1,69 @@
+package com.pig4cloud.pig.marketing.api.vo.config;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-24
+ * @description: 获取IP集合出参
+ */
+@Data
+@Schema(description = "获取IP集合出参")
+public class GetMarketingConfigIpListVO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * id
+	 */
+	@Schema(description = "id")
+	private Long id;
+
+	/**
+	 * ip类型
+	 */
+	@Schema(description = "ip类型,1-白名单,2-黑名单")
+	private Integer ipType;
+
+	/**
+	 * 来源类型
+	 */
+	@Schema(description = "来源类型,1-来自分组,2-具体IP")
+	private Integer sourceType;
+
+	/**
+	 * 分组ID
+	 */
+	@Schema(description = "分组ID")
+	private Long groupId;
+
+	/**
+	 * 分组名称
+	 */
+	@Schema(description = "分组名称")
+	private String groupName;
+
+	/**
+	 * ip模式
+	 */
+	@Schema(description = "ip模式,1-单IP,2-IP段")
+	private Integer ipMode;
+
+	/**
+	 * 起始IP
+	 */
+	@Schema(description = "起始IP")
+	private String startIp;
+
+	/**
+	 * 结束IP
+	 */
+	@Schema(description = "结束IP")
+	private String endIp;
+}

+ 58 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/config/GetMarketingGlobalConfigVO.java

@@ -0,0 +1,58 @@
+package com.pig4cloud.pig.marketing.api.vo.config;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-25
+ * @description: 全局配置信息
+ */
+@Data
+@Schema(description = "全局配置信息")
+public class GetMarketingGlobalConfigVO implements Serializable {
+
+	@Serial
+	private final static long serialVersionUID = 1L;
+
+	/**
+	 * 触发方式
+	 */
+	@Schema(description = "触发方式")
+	@NotNull(message = "触发方式不能为空")
+	Integer triggerMode;
+
+	/**
+	 * 触发规则
+	 */
+	@Schema(description = "触发规则")
+	@NotNull(message = "触发规则不能为空")
+	Integer triggerRule;
+
+	/**
+	 * 触发频率
+	 */
+	@Schema(description = "触发频率,小于1为百分比,大于1为周期")
+	@NotBlank(message = "触发频率不能为空")
+	String triggerNum;
+
+	/**
+	 * 提示信息
+	 */
+	@Schema(description = "提示信息")
+	String promptMsg;
+
+	/**
+	 * 跳转链接
+	 */
+	@Schema(description = "跳转链接")
+	@NotBlank(message = "跳转链接不能为空")
+	String url;
+}

+ 33 - 3
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/vo/data/MarketingDataReportVO.java

@@ -19,10 +19,40 @@ public class MarketingDataReportVO implements Serializable {
 	@Serial
 	@Serial
 	private static final long serialVersionUID = 1L;
 	private static final long serialVersionUID = 1L;
 
 
-	@Schema(description = "跳转地址")
-	private String downloadUrl;
-
+	/**
+	 * 应用ID
+	 */
+	@Schema(description = "应用ID")
+	private String appId;
+
+	/**
+	 * 跳转类型
+	 */
 	@Schema(description = "跳转类型")
 	@Schema(description = "跳转类型")
 	private String type;
 	private String type;
 
 
+	/**
+	 * 触发方式
+	 */
+	@Schema(description = "触发方式,全局获取")
+	private Integer triggerMode;
+
+	/**
+	 * 触发规则
+	 */
+	@Schema(description = "触发规则,具体应用获取")
+	private Integer triggerRule;
+
+	/**
+	 * 提示信息
+	 */
+	@Schema(description = "提示信息")
+	private String promptMsg;
+
+	/**
+	 * 跳转链接
+	 */
+	@Schema(description = "跳转链接")
+	private String url;
+
 }
 }

+ 5 - 0
pig-marketing/pig-marketing-biz/pom.xml

@@ -36,6 +36,11 @@
 			<artifactId>pig-marketing-api</artifactId>
 			<artifactId>pig-marketing-api</artifactId>
 			<version>${revision}</version>
 			<version>${revision}</version>
 		</dependency>
 		</dependency>
+		<!--UPMS接口模块-->
+		<dependency>
+			<groupId>com.pig4cloud</groupId>
+			<artifactId>pig-upms-api</artifactId>
+		</dependency>
 		<!--文件管理-->
 		<!--文件管理-->
 		<dependency>
 		<dependency>
 			<groupId>com.pig4cloud</groupId>
 			<groupId>com.pig4cloud</groupId>

+ 65 - 40
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingAppsController.java

@@ -3,12 +3,14 @@ package com.pig4cloud.pig.marketing.controller;
 
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.common.core.util.R;
-import com.pig4cloud.pig.marketing.api.dto.app.BatchUpdateMarketingAppsDTO;
-import com.pig4cloud.pig.marketing.api.dto.app.PageMarketingAppsDTO;
-import com.pig4cloud.pig.marketing.api.dto.app.SetMarketingAppsDTO;
-import com.pig4cloud.pig.marketing.api.dto.app.UpdateMarketingAppsDTO;
+import com.pig4cloud.pig.marketing.api.dto.app.*;
+import com.pig4cloud.pig.marketing.api.dto.data.PageFirstLevelDataDTO;
+import com.pig4cloud.pig.marketing.api.dto.data.PageSecondLevelDataDTO;
+import com.pig4cloud.pig.marketing.api.vo.app.PageMarketingAppsVO;
 import com.pig4cloud.pig.marketing.service.MarketingAppsService;
 import com.pig4cloud.pig.marketing.service.MarketingAppsService;
+import com.pig4cloud.pig.marketing.service.MarketingDataService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.security.SecurityRequirement;
 import io.swagger.v3.oas.annotations.security.SecurityRequirement;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.validation.Valid;
 import jakarta.validation.Valid;
@@ -43,64 +45,66 @@ public class MarketingAppsController {
 	@GetMapping("/page")
 	@GetMapping("/page")
 	@Operation(summary = "分页查询应用列表")
 	@Operation(summary = "分页查询应用列表")
 	public R pageMarketingApps(@ParameterObject PageMarketingAppsDTO reqDto) {
 	public R pageMarketingApps(@ParameterObject PageMarketingAppsDTO reqDto) {
-		Page page = marketingAppsService.pageMarketingApps(reqDto);
+		Page page = marketingAppsService.pageMarketingApps(reqDto, true);
 		return R.ok(page);
 		return R.ok(page);
 	}
 	}
 
 
-	/**
-	 * 根据ID删除应用
-	 * @param id 应用ID
-	 * @return id
-	 */
-	@GetMapping("/del/{id}")
-	@Operation(summary = "根据ID删除应用")
-	public R delAppById(@PathVariable String id) {
-		if (id == null || id.isEmpty()){
-			return R.failed("ID不能为空");
+	@GetMapping("/detail")
+	@Operation(summary = "查询应用详情")
+	public R getMarketingAppById(@ParameterObject Long id) {
+		if (id == null){
+			throw new RuntimeException("应用ID不能为空");
 		}
 		}
-		Long res = marketingAppsService.delAppById(id);
+		PageMarketingAppsVO res = marketingAppsService.getMarketingAppById(id);
 		return R.ok(res);
 		return R.ok(res);
 	}
 	}
 
 
+	/**
+	 * 分页查询拉黑应用列表
+	 * @param reqDto 分页参数对象
+	 * @return 分页查询结果
+	 */
+	@GetMapping("/pageDel")
+	@Operation(summary = "分页查询拉黑应用列表")
+	public R pageDelMarketingApps(@ParameterObject PageMarketingAppsDTO reqDto) {
+		Page page = marketingAppsService.pageMarketingApps(reqDto, false);
+		return R.ok(page);
+	}
 
 
 	/**
 	/**
-	 * 设置应用信息
-	 * @param reqDto 应用信息
+	 * 批量更新应用信息
+	 * @param reqDtoList 批量更新参数
 	 * @return 保存结果
 	 * @return 保存结果
 	 */
 	 */
-	@PostMapping("/set")
-	@Operation(summary = "设置应用信息")
-	public R setMarketingApps(@Valid @RequestBody SetMarketingAppsDTO reqDto) {
-		// 先查询域名是否存在
-		Long id = marketingAppsService.setMarketingApps(reqDto);
-		return R.ok(id);
+	@PostMapping("/update")
+	@Operation(summary = "批量更新应用信息")
+	public R batchUpdateMarketingApps(@Valid @RequestBody List<BatchUpdateMarketingAppsDTO> reqDtoList) {
+		return marketingAppsService.batchUpdateMarketingApps(reqDtoList);
 	}
 	}
 
 
-
 	/**
 	/**
-	 * 更新应用信息
+	 * 设置应用信息
 	 * @param reqDto 应用信息
 	 * @param reqDto 应用信息
 	 * @return 保存结果
 	 * @return 保存结果
 	 */
 	 */
-	@PostMapping("/update")
-	@Operation(summary = "更新应用信息")
-	public R updateMarketingApps(@Valid @RequestBody UpdateMarketingAppsDTO reqDto) {
+	@PostMapping("/setInfo")
+	@Operation(summary = "设置应用信息")
+	public R setMarketingAppsInfo(@Valid @RequestBody SetMarketingAppsDTO reqDto) {
 		// 先查询域名是否存在
 		// 先查询域名是否存在
-		Long id = marketingAppsService.updateMarketingApps(reqDto);
-		return R.ok(id);
+		Boolean result = marketingAppsService.setMarketingAppsInfo(reqDto);
+		return result?R.ok():R.failed();
 	}
 	}
 
 
-
 	/**
 	/**
-	 * 批量更新应用信息
-	 * @param reqDtoList 批量更新参数
-	 * @return 保存结果
+	 * 设置应用状态
+	 * @param reqDto 应用信息
+	 * @return R
 	 */
 	 */
-	@PostMapping("/batch")
-	@Operation(summary = "批量更新应用信息")
-	public R batchUpdateMarketingApps(@Valid @RequestBody List<BatchUpdateMarketingAppsDTO> reqDtoList) {
-		List<Long> id = marketingAppsService.batchUpdateMarketingApps(reqDtoList);
-		return R.ok(id);
+	@PostMapping("/setStatus")
+	@Operation(summary = "设置应用状态")
+	public R setAppStatusById(@Valid @RequestBody SetMarketingAppsStatusDTO reqDto)  {
+		Boolean res = marketingAppsService.setAppStatusById(reqDto);
+		return res?R.ok():R.failed();
 	}
 	}
 
 
 	@PostMapping("/synced")
 	@PostMapping("/synced")
@@ -109,4 +113,25 @@ public class MarketingAppsController {
 		return R.ok(marketingAppsService.syncedAppList());
 		return R.ok(marketingAppsService.syncedAppList());
 	}
 	}
 
 
+	/**
+	 * 修改应用IP列表
+	 * @param reqDto IP参数
+	 * @return 保存结果
+	 */
+	@PostMapping("/modIp")
+	@Operation(summary = "修改应用IP集合")
+	public R modMarketingAppsIp(@Valid @RequestBody ModMarketingAppsIpDTO reqDto) {
+		return marketingAppsService.modMarketingAppsIps(reqDto);
+	}
+
+	/**
+	 * 修改应用域名集合
+	 * @param reqDto 域名参数
+	 * @return 保存结果
+	 */
+	@PostMapping("/modDomain")
+	@Operation(summary = "修改应用域名集合")
+	public R modMarketingAppsIp(@Valid @RequestBody ModMarketingAppsDomainDTO reqDto) {
+		return marketingAppsService.modMarketingAppsDomains(reqDto);
+	}
 }
 }

+ 100 - 8
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingConfigController.java

@@ -2,18 +2,15 @@ package com.pig4cloud.pig.marketing.controller;
 
 
 
 
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.common.core.util.R;
-import com.pig4cloud.pig.marketing.api.dto.config.AddMarketingGroupDTO;
-import com.pig4cloud.pig.marketing.api.dto.config.DelMarketingGroupDTO;
-import com.pig4cloud.pig.marketing.api.dto.config.ModMarketingGroupDomainDTO;
-import com.pig4cloud.pig.marketing.api.dto.config.ModMarketingGroupIPDTO;
-import com.pig4cloud.pig.marketing.api.vo.config.GetMarketingDomainGroupVO;
-import com.pig4cloud.pig.marketing.api.vo.config.GetMarketingIpGroupVO;
+import com.pig4cloud.pig.marketing.api.dto.config.*;
+import com.pig4cloud.pig.marketing.api.vo.config.*;
 import com.pig4cloud.pig.marketing.service.MarketingConfigService;
 import com.pig4cloud.pig.marketing.service.MarketingConfigService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.security.SecurityRequirement;
 import io.swagger.v3.oas.annotations.security.SecurityRequirement;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.validation.Valid;
 import jakarta.validation.Valid;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
+import org.springdoc.core.annotations.ParameterObject;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpHeaders;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
@@ -54,6 +51,19 @@ public class MarketingConfigController {
 		return R.ok(marketingConfigService.delMarketingConfigGroup(reqDto));
 		return R.ok(marketingConfigService.delMarketingConfigGroup(reqDto));
 	}
 	}
 
 
+	/**
+	 * 根据ID查询分组详情
+	 * @return R
+	 */
+	@GetMapping("/group/detail")
+	@Operation(summary = "根据ID查询分组详情")
+	public R getMarketingGroupDetail(@ParameterObject  Long id) {
+		if (id == null){
+			throw new RuntimeException("分组ID不能为空");
+		}
+		return marketingConfigService.getMarketingGroupDetail(id);
+	}
+
 	/**
 	/**
 	 * 修改域名分组
 	 * 修改域名分组
 	 * @return 域名分组列表
 	 * @return 域名分组列表
@@ -76,7 +86,7 @@ public class MarketingConfigController {
 	}
 	}
 
 
 	/**
 	/**
-	 * 修改IP分组
+	 * 修改分组IP
 	 * @return IP分组列表
 	 * @return IP分组列表
 	 */
 	 */
 	@PostMapping("/modIpGroup")
 	@PostMapping("/modIpGroup")
@@ -90,10 +100,92 @@ public class MarketingConfigController {
 	 * @return ip分组列表
 	 * @return ip分组列表
 	 */
 	 */
 	@GetMapping("/getIpGroup")
 	@GetMapping("/getIpGroup")
-	@Operation(summary = "获取ip分组列表")
+	@Operation(summary = "获取IP分组列表")
 	public R getMarketingIpGroupList() {
 	public R getMarketingIpGroupList() {
 		List<GetMarketingIpGroupVO> res = marketingConfigService.getMarketingIpGroupList();
 		List<GetMarketingIpGroupVO> res = marketingConfigService.getMarketingIpGroupList();
 		return R.ok(res);
 		return R.ok(res);
 	}
 	}
 
 
+	/**
+	 * 获取ip集合
+	 * @return ip分组列表
+	 */
+	@GetMapping("/ipList")
+	@Operation(summary = "获取IP集合")
+	public R getMarketingConfigIpList() {
+		List<GetMarketingConfigIpListVO> res = marketingConfigService.getMarketingConfigIpList();
+		return R.ok(res);
+	}
+
+	/**
+	 * 添加IP集合
+	 * @return R
+	 */
+	@PostMapping("/addIp")
+	@Operation(summary = "IP集合添加IP")
+	public R addMarketingConfigIpList(@Valid @RequestBody AddMarketingConfigIpListDTO reqDto) {
+		return R.ok(marketingConfigService.addMarketingConfigIpList(reqDto));
+	}
+
+	/**
+	 * 删除IP集合
+	 * @return R
+	 */
+	@GetMapping("/delIp/{id}")
+	@Operation(summary = "IP集合删除IP")
+	public R delMarketingConfigIpList(@PathVariable Long id) {
+		return R.ok(marketingConfigService.delMarketingConfigIpList(id));
+	}
+
+	/**
+	 * 获取域名集合
+	 * @return 域名分组列表
+	 */
+	@GetMapping("/domainList")
+	@Operation(summary = "获取域名集合")
+	public R getMarketingConfigDomainList() {
+		List<GetMarketingConfigDomainListVO> res = marketingConfigService.getMarketingConfigDomainList();
+		return R.ok(res);
+	}
+
+	/**
+	 * 添加域名集合
+	 * @return R
+	 */
+	@PostMapping("/addDomain")
+	@Operation(summary = "域名集合添加域名")
+	public R addMarketingConfigDomainList(@Valid @RequestBody AddMarketingConfigDomainListDTO reqDto) {
+		return R.ok(marketingConfigService.addMarketingConfigDomainList(reqDto));
+	}
+
+	/**
+	 * 删除IP集合
+	 * @return R
+	 */
+	@GetMapping("/delDomain/{id}")
+	@Operation(summary = "域名集合删除域名")
+	public R delMarketingConfigDomainList(@PathVariable Long id) {
+		return R.ok(marketingConfigService.delMarketingConfigDomainList(id));
+	}
+
+	/**
+	 * 查询全局配置信息
+	 * @return R
+	 */
+	@GetMapping("/getConfig")
+	@Operation(summary = "查询全局配置信息")
+	public R getMarketingGlobalConfig() {
+		return R.ok(marketingConfigService.getMarketingGlobalConfig());
+	}
+
+	/**
+	 * 查询全局配置信息
+	 * @return R
+	 */
+	@PostMapping("/setConfig")
+	@Operation(summary = "设置全局配置信息")
+	public R setMarketingGlobalConfig(@Valid @RequestBody GetMarketingGlobalConfigVO reDto) {
+		return R.ok(marketingConfigService.setMarketingGlobalConfig(reDto));
+	}
+
 }
 }

+ 0 - 1
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingDataController.java

@@ -40,7 +40,6 @@ public class MarketingDataController {
 		return R.ok(result);
 		return R.ok(result);
 	}
 	}
 
 
-
 	@GetMapping("/page")
 	@GetMapping("/page")
 	@Operation(summary = "分页统计一级营销数据")
 	@Operation(summary = "分页统计一级营销数据")
 	public R pageFirstLevelData(@ParameterObject PageFirstLevelDataDTO reqDto) {
 	public R pageFirstLevelData(@ParameterObject PageFirstLevelDataDTO reqDto) {

+ 3 - 0
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/mapper/MarketingAppsIpMapper.java

@@ -3,7 +3,9 @@ package com.pig4cloud.pig.marketing.mapper;
 
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.pig4cloud.pig.marketing.api.entity.MarketingAppsIp;
 import com.pig4cloud.pig.marketing.api.entity.MarketingAppsIp;
+import jakarta.validation.constraints.NotNull;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 
 /**
 /**
  * @author: lwh
  * @author: lwh
@@ -12,4 +14,5 @@ import org.apache.ibatis.annotations.Mapper;
  */
  */
 @Mapper
 @Mapper
 public interface MarketingAppsIpMapper extends BaseMapper<MarketingAppsIp> {
 public interface MarketingAppsIpMapper extends BaseMapper<MarketingAppsIp> {
+
 }
 }

+ 2 - 1
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/mapper/MarketingDataMapper.java

@@ -20,13 +20,14 @@ public interface MarketingDataMapper extends BaseMapper<MarketingData> {
 
 
 	List<PageFirstLevelDataVO> countFirstLevelMarketingData(
 	List<PageFirstLevelDataVO> countFirstLevelMarketingData(
 			@Param("ip") String ip,
 			@Param("ip") String ip,
+			@Param("appId") String appId,
 			@Param("lastHourTime") String lastHourTime,
 			@Param("lastHourTime") String lastHourTime,
 			@Param("todayStartTime") String todayStartTime,
 			@Param("todayStartTime") String todayStartTime,
 			@Param("offset") Long offset,
 			@Param("offset") Long offset,
 			@Param("pageSize") Long pageSize);
 			@Param("pageSize") Long pageSize);
 
 
 
 
-	Long countFirstLevelDataTotal(@Param("ip") String ip);
+	Long countFirstLevelDataTotal(@Param("ip") String ip, @Param("appId") String appId);
 
 
 
 
 	List<PageSecondLevelDataVO> countSecondLevelMarketingData(
 	List<PageSecondLevelDataVO> countSecondLevelMarketingData(

+ 34 - 19
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/MarketingAppsService.java

@@ -2,10 +2,10 @@ package com.pig4cloud.pig.marketing.service;
 
 
 
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.pig4cloud.pig.marketing.api.dto.app.BatchUpdateMarketingAppsDTO;
-import com.pig4cloud.pig.marketing.api.dto.app.PageMarketingAppsDTO;
-import com.pig4cloud.pig.marketing.api.dto.app.SetMarketingAppsDTO;
-import com.pig4cloud.pig.marketing.api.dto.app.UpdateMarketingAppsDTO;
+import com.pig4cloud.pig.common.core.util.R;
+import com.pig4cloud.pig.marketing.api.dto.app.*;
+import com.pig4cloud.pig.marketing.api.vo.app.PageMarketingAppsVO;
+import jakarta.validation.Valid;
 
 
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
@@ -17,44 +17,59 @@ import java.util.Map;
  */
  */
 
 
 public interface MarketingAppsService {
 public interface MarketingAppsService {
+
 	/**
 	/**
 	 * 分页查询应用列表
 	 * 分页查询应用列表
 	 * @param reqDto 查询参数
 	 * @param reqDto 查询参数
 	 * @return Page
 	 * @return Page
 	 */
 	 */
-	Page pageMarketingApps(PageMarketingAppsDTO reqDto);
+	Page pageMarketingApps(PageMarketingAppsDTO reqDto, Boolean status);
 
 
 	/**
 	/**
-	 * 根据ID删除应用
+	 * 根据ID获取应用详情
 	 * @param id 应用ID
 	 * @param id 应用ID
-	 * @return Long
+	 * @return 应用详情
 	 */
 	 */
-	Long delAppById(String id);
+	PageMarketingAppsVO getMarketingAppById(Long id);
 
 
 	/**
 	/**
-	 * 设置应用信息
-	 * @param reqDto 应用信息
-	 * @return Long
+	 * 批量更新应用信息
+	 * @param reqDtoList 批量更新参数
+	 * @return List<Long>
 	 */
 	 */
-	Long setMarketingApps(SetMarketingAppsDTO reqDto);
+	R batchUpdateMarketingApps(List<BatchUpdateMarketingAppsDTO> reqDtoList);
 
 
 	/**
 	/**
-	 * 更新应用信息
+	 * 设置应用信息
 	 * @param reqDto 应用信息
 	 * @param reqDto 应用信息
-	 * @return Long
+	 * @return Boolean
 	 */
 	 */
-	Long updateMarketingApps(UpdateMarketingAppsDTO reqDto);
+	Boolean setMarketingAppsInfo(SetMarketingAppsDTO reqDto);
 
 
 	/**
 	/**
-	 * 批量更新应用信息
-	 * @param reqDtoList 批量更新参数
-	 * @return List<Long>
+	 * 设置应用状态
+	 * @param reqDto 设置参数
+	 * @return  Boolean
 	 */
 	 */
-	List<Long> batchUpdateMarketingApps(List<BatchUpdateMarketingAppsDTO> reqDtoList);
+	Boolean setAppStatusById(SetMarketingAppsStatusDTO reqDto);
 
 
 	/**
 	/**
 	 * 同步应用列表
 	 * 同步应用列表
 	 * @return Map<String, Integer>
 	 * @return Map<String, Integer>
 	 */
 	 */
 	Map<String, Integer> syncedAppList();
 	Map<String, Integer> syncedAppList();
+
+	/**
+	 * 修改应用ip列表
+	 * @param reqDto 修改参数
+	 * @return R
+	 */
+	R modMarketingAppsIps(@Valid ModMarketingAppsIpDTO reqDto);
+
+	/**
+	 * 修改应用域名列表
+	 * @param reqDto 修改参数
+	 * @return R
+	 */
+	R modMarketingAppsDomains(@Valid ModMarketingAppsDomainDTO reqDto);
 }
 }

+ 62 - 7
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/MarketingConfigService.java

@@ -2,12 +2,8 @@ package com.pig4cloud.pig.marketing.service;
 
 
 
 
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.common.core.util.R;
-import com.pig4cloud.pig.marketing.api.dto.config.AddMarketingGroupDTO;
-import com.pig4cloud.pig.marketing.api.dto.config.DelMarketingGroupDTO;
-import com.pig4cloud.pig.marketing.api.dto.config.ModMarketingGroupDomainDTO;
-import com.pig4cloud.pig.marketing.api.dto.config.ModMarketingGroupIPDTO;
-import com.pig4cloud.pig.marketing.api.vo.config.GetMarketingDomainGroupVO;
-import com.pig4cloud.pig.marketing.api.vo.config.GetMarketingIpGroupVO;
+import com.pig4cloud.pig.marketing.api.dto.config.*;
+import com.pig4cloud.pig.marketing.api.vo.config.*;
 import jakarta.validation.Valid;
 import jakarta.validation.Valid;
 
 
 import java.util.List;
 import java.util.List;
@@ -34,6 +30,13 @@ public interface MarketingConfigService {
 	 */
 	 */
 	Boolean delMarketingConfigGroup(DelMarketingGroupDTO reqDto);
 	Boolean delMarketingConfigGroup(DelMarketingGroupDTO reqDto);
 
 
+	/**
+	 * 根据ID查询分组详情
+	 * @param id ID
+	 * @return 分组详情
+	 */
+	R getMarketingGroupDetail(Long id);
+
 	/**
 	/**
 	 * 修改域名分组
 	 * 修改域名分组
 	 * @param reqDto 修改域名分组入参
 	 * @param reqDto 修改域名分组入参
@@ -48,7 +51,7 @@ public interface MarketingConfigService {
 	List<GetMarketingDomainGroupVO> getMarketingDomainGroupList();
 	List<GetMarketingDomainGroupVO> getMarketingDomainGroupList();
 
 
 	/**
 	/**
-	 * 修改IP分组
+	 * 修改分组IP
 	 * @param reqDto 修改IP分组入参
 	 * @param reqDto 修改IP分组入参
 	 * @return R
 	 * @return R
 	 */
 	 */
@@ -60,4 +63,56 @@ public interface MarketingConfigService {
 	 */
 	 */
 	List<GetMarketingIpGroupVO> getMarketingIpGroupList();
 	List<GetMarketingIpGroupVO> getMarketingIpGroupList();
 
 
+	/**
+	 * 获取IP集合
+	 * @return IP集合
+	 */
+    List<GetMarketingConfigIpListVO> getMarketingConfigIpList();
+
+	/**
+	 * 添加IP集合
+	 * @param reqDto 添加IP集合入参
+	 * @return ID
+	 */
+	Boolean addMarketingConfigIpList(@Valid AddMarketingConfigIpListDTO reqDto);
+
+	/**
+	 * 删除IP集合
+	 * @param id id
+	 * @return Boolean
+	 */
+	Boolean delMarketingConfigIpList(Long id);
+
+	/**
+	 * 获取域名集合
+	 * @return 域名集合
+	 */
+	List<GetMarketingConfigDomainListVO> getMarketingConfigDomainList();
+
+	/**
+	 * 添加域名集合
+	 * @param reqDto 添加域名集合入参
+	 * @return Boolean
+	 */
+	Boolean addMarketingConfigDomainList(@Valid AddMarketingConfigDomainListDTO reqDto);
+
+	/**
+	 * 删除域名集合
+	 * @param id id
+	 * @return Boolean
+	 */
+	Boolean delMarketingConfigDomainList(Long id);
+
+	/**
+	 * 查询全局配置信息
+	 * @return 全局配置信息
+	 */
+	GetMarketingGlobalConfigVO getMarketingGlobalConfig();
+
+	/**
+	 * 设置全局配置信息
+	 * @param reDto 全局配置信息
+	 * @return 全局配置信息
+	 */
+	Boolean setMarketingGlobalConfig(GetMarketingGlobalConfigVO reDto);
 }
 }

+ 409 - 36
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingAppsServiceImpl.java

@@ -4,25 +4,20 @@ package com.pig4cloud.pig.marketing.service.impl;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.pig4cloud.pig.marketing.api.dto.app.BatchUpdateMarketingAppsDTO;
-import com.pig4cloud.pig.marketing.api.dto.app.PageMarketingAppsDTO;
-import com.pig4cloud.pig.marketing.api.dto.app.SetMarketingAppsDTO;
-import com.pig4cloud.pig.marketing.api.dto.app.UpdateMarketingAppsDTO;
-import com.pig4cloud.pig.marketing.api.entity.MarketingApps;
-import com.pig4cloud.pig.marketing.api.entity.MarketingAppsDomain;
-import com.pig4cloud.pig.marketing.api.entity.MarketingAppsIp;
-import com.pig4cloud.pig.marketing.api.entity.MarketingConfigGroup;
+import com.pig4cloud.pig.common.core.util.R;
+import com.pig4cloud.pig.marketing.api.dto.app.*;
+import com.pig4cloud.pig.marketing.api.entity.*;
 import com.pig4cloud.pig.marketing.api.vo.app.MarketingAppsDomainVO;
 import com.pig4cloud.pig.marketing.api.vo.app.MarketingAppsDomainVO;
 import com.pig4cloud.pig.marketing.api.vo.app.MarketingAppsIpVO;
 import com.pig4cloud.pig.marketing.api.vo.app.MarketingAppsIpVO;
 import com.pig4cloud.pig.marketing.api.vo.app.PageMarketingAppsVO;
 import com.pig4cloud.pig.marketing.api.vo.app.PageMarketingAppsVO;
-import com.pig4cloud.pig.marketing.mapper.MarketingAppsDomainMapper;
-import com.pig4cloud.pig.marketing.mapper.MarketingAppsIpMapper;
-import com.pig4cloud.pig.marketing.mapper.MarketingAppsMapper;
-import com.pig4cloud.pig.marketing.mapper.MarketingConfigGroupMapper;
+import com.pig4cloud.pig.marketing.api.vo.config.GetMarketingGlobalConfigVO;
+import com.pig4cloud.pig.marketing.mapper.*;
 import com.pig4cloud.pig.marketing.service.MarketingAppsService;
 import com.pig4cloud.pig.marketing.service.MarketingAppsService;
+import com.pig4cloud.pig.marketing.service.MarketingConfigService;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.*;
 import okhttp3.*;
@@ -47,7 +42,7 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 
 
 	// 从配置文件读取URL
 	// 从配置文件读取URL
 //	@Value("${marketing.app.url}")
 //	@Value("${marketing.app.url}")
-	private static final String getAppListUrl = "http://192.168.80.130:8000/ipa/getApps";
+	private static final String getAppListUrl = "http://192.168.3.17:2888/ipa/getApps";
 
 
 	// 从配置文件读取accessKey
 	// 从配置文件读取accessKey
 //	@Value("${marketing.app.access-key}")
 //	@Value("${marketing.app.access-key}")
@@ -59,8 +54,15 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 
 
 	private final MarketingAppsDomainMapper appsDomainMapper;
 	private final MarketingAppsDomainMapper appsDomainMapper;
 
 
+	private final MarketingGroupDomainMapper groupDomainMapper;
+
 	private final MarketingConfigGroupMapper groupMapper;
 	private final MarketingConfigGroupMapper groupMapper;
 
 
+	private final MarketingGroupIpMapper groupIpMapper;
+
+	private final MarketingConfigService marketingConfigService;
+
+
 
 
 	/**
 	/**
 	 * 分页查询应用列表
 	 * 分页查询应用列表
@@ -68,9 +70,10 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 	 * @return Page
 	 * @return Page
 	 */
 	 */
 	@Override
 	@Override
-	public Page pageMarketingApps(PageMarketingAppsDTO reqDto){
+	public Page pageMarketingApps(PageMarketingAppsDTO reqDto, Boolean status){
 		Page page = appsMapper.selectPage(new Page(reqDto.getCurrent(), reqDto.getSize()),
 		Page page = appsMapper.selectPage(new Page(reqDto.getCurrent(), reqDto.getSize()),
 				Wrappers.<MarketingApps>lambdaQuery()
 				Wrappers.<MarketingApps>lambdaQuery()
+						.eq(MarketingApps::getStatus, status)
 						.like(StrUtil.isNotBlank(reqDto.getAppId()), MarketingApps::getAppId, reqDto.getAppId())
 						.like(StrUtil.isNotBlank(reqDto.getAppId()), MarketingApps::getAppId, reqDto.getAppId())
 						.like(StrUtil.isNotBlank(reqDto.getAppName()), MarketingApps::getAppName, reqDto.getAppName())
 						.like(StrUtil.isNotBlank(reqDto.getAppName()), MarketingApps::getAppName, reqDto.getAppName())
 						.like(StrUtil.isNotBlank(reqDto.getDomainType()), MarketingApps::getDomainType, reqDto.getDomainType())
 						.like(StrUtil.isNotBlank(reqDto.getDomainType()), MarketingApps::getDomainType, reqDto.getDomainType())
@@ -118,49 +121,123 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 		return page;
 		return page;
 	}
 	}
 
 
-
 	/**
 	/**
-	 * 删除应用
-	 * @param id 应用id
-	 * @return Long
+	 * 根据ID获取应用详情
+	 * @param id 应用ID
+	 * @return 应用详情
 	 */
 	 */
 	@Override
 	@Override
-	public Long delAppById(String id) {
-		return 0L;
+	public PageMarketingAppsVO getMarketingAppById(Long id) {
+		MarketingApps app = appsMapper.selectById(id);
+		if (app == null){
+			throw new RuntimeException("应用不存在");
+		}
+		PageMarketingAppsVO appsVO = new PageMarketingAppsVO();
+		BeanUtils.copyProperties(app, appsVO);
+		// 组装IP
+		List<MarketingAppsIp> ips = appsIpMapper.selectList(new QueryWrapper<MarketingAppsIp>().eq("app_id", app.getId()));
+		List<MarketingAppsIpVO> ipVOList = new ArrayList<>();
+		for (MarketingAppsIp ip : ips) {
+			MarketingAppsIpVO ipVO = new MarketingAppsIpVO();
+			BeanUtils.copyProperties(ip, ipVO);
+			if (ip.getGroupId() != null){
+				MarketingConfigGroup group = groupMapper.selectById(ip.getGroupId());
+				if (group != null)
+					ipVO.setGroupName(group.getGroupName());
+			}
+			ipVOList.add(ipVO);
+		}
+		appsVO.setIps(ipVOList);
+		// 组装域名
+
+		List<MarketingAppsDomain> domains = appsDomainMapper.selectList(new QueryWrapper<MarketingAppsDomain>().eq("app_id", app.getId()));
+		ArrayList<MarketingAppsDomainVO> domainVOList = new ArrayList<>();
+		for (MarketingAppsDomain domain : domains) {
+			MarketingAppsDomainVO domainVO = new MarketingAppsDomainVO();
+			BeanUtils.copyProperties(domain, domainVO);
+			if (domain.getGroupId() != null){
+				MarketingConfigGroup group = groupMapper.selectById(domain.getGroupId());
+				if (group != null)
+					domainVO.setGroupName(group.getGroupName());
+			}
+			domainVOList.add(domainVO);
+		}
+		appsVO.setDomains(domainVOList);
+		return appsVO;
 	}
 	}
 
 
 	/**
 	/**
-	 * 设置应用信息
-	 * @param reqDto 更新参数
+	 * 批量更新应用信息
+	 * @param reqDtoList 批量更新参数
 	 * @return Long
 	 * @return Long
 	 */
 	 */
 	@Override
 	@Override
-	public Long setMarketingApps(SetMarketingAppsDTO reqDto) {
-		return 0L;
+	@Transactional(rollbackFor = Exception.class)
+	public R batchUpdateMarketingApps(List<BatchUpdateMarketingAppsDTO> reqDtoList) {
+		for (BatchUpdateMarketingAppsDTO reqDto : reqDtoList) {
+			Long id = reqDto.getId();
+			if (reqDto.getId() == null){
+				throw new RuntimeException("应用ID不能为空");
+			}
+
+			MarketingApps apps = appsMapper.selectById(id);
+			if (apps == null){
+				throw new RuntimeException("应用ID:"+id+"不存在");
+			}
+			if (!apps.getStatus()){
+				throw new RuntimeException("应用ID:"+id+"已拉黑,请还原后操作");
+			}
+
+			// 1、更新基本信息
+			MarketingApps marketingApps = new MarketingApps();
+			BeanUtils.copyProperties(reqDto, marketingApps);
+			appsMapper.updateById(marketingApps);
+
+
+			// 2. 处理IP信息(包含分组检查)
+			handleIpOperations(reqDto, id);
+
+			// 3. 处理域名信息(包含分组检查)
+			handleDomainOperations(reqDto, id);
+		}
+		return R.ok();
 	}
 	}
 
 
 	/**
 	/**
-	 * 更新应用信息
+	 * 设置应用信息
 	 * @param reqDto 更新参数
 	 * @param reqDto 更新参数
 	 * @return Long
 	 * @return Long
 	 */
 	 */
 	@Override
 	@Override
-	public Long updateMarketingApps(UpdateMarketingAppsDTO reqDto) {
-		return 0L;
+	public Boolean setMarketingAppsInfo(SetMarketingAppsDTO reqDto) {
+		MarketingApps app = appsMapper.selectById(reqDto.getId());
+		if (app == null){
+			throw new RuntimeException("应用不存在");
+		}
+		if (!app.getStatus()){
+			throw new RuntimeException("应用ID:"+app.getId()+"已拉黑,请还原后操作");
+		}
+		MarketingApps apps = new MarketingApps();
+		BeanUtils.copyProperties(reqDto, apps);
+		int i = appsMapper.updateById(apps);
+		return i>0 ;
 	}
 	}
 
 
 	/**
 	/**
-	 * 批量更新应用信息
-	 * @param reqDtoList 批量更新参数
-	 * @return Long
+	 * 设置应用状态
+	 * @param reqDto 设置参数
+	 * @return  Boolean
 	 */
 	 */
 	@Override
 	@Override
-	public List<Long> batchUpdateMarketingApps(List<BatchUpdateMarketingAppsDTO> reqDtoList) {
-		return List.of();
+	public Boolean setAppStatusById(SetMarketingAppsStatusDTO reqDto) {
+		MarketingApps apps = appsMapper.selectById(reqDto.getId());
+		if (apps == null) {
+			throw new RuntimeException("应用不存在");
+		}
+		apps.setStatus(reqDto.getStatus());
+		return appsMapper.updateById(apps) > 0;
 	}
 	}
 
 
-
-
 	/**
 	/**
 	 * 同步应用列表
 	 * 同步应用列表
 	 *
 	 *
@@ -195,11 +272,15 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 			MarketingApps localApp = localAppMap.get(app.getAppId());
 			MarketingApps localApp = localAppMap.get(app.getAppId());
 
 
 			if (localApp == null) {
 			if (localApp == null) {
+				// 获取全局配置信息
+				GetMarketingGlobalConfigVO globalConfig = marketingConfigService.getMarketingGlobalConfig();
+
 				// 4.1 本地不存在,新增
 				// 4.1 本地不存在,新增
+				app.setStatus( true);
 				app.setDomainLimit(false);
 				app.setDomainLimit(false);
 				app.setLaunch( true);
 				app.setLaunch( true);
-				app.setTriggerRule(1);
-				app.setTriggerNum(1);
+				app.setTriggerRule(globalConfig.getTriggerRule());
+				app.setTriggerNum(globalConfig.getTriggerNum());
 				appsMapper.insert(app);
 				appsMapper.insert(app);
 				addCount++;
 				addCount++;
 			} else {
 			} else {
@@ -219,6 +300,9 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 		for (MarketingApps localApp : localApps) {
 		for (MarketingApps localApp : localApps) {
 			if (!lafaAppIds.contains(localApp.getAppId())) {
 			if (!lafaAppIds.contains(localApp.getAppId())) {
 				appsMapper.deleteById(localApp);
 				appsMapper.deleteById(localApp);
+				// 删除应用关联的IP、域名
+				appsIpMapper.delete(Wrappers.<MarketingAppsIp>lambdaQuery().eq(MarketingAppsIp::getAppId, localApp.getId()));
+				appsDomainMapper.delete(Wrappers.<MarketingAppsDomain>lambdaQuery().eq(MarketingAppsDomain::getAppId, localApp.getId()));
 				deleteCount++;
 				deleteCount++;
 			}
 			}
 		}
 		}
@@ -230,6 +314,60 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 		return result;
 		return result;
 	}
 	}
 
 
+	/**
+	 * 修改应用IP列表
+	 * @param reqDto 修改参数
+	 * @return R
+	 */
+	@Override
+	public R modMarketingAppsIps(ModMarketingAppsIpDTO reqDto) {
+		Long appId = reqDto.getId();
+		if (reqDto.getId() == null) {
+			throw new RuntimeException("应用ID不能为空");
+		}
+		MarketingApps app = appsMapper.selectById(appId);
+		if (app == null){
+			throw new RuntimeException("应用ID:"+appId+"不存在");
+		}
+		if (!app.getStatus()){
+			throw new RuntimeException("应用ID:"+app.getId()+"已拉黑,请还原后操作");
+		}
+		BatchUpdateMarketingAppsDTO updateIp = new BatchUpdateMarketingAppsDTO();
+		updateIp.setId(appId);
+		updateIp.setIps(reqDto.getIps());
+		updateIp.setDelIps(reqDto.getDelIps());
+		// 处理IP信息
+		handleIpOperations(updateIp, appId);
+		return  R.ok();
+	}
+
+	/**
+	 * 修改应用域名列表
+	 * @param reqDto 修改参数
+	 * @return R
+	 */
+	@Override
+	public R modMarketingAppsDomains(ModMarketingAppsDomainDTO reqDto) {
+		Long appId = reqDto.getId();
+		if (reqDto.getId() == null){
+			throw new RuntimeException("应用ID不能为空");
+		}
+		MarketingApps app = appsMapper.selectById(appId);
+		if (app == null){
+			throw new RuntimeException("应用ID:"+appId+"不存在");
+		}
+		if (!app.getStatus()){
+			throw new RuntimeException("应用ID:"+app.getId()+"已拉黑,请还原后操作");
+		}
+		BatchUpdateMarketingAppsDTO updateDomain = new BatchUpdateMarketingAppsDTO();
+		updateDomain.setId(appId);
+		updateDomain.setDomains(reqDto.getDomains());
+		updateDomain.setDelDomains(reqDto.getDelDomains());
+		// 处理域名信息
+		handleDomainOperations(updateDomain, appId);
+		return R.ok();
+	}
+
 	/**
 	/**
 	 * 从lafa服务获取应用列表
 	 * 从lafa服务获取应用列表
 	 * @return 应用列表
 	 * @return 应用列表
@@ -299,4 +437,239 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 				Objects.equals(newApp.getDomainType(), oldApp.getDomainType());
 				Objects.equals(newApp.getDomainType(), oldApp.getDomainType());
 	}
 	}
 
 
+	/**
+	 * 处理IP的新增/修改/删除,包含分组存在性检查
+	 */
+	private void handleIpOperations(BatchUpdateMarketingAppsDTO reqDto, Long appId) {
+		// 2.1 删除指定IP
+		if (reqDto.getDelIps() != null && !reqDto.getDelIps().isEmpty()) {
+			appsIpMapper.deleteByIds(reqDto.getDelIps());
+		}
+
+		// 2.2 新增或修改IP
+		if (reqDto.getIps() != null && !reqDto.getIps().isEmpty()) {
+			for (MarketingAppsIpDTO ipDto : reqDto.getIps()) {
+				if (ipDto.getId() != null && (ipDto.getModify()==null || !ipDto.getModify())){
+					continue;
+				}
+
+				// 查询ip表和ip分组表中是否存在
+				if (checkIp(ipDto, appId)){
+					throw new RuntimeException("ip已存在");
+				}
+
+				// 执行新增或修改
+				MarketingAppsIp appsIp = new MarketingAppsIp();
+				BeanUtils.copyProperties(ipDto, appsIp);
+				appsIp.setAppId(appId);
+
+				if (ipDto.getId() == null) {
+					appsIp.setConfig(false);
+					appsIpMapper.insert(appsIp);
+				} else if (ipDto.getModify() != null && ipDto.getModify()) {
+					appsIpMapper.updateById(appsIp);
+				}
+			}
+		}
+	}
+
+	/**
+	 * 处理域名的新增/修改/删除,包含完整校验逻辑
+	 */
+	private void handleDomainOperations(BatchUpdateMarketingAppsDTO reqDto, Long appId) {
+		// 3.1 删除指定域名
+		if (reqDto.getDelDomains() != null && !reqDto.getDelDomains().isEmpty()) {
+			appsDomainMapper.deleteBatchIds(reqDto.getDelDomains());
+		}
+
+		// 3.2 新增或修改域名
+		if (reqDto.getDomains() != null && !reqDto.getDomains().isEmpty()) {
+			for (MarketingAppsDomainDTO domainDto : reqDto.getDomains()) {
+				if (domainDto.getId() != null && (domainDto.getModify()==null || !domainDto.getModify())){
+					continue;
+				}
+
+				if (checkDomain(domainDto, appId)){
+					throw new RuntimeException("域名已存在");
+				}
+
+				// 执行新增或修改
+				MarketingAppsDomain appsDomain = new MarketingAppsDomain();
+				BeanUtils.copyProperties(domainDto, appsDomain);
+				appsDomain.setAppId(appId);
+
+				if (domainDto.getId() == null) {
+					appsDomain.setConfig(false);
+					appsDomainMapper.insert(appsDomain);
+				} else if (domainDto.getModify() != null && domainDto.getModify()) {
+					appsDomainMapper.updateById(appsDomain);
+				}
+			}
+		}
+	}
+
+	/**
+	 * 判断IP是否已存在(单IP或IP段)
+	 * @param appId 应用数据ID
+	 * @param ipDTO IP
+	 * @return 是否存在
+	 */
+	public boolean checkIp(MarketingAppsIpDTO ipDTO, Long appId) {
+		// 1. 检查应用IP表
+		if (checkAppsIpExists(ipDTO, appId)) {
+			return true;
+		}
+
+		// 2. 检查分组IP表(需要关联应用关联的分组)
+		return checkGroupIpExists(ipDTO, appId);
+	}
+
+	/**
+	 * 判断域名是否已存在
+	 * @param domainDTO 域名信息DTO
+	 * @param appId 应用ID
+	 * @return 是否存在
+	 */
+	public Boolean checkDomain(MarketingAppsDomainDTO domainDTO, Long appId) {
+		// 1. 检查应用域名表
+		LambdaQueryWrapper<MarketingAppsDomain> appsQuery = new LambdaQueryWrapper<>();
+		appsQuery.eq(MarketingAppsDomain::getAppId, appId)
+				.eq(MarketingAppsDomain::getDomain, domainDTO.getDomain());
+		if (appsDomainMapper.selectCount(appsQuery) > 0) {
+			return true;
+		}
+
+		// 2. 检查分组域名表(需要关联应用关联的分组)
+		List<Long> groupIds = getAppRelatedGroupIds(appId, false);  // 需要实现获取应用关联的分组ID列表
+		if (!groupIds.isEmpty()) {
+			LambdaQueryWrapper<MarketingGroupDomain> groupQuery = new LambdaQueryWrapper<>();
+			groupQuery.in(MarketingGroupDomain::getGroupId, groupIds)
+					.eq(MarketingGroupDomain::getDomain, domainDTO.getDomain());
+			return groupDomainMapper.selectCount(groupQuery) > 0;
+		}
+		return false;
+	}
+
+	/**
+	 * 检查应用IP表中是否存在冲突
+	 */
+	private Boolean checkAppsIpExists(MarketingAppsIpDTO ipDto,Long appId){
+		// 1、校验该appId应用下ip表,及ip分组表中,是否存在该ip
+		// 1.1、校验marketing_apps_ip表,appId=appId,是否包含
+		// 1.2、校验marketing_group_ip表,是否包含ip,如果包含查出分组id,在查看appId下是否包含这个分组
+		QueryWrapper<MarketingAppsIp> query = new QueryWrapper<>();
+		query.eq("app_id", appId);
+
+		// 单IP模式检查
+		if (ipDto.getIpMode() == 1) {
+			String targetIp = ipDto.getStartIp();
+			// 检查是否有相同单IP
+			query.and(wrapper -> wrapper
+					.eq("ip_mode", 1)
+					.eq("start_ip", targetIp));
+
+			// 检查是否被IP段包含
+			query.or(wrapper -> wrapper
+					.eq("ip_mode", 2)
+					.apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", targetIp));
+
+		}
+
+		// IP段模式检查
+		if (ipDto.getIpMode() == 2) {
+			String startIp = ipDto.getStartIp();
+			String endIp = ipDto.getEndIp();
+
+			// 检查是否与单IP重叠:单IP在输入IP段范围内
+			query.and(wrapper -> wrapper
+					.eq("ip_mode", 1)
+					.apply("INET_ATON(start_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp));
+			// 检查是否与IP段重叠:两个IP段有交集
+			query.or(wrapper -> wrapper
+					.eq("ip_mode", 2)
+					.and(w2 -> w2
+							.apply("INET_ATON(start_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp)
+							.or().apply("INET_ATON(end_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp)
+							.or().apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", startIp)
+					)
+			);
+		}
+
+		return appsIpMapper.selectCount(query) > 0;
+	}
+
+	/**
+	 * 检查分组IP表中是否存在冲突
+	 */
+	private boolean checkGroupIpExists(MarketingAppsIpDTO ipDTO, Long appId) {
+		List<Long> groupIds = getAppRelatedGroupIds(appId, true);  // 需要实现获取应用关联的分组ID列表
+		if (groupIds.isEmpty()) {
+			return false;
+		}
+
+		QueryWrapper<MarketingGroupIp> query = new QueryWrapper<>();
+		query.in("group_id", groupIds);
+
+		// 单IP模式
+		if (ipDTO.getIpMode() == 1) {
+			String targetIp = ipDTO.getStartIp();
+			// 检查是否有相同单IP
+			query.and(wrapper -> wrapper
+					.eq("ip_mode", 1)
+					.eq("start_ip", targetIp));
+
+			// 检查是否被IP段包含
+			query.or(wrapper -> wrapper
+					.eq("ip_mode", 2)
+					.apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", targetIp));
+		}
+
+		// IP段模式检查
+		if (ipDTO.getIpMode() == 2) {
+			String startIp = ipDTO.getStartIp();
+			String endIp = ipDTO.getEndIp();
+
+			query.and(wrapper -> wrapper
+					.eq("ip_mode", 1)
+					.apply("INET_ATON(start_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp));
+
+			query.or(wrapper -> wrapper
+					.eq("ip_mode", 2)
+					.and(w2 -> w2
+							.apply("INET_ATON(start_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp)
+							.or().apply("INET_ATON(end_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp)
+							.or().apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", startIp)
+					)
+			);
+		}
+		return groupIpMapper.selectCount(query) > 0;
+	}
+
+	/**
+	 * 获取应用关联的所有分组ID
+	 */
+	private List<Long> getAppRelatedGroupIds(Long appId, Boolean isIp) {
+		// 示例实现,实际需根据业务调整
+		if (isIp) {
+			LambdaQueryWrapper<MarketingAppsIp> query = new LambdaQueryWrapper<>();
+			query.eq(MarketingAppsIp::getAppId, appId)
+					.eq(MarketingAppsIp::getSourceType, 1)  // 来源类型为分组
+					.select(MarketingAppsIp::getGroupId)
+					.groupBy(MarketingAppsIp::getGroupId);
+			return appsIpMapper.selectObjs(query).stream()
+					.map(obj -> (Long) obj)
+					.toList();
+		}else {
+			LambdaQueryWrapper<MarketingAppsDomain> query = new LambdaQueryWrapper<>();
+			query.eq(MarketingAppsDomain::getAppId, appId)
+					.eq(MarketingAppsDomain::getSourceType, 1)  // 来源类型为分组
+					.select(MarketingAppsDomain::getGroupId)
+					.groupBy(MarketingAppsDomain::getGroupId);
+			return appsDomainMapper.selectObjs(query).stream()
+					.map(obj -> (Long) obj)
+					.toList();
+		}
+	}
+
+
 }
 }

+ 294 - 30
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingConfigServiceImpl.java

@@ -1,24 +1,21 @@
 package com.pig4cloud.pig.marketing.service.impl;
 package com.pig4cloud.pig.marketing.service.impl;
 
 
 
 
-import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.pig4cloud.pig.admin.api.dto.SysPublicParamDTO;
+import com.pig4cloud.pig.admin.api.feign.RemoteParamService;
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.marketing.api.dto.config.*;
 import com.pig4cloud.pig.marketing.api.dto.config.*;
-import com.pig4cloud.pig.marketing.api.entity.MarketingConfigGroup;
-import com.pig4cloud.pig.marketing.api.entity.MarketingGroupDomain;
-import com.pig4cloud.pig.marketing.api.entity.MarketingGroupIp;
-import com.pig4cloud.pig.marketing.api.vo.config.GetMarketingDomainGroupVO;
-import com.pig4cloud.pig.marketing.api.vo.config.GetMarketingIpGroupVO;
-import com.pig4cloud.pig.marketing.api.vo.config.MarketingGroupDomainVO;
-import com.pig4cloud.pig.marketing.api.vo.config.MarketingGroupIpVO;
-import com.pig4cloud.pig.marketing.mapper.MarketingConfigGroupMapper;
-import com.pig4cloud.pig.marketing.mapper.MarketingGroupDomainMapper;
-import com.pig4cloud.pig.marketing.mapper.MarketingGroupIpMapper;
+import com.pig4cloud.pig.marketing.api.entity.*;
+import com.pig4cloud.pig.marketing.api.vo.config.*;
+import com.pig4cloud.pig.marketing.mapper.*;
 import com.pig4cloud.pig.marketing.service.MarketingConfigService;
 import com.pig4cloud.pig.marketing.service.MarketingConfigService;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
@@ -42,6 +39,12 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 
 
 	private final MarketingGroupIpMapper groupIpMapper;
 	private final MarketingGroupIpMapper groupIpMapper;
 
 
+	private final MarketingAppsIpMapper ipMapper;
+
+	private final MarketingAppsDomainMapper domainMapper;
+
+	private final RemoteParamService remoteParamService;
+
 	/**
 	/**
 	 * 添加分组
 	 * 添加分组
 	 * @param reqDto 分组信息
 	 * @param reqDto 分组信息
@@ -50,9 +53,9 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 	@Override
 	@Override
 	public R addMarketingConfigGroup(AddMarketingGroupDTO reqDto) {
 	public R addMarketingConfigGroup(AddMarketingGroupDTO reqDto) {
 		// 先查询是否已存在
 		// 先查询是否已存在
-		MarketingConfigGroup group = groupMapper.selectOne(new QueryWrapper<MarketingConfigGroup>()
-				.eq("group_name", reqDto.getGroupName())
-				.eq("group_type", reqDto.getGroupType())
+		MarketingConfigGroup group = groupMapper.selectOne(Wrappers.<MarketingConfigGroup>lambdaQuery()
+				.eq(MarketingConfigGroup::getGroupName, reqDto.getGroupName())
+				.eq(MarketingConfigGroup::getGroupType, reqDto.getGroupType())
 		);
 		);
 		if (group != null){
 		if (group != null){
 			return R.failed("分组名已存在");
 			return R.failed("分组名已存在");
@@ -68,22 +71,77 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 	 * @return Boolean
 	 * @return Boolean
 	 */
 	 */
 	@Override
 	@Override
+	@Transactional(rollbackFor = Exception.class)
 	public Boolean delMarketingConfigGroup(DelMarketingGroupDTO reqDto) {
 	public Boolean delMarketingConfigGroup(DelMarketingGroupDTO reqDto) {
 		List<Long> ids = reqDto.getIds();
 		List<Long> ids = reqDto.getIds();
 		// 删除分组
 		// 删除分组
 		int delGroup = groupMapper.deleteByIds(ids);
 		int delGroup = groupMapper.deleteByIds(ids);
 		// 删除分组下域名或ip
 		// 删除分组下域名或ip
 		int item = 0;
 		int item = 0;
+		// 删除分组子项
 		if (reqDto.getGroupType() == 1){
 		if (reqDto.getGroupType() == 1){
 			// 删除IP
 			// 删除IP
-			item = groupIpMapper.delete(new QueryWrapper<MarketingGroupIp>().in("group_id", ids));
+			item = groupIpMapper.delete(Wrappers.<MarketingGroupIp>lambdaQuery().in(MarketingGroupIp::getGroupId, ids));
+			// 删除应用、全局配置关联的IP分组
+			ipMapper.delete(Wrappers.<MarketingAppsIp>lambdaQuery().in(MarketingAppsIp::getGroupId, ids));
 		}else if (reqDto.getGroupType() == 2){
 		}else if (reqDto.getGroupType() == 2){
 			// 删除域名
 			// 删除域名
-			item = groupDomainMapper.delete(new QueryWrapper<MarketingGroupDomain>().in("group_id", ids));
+			item = groupDomainMapper.delete(Wrappers.<MarketingGroupDomain>lambdaQuery().in(MarketingGroupDomain::getGroupId, ids));
+			// 删除应用、全局配置关联的域名分组
+			domainMapper.delete(Wrappers.<MarketingAppsDomain>lambdaQuery().in(MarketingAppsDomain::getGroupId, ids));
 		}
 		}
 		return delGroup > 0 && item > 0;
 		return delGroup > 0 && item > 0;
 	}
 	}
 
 
+	/**
+	 * 根据ID查询分组详情
+	 * @param id ID
+	 * @return 分组详情
+	 */
+	@Override
+	public R getMarketingGroupDetail(Long id) {
+		MarketingConfigGroup group = groupMapper.selectById(id);
+		if (group == null){
+			throw new RuntimeException("id:"+id+",分组不存在");
+		}
+		if (group.getGroupType().equals(1)){
+			// IP类型
+			GetMarketingIpGroupVO rspVO = new GetMarketingIpGroupVO();
+			rspVO.setId(group.getId());
+			rspVO.setGroupName(group.getGroupName());
+
+			// 查询分组下IP列表
+			List<MarketingGroupIp> ipList = groupIpMapper.selectList(Wrappers.<MarketingGroupIp>lambdaQuery().eq(MarketingGroupIp::getGroupId, group.getId()));
+			ArrayList<MarketingGroupIpVO> ips = new ArrayList<>();
+			for (MarketingGroupIp ip : ipList) {
+				MarketingGroupIpVO ipVO = new MarketingGroupIpVO();
+				BeanUtils.copyProperties(ip, ipVO);
+				ips.add(ipVO);
+			}
+			rspVO.setIps(ips);
+			return R.ok(rspVO);
+		}else if (group.getGroupType().equals(2)){
+			// 域名类型
+			GetMarketingDomainGroupVO rspVO = new GetMarketingDomainGroupVO();
+			rspVO.setId(group.getId());
+			rspVO.setGroupName(group.getGroupName());
+
+			// 查询分组下域名列表
+			List<MarketingGroupDomain> domains = groupDomainMapper.selectList(Wrappers.<MarketingGroupDomain>lambdaQuery()
+					.eq(MarketingGroupDomain::getGroupId, group.getId()));
+
+			ArrayList<MarketingGroupDomainVO> domainVOS = new ArrayList<>();
+			for (MarketingGroupDomain domain : domains) {
+				MarketingGroupDomainVO domainVO = new MarketingGroupDomainVO();
+				BeanUtils.copyProperties(domain, domainVO);
+				domainVOS.add(domainVO);
+			}
+			rspVO.setDomains(domainVOS);
+			return R.ok(rspVO);
+		}
+		return R.failed();
+	}
+
 	/**
 	/**
 	 * 修改分组域名
 	 * 修改分组域名
 	 * @param reqDto 分组域名信息
 	 * @param reqDto 分组域名信息
@@ -93,9 +151,9 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 	@Transactional
 	@Transactional
 	public R modMarketingGroupDomain(ModMarketingGroupDomainDTO reqDto) {
 	public R modMarketingGroupDomain(ModMarketingGroupDomainDTO reqDto) {
 		// 先查询域名分组是否存在
 		// 先查询域名分组是否存在
-		MarketingConfigGroup groupExist = groupMapper.selectOne(new QueryWrapper<MarketingConfigGroup>()
-				.eq("group_type", "2")
-				.eq("group_name", reqDto.getGroupName()));
+		MarketingConfigGroup groupExist = groupMapper.selectOne(Wrappers.<MarketingConfigGroup>lambdaQuery()
+				.eq(MarketingConfigGroup::getGroupType, "2")
+				.eq(MarketingConfigGroup::getGroupName, reqDto.getGroupName()));
 		if (groupExist != null && !groupExist.getId().equals(reqDto.getId())){
 		if (groupExist != null && !groupExist.getId().equals(reqDto.getId())){
 			return R.failed("分组名已存在");
 			return R.failed("分组名已存在");
 		}
 		}
@@ -112,8 +170,8 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 		List<MarketingGroupDomainDTO> domains = reqDto.getDomains();
 		List<MarketingGroupDomainDTO> domains = reqDto.getDomains();
 		for (MarketingGroupDomainDTO domainDto : domains) {
 		for (MarketingGroupDomainDTO domainDto : domains) {
 			// 新增、修改
 			// 新增、修改
-			MarketingGroupDomain domainExist = groupDomainMapper.selectOne(new QueryWrapper<MarketingGroupDomain>()
-					.eq("domain", domainDto.getDomain()));
+			MarketingGroupDomain domainExist = groupDomainMapper.selectOne(Wrappers.<MarketingGroupDomain>lambdaQuery()
+					.eq(MarketingGroupDomain::getDomain, domainDto.getDomain()));
 			if (domainExist != null && !domainExist.getId().equals(domainDto.getId())){
 			if (domainExist != null && !domainExist.getId().equals(domainDto.getId())){
 				return R.failed("域名已存在");
 				return R.failed("域名已存在");
 			}
 			}
@@ -142,7 +200,7 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 	 */
 	 */
 	@Override
 	@Override
 	public List<GetMarketingDomainGroupVO> getMarketingDomainGroupList() {
 	public List<GetMarketingDomainGroupVO> getMarketingDomainGroupList() {
-		List<MarketingConfigGroup> domainGroups = groupMapper.selectList(new QueryWrapper<MarketingConfigGroup>().eq("group_type", 2));
+		List<MarketingConfigGroup> domainGroups = groupMapper.selectList(Wrappers.<MarketingConfigGroup>lambdaQuery().eq(MarketingConfigGroup::getGroupType, 2));
 
 
 		ArrayList<GetMarketingDomainGroupVO> result = new ArrayList<>();
 		ArrayList<GetMarketingDomainGroupVO> result = new ArrayList<>();
 		for (MarketingConfigGroup domainGroup : domainGroups) {
 		for (MarketingConfigGroup domainGroup : domainGroups) {
@@ -151,7 +209,7 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 			rspVO.setGroupName(domainGroup.getGroupName());
 			rspVO.setGroupName(domainGroup.getGroupName());
 
 
 			// 查询分组下域名列表
 			// 查询分组下域名列表
-			List<MarketingGroupDomain> domains = groupDomainMapper.selectList(new QueryWrapper<MarketingGroupDomain>().eq("group_id", domainGroup.getId()));
+			List<MarketingGroupDomain> domains = groupDomainMapper.selectList(Wrappers.<MarketingGroupDomain>lambdaQuery().eq(MarketingGroupDomain::getGroupId, domainGroup.getId()));
 			ArrayList<MarketingGroupDomainVO> domainVOS = new ArrayList<>();
 			ArrayList<MarketingGroupDomainVO> domainVOS = new ArrayList<>();
 			for (MarketingGroupDomain domain : domains) {
 			for (MarketingGroupDomain domain : domains) {
 				MarketingGroupDomainVO domainVO = new MarketingGroupDomainVO();
 				MarketingGroupDomainVO domainVO = new MarketingGroupDomainVO();
@@ -164,11 +222,16 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 		return result;
 		return result;
 	}
 	}
 
 
+	/**
+	 * 修改分组IP
+	 * @param reqDto 修改IP分组入参
+	 * @return R
+	 */
 	@Override
 	@Override
 	public R modMarketingGroupIp(ModMarketingGroupIPDTO reqDto) {
 	public R modMarketingGroupIp(ModMarketingGroupIPDTO reqDto) {
-		MarketingConfigGroup groupExist = groupMapper.selectOne(new QueryWrapper<MarketingConfigGroup>()
-				.eq("group_type", "1")
-				.eq("group_name", reqDto.getGroupName())
+		MarketingConfigGroup groupExist = groupMapper.selectOne(Wrappers.<MarketingConfigGroup>lambdaQuery()
+				.eq(MarketingConfigGroup::getGroupType, "1")
+				.eq(MarketingConfigGroup::getGroupName, reqDto.getGroupName())
 		);
 		);
 		if (groupExist != null && !groupExist.getId().equals(reqDto.getId())){
 		if (groupExist != null && !groupExist.getId().equals(reqDto.getId())){
 			return R.failed("分组名已存在");
 			return R.failed("分组名已存在");
@@ -215,15 +278,13 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 		return R.ok();
 		return R.ok();
 	}
 	}
 
 
-
-
 	/**
 	/**
 	 * 获取ip分组列表
 	 * 获取ip分组列表
 	 * @return ip分组列表
 	 * @return ip分组列表
 	 */
 	 */
 	@Override
 	@Override
 	public List<GetMarketingIpGroupVO> getMarketingIpGroupList() {
 	public List<GetMarketingIpGroupVO> getMarketingIpGroupList() {
-		List<MarketingConfigGroup> ipGroups = groupMapper.selectList(new QueryWrapper<MarketingConfigGroup>().eq("group_type", 1));
+		List<MarketingConfigGroup> ipGroups = groupMapper.selectList(Wrappers.<MarketingConfigGroup>lambdaQuery().eq(MarketingConfigGroup::getGroupType, 1));
 
 
 		ArrayList<GetMarketingIpGroupVO> result = new ArrayList<>();
 		ArrayList<GetMarketingIpGroupVO> result = new ArrayList<>();
 		for (MarketingConfigGroup ipGroup : ipGroups) {
 		for (MarketingConfigGroup ipGroup : ipGroups) {
@@ -232,7 +293,7 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 			rspVO.setGroupName(ipGroup.getGroupName());
 			rspVO.setGroupName(ipGroup.getGroupName());
 
 
 			// 查询分组下IP列表
 			// 查询分组下IP列表
-			List<MarketingGroupIp> ipList = groupIpMapper.selectList(new QueryWrapper<MarketingGroupIp>().eq("group_id", ipGroup.getId()));
+			List<MarketingGroupIp> ipList = groupIpMapper.selectList(Wrappers.<MarketingGroupIp>lambdaQuery().eq(MarketingGroupIp::getGroupId, ipGroup.getId()));
 			ArrayList<MarketingGroupIpVO> ips = new ArrayList<>();
 			ArrayList<MarketingGroupIpVO> ips = new ArrayList<>();
 			for (MarketingGroupIp ip : ipList) {
 			for (MarketingGroupIp ip : ipList) {
 				MarketingGroupIpVO ipVO = new MarketingGroupIpVO();
 				MarketingGroupIpVO ipVO = new MarketingGroupIpVO();
@@ -244,4 +305,207 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 		}
 		}
 		return result;
 		return result;
 	}
 	}
+
+	/**
+	 * 获取IP集合
+	 * @return IP集合
+	 */
+	@Override
+	public List<GetMarketingConfigIpListVO> getMarketingConfigIpList() {
+		List<GetMarketingConfigIpListVO> result = new ArrayList<>();
+		List<MarketingAppsIp> ips = ipMapper.selectList(Wrappers.<MarketingAppsIp>lambdaQuery().eq(MarketingAppsIp::getConfig, true));
+		ips.forEach(ip -> {
+			GetMarketingConfigIpListVO ipVO = new GetMarketingConfigIpListVO();
+			BeanUtils.copyProperties(ip, ipVO);
+
+			if (ip.getGroupId() != null){
+				MarketingConfigGroup group = groupMapper.selectById(ip.getGroupId());
+				if (group != null)
+					ipVO.setGroupName(group.getGroupName());
+			}
+			result.add(ipVO);
+		});
+		return result;
+	}
+
+	/**
+	 * 添加IP集合
+	 * @param reqDto 添加IP集合入参
+	 * @return Boolean
+	 */
+	@Override
+	public Boolean addMarketingConfigIpList(AddMarketingConfigIpListDTO reqDto) {
+		// 判断IP表中是否重复
+		// 判断分组中是否重复
+
+		MarketingAppsIp marketingAppsIp = new MarketingAppsIp();
+		BeanUtils.copyProperties(reqDto, marketingAppsIp);
+		marketingAppsIp.setConfig(true);
+		int insert = ipMapper.insert(marketingAppsIp);
+		return insert > 0;
+	}
+
+	/**
+	 * 删除IP集合
+	 * @param id id
+	 * @return Boolean
+	 */
+	@Override
+	public Boolean delMarketingConfigIpList(Long id) {
+		MarketingAppsIp ip = ipMapper.selectOne(Wrappers.<MarketingAppsIp>lambdaQuery()
+				.eq(MarketingAppsIp::getId, id)
+				.eq(MarketingAppsIp::getConfig, true));
+		if (ip == null) {
+			throw new RuntimeException("id: "+id+" ,IP不存在");
+		}
+		int delete = ipMapper.deleteById(id);
+		return delete > 0;
+	}
+
+	/**
+	 * 获取域名集合
+	 * @return 域名集合
+	 */
+	@Override
+	public List<GetMarketingConfigDomainListVO> getMarketingConfigDomainList() {
+		List<GetMarketingConfigDomainListVO> result = new ArrayList<>();
+
+		List<MarketingAppsDomain> domains = domainMapper.selectList(Wrappers.<MarketingAppsDomain>lambdaQuery().eq(MarketingAppsDomain::getConfig, true));
+		domains.forEach(domain -> {
+			GetMarketingConfigDomainListVO domainVO = new GetMarketingConfigDomainListVO();
+			BeanUtils.copyProperties(domain, domainVO);
+			if (domain.getGroupId() != null){
+				MarketingConfigGroup group = groupMapper.selectById(domain.getGroupId());
+				if (group != null)
+					domainVO.setGroupName(group.getGroupName());
+			}
+			result.add(domainVO);
+		});
+		return result;
+	}
+
+	/**
+	 * 添加域名集合
+	 * @param reqDto 添加域名集合入参
+	 * @return Boolean
+	 */
+	@Override
+	public Boolean addMarketingConfigDomainList(AddMarketingConfigDomainListDTO reqDto) {
+		// 判断域名表中是否重复
+		// 判断分组中是否重复
+
+		MarketingAppsDomain domain = new MarketingAppsDomain();
+		BeanUtils.copyProperties(reqDto, domain);
+		domain.setConfig( true);
+		int insert = domainMapper.insert(domain);
+		return insert > 0;
+	}
+
+	/**
+	 * 删除域名集合
+	 * @param id id
+	 * @return Boolean
+	 */
+	@Override
+	public Boolean delMarketingConfigDomainList(Long id) {
+		// 判断是否存在
+		MarketingAppsDomain domain = domainMapper.selectOne(Wrappers.<MarketingAppsDomain>lambdaQuery()
+				.eq(MarketingAppsDomain::getId, id)
+				.eq(MarketingAppsDomain::getConfig, true));
+		if (domain == null){
+			throw new RuntimeException("id:"+id+",域名不存在");
+		}
+		int delete = domainMapper.deleteById(id);
+		return delete > 0;
+	}
+
+	private static final String TRIGGER_MODE = "TRIGGER_MODE";
+	private static final String TRIGGER_RULE = "TRIGGER_RULE";
+	private static final String TRIGGER_NUM = "TRIGGER_NUM";
+	private static final String PROMPT_MSG = "PROMPT_MSG";
+	private static final String URL = "URL";
+
+	/**
+	 * 查询全局配置信息
+	 * @return 全局配置信息
+	 */
+	@Override
+	public GetMarketingGlobalConfigVO getMarketingGlobalConfig() {
+		GetMarketingGlobalConfigVO res = new GetMarketingGlobalConfigVO();
+		R<ArrayList<SysPublicParamDTO>> ParamDTO = remoteParamService.getParamList(Arrays.asList(TRIGGER_MODE, TRIGGER_RULE, TRIGGER_NUM, PROMPT_MSG, URL));
+		ParamDTO.getData().forEach(item -> {
+			switch (item.getPublicKey()) {
+				case TRIGGER_MODE:
+					res.setTriggerMode(Integer.valueOf(item.getPublicValue()));
+					break;
+				case TRIGGER_RULE:
+					res.setTriggerRule(Integer.valueOf(item.getPublicValue()));
+					break;
+				case TRIGGER_NUM:
+					res.setTriggerNum(item.getPublicValue());
+					break;
+				case PROMPT_MSG:
+					res.setPromptMsg(item.getPublicValue());
+					break;
+				case URL:
+					res.setUrl(item.getPublicValue());
+					break;
+			}
+		});
+		return res;
+	}
+
+	/**
+	 * 修改全局配置
+	 * @param reDto 全局配置信息
+	 * @return Boolean
+	 */
+	@Override
+	public Boolean setMarketingGlobalConfig(GetMarketingGlobalConfigVO reDto) {
+		List<SysPublicParamDTO> sysParamList = new ArrayList<>();
+		SysPublicParamDTO sysParam = new SysPublicParamDTO();
+		if (reDto.getTriggerMode() != null){
+			sysParam.setPublicKey(TRIGGER_MODE);
+			sysParam.setPublicValue(reDto.getTriggerMode().toString());
+			sysParamList.add(sysParam);
+		}
+		if (reDto.getTriggerRule() != null){
+			sysParam = new SysPublicParamDTO();
+			sysParam.setPublicKey(TRIGGER_RULE);
+			sysParam.setPublicValue(reDto.getTriggerRule().toString());
+			sysParamList.add(sysParam);
+		}
+		if (StringUtils.isNotBlank(reDto.getTriggerNum())){
+			sysParam = new SysPublicParamDTO();
+			sysParam.setPublicKey(TRIGGER_NUM);
+			sysParam.setPublicValue(reDto.getTriggerNum());
+			sysParamList.add(sysParam);
+		}
+		if (StringUtils.isNotBlank(reDto.getPromptMsg())){
+			sysParam = new SysPublicParamDTO();
+			sysParam.setPublicKey(PROMPT_MSG);
+			sysParam.setPublicValue(reDto.getPromptMsg());
+			sysParamList.add(sysParam);
+		}
+		if (StringUtils.isNotBlank(reDto.getUrl())){
+			sysParam = new SysPublicParamDTO();
+			sysParam.setPublicKey(URL);
+			sysParam.setPublicValue(reDto.getUrl());
+			sysParamList.add(sysParam);
+		}
+		remoteParamService.setByKey(sysParamList);
+		return null;
+	}
+
+//	@Override
+//	public Boolean getMarketingConfig(AddMarketingConfigDomainListDTO reqDto) {
+//		// 判断域名表中是否重复
+//		// 判断分组中是否重复
+//
+//		MarketingAppsDomain domain = new MarketingAppsDomain();
+//		BeanUtils.copyProperties(reqDto, domain);
+//		domain.setConfig( true);
+//		int insert = domainMapper.insert(domain);
+//		return insert > 0;
+//	}
 }
 }

+ 278 - 21
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingDataServiceImpl.java

@@ -1,25 +1,37 @@
 package com.pig4cloud.pig.marketing.service.impl;
 package com.pig4cloud.pig.marketing.service.impl;
 
 
 
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.pig4cloud.pig.marketing.api.dto.data.MarketingDataReportDTO;
 import com.pig4cloud.pig.marketing.api.dto.data.MarketingDataReportDTO;
 import com.pig4cloud.pig.marketing.api.dto.data.PageFirstLevelDataDTO;
 import com.pig4cloud.pig.marketing.api.dto.data.PageFirstLevelDataDTO;
 import com.pig4cloud.pig.marketing.api.dto.data.PageSecondLevelDataDTO;
 import com.pig4cloud.pig.marketing.api.dto.data.PageSecondLevelDataDTO;
+import com.pig4cloud.pig.marketing.api.entity.*;
+import com.pig4cloud.pig.marketing.api.vo.config.GetMarketingGlobalConfigVO;
 import com.pig4cloud.pig.marketing.api.vo.data.MarketingDataReportVO;
 import com.pig4cloud.pig.marketing.api.vo.data.MarketingDataReportVO;
 import com.pig4cloud.pig.marketing.api.vo.data.PageFirstLevelDataVO;
 import com.pig4cloud.pig.marketing.api.vo.data.PageFirstLevelDataVO;
 import com.pig4cloud.pig.marketing.api.vo.data.PageSecondLevelDataVO;
 import com.pig4cloud.pig.marketing.api.vo.data.PageSecondLevelDataVO;
-import com.pig4cloud.pig.marketing.mapper.MarketingDataMapper;
+import com.pig4cloud.pig.marketing.mapper.*;
+import com.pig4cloud.pig.marketing.service.MarketingConfigService;
 import com.pig4cloud.pig.marketing.service.MarketingDataService;
 import com.pig4cloud.pig.marketing.service.MarketingDataService;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.net.InetAddress;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.net.UnknownHostException;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatter;
-import java.util.List;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 
 /**
 /**
  * @author: lwh
  * @author: lwh
@@ -33,6 +45,21 @@ public class MarketingDataServiceImpl implements MarketingDataService {
 
 
 	private final MarketingDataMapper marketingDataMapper;
 	private final MarketingDataMapper marketingDataMapper;
 
 
+	private final MarketingAppsMapper marketingAppsMapper;
+
+	private final MarketingAppsIpMapper marketingAppsIpMapper;
+
+	private final MarketingGroupIpMapper marketingGroupIpMapper;
+
+	private final MarketingAppsDomainMapper marketingAppsDomainMapper;
+
+	private final MarketingGroupDomainMapper marketingGroupDomainMapper;
+
+	private final MarketingConfigService marketingConfigService;
+
+	private final RedisTemplate redisTemplate;
+
+
 	/**
 	/**
 	 * 上报营销数据
 	 * 上报营销数据
 	 * @param reqDto 营销数据
 	 * @param reqDto 营销数据
@@ -42,30 +69,260 @@ public class MarketingDataServiceImpl implements MarketingDataService {
 	@Override
 	@Override
 	public MarketingDataReportVO reportMarketingData(MarketingDataReportDTO reqDto, HttpServletRequest request) {
 	public MarketingDataReportVO reportMarketingData(MarketingDataReportDTO reqDto, HttpServletRequest request) {
 
 
+		// 获取全局配置
+		GetMarketingGlobalConfigVO config = marketingConfigService.getMarketingGlobalConfig();
+
+		MarketingDataReportVO result = new MarketingDataReportVO();
+		BeanUtils.copyProperties(config,  result);
+		result.setType("link");
+
 		// 获取客户端IP地址
 		// 获取客户端IP地址
 		String ip = getIp(request);
 		String ip = getIp(request);
+		// 获取域名
+		String domain = reqDto.getDomain();
+		// 应用匹配
+		MarketingApps marketingApps = matchedApp(ip, domain);
+		// 未匹配到应用,返回默认信息
+		if (marketingApps == null){
+			return result;
+		}
 
 
-//		MarketingReport marketingReport = new MarketingReport();
-//		BeanUtils.copyProperties(reportDTO, marketingReport);
-//		marketingReport.setTimestamp(OffsetDateTime.parse(reportDTO.getTimestamp()).toLocalDateTime());
-//		marketingReport.setIp(ip);
-//		reportService.save(marketingReport);
+		// 入库
+		MarketingData marketingData = new MarketingData();
+		BeanUtils.copyProperties(reqDto, marketingData);
+		marketingData.setIp( ip);
+		marketingData.setAppId(marketingApps.getAppId());
+		marketingDataMapper.insert(marketingData);
+
+		// 计算是否达到频率
+		result.setAppId(marketingApps.getAppId());
+		result.setUrl(getTriggeredUrl(marketingApps, ip));
+
+		// 返回结果
 
 
-		MarketingDataReportVO result = new MarketingDataReportVO();
-//		result.put("type","link");
-//		result.put("downloadUrl", "");
-//		MarketingConfigDomain domain = domainService.getOne(new QueryWrapper<MarketingConfigDomain>().eq("domain", reqVo.getDomain()));
-//		if (domain == null) {
-//			return result;
-//		}
-//		MarketingConfigDetail detail = detailService.getOne(new QueryWrapper<MarketingConfigDetail>().eq("domain_id", domain.getId()).eq("ip", ip));
-//		if (detail == null) {
-//			return result;
-//		}
-//		result.put("downloadUrl", detail.getAppUrl());
 		return result;
 		return result;
 	}
 	}
 
 
+	/**
+	 * 获取匹配的app
+	 * @param ip ip
+	 * @param domain 域名
+	 * @return MarketingApps
+	 */
+	private MarketingApps matchedApp(String ip, String domain){
+		// 根据IP和域名查询跳转链接
+		// 1、筛选营销投放开启、域名限制开启的应用
+		// 1.1、 查询ip表和ip分组表中,包含该ip的应用id列表,条件为应用的营销投放开启、域名限制开启
+		List<Long> ipMatchedAppIds = getIpMatchedAppIds(ip, true);
+
+		if (!ipMatchedAppIds.isEmpty()) {
+			// 1.2 查询域名匹配的应用ID列表
+			List<Long> domainMatchedAppIds = getDomainMatchedAppIds(domain, ipMatchedAppIds);
+			if (!domainMatchedAppIds.isEmpty()) {
+				// 1.3 查找最新创建的应用
+				return getLatestMarketingApp(domainMatchedAppIds);
+			}
+		}
+		// 2、筛选营销投放开启、域名限制关闭的应用
+		List<Long> ipMatchedAppIdsWithoutDomainLimit = getIpMatchedAppIds(ip, false);
+		if (!ipMatchedAppIdsWithoutDomainLimit.isEmpty()) {
+			return getLatestMarketingApp(ipMatchedAppIdsWithoutDomainLimit);
+		}
+		return null;
+	}
+
+	/**
+	 * 根据triggerNum和Redis计数决定是否返回URL
+	 */
+	private String getTriggeredUrl(MarketingApps app, String userKey) {
+
+		if (app == null || userKey == null) {
+			return "";
+		}
+
+		BigDecimal triggerNum = new BigDecimal(app.getTriggerNum())
+				.setScale(2, RoundingMode.HALF_UP);
+		String url = app.getAppUrl();
+		String countKey = String.format("marketing:trigger:count:%s:%s", app.getAppId(), userKey);
+
+		// 1. 概率模式(triggerNum < 1)
+		if (triggerNum.compareTo(BigDecimal.ONE) < 0) {
+			// 生成0-1之间的随机数与triggerNum比较
+			double random = Math.random();
+			return random <= triggerNum.doubleValue() ? url : "";
+		}
+
+		// 2. 每次返回(triggerNum = 1)
+		if (triggerNum.compareTo(BigDecimal.ONE) == 0) {
+			return url;
+		}
+
+		// 3. 周期模式(triggerNum > 1)
+		// 向上取整转换为整数周期(如2.3 → 3,3.9 → 4)
+		int cycle = triggerNum.setScale(0, RoundingMode.CEILING).intValue();
+		if (cycle < 1) {
+			return "";
+		}
+
+		// Redis原子自增计数
+		Long currentCount = redisTemplate.opsForValue().increment(countKey);
+		if (currentCount == null) {
+			return "";
+		}
+
+		// 首次访问设置过期时间(24小时)
+		if (currentCount == 1) {
+			redisTemplate.expire(countKey, 24, TimeUnit.HOURS);
+		}
+
+		// 达到周期次数时返回URL并重置计数
+		if (currentCount % cycle == 0) {
+			redisTemplate.delete(countKey);
+			return url;
+		}
+		return "";
+	}
+
+	/**
+	 * 根据IP获取匹配的应用ID列表
+	 * @param ip IP地址
+	 * @param domainLimit 是否开启域名限制
+	 * @return 应用ID列表
+	 */
+	private List<Long> getIpMatchedAppIds(String ip, boolean domainLimit) {
+		// 查询营销投放开启、域名限制符合条件的应用ID
+		List<MarketingApps> qualifiedApps = marketingAppsMapper.selectList(Wrappers.<MarketingApps>lambdaQuery()
+				.eq(MarketingApps::getLaunch, true)
+				.eq(MarketingApps::getDomainLimit, domainLimit)
+		);
+		if (qualifiedApps.isEmpty()) {
+			return Collections.emptyList();
+		}
+		List<Long> qualifiedAppIds = qualifiedApps.stream()
+				.map(MarketingApps::getId)
+				.collect(Collectors.toList());
+
+		// 转换IP为长整型用于比较
+		long ipLong = ipToLong(ip);
+
+		// 1. 从marketing_apps_ip表查询直接关联的IP匹配
+		QueryWrapper<MarketingAppsIp> directIpQuery = new QueryWrapper<>();
+		directIpQuery.eq("ip_type",1)
+				.in("app_id", qualifiedAppIds)
+				.and(wrapper -> wrapper
+						// 单IP匹配
+						.eq("ip_mode", 1).eq("start_ip", ip)
+						// IP段匹配:将数据库字符串IP转换为长整型后比较
+						.or().eq("ip_mode", 2)
+						.le("INET_ATON(start_ip)", ipLong)
+						.ge("INET_ATON(end_ip)", ipLong)
+				);
+		List<MarketingAppsIp> directIpMatches = marketingAppsIpMapper.selectList(directIpQuery);
+		Set<Long> appIdSet = directIpMatches.stream()
+				.map(MarketingAppsIp::getAppId)
+				.collect(Collectors.toSet());
+
+		// 2. 从分组查询IP匹配的应用
+		// 2.1 查询包含该IP的分组ID
+		QueryWrapper<MarketingGroupIp> groupIpQuery = new QueryWrapper<>();
+		groupIpQuery.and(qw -> qw
+						// 单IP匹配
+						.eq("ip_mode", 1).eq("start_ip", ip)
+						// IP段匹配:转换为长整型后比较
+						.or().eq("ip_mode", 2)
+						.le("INET_ATON(start_ip)", ipLong)
+						.ge("INET_ATON(end_ip)", ipLong)
+				);
+		List<MarketingGroupIp> groupIpMatches = marketingGroupIpMapper.selectList(groupIpQuery);
+		if (!groupIpMatches.isEmpty()) {
+			List<Long> groupIds = groupIpMatches.stream()
+					.map(MarketingGroupIp::getGroupId)
+					.collect(Collectors.toList());
+
+			// 2.2 查询关联这些分组的应用
+			List<MarketingAppsIp> groupAppMatches = marketingAppsIpMapper.selectList(Wrappers.<MarketingAppsIp>lambdaQuery()
+					.in(MarketingAppsIp::getGroupId, groupIds)
+					.eq(MarketingAppsIp::getSourceType, 1) // 来源类型为分组
+					.eq(MarketingAppsIp::getIpType, 1)	// 白名单
+					.in(MarketingAppsIp::getAppId, qualifiedAppIds)
+			);
+			groupAppMatches.forEach(appIp -> appIdSet.add(appIp.getAppId()));
+		}
+
+		return new ArrayList<>(appIdSet);
+	}
+
+	/**
+	 * 根据域名获取匹配的应用ID列表
+	 * @param domain 域名
+	 * @param appIdList 待筛选的应用ID列表
+	 * @return 匹配的应用ID列表
+	 */
+	private List<Long> getDomainMatchedAppIds(String domain, List<Long> appIdList) {
+		Set<Long> matchedAppIds = new HashSet<>();
+
+		// 1. 从marketing_apps_domain表查询直接关联的域名匹配
+		List<MarketingAppsDomain> directDomainMatches = marketingAppsDomainMapper.selectList(Wrappers.<MarketingAppsDomain>lambdaQuery()
+				.in(MarketingAppsDomain::getAppId, appIdList)
+				.eq(MarketingAppsDomain::getSourceType, 2)
+				.eq(MarketingAppsDomain::getDomain, domain)
+		);
+		directDomainMatches.forEach(domainApp -> matchedAppIds.add(domainApp.getAppId()));
+
+		// 2. 从分组查询域名匹配的应用
+		// 2.1 查询包含该域名的分组ID
+		List<MarketingGroupDomain> groupDomainMatches = marketingGroupDomainMapper.selectList(Wrappers.<MarketingGroupDomain>lambdaQuery()
+				.eq(MarketingGroupDomain::getDomain, domain)
+		);
+		if (!groupDomainMatches.isEmpty()) {
+			List<Long> groupIds = groupDomainMatches.stream()
+					.map(MarketingGroupDomain::getGroupId)
+					.collect(Collectors.toList());
+
+			// 2.2 查询关联这些分组的应用
+			List<MarketingAppsDomain> groupAppMatches = marketingAppsDomainMapper.selectList(Wrappers.<MarketingAppsDomain>lambdaQuery()
+					.in(MarketingAppsDomain::getGroupId, groupIds)
+					.eq(MarketingAppsDomain::getSourceType, 1)
+					.in(MarketingAppsDomain::getAppId, appIdList)
+			);
+			groupAppMatches.forEach(domainApp -> matchedAppIds.add(domainApp.getAppId()));
+		}
+		return new ArrayList<>(matchedAppIds);
+	}
+
+	/**
+	 * 获取最新创建的应用
+	 * @param appIds 应用ID列表
+	 * @return 最新创建的应用
+	 */
+	private MarketingApps getLatestMarketingApp(List<Long> appIds) {
+		if (appIds.isEmpty()) {
+			return null;
+		}
+
+		MarketingApps marketingApps = marketingAppsMapper.selectOne(Wrappers.<MarketingApps>lambdaQuery()
+				.in(MarketingApps::getId, appIds)
+				.orderByDesc(MarketingApps::getCreateTime)
+				.last("LIMIT 1")
+		);
+		return marketingApps;
+	}
+
+
+	/**
+	 * IP地址转长整型
+	 * @param ip IP地址
+	 * @return 长整型IP
+	 */
+	private long ipToLong(String ip) {
+		String[] parts = ip.split("\\.");
+		long result = 0;
+		for (int i = 0; i < 4; i++) {
+			result |= Long.parseLong(parts[i]) << (24 - i * 8);
+		}
+		return result & 0xFFFFFFFFL;
+	}
+
 	@Override
 	@Override
 	public Page pageFirstLevelData(PageFirstLevelDataDTO reqDto) {
 	public Page pageFirstLevelData(PageFirstLevelDataDTO reqDto) {
 		String ip = reqDto.getIp();
 		String ip = reqDto.getIp();
@@ -85,9 +342,9 @@ public class MarketingDataServiceImpl implements MarketingDataService {
 		// 查询数据
 		// 查询数据
 		Page<PageFirstLevelDataVO> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());
 		Page<PageFirstLevelDataVO> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());
 
 
-		List<PageFirstLevelDataVO> rs = marketingDataMapper.countFirstLevelMarketingData(ip, lastHourTimeStr, todayStartTimeStr, offset, reqDto.getSize());
+		List<PageFirstLevelDataVO> rs = marketingDataMapper.countFirstLevelMarketingData(ip, reqDto.getAppId(), lastHourTimeStr, todayStartTimeStr, offset, reqDto.getSize());
 		page.setRecords(rs);
 		page.setRecords(rs);
-		page.setTotal(marketingDataMapper.countFirstLevelDataTotal(ip));
+		page.setTotal(marketingDataMapper.countFirstLevelDataTotal(ip, reqDto.getAppId()));
 
 
 		return page;
 		return page;
 	}
 	}

+ 25 - 0
pig-marketing/pig-marketing-biz/src/main/resources/mapper/MarketingAppsDomainMapper.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng ([email protected])
+  ~
+  -->
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pig4cloud.pig.marketing.mapper.MarketingAppsDomainMapper">
+
+
+</mapper>

+ 25 - 0
pig-marketing/pig-marketing-biz/src/main/resources/mapper/MarketingAppsIpMapper.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng ([email protected])
+  ~
+  -->
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pig4cloud.pig.marketing.mapper.MarketingAppsIpMapper">
+
+
+</mapper>

+ 38 - 36
pig-marketing/pig-marketing-biz/src/main/resources/mapper/MarketingDataMapper.xml

@@ -22,55 +22,57 @@
 <mapper namespace="com.pig4cloud.pig.marketing.mapper.MarketingDataMapper">
 <mapper namespace="com.pig4cloud.pig.marketing.mapper.MarketingDataMapper">
 
 
 	<select id="countFirstLevelMarketingData" resultType="com.pig4cloud.pig.marketing.api.vo.data.PageFirstLevelDataVO">
 	<select id="countFirstLevelMarketingData" resultType="com.pig4cloud.pig.marketing.api.vo.data.PageFirstLevelDataVO">
-		SELECT
-		ip,
-		COUNT(*) AS total,
-		SUM(CASE WHEN create_time >= #{lastHourTime} THEN 1 ELSE 0 END) AS hourly,
-		SUM(CASE WHEN create_time >= #{todayStartTime} THEN 1 ELSE 0 END) AS daily
-		FROM
-		marketing_data
-		<where>
-			<if test="ip != null and ip != ''">
-				AND ip LIKE CONCAT('%', #{ip}, '%')
+        SELECT
+        ip,
+        COUNT(*) AS total,
+        SUM(CASE WHEN create_time >= #{lastHourTime} THEN 1 ELSE 0 END) AS hourly,
+        SUM(CASE WHEN create_time >= #{todayStartTime} THEN 1 ELSE 0 END) AS daily
+        FROM
+        marketing_data
+        <where>
+            <if test="ip != null and ip != ''">
+                AND ip LIKE CONCAT('%', #{ip}, '%')
+            </if>
+			<if test="appId != null and appId != ''">
+				AND app_id LIKE CONCAT('%', #{appId}, '%')
 			</if>
 			</if>
-		</where>
-		GROUP BY ip
-		LIMIT #{offset}, #{pageSize}
-	</select>
+        </where>
+        GROUP BY ip
+        LIMIT #{offset}, #{pageSize}
+    </select>
 
 
 	<select id="countFirstLevelDataTotal" resultType="java.lang.Long">
 	<select id="countFirstLevelDataTotal" resultType="java.lang.Long">
 		SELECT
 		SELECT
-			COUNT(DISTINCT ip)
+		COUNT(DISTINCT ip)
 		FROM
 		FROM
-			marketing_data
+		marketing_data
 		<where>
 		<where>
 			<if test="ip != null and ip != ''">
 			<if test="ip != null and ip != ''">
 				AND ip LIKE CONCAT('%', #{ip}, '%')
 				AND ip LIKE CONCAT('%', #{ip}, '%')
 			</if>
 			</if>
+			<if test="appId != null and appId != ''">
+				AND app_id LIKE CONCAT('%', #{appId}, '%')
+			</if>
 		</where>
 		</where>
 	</select>
 	</select>
 
 
-	<select id="countSecondLevelMarketingData" resultType="com.pig4cloud.pig.marketing.api.vo.data.PageSecondLevelDataVO">
-		SELECT
-			domain,referrer,fingerprint,
-			COUNT(*) AS total,
-			SUM(CASE WHEN create_time >= #{lastHourTime} THEN 1 ELSE 0 END) AS hourly,
-			SUM(CASE WHEN create_time >= #{todayStartTime} THEN 1 ELSE 0 END) AS daily
-		FROM
-			marketing_data
-		WHERE
-			ip = #{ip}
-		GROUP BY
-			domain, referrer, fingerprint
-		LIMIT #{offset}, #{pageSize}
-	</select>
+	<select id="countSecondLevelMarketingData"
+			resultType="com.pig4cloud.pig.marketing.api.vo.data.PageSecondLevelDataVO">
+        SELECT
+            domain, referrer, fingerprint, COUNT (*) AS total, SUM (CASE WHEN create_time >= #{lastHourTime} THEN 1 ELSE 0 END) AS hourly, SUM (CASE WHEN create_time >=
+                                                                                             #{todayStartTime} THEN 1 ELSE 0 END) AS daily
+        FROM
+            marketing_data
+        WHERE
+            ip = #{ip}
+        GROUP BY
+            domain, referrer, fingerprint
+            LIMIT #{offset}, #{pageSize}
+    </select>
 
 
 	<select id="countSecondLevelDataTotal" resultType="java.lang.Long">
 	<select id="countSecondLevelDataTotal" resultType="java.lang.Long">
-		SELECT
-			COUNT(DISTINCT domain, referrer, fingerprint)
-		FROM
-			marketing_data
-		WHERE
-			ip = #{ip}
+		SELECT COUNT(DISTINCT domain, referrer, fingerprint)
+		FROM marketing_data
+		WHERE ip = #{ip}
 	</select>
 	</select>
 </mapper>
 </mapper>

+ 0 - 58
pig-marketing/pig-marketing-biz/src/main/resources/mapper/MarketingGroupDomainMapper.xml

@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~
-  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
-  ~
-  ~  Redistribution and use in source and binary forms, with or without
-  ~  modification, are permitted provided that the following conditions are met:
-  ~
-  ~ Redistributions of source code must retain the above copyright notice,
-  ~  this list of conditions and the following disclaimer.
-  ~  Redistributions in binary form must reproduce the above copyright
-  ~  notice, this list of conditions and the following disclaimer in the
-  ~  documentation and/or other materials provided with the distribution.
-  ~  Neither the name of the pig4cloud.com developer nor the names of its
-  ~  contributors may be used to endorse or promote products derived from
-  ~  this software without specific prior written permission.
-  ~  Author: lengleng ([email protected])
-  ~
-  -->
-
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.pig4cloud.pig.marketing.mapper.MarketingGroupIpMapper">
-
-	<select id="checkIpConflict" resultType="java.lang.Boolean">
-		SELECT
-			COUNT(*) > 0 AS exists_flag
-		FROM
-			marketing_group_ip
-		WHERE del_flag = '0'
-		<if test="groupId != null">
-			AND group_id = #{groupId}
-		</if>
-		<if test="id != null">
-			AND id != #{id}
-		</if>
-		AND (
-			<if test="ipMode == 1">
-				(
-				(ip_mode = 1 AND start_ip = #{startIp}) OR
-				(ip_mode = 2 AND INET_ATON(#{startIp}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip))
-				)
-			</if>
-
-			<if test="ipMode == 2">
-				(
-				<!-- 与单IP重叠:单IP在输入IP段范围内 -->
-				(ip_mode = 1 AND INET_ATON(start_ip) BETWEEN INET_ATON(#{startIp}) AND INET_ATON(#{endIp})) OR
-				<!-- 与IP段重叠:两个IP段有交集 -->
-				(ip_mode = 2 AND
-					(INET_ATON(start_ip) BETWEEN INET_ATON(#{startIp}) AND INET_ATON(#{endIp})) OR
-					(INET_ATON(end_ip) BETWEEN INET_ATON(#{startIp}) AND INET_ATON(#{endIp})) OR
-					(INET_ATON(#{startIp}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip))
-				)
-				)
-			</if>
-		)
-	</select>
-</mapper>

+ 58 - 0
pig-marketing/pig-marketing-biz/src/main/resources/mapper/MarketingGroupIpMapper.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng ([email protected])
+  ~
+  -->
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pig4cloud.pig.marketing.mapper.MarketingGroupIpMapper">
+
+	<select id="checkIpConflict" resultType="java.lang.Boolean">
+        SELECT
+        COUNT(*) > 0 AS exists_flag
+        FROM
+        marketing_group_ip
+        WHERE del_flag = '0'
+        <if test="groupId != null">
+            AND group_id = #{groupId}
+        </if>
+        <if test="id != null">
+            AND id != #{id}
+        </if>
+        AND (
+        <if test="ipMode == 1">
+            (
+            (ip_mode = 1 AND start_ip = #{startIp}) OR
+            (ip_mode = 2 AND INET_ATON(#{startIp}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip))
+            )
+        </if>
+
+        <if test="ipMode == 2">
+            (
+            <!-- 与单IP重叠:单IP在输入IP段范围内 -->
+            (ip_mode = 1 AND INET_ATON(start_ip) BETWEEN INET_ATON(#{startIp}) AND INET_ATON(#{endIp})) OR
+            <!-- 与IP段重叠:两个IP段有交集 -->
+            (ip_mode = 2 AND
+            (INET_ATON(start_ip) BETWEEN INET_ATON(#{startIp}) AND INET_ATON(#{endIp})) OR
+            (INET_ATON(end_ip) BETWEEN INET_ATON(#{startIp}) AND INET_ATON(#{endIp})) OR
+            (INET_ATON(#{startIp}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip))
+            )
+            )
+        </if>
+        )
+    </select>
+</mapper>

+ 33 - 0
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/dto/SysPublicParamDTO.java

@@ -0,0 +1,33 @@
+package com.pig4cloud.pig.admin.api.dto;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author: lwh
+ * @date: 2025-07-25
+ * @description: 系统参数DTO
+ */
+@Data
+@Schema(description = "系统参数对象")
+public class SysPublicParamDTO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * key
+	 */
+	@Schema(description = "key")
+	private String publicKey;
+
+	/**
+	 * value
+	 */
+	@Schema(description = "value")
+	private String publicValue;
+}

+ 20 - 0
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/RemoteParamService.java

@@ -1,11 +1,17 @@
 package com.pig4cloud.pig.admin.api.feign;
 package com.pig4cloud.pig.admin.api.feign;
 
 
+import com.pig4cloud.pig.admin.api.dto.SysPublicParamDTO;
 import com.pig4cloud.pig.common.core.constant.ServiceNameConstants;
 import com.pig4cloud.pig.common.core.constant.ServiceNameConstants;
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.common.feign.annotation.NoToken;
 import com.pig4cloud.pig.common.feign.annotation.NoToken;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.ArrayList;
+import java.util.List;
 
 
 /**
 /**
  * 远程参数服务接口
  * 远程参数服务接口
@@ -29,4 +35,18 @@ public interface RemoteParamService {
 	@GetMapping("/param/publicValue/{key}")
 	@GetMapping("/param/publicValue/{key}")
 	R<String> getByKey(@PathVariable("key") String key);
 	R<String> getByKey(@PathVariable("key") String key);
 
 
+
+	/**
+	 * 通过key 修改公共参数值
+	 * @param paramList 公共参数列表
+	 * @NoToken 声明成内部调用,避免MQ 等无法调用
+	 */
+	@NoToken
+	@PostMapping("/param/set")
+	R<Boolean> setByKey(@RequestBody List<SysPublicParamDTO> paramList);
+
+	@NoToken
+	@PostMapping("/param/getList")
+	R<ArrayList<SysPublicParamDTO>> getParamList(@RequestBody List<String> keyList);
+
 }
 }

+ 42 - 0
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/controller/SysPublicParamController.java

@@ -21,6 +21,7 @@ import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.pig4cloud.pig.admin.api.dto.SysPublicParamDTO;
 import com.pig4cloud.pig.admin.api.entity.SysPublicParam;
 import com.pig4cloud.pig.admin.api.entity.SysPublicParam;
 import com.pig4cloud.pig.admin.service.SysPublicParamService;
 import com.pig4cloud.pig.admin.service.SysPublicParamService;
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.common.core.util.R;
@@ -36,6 +37,7 @@ import org.springdoc.core.annotations.ParameterObject;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpHeaders;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 
 
 /**
 /**
@@ -65,6 +67,46 @@ public class SysPublicParamController {
 		return R.ok(sysPublicParamService.getParamValue(publicKey));
 		return R.ok(sysPublicParamService.getParamValue(publicKey));
 	}
 	}
 
 
+	/**
+	 * 根据key修改公共参数值
+	 * @param paramList 公共参数列表
+	 * @return 公共参数值
+	 */
+	@Inner(value = false)
+	@Operation(description = "根据key修改公共参数值", summary = "根据key修改公共参数值")
+	@PostMapping("/set")
+	public R setByKey(@RequestBody List<SysPublicParamDTO> paramList) {
+		ArrayList<SysPublicParam> params = new ArrayList<>();
+		paramList.forEach(paramDTO -> {
+			SysPublicParam param = sysPublicParamService.getOne(Wrappers.<SysPublicParam>lambdaQuery()
+					.eq(SysPublicParam::getPublicKey, paramDTO.getPublicKey()));
+			if (param == null){
+				throw new RuntimeException("key:"+paramDTO.getPublicKey()+"参数不存在");
+			}
+			param.setPublicValue(paramDTO.getPublicValue());
+			params.add(param);
+		});
+		return R.ok(sysPublicParamService.updateBatchById(params));
+	}
+
+	@Inner(value = false)
+	@Operation(description = "根据key列表获取参数列表", summary = "根据key列表获取参数列表")
+	@PostMapping("/getList")
+	public R<ArrayList<SysPublicParamDTO>> getParamList(@RequestBody List<String> keyList) {
+		ArrayList<SysPublicParamDTO> result = new ArrayList<>();
+		keyList.forEach(key -> {
+			SysPublicParamDTO dto = new SysPublicParamDTO();
+			SysPublicParam param = sysPublicParamService.getOne(Wrappers.<SysPublicParam>lambdaQuery()
+					.eq(SysPublicParam::getPublicKey, key));
+			if (param != null) {
+				dto.setPublicKey(param.getPublicKey());
+				dto.setPublicValue(param.getPublicValue());
+				result.add(dto);
+			}
+		});
+		return R.ok(result);
+	}
+
 	/**
 	/**
 	 * 分页查询系统公共参数
 	 * 分页查询系统公共参数
 	 * @param page 分页对象
 	 * @param page 分页对象