refactor(ops): 巡检接口重构 — 位置校验前移、列表/详情分离、表单聚合

接口变更:
- 删除 POST /verify-location,位置校验改为前端本地蓝牙信标匹配
- 新增 GET /record/get 巡检记录详情(含明细项、照片)
- GET /list-by-area 升级为返回完整巡检表单(区域+检查项+信标配置)
- GET /record/page 返回类型改为 VO,新增区域全路径名称和巡检员姓名
- 提交和表单接口增加 inspector 角色校验

代码质量(Code Review 修复):
- 提取 buildAreaFullName 至 OpsBusAreaMapper 消除两个 Service 的重复
- 新增 buildAreaFullNameMap 批量方法,修复分页场景 N+1 查询
- getRecordDetail 中 adminUserApi 改用 getUserMap + try-catch 降级
- InspectionTemplateServiceImpl 去掉 ObjectMapper 依赖,直接 Map 取值
- RSSI 阈值取最宽松值逻辑添加语义注释
- 巡检错误码从 1-020-003 迁移至 1-020-004,修复与安保模块的码段冲突
- InspectionRecordDetailRespVO.photos 使用 @OssPresignUrl 自动预签名

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
lzh
2026-03-22 15:00:07 +08:00
parent e11d3e1b6e
commit f213510b03
24 changed files with 585 additions and 246 deletions

View File

@@ -6,7 +6,8 @@ import com.viewsh.module.ops.dal.dataobject.area.OpsBusAreaDO;
import com.viewsh.module.ops.dal.dataobject.vo.area.OpsBusAreaPageReqVO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
* 业务区域 Mapper
@@ -103,4 +104,91 @@ public interface OpsBusAreaMapper extends BaseMapperX<OpsBusAreaDO> {
return selectCount(OpsBusAreaDO::getParentId, parentId);
}
// ==================== 区域全路径名称 ====================
/**
* 拼接区域全路径名称(如 "A园区/1号楼/2层/男卫"
*
* @param area 区域对象
* @return 全路径名称
*/
default String buildAreaFullName(OpsBusAreaDO area) {
if (area.getParentPath() == null || area.getParentPath().isEmpty()) {
return area.getAreaName();
}
List<Long> ancestorIds = Arrays.stream(area.getParentPath().split("/"))
.filter(s -> !s.isEmpty())
.map(Long::valueOf)
.collect(Collectors.toList());
if (ancestorIds.isEmpty()) {
return area.getAreaName();
}
Map<Long, String> nameMap = selectBatchIds(ancestorIds).stream()
.collect(Collectors.toMap(OpsBusAreaDO::getId, OpsBusAreaDO::getAreaName));
StringBuilder sb = new StringBuilder();
for (Long ancestorId : ancestorIds) {
String name = nameMap.get(ancestorId);
if (name != null) {
if (!sb.isEmpty()) {
sb.append("/");
}
sb.append(name);
}
}
sb.append("/").append(area.getAreaName());
return sb.toString();
}
/**
* 批量构建区域全路径名称(优化 N+1 查询,一次性查出所有祖先节点)
*
* @param areas 区域列表
* @return area.id → 全路径名称
*/
default Map<Long, String> buildAreaFullNameMap(Collection<OpsBusAreaDO> areas) {
if (areas == null || areas.isEmpty()) {
return Collections.emptyMap();
}
// 收集所有祖先 ID一次性批量查询
Set<Long> allAncestorIds = new HashSet<>();
for (OpsBusAreaDO area : areas) {
if (area.getParentPath() != null && !area.getParentPath().isEmpty()) {
Arrays.stream(area.getParentPath().split("/"))
.filter(s -> !s.isEmpty())
.map(Long::valueOf)
.forEach(allAncestorIds::add);
}
}
Map<Long, String> ancestorNameMap = allAncestorIds.isEmpty()
? Collections.emptyMap()
: selectBatchIds(allAncestorIds).stream()
.collect(Collectors.toMap(OpsBusAreaDO::getId, OpsBusAreaDO::getAreaName));
// 拼装每个区域的全路径
Map<Long, String> result = new HashMap<>(areas.size());
for (OpsBusAreaDO area : areas) {
if (area.getParentPath() == null || area.getParentPath().isEmpty()) {
result.put(area.getId(), area.getAreaName());
continue;
}
List<Long> ancestorIds = Arrays.stream(area.getParentPath().split("/"))
.filter(s -> !s.isEmpty())
.map(Long::valueOf)
.toList();
StringBuilder sb = new StringBuilder();
for (Long ancestorId : ancestorIds) {
String name = ancestorNameMap.get(ancestorId);
if (name != null) {
if (!sb.isEmpty()) {
sb.append("/");
}
sb.append(name);
}
}
sb.append("/").append(area.getAreaName());
result.put(area.getId(), sb.toString());
}
return result;
}
}