refactor(ops): 提取 AreaPathBuilder 公共组件,消除保洁/安保 buildAreaPath 重复代码

将 CleanOrderServiceImpl 中的 buildAreaPath 私有方法提取到 ops-biz 公共层
AreaPathBuilder 组件,供各业务模块(保洁、安保等)共享使用。同时优化:
- 用正则 matches("\d+") 替代 try-catch NumberFormatException 做数字校验
- 增加相邻重复ID去重保护

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
lzh
2026-03-15 10:30:03 +08:00
parent 2a20f7a89f
commit 825c8eecca
5 changed files with 174 additions and 96 deletions

View File

@@ -0,0 +1,108 @@
package com.viewsh.module.ops.infrastructure.area;
import cn.hutool.core.util.StrUtil;
import com.viewsh.module.ops.dal.dataobject.area.OpsBusAreaDO;
import com.viewsh.module.ops.dal.mysql.area.OpsBusAreaMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 区域路径构建器
* <p>
* 根据 areaId 拼接完整的区域路径,如 "A园区/A栋/3层/电梯厅"。
* 供保洁、安保等各业务模块共享使用。
*
* @author lzh
*/
@Slf4j
@Component
public class AreaPathBuilder {
@Resource
private OpsBusAreaMapper opsBusAreaMapper;
/**
* 根据已查询到的区域对象构建完整路径
*
* @param area 区域对象(非 null
* @return 完整区域路径,用 "/" 分隔
*/
public String buildPath(OpsBusAreaDO area) {
if (area == null) {
return null;
}
String parentPath = area.getParentPath();
if (StrUtil.isEmpty(parentPath)) {
return area.getAreaName();
}
// 解析父级ID列表
List<Long> parentIds = Arrays.stream(parentPath.split("/"))
.filter(StrUtil::isNotBlank)
.filter(pid -> pid.matches("\\d+"))
.map(Long::parseLong)
.filter(pid -> !pid.equals(area.getId()))
.collect(Collectors.toList());
// ID层面去重相邻重复数据异常保护
List<Long> deduplicatedIds = new ArrayList<>();
Long lastId = null;
for (Long parentId : parentIds) {
if (!parentId.equals(lastId)) {
deduplicatedIds.add(parentId);
lastId = parentId;
} else {
log.warn("检测到parent_path中重复的ID: areaId={}, duplicateId={}", area.getId(), parentId);
}
}
if (deduplicatedIds.isEmpty()) {
return area.getAreaName();
}
// 批量查询父级区域
List<OpsBusAreaDO> parents = opsBusAreaMapper.selectBatchIds(deduplicatedIds);
if (parents == null || parents.isEmpty()) {
log.warn("未找到父级区域: areaId={}, parentIds={}", area.getId(), deduplicatedIds);
return area.getAreaName();
}
Map<Long, String> parentNameMap = parents.stream()
.collect(Collectors.toMap(OpsBusAreaDO::getId, OpsBusAreaDO::getAreaName, (a, b) -> a));
List<String> pathSegments = deduplicatedIds.stream()
.filter(parentNameMap::containsKey)
.map(parentNameMap::get)
.collect(Collectors.toList());
String path = String.join("/", pathSegments);
return StrUtil.isBlank(path) ? area.getAreaName() : path + "/" + area.getAreaName();
}
/**
* 根据 areaId 查询并构建完整路径
*
* @param areaId 区域ID
* @return 完整区域路径,用 "/" 分隔;区域不存在时返回 null
*/
public String buildPath(Long areaId) {
if (areaId == null) {
return null;
}
OpsBusAreaDO area = opsBusAreaMapper.selectById(areaId);
if (area == null) {
log.warn("区域不存在: areaId={}", areaId);
return null;
}
return buildPath(area);
}
}