|
@@ -60,6 +60,22 @@ public class MktMgmtRuleServiceImpl implements MktMgmtRuleService {
|
|
|
List<String> ipList = reqDto.getIp();
|
|
|
// 验证域名列表
|
|
|
List<String> domainList = reqDto.getDomain();
|
|
|
+ // 验证关键字列表
|
|
|
+ List<String> keywords = reqDto.getKeyword();
|
|
|
+
|
|
|
+ // 统一验证输入数据
|
|
|
+ if (ipList != null && !ipList.isEmpty()) {
|
|
|
+ validateIpList(ipList);
|
|
|
+ }
|
|
|
+ if (domainList != null && !domainList.isEmpty()) {
|
|
|
+ validateDomainList(domainList);
|
|
|
+ }
|
|
|
+ if (keywords != null && !keywords.isEmpty()) {
|
|
|
+ validateKeywordList(keywords);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证规则名
|
|
|
+ validateRuleName(reqDto.getRuleName(), reqDto.getId());
|
|
|
|
|
|
if (reqDto.getId() == null) {
|
|
|
// 新增规则
|
|
@@ -71,32 +87,7 @@ public class MktMgmtRuleServiceImpl implements MktMgmtRuleService {
|
|
|
if (ipList != null && !ipList.isEmpty()) {
|
|
|
for (String ip : ipList) {
|
|
|
if (StringUtils.hasText(ip)) {
|
|
|
- MktMgmtRuleIp ruleIp = new MktMgmtRuleIp();
|
|
|
- ruleIp.setRuleId(rule.getId());
|
|
|
-
|
|
|
- // 处理IP格式
|
|
|
- if (ip.contains("/")) {
|
|
|
- // IP段格式
|
|
|
- String[] parts = ip.split("/");
|
|
|
- String startIp = parts[0];
|
|
|
- String endIpSuffix = parts[1];
|
|
|
-
|
|
|
- String[] startParts = startIp.split("\\.");
|
|
|
- int endSuffix = Integer.parseInt(endIpSuffix);
|
|
|
- String endIp = String.format("%s.%s.%s.%d",
|
|
|
- startParts[0], startParts[1], startParts[2], endSuffix);
|
|
|
-
|
|
|
- ruleIp.setIpMode(2); // IP段模式
|
|
|
- ruleIp.setStartIp(startIp);
|
|
|
- ruleIp.setEndIp(endIp);
|
|
|
- } else {
|
|
|
- // 单IP格式
|
|
|
- ruleIp.setIpMode(1);
|
|
|
- ruleIp.setStartIp(ip);
|
|
|
- ruleIp.setEndIp("");
|
|
|
- }
|
|
|
- // 校验IP合法性
|
|
|
- validateIp(ruleIp);
|
|
|
+ MktMgmtRuleIp ruleIp = buildRuleIp(ip, rule.getId());
|
|
|
mktMgmtRuleIpMapper.insert(ruleIp);
|
|
|
}
|
|
|
}
|
|
@@ -106,27 +97,20 @@ public class MktMgmtRuleServiceImpl implements MktMgmtRuleService {
|
|
|
if (domainList != null && !domainList.isEmpty()) {
|
|
|
for (String domain : domainList) {
|
|
|
if (StringUtils.hasText(domain)) {
|
|
|
- // 校验域名
|
|
|
- validateDomain(domain);
|
|
|
MktMgmtRuleDomain ruleDomain = new MktMgmtRuleDomain();
|
|
|
ruleDomain.setRuleId(rule.getId());
|
|
|
- ruleDomain.setDomain(domain);
|
|
|
+ ruleDomain.setDomain(domain.trim());
|
|
|
mktMgmtRuleDomainMapper.insert(ruleDomain);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 保存关键字
|
|
|
- List<String> keywords = reqDto.getKeyword();
|
|
|
if (keywords != null && !keywords.isEmpty()) {
|
|
|
for (String keyword : keywords) {
|
|
|
if (StringUtils.hasText(keyword)) {
|
|
|
- if (checkRuleKeywordExists(keyword)) {
|
|
|
- throw new BusinessException("关键字 '" + keyword + "' 已存在,不能重复");
|
|
|
- }
|
|
|
-
|
|
|
MktMgmtKeyword mktMgmtKeyword = new MktMgmtKeyword();
|
|
|
- mktMgmtKeyword.setKeyword(keyword);
|
|
|
+ mktMgmtKeyword.setKeyword(keyword.trim());
|
|
|
mktMgmtKeyword.setRuleId(rule.getId());
|
|
|
mktMgmtKeywordMapper.insert(mktMgmtKeyword);
|
|
|
}
|
|
@@ -134,6 +118,7 @@ public class MktMgmtRuleServiceImpl implements MktMgmtRuleService {
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
+ // 修改规则
|
|
|
// 1. 更新主规则信息
|
|
|
MktMgmtRule mktMgmtRule = mktMgmtRuleMapper.selectById(reqDto.getId());
|
|
|
if (mktMgmtRule == null) {
|
|
@@ -143,168 +128,16 @@ public class MktMgmtRuleServiceImpl implements MktMgmtRuleService {
|
|
|
BeanUtils.copyProperties(reqDto, rule);
|
|
|
mktMgmtRuleMapper.updateById(rule);
|
|
|
|
|
|
- // 2. 处理IP列表
|
|
|
Long ruleId = reqDto.getId();
|
|
|
|
|
|
- // 查询现有的IP记录
|
|
|
- List<MktMgmtRuleIp> oldIpRecords = mktMgmtRuleIpMapper.selectList(Wrappers.<MktMgmtRuleIp>lambdaQuery()
|
|
|
- .eq(MktMgmtRuleIp::getRuleId, ruleId));
|
|
|
-
|
|
|
- // 构建现有IP的映射(startIp -> record)
|
|
|
- Map<String, MktMgmtRuleIp> oldIpMap = oldIpRecords.stream()
|
|
|
- .collect(Collectors.toMap(MktMgmtRuleIp::getStartIp, ip -> ip));
|
|
|
-
|
|
|
- // 构建新IP的映射
|
|
|
- Map<String, MktMgmtRuleIp> newIpMap = new HashMap<>();
|
|
|
- if (ipList != null && !ipList.isEmpty()) {
|
|
|
- for (String ip : ipList) {
|
|
|
- if (StringUtils.hasText(ip)) {
|
|
|
- MktMgmtRuleIp ruleIp = new MktMgmtRuleIp();
|
|
|
- ruleIp.setRuleId(ruleId);
|
|
|
-
|
|
|
- // 处理IP格式
|
|
|
- if (ip.contains("/")) {
|
|
|
- // IP段格式
|
|
|
- String[] parts = ip.split("/");
|
|
|
- String startIpPart = parts[0];
|
|
|
- String endIpSuffix = parts[1];
|
|
|
-
|
|
|
- String[] startParts = startIpPart.split("\\.");
|
|
|
- int endSuffix = Integer.parseInt(endIpSuffix);
|
|
|
- String endIp = String.format("%s.%s.%s.%d",
|
|
|
- startParts[0], startParts[1], startParts[2], endSuffix);
|
|
|
-
|
|
|
- ruleIp.setIpMode(2); // IP段模式
|
|
|
- ruleIp.setStartIp(startIpPart);
|
|
|
- ruleIp.setEndIp(endIp);
|
|
|
- } else {
|
|
|
- // 单IP格式
|
|
|
- ruleIp.setIpMode(1);
|
|
|
- ruleIp.setStartIp(ip);
|
|
|
- ruleIp.setEndIp("");
|
|
|
- }
|
|
|
-
|
|
|
- newIpMap.put(ruleIp.getStartIp(), ruleIp);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 处理需要删除的IP(存在于旧列表但不存在于新列表)
|
|
|
- List<Long> needDeleteIpIds = oldIpRecords.stream()
|
|
|
- .filter(oldIp -> !newIpMap.containsKey(oldIp.getStartIp()))
|
|
|
- .map(MktMgmtRuleIp::getId)
|
|
|
- .toList();
|
|
|
- if (!needDeleteIpIds.isEmpty()) {
|
|
|
- mktMgmtRuleIpMapper.deleteByIds(needDeleteIpIds);
|
|
|
- }
|
|
|
-
|
|
|
- // 处理需要新增的IP(存在于新列表但不存在于旧列表)
|
|
|
- List<MktMgmtRuleIp> needAddIps = newIpMap.values().stream()
|
|
|
- .filter(newIp -> !oldIpMap.containsKey(newIp.getStartIp()))
|
|
|
- .toList();
|
|
|
- if (!needAddIps.isEmpty()) {
|
|
|
- for (MktMgmtRuleIp ruleIp : needAddIps) {
|
|
|
- // 校验IP合法性
|
|
|
- validateIp(ruleIp);
|
|
|
- // 校验IP是否已存在
|
|
|
- if (checkRuleIpExists(ruleIp, ruleId)) {
|
|
|
- if (ruleIp.getIpMode() == 1) {
|
|
|
- throw new BusinessException("IP '" + ruleIp.getStartIp() + "' 已存在或被其他IP段包含");
|
|
|
- } else {
|
|
|
- String[] end = ruleIp.getEndIp().split("\\.");
|
|
|
- throw new BusinessException("IP段 '" + ruleIp.getStartIp() + "/" + end[3] + "' 已存在或与其他IP段重叠");
|
|
|
- }
|
|
|
- }
|
|
|
- mktMgmtRuleIpMapper.insert(ruleIp);
|
|
|
- }
|
|
|
- }
|
|
|
+ // 2. 处理IP列表
|
|
|
+ updateIpList(ipList, ruleId);
|
|
|
|
|
|
// 3. 处理域名列表
|
|
|
- // 查询现有的域名记录
|
|
|
- List<MktMgmtRuleDomain> oldDomainRecords = mktMgmtRuleDomainMapper.selectList(Wrappers.<MktMgmtRuleDomain>lambdaQuery()
|
|
|
- .eq(MktMgmtRuleDomain::getRuleId, ruleId));
|
|
|
-
|
|
|
- // 构建现有域名的映射(domain -> record)
|
|
|
- Map<String, MktMgmtRuleDomain> oldDomainMap = oldDomainRecords.stream()
|
|
|
- .collect(Collectors.toMap(MktMgmtRuleDomain::getDomain, domain -> domain));
|
|
|
-
|
|
|
- // 构建新域名的映射
|
|
|
- Map<String, MktMgmtRuleDomain> newDomainMap = new HashMap<>();
|
|
|
- if (domainList != null && !domainList.isEmpty()) {
|
|
|
- for (String domain : domainList) {
|
|
|
- if (StringUtils.hasText(domain)) {
|
|
|
- MktMgmtRuleDomain ruleDomain = new MktMgmtRuleDomain();
|
|
|
- ruleDomain.setRuleId(ruleId);
|
|
|
- ruleDomain.setDomain(domain);
|
|
|
- newDomainMap.put(domain, ruleDomain);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ updateDomainList(domainList, ruleId);
|
|
|
|
|
|
- // 处理需要删除的域名(存在于旧列表但不存在于新列表)
|
|
|
- List<Long> needDeleteDomainIds = oldDomainRecords.stream()
|
|
|
- .filter(oldDomain -> !newDomainMap.containsKey(oldDomain.getDomain()))
|
|
|
- .map(MktMgmtRuleDomain::getId)
|
|
|
- .toList();
|
|
|
- if (!needDeleteDomainIds.isEmpty()) {
|
|
|
- mktMgmtRuleDomainMapper.deleteByIds(needDeleteDomainIds);
|
|
|
- }
|
|
|
-
|
|
|
- // 处理需要新增的域名(存在于新列表但不存在于旧列表)
|
|
|
- List<MktMgmtRuleDomain> needAddDomains = newDomainMap.values().stream()
|
|
|
- .filter(newDomain -> !oldDomainMap.containsKey(newDomain.getDomain()))
|
|
|
- .toList();
|
|
|
- if (!needAddDomains.isEmpty()) {
|
|
|
- for (MktMgmtRuleDomain ruleDomain : needAddDomains) {
|
|
|
- // 校验域名合法性
|
|
|
- validateDomain(ruleDomain.getDomain());
|
|
|
- // 校验新增的域名是否重复
|
|
|
- if (checkRuleDomainExists(ruleDomain.getDomain(), ruleId)) {
|
|
|
- throw new BusinessException("域名 '" + ruleDomain.getDomain() + "' 已存在,不能重复");
|
|
|
- }
|
|
|
- mktMgmtRuleDomainMapper.insert(ruleDomain);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 4. 处理关键字(精确更新)
|
|
|
- List<String> newKeywords = reqDto.getKeyword();
|
|
|
- newKeywords = newKeywords == null ? Collections.emptyList() : newKeywords;
|
|
|
-
|
|
|
- List<MktMgmtKeyword> oldKeywords = mktMgmtKeywordMapper.selectList(Wrappers.<MktMgmtKeyword>lambdaQuery()
|
|
|
- .eq(MktMgmtKeyword::getRuleId, ruleId));
|
|
|
- Set<String> oldKeywordSet = oldKeywords.stream()
|
|
|
- .map(MktMgmtKeyword::getKeyword)
|
|
|
- .collect(Collectors.toSet());
|
|
|
-
|
|
|
- // 提取新关键字集合
|
|
|
- Set<String> newKeywordSet = new HashSet<>(newKeywords);
|
|
|
-
|
|
|
- // 处理需要删除的关键字(存在于旧列表但不存在于新列表)
|
|
|
- List<Long> needDeleteIds = oldKeywords.stream()
|
|
|
- .filter(keyword -> !newKeywordSet.contains(keyword.getKeyword()))
|
|
|
- .map(MktMgmtKeyword::getId)
|
|
|
- .toList();
|
|
|
- if (!needDeleteIds.isEmpty()) {
|
|
|
- mktMgmtKeywordMapper.deleteByIds(needDeleteIds);
|
|
|
- }
|
|
|
-
|
|
|
- // 处理需要新增的关键字(存在于新列表但不存在于旧列表)
|
|
|
- List<String> needAddKeywords = newKeywordSet.stream()
|
|
|
- .filter(keyword -> !oldKeywordSet.contains(keyword))
|
|
|
- .toList();
|
|
|
- if (!needAddKeywords.isEmpty()) {
|
|
|
- for (String keyword : needAddKeywords) {
|
|
|
- // 检查关键字是否重复
|
|
|
- if (checkRuleKeywordExists(keyword)) {
|
|
|
- throw new BusinessException("关键字 '" + keyword + "' 已被其他规则使用,不能重复");
|
|
|
- }
|
|
|
-
|
|
|
- MktMgmtKeyword mktMgmtKeyword = new MktMgmtKeyword();
|
|
|
- mktMgmtKeyword.setKeyword(keyword);
|
|
|
- mktMgmtKeyword.setRuleId(ruleId);
|
|
|
- mktMgmtKeywordMapper.insert(mktMgmtKeyword);
|
|
|
- }
|
|
|
- }
|
|
|
+ // 4. 处理关键字列表
|
|
|
+ updateKeywordList(keywords, ruleId);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -412,7 +245,7 @@ public class MktMgmtRuleServiceImpl implements MktMgmtRuleService {
|
|
|
}
|
|
|
|
|
|
// 按创建时间倒序排列
|
|
|
- queryWrapper.orderByDesc("create_time");
|
|
|
+ queryWrapper.orderByDesc("create_time","id");
|
|
|
|
|
|
// 执行分页查询
|
|
|
Page<MktMgmtRule> rulePage = mktMgmtRuleMapper.selectPage(page, queryWrapper);
|
|
@@ -480,88 +313,6 @@ public class MktMgmtRuleServiceImpl implements MktMgmtRuleService {
|
|
|
return resultPage;
|
|
|
}
|
|
|
|
|
|
- public Page<PageMktRuleVO> pageMktRule2(PageMktRuleDTO reqDto) {
|
|
|
- Page<MktMgmtRule> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());
|
|
|
-
|
|
|
- // 构建查询条件
|
|
|
- QueryWrapper<MktMgmtRule> queryWrapper = new QueryWrapper<>();
|
|
|
-
|
|
|
- // 1.1、关键字模糊查询 - 通过关联查询关键字表
|
|
|
- if (StringUtils.hasText(reqDto.getKeyword())) {
|
|
|
- // 先查询包含该关键字的规则ID
|
|
|
- List<MktMgmtKeyword> keywords = mktMgmtKeywordMapper.selectList(
|
|
|
- Wrappers.<MktMgmtKeyword>lambdaQuery()
|
|
|
- .like(MktMgmtKeyword::getKeyword, reqDto.getKeyword())
|
|
|
- );
|
|
|
-
|
|
|
- if (!keywords.isEmpty()) {
|
|
|
- List<Long> ruleIds = keywords.stream()
|
|
|
- .map(MktMgmtKeyword::getRuleId)
|
|
|
- .distinct()
|
|
|
- .collect(Collectors.toList());
|
|
|
- queryWrapper.in("id", ruleIds);
|
|
|
- } else {
|
|
|
- // 如果没有找到匹配的关键字,返回空结果
|
|
|
- return new Page<>();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 1.2、IP匹配逻辑 - 支持单IP和IP段匹配
|
|
|
- if (StringUtils.hasText(reqDto.getIp())) {
|
|
|
- String inputIp = reqDto.getIp();
|
|
|
- // 验证输入IP格式
|
|
|
- if (!IPUtils.isValidIp(inputIp)) {
|
|
|
- throw new BusinessException("输入的IP格式不正确");
|
|
|
- }
|
|
|
-
|
|
|
- queryWrapper.and(wrapper -> wrapper
|
|
|
- // 匹配单IP模式:ipMode=1 且 startIp等于输入IP
|
|
|
- .and(w -> w.eq("ip_mode", 1).eq("start_ip", inputIp))
|
|
|
- // 匹配IP段模式:ipMode=2 且 输入IP在startIp和endIp范围内
|
|
|
- .or(w -> w.eq("ip_mode", 2)
|
|
|
- .apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", inputIp))
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- // 1.3、域名模糊查询
|
|
|
- if (StringUtils.hasText(reqDto.getDomain())) {
|
|
|
- queryWrapper.like("domain", reqDto.getDomain());
|
|
|
- }
|
|
|
-
|
|
|
- // 按创建时间倒序排列
|
|
|
- queryWrapper.orderByDesc("create_time");
|
|
|
-
|
|
|
- // 执行分页查询
|
|
|
- Page<MktMgmtRule> rulePage = mktMgmtRuleMapper.selectPage(page, queryWrapper);
|
|
|
-
|
|
|
- // 转换为VO对象
|
|
|
- Page<PageMktRuleVO> resultPage = new Page<>(reqDto.getCurrent(), reqDto.getSize());
|
|
|
- resultPage.setTotal(rulePage.getTotal());
|
|
|
- resultPage.setPages(rulePage.getPages());
|
|
|
-
|
|
|
- List<PageMktRuleVO> voList = rulePage.getRecords().stream().map(rule -> {
|
|
|
- PageMktRuleVO vo = new PageMktRuleVO();
|
|
|
- BeanUtils.copyProperties(rule, vo);
|
|
|
-
|
|
|
- // 查询该规则对应的关键字列表
|
|
|
- List<MktMgmtKeyword> keywords = mktMgmtKeywordMapper.selectList(
|
|
|
- Wrappers.<MktMgmtKeyword>lambdaQuery()
|
|
|
- .eq(MktMgmtKeyword::getRuleId, rule.getId())
|
|
|
- );
|
|
|
-
|
|
|
- List<String> keywordList = keywords.stream()
|
|
|
- .map(MktMgmtKeyword::getKeyword)
|
|
|
- .collect(Collectors.toList());
|
|
|
- vo.setKeyword(keywordList);
|
|
|
-
|
|
|
- return vo;
|
|
|
- }).collect(Collectors.toList());
|
|
|
-
|
|
|
- resultPage.setRecords(voList);
|
|
|
-
|
|
|
- return resultPage;
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 根据ID查询营销规则
|
|
|
* @param id id
|
|
@@ -623,22 +374,6 @@ public class MktMgmtRuleServiceImpl implements MktMgmtRuleService {
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
- public PageMktRuleVO getMktRuleById2(Long id) {
|
|
|
- MktMgmtRule mktMgmtRule = mktMgmtRuleMapper.selectById(id);
|
|
|
- if (mktMgmtRule == null){
|
|
|
- throw new BusinessException("规则不存在");
|
|
|
- }
|
|
|
- PageMktRuleVO result = new PageMktRuleVO();
|
|
|
- BeanUtils.copyProperties(mktMgmtRule, result);
|
|
|
- // 查询该规则对应关键字列表
|
|
|
- List<MktMgmtKeyword> keywords = mktMgmtKeywordMapper.selectList(Wrappers.<MktMgmtKeyword>lambdaQuery()
|
|
|
- .eq(MktMgmtKeyword::getRuleId, id));
|
|
|
- List<String> keywordList = keywords.stream()
|
|
|
- .map(MktMgmtKeyword::getKeyword)
|
|
|
- .collect(Collectors.toList());
|
|
|
- result.setKeyword(keywordList);
|
|
|
- return result;
|
|
|
- }
|
|
|
|
|
|
/**
|
|
|
* 校验IP格式是否合法
|
|
@@ -663,81 +398,432 @@ public class MktMgmtRuleServiceImpl implements MktMgmtRuleService {
|
|
|
* @param domain 域名
|
|
|
*/
|
|
|
private void validateDomain(String domain){
|
|
|
- if (!DomainValidationUtil.isValidDomain(domain)) {
|
|
|
+ if (!DomainValidationUtil.isValidDomain2(domain)) {
|
|
|
throw new BusinessException("域名格式错误: " + domain);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 检查规则IP是否重复
|
|
|
- * @param ruleIp 要检查的IP信息
|
|
|
- * @param ruleId 规则ID(更新时使用,新增时为null)
|
|
|
- * @return 是否存在重复
|
|
|
+ * 验证规则名是否重复
|
|
|
+ * @param ruleName 规则名
|
|
|
+ * @param ruleId 规则ID(修改时为当前规则ID,新增时为null)
|
|
|
+ */
|
|
|
+ private void validateRuleName(String ruleName, Long ruleId) {
|
|
|
+ if (!StringUtils.hasText(ruleName)) {
|
|
|
+ throw new BusinessException("规则名不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查规则名是否已存在
|
|
|
+ LambdaQueryWrapper<MktMgmtRule> wrapper = Wrappers.<MktMgmtRule>lambdaQuery()
|
|
|
+ .eq(MktMgmtRule::getRuleName, ruleName.trim());
|
|
|
+
|
|
|
+ // 如果是修改操作,排除当前规则
|
|
|
+ if (ruleId != null) {
|
|
|
+ wrapper.ne(MktMgmtRule::getId, ruleId);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mktMgmtRuleMapper.selectCount(wrapper) > 0) {
|
|
|
+ throw new BusinessException("规则名 '" + ruleName.trim() + "' 已存在,不能重复");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证IP列表,检查是否存在冲突
|
|
|
+ * @param ipList IP列表
|
|
|
*/
|
|
|
- private Boolean checkRuleIpExists(MktMgmtRuleIp ruleIp, Long ruleId){
|
|
|
- QueryWrapper<MktMgmtRuleIp> query = new QueryWrapper<MktMgmtRuleIp>().eq("rule_id", ruleId);
|
|
|
-
|
|
|
- query.and(wrapper -> {
|
|
|
- // 单IP模式检查
|
|
|
- if (ruleIp.getIpMode() == 1) {
|
|
|
- String targetIp = ruleIp.getStartIp();
|
|
|
- // 检查是否有相同单IP
|
|
|
- wrapper.and(w -> w
|
|
|
- .eq("ip_mode", 1)
|
|
|
- .eq("start_ip", targetIp));
|
|
|
-
|
|
|
- // 检查是否被IP段包含
|
|
|
- wrapper.or(w -> w
|
|
|
- .eq("ip_mode", 2)
|
|
|
- .apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", targetIp));
|
|
|
+ private void validateIpList(List<String> ipList) {
|
|
|
+ if (ipList == null || ipList.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 过滤空值和去重
|
|
|
+ List<String> validIps = ipList.stream()
|
|
|
+ .filter(StringUtils::hasText)
|
|
|
+ .map(String::trim)
|
|
|
+ .toList();
|
|
|
+
|
|
|
+ // 检查是否有重复的单IP
|
|
|
+ Set<String> singleIps = new HashSet<>();
|
|
|
+ Set<String> ipRanges = new HashSet<>();
|
|
|
+
|
|
|
+ for (String ip : validIps) {
|
|
|
+ if (ip.contains("/")) {
|
|
|
+ // IP段格式
|
|
|
+ ipRanges.add(ip);
|
|
|
+ } else {
|
|
|
+ // 单IP格式
|
|
|
+ if (!singleIps.add(ip)) {
|
|
|
+ throw new BusinessException("IP列表中存在重复的单IP: " + ip);
|
|
|
+ }
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否有重复的IP段
|
|
|
+ List<String> rangeList = validIps.stream()
|
|
|
+ .filter(ip -> ip.contains("/"))
|
|
|
+ .toList();
|
|
|
+ Set<String> uniqueRanges = new HashSet<>(rangeList);
|
|
|
+ if (rangeList.size() != uniqueRanges.size()) {
|
|
|
+ throw new BusinessException("IP列表中存在重复的IP段");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查单IP是否在IP段中
|
|
|
+ for (String singleIp : singleIps) {
|
|
|
+ for (String ipRange : ipRanges) {
|
|
|
+ if (isIpInRange(singleIp, ipRange)) {
|
|
|
+ throw new BusinessException("单IP '" + singleIp + "' 在IP段 '" + ipRange + "' 中,存在冲突");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查IP段之间是否重叠
|
|
|
+ List<String> uniqueRangeList = new ArrayList<>(ipRanges);
|
|
|
+ for (int i = 0; i < uniqueRangeList.size(); i++) {
|
|
|
+ for (int j = i + 1; j < uniqueRangeList.size(); j++) {
|
|
|
+ if (isIpRangesOverlap(uniqueRangeList.get(i), uniqueRangeList.get(j))) {
|
|
|
+ throw new BusinessException("IP段 '" + uniqueRangeList.get(i) + "' 和 '" + uniqueRangeList.get(j) + "' 存在重叠");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证域名列表,检查格式和重复
|
|
|
+ * @param domainList 域名列表
|
|
|
+ */
|
|
|
+ private void validateDomainList(List<String> domainList) {
|
|
|
+ if (domainList == null || domainList.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 过滤空值,但不去重(保留重复项用于检测)
|
|
|
+ List<String> validDomains = domainList.stream()
|
|
|
+ .filter(StringUtils::hasText)
|
|
|
+ .map(String::trim)
|
|
|
+ .toList();
|
|
|
+
|
|
|
+ // 检查是否有重复的域名
|
|
|
+ Set<String> uniqueDomains = new HashSet<>();
|
|
|
+ for (String domain : validDomains) {
|
|
|
+ if (!uniqueDomains.add(domain)) {
|
|
|
+ throw new BusinessException("域名列表中存在重复的域名: " + domain);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验每个域名的格式
|
|
|
+ for (String domain : validDomains) {
|
|
|
+ validateDomain(domain);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证关键字列表,检查重复
|
|
|
+ * @param keywordList 关键字列表
|
|
|
+ */
|
|
|
+ private void validateKeywordList(List<String> keywordList) {
|
|
|
+ if (keywordList == null || keywordList.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 过滤空值,但不去重(保留重复项用于检测)
|
|
|
+ List<String> validKeywords = keywordList.stream()
|
|
|
+ .filter(StringUtils::hasText)
|
|
|
+ .map(String::trim)
|
|
|
+ .toList();
|
|
|
+
|
|
|
+ // 检查是否有重复的关键字
|
|
|
+ Set<String> uniqueKeywords = new HashSet<>();
|
|
|
+ for (String keyword : validKeywords) {
|
|
|
+ if (!uniqueKeywords.add(keyword)) {
|
|
|
+ throw new BusinessException("关键字列表中存在重复的关键字: " + keyword);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查单IP是否在IP段范围内
|
|
|
+ * @param singleIp 单IP
|
|
|
+ * @param ipRange IP段 (格式: 192.168.10.200/220 表示 192.168.10.200~192.168.10.220)
|
|
|
+ * @return 是否在范围内
|
|
|
+ */
|
|
|
+ private boolean isIpInRange(String singleIp, String ipRange) {
|
|
|
+ if (!IPUtils.isValidIp(singleIp)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ String[] parts = ipRange.split("/");
|
|
|
+ if (parts.length != 2) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ String startIp = parts[0];
|
|
|
+ String endPart = parts[1];
|
|
|
+
|
|
|
+ if (!IPUtils.isValidIp(startIp)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- // IP段模式检查
|
|
|
- if (ruleIp.getIpMode() == 2) {
|
|
|
- String startIp = ruleIp.getStartIp();
|
|
|
- String endIp = ruleIp.getEndIp();
|
|
|
-
|
|
|
- // 检查是否与单IP重叠:单IP在输入IP段范围内
|
|
|
- wrapper.and(w -> w
|
|
|
- .eq("ip_mode", 1)
|
|
|
- .apply("INET_ATON(start_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp));
|
|
|
-
|
|
|
- // 检查是否与IP段重叠:两个IP段有交集
|
|
|
- wrapper.or(w -> w
|
|
|
- .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)
|
|
|
- )
|
|
|
- );
|
|
|
+ // 构造完整的结束IP
|
|
|
+ String[] startParts = startIp.split("\\.");
|
|
|
+ String endIp = String.format("%s.%s.%s.%s",
|
|
|
+ startParts[0], startParts[1], startParts[2], endPart);
|
|
|
+
|
|
|
+ if (!IPUtils.isValidIp(endIp)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ long singleIpLong = ipToLong(singleIp);
|
|
|
+ long startIpLong = ipToLong(startIp);
|
|
|
+ long endIpLong = ipToLong(endIp);
|
|
|
+
|
|
|
+ // 确保开始IP小于等于结束IP
|
|
|
+ if (startIpLong > endIpLong) {
|
|
|
+ long temp = startIpLong;
|
|
|
+ startIpLong = endIpLong;
|
|
|
+ endIpLong = temp;
|
|
|
+ }
|
|
|
+
|
|
|
+ return singleIpLong >= startIpLong && singleIpLong <= endIpLong;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查两个IP段是否重叠
|
|
|
+ * @param range1 第一个IP段
|
|
|
+ * @param range2 第二个IP段
|
|
|
+ * @return 是否重叠
|
|
|
+ */
|
|
|
+ private boolean isIpRangesOverlap(String range1, String range2) {
|
|
|
+ String[] parts1 = range1.split("/");
|
|
|
+ String[] parts2 = range2.split("/");
|
|
|
+
|
|
|
+ if (parts1.length != 2 || parts2.length != 2) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ String network1 = parts1[0];
|
|
|
+ String network2 = parts2[0];
|
|
|
+ int prefix1 = Integer.parseInt(parts1[1]);
|
|
|
+ int prefix2 = Integer.parseInt(parts2[1]);
|
|
|
+
|
|
|
+ if (!IPUtils.isValidIp(network1) || !IPUtils.isValidIp(network2)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ long network1Long = ipToLong(network1);
|
|
|
+ long network2Long = ipToLong(network2);
|
|
|
+
|
|
|
+ // 计算网络掩码
|
|
|
+ long mask1 = (0xFFFFFFFFL << (32 - prefix1)) & 0xFFFFFFFFL;
|
|
|
+ long mask2 = (0xFFFFFFFFL << (32 - prefix2)) & 0xFFFFFFFFL;
|
|
|
+
|
|
|
+ // 计算网络地址
|
|
|
+ long net1 = network1Long & mask1;
|
|
|
+ long net2 = network2Long & mask2;
|
|
|
+
|
|
|
+ // 计算广播地址
|
|
|
+ long broadcast1 = net1 | (~mask1 & 0xFFFFFFFFL);
|
|
|
+ long broadcast2 = net2 | (~mask2 & 0xFFFFFFFFL);
|
|
|
+
|
|
|
+ // 检查是否重叠:一个网络的开始地址小于等于另一个网络的结束地址,且一个网络的结束地址大于等于另一个网络的开始地址
|
|
|
+ return net1 <= broadcast2 && broadcast1 >= net2;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将IP地址转换为长整型
|
|
|
+ * @param ip IP地址
|
|
|
+ * @return 长整型值
|
|
|
+ */
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建IP规则对象
|
|
|
+ * @param ip IP字符串
|
|
|
+ * @param ruleId 规则ID
|
|
|
+ * @return IP规则对象
|
|
|
+ */
|
|
|
+ private MktMgmtRuleIp buildRuleIp(String ip, Long ruleId) {
|
|
|
+ MktMgmtRuleIp ruleIp = new MktMgmtRuleIp();
|
|
|
+ ruleIp.setRuleId(ruleId);
|
|
|
+
|
|
|
+ if (ip.contains("/")) {
|
|
|
+ // IP段格式
|
|
|
+ String[] parts = ip.split("/");
|
|
|
+ String startIp = parts[0];
|
|
|
+ String endIpSuffix = parts[1];
|
|
|
+
|
|
|
+ String[] startParts = startIp.split("\\.");
|
|
|
+ int endSuffix = Integer.parseInt(endIpSuffix);
|
|
|
+ String endIp = String.format("%s.%s.%s.%d",
|
|
|
+ startParts[0], startParts[1], startParts[2], endSuffix);
|
|
|
+
|
|
|
+ ruleIp.setIpMode(2); // IP段模式
|
|
|
+ ruleIp.setStartIp(startIp);
|
|
|
+ ruleIp.setEndIp(endIp);
|
|
|
+ } else {
|
|
|
+ // 单IP格式
|
|
|
+ ruleIp.setIpMode(1);
|
|
|
+ ruleIp.setStartIp(ip);
|
|
|
+ ruleIp.setEndIp("");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验IP合法性
|
|
|
+ validateIp(ruleIp);
|
|
|
+ return ruleIp;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新IP列表
|
|
|
+ * @param ipList 新IP列表
|
|
|
+ * @param ruleId 规则ID
|
|
|
+ */
|
|
|
+ private void updateIpList(List<String> ipList, Long ruleId) {
|
|
|
+ // 查询现有的IP记录
|
|
|
+ List<MktMgmtRuleIp> oldIpRecords = mktMgmtRuleIpMapper.selectList(Wrappers.<MktMgmtRuleIp>lambdaQuery()
|
|
|
+ .eq(MktMgmtRuleIp::getRuleId, ruleId));
|
|
|
+
|
|
|
+ // 构建现有IP的映射(使用复合键:startIp + endIp + ipMode)
|
|
|
+ Map<String, MktMgmtRuleIp> oldIpMap = oldIpRecords.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ ip -> ip.getStartIp() + "|" + ip.getEndIp() + "|" + ip.getIpMode(),
|
|
|
+ ip -> ip
|
|
|
+ ));
|
|
|
+
|
|
|
+ // 构建新IP的映射
|
|
|
+ Map<String, MktMgmtRuleIp> newIpMap = new HashMap<>();
|
|
|
+ if (ipList != null && !ipList.isEmpty()) {
|
|
|
+ for (String ip : ipList) {
|
|
|
+ if (StringUtils.hasText(ip)) {
|
|
|
+ MktMgmtRuleIp ruleIp = buildRuleIp(ip, ruleId);
|
|
|
+ String key = ruleIp.getStartIp() + "|" + ruleIp.getEndIp() + "|" + ruleIp.getIpMode();
|
|
|
+ newIpMap.put(key, ruleIp);
|
|
|
+ }
|
|
|
}
|
|
|
- });
|
|
|
+ }
|
|
|
|
|
|
- return mktMgmtRuleIpMapper.selectCount(query) > 0;
|
|
|
+ // 处理需要删除的IP
|
|
|
+ List<Long> needDeleteIpIds = oldIpRecords.stream()
|
|
|
+ .filter(oldIp -> {
|
|
|
+ String oldKey = oldIp.getStartIp() + "|" + oldIp.getEndIp() + "|" + oldIp.getIpMode();
|
|
|
+ return !newIpMap.containsKey(oldKey);
|
|
|
+ })
|
|
|
+ .map(MktMgmtRuleIp::getId)
|
|
|
+ .toList();
|
|
|
+ if (!needDeleteIpIds.isEmpty()) {
|
|
|
+ mktMgmtRuleIpMapper.deleteByIds(needDeleteIpIds);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理需要新增的IP
|
|
|
+ List<MktMgmtRuleIp> needAddIps = newIpMap.values().stream()
|
|
|
+ .filter(newIp -> {
|
|
|
+ String newKey = newIp.getStartIp() + "|" + newIp.getEndIp() + "|" + newIp.getIpMode();
|
|
|
+ return !oldIpMap.containsKey(newKey);
|
|
|
+ })
|
|
|
+ .toList();
|
|
|
+ if (!needAddIps.isEmpty()) {
|
|
|
+ for (MktMgmtRuleIp ruleIp : needAddIps) {
|
|
|
+ mktMgmtRuleIpMapper.insert(ruleIp);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 检查规则域名是否存在重复
|
|
|
- * @param domain 要检查的域名
|
|
|
- * @param ruleId 规则ID(更新时使用,新增时为null)
|
|
|
- * @return 是否存在重复
|
|
|
+ * 更新域名列表
|
|
|
+ * @param domainList 新域名列表
|
|
|
+ * @param ruleId 规则ID
|
|
|
*/
|
|
|
- private Boolean checkRuleDomainExists(String domain, Long ruleId) {
|
|
|
- LambdaQueryWrapper<MktMgmtRuleDomain> wrapper = Wrappers.<MktMgmtRuleDomain>lambdaQuery()
|
|
|
- .eq(MktMgmtRuleDomain::getDomain, domain)
|
|
|
- .ne(MktMgmtRuleDomain::getRuleId, ruleId);
|
|
|
- return mktMgmtRuleDomainMapper.selectCount(wrapper) > 0;
|
|
|
+ private void updateDomainList(List<String> domainList, Long ruleId) {
|
|
|
+ // 查询现有的域名记录
|
|
|
+ List<MktMgmtRuleDomain> oldDomainRecords = mktMgmtRuleDomainMapper.selectList(Wrappers.<MktMgmtRuleDomain>lambdaQuery()
|
|
|
+ .eq(MktMgmtRuleDomain::getRuleId, ruleId));
|
|
|
+
|
|
|
+ // 构建现有域名的映射
|
|
|
+ Map<String, MktMgmtRuleDomain> oldDomainMap = oldDomainRecords.stream()
|
|
|
+ .collect(Collectors.toMap(MktMgmtRuleDomain::getDomain, domain -> domain));
|
|
|
+
|
|
|
+ // 构建新域名的映射
|
|
|
+ Map<String, MktMgmtRuleDomain> newDomainMap = new HashMap<>();
|
|
|
+ if (domainList != null && !domainList.isEmpty()) {
|
|
|
+ for (String domain : domainList) {
|
|
|
+ if (StringUtils.hasText(domain)) {
|
|
|
+ MktMgmtRuleDomain ruleDomain = new MktMgmtRuleDomain();
|
|
|
+ ruleDomain.setRuleId(ruleId);
|
|
|
+ ruleDomain.setDomain(domain.trim());
|
|
|
+ newDomainMap.put(domain.trim(), ruleDomain);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理需要删除的域名
|
|
|
+ List<Long> needDeleteDomainIds = oldDomainRecords.stream()
|
|
|
+ .filter(oldDomain -> !newDomainMap.containsKey(oldDomain.getDomain()))
|
|
|
+ .map(MktMgmtRuleDomain::getId)
|
|
|
+ .toList();
|
|
|
+ if (!needDeleteDomainIds.isEmpty()) {
|
|
|
+ mktMgmtRuleDomainMapper.deleteByIds(needDeleteDomainIds);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理需要新增的域名
|
|
|
+ List<MktMgmtRuleDomain> needAddDomains = newDomainMap.values().stream()
|
|
|
+ .filter(newDomain -> !oldDomainMap.containsKey(newDomain.getDomain()))
|
|
|
+ .toList();
|
|
|
+ if (!needAddDomains.isEmpty()) {
|
|
|
+ for (MktMgmtRuleDomain ruleDomain : needAddDomains) {
|
|
|
+ mktMgmtRuleDomainMapper.insert(ruleDomain);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 检查规则关键则是否存在重复
|
|
|
- * @param keyword 要检查的域名
|
|
|
- * @return 是否存在重复
|
|
|
+ * 更新关键字列表
|
|
|
+ * @param keywords 新关键字列表
|
|
|
+ * @param ruleId 规则ID
|
|
|
*/
|
|
|
- private Boolean checkRuleKeywordExists(String keyword){
|
|
|
- LambdaQueryWrapper<MktMgmtKeyword> wrapper = Wrappers.<MktMgmtKeyword>lambdaQuery()
|
|
|
- .eq(MktMgmtKeyword::getKeyword, keyword);
|
|
|
- return mktMgmtKeywordMapper.selectCount(wrapper) > 0;
|
|
|
+ private void updateKeywordList(List<String> keywords, Long ruleId) {
|
|
|
+ List<String> newKeywords = keywords == null ? Collections.emptyList() : keywords;
|
|
|
+
|
|
|
+ // 查询现有的关键字记录
|
|
|
+ List<MktMgmtKeyword> oldKeywords = mktMgmtKeywordMapper.selectList(Wrappers.<MktMgmtKeyword>lambdaQuery()
|
|
|
+ .eq(MktMgmtKeyword::getRuleId, ruleId));
|
|
|
+ Set<String> oldKeywordSet = oldKeywords.stream()
|
|
|
+ .map(MktMgmtKeyword::getKeyword)
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+
|
|
|
+ // 提取新关键字集合
|
|
|
+ Set<String> newKeywordSet = new HashSet<>();
|
|
|
+ for (String keyword : newKeywords) {
|
|
|
+ if (StringUtils.hasText(keyword)) {
|
|
|
+ newKeywordSet.add(keyword.trim());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理需要删除的关键字
|
|
|
+ List<Long> needDeleteIds = oldKeywords.stream()
|
|
|
+ .filter(keyword -> !newKeywordSet.contains(keyword.getKeyword()))
|
|
|
+ .map(MktMgmtKeyword::getId)
|
|
|
+ .toList();
|
|
|
+ if (!needDeleteIds.isEmpty()) {
|
|
|
+ mktMgmtKeywordMapper.deleteByIds(needDeleteIds);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理需要新增的关键字
|
|
|
+ List<String> needAddKeywords = newKeywordSet.stream()
|
|
|
+ .filter(keyword -> !oldKeywordSet.contains(keyword))
|
|
|
+ .toList();
|
|
|
+ if (!needAddKeywords.isEmpty()) {
|
|
|
+ for (String keyword : needAddKeywords) {
|
|
|
+ MktMgmtKeyword mktMgmtKeyword = new MktMgmtKeyword();
|
|
|
+ mktMgmtKeyword.setKeyword(keyword);
|
|
|
+ mktMgmtKeyword.setRuleId(ruleId);
|
|
|
+ mktMgmtKeywordMapper.insert(mktMgmtKeyword);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|