fix(产品需求): 修复产品需求查询的问题、修复产品需求树返回数据的问题

This commit is contained in:
dk
2026-05-07 11:10:21 +08:00
parent 7913c210cd
commit 73360d70ce
2 changed files with 114 additions and 32 deletions

View File

@@ -20,6 +20,22 @@ public interface ProductRequirementMapper extends BaseMapperX<ProductRequirement
* 分页查询需求列表
*/
default PageResult<ProductRequirementDO> selectPage(ProductRequirementPageReqVO reqVO) {
LambdaQueryWrapperX<ProductRequirementDO> queryWrapper = buildQueryWrapper(reqVO);
return selectPage(reqVO, queryWrapper);
}
/**
* 查询所有符合条件的需求列表(不分页,用于树形查询)
*/
default List<ProductRequirementDO> selectList(ProductRequirementPageReqVO reqVO) {
LambdaQueryWrapperX<ProductRequirementDO> queryWrapper = buildQueryWrapper(reqVO);
return selectList(queryWrapper);
}
/**
* 构建查询条件
*/
private LambdaQueryWrapperX<ProductRequirementDO> buildQueryWrapper(ProductRequirementPageReqVO reqVO) {
LambdaQueryWrapperX<ProductRequirementDO> queryWrapper = new LambdaQueryWrapperX<>();
// 标题模糊搜索
if (StringUtils.hasText(reqVO.getTitle())) {
@@ -46,7 +62,7 @@ public interface ProductRequirementMapper extends BaseMapperX<ProductRequirement
// 按排序值升序,再按创建时间降序
.orderByAsc(ProductRequirementDO::getSort)
.orderByDesc(ProductRequirementDO::getCreateTime);
return selectPage(reqVO, queryWrapper);
return queryWrapper;
}
/**

View File

@@ -24,9 +24,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -191,27 +189,110 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
@CheckObjectPermission(objectType = PRODUCT_OBJECT_TYPE, objectId = "#pageReqVO.productId",
permission = PRODUCT_QUERY_PERMISSION)
public PageResult<ProductRequirementRespVO> getRequirementTree(ProductRequirementPageReqVO pageReqVO) {
System.out.println("--------------");
System.out.println(pageReqVO);
// 查询当前产品下的所有顶级需求
Long moduleId = pageReqVO.getModuleId();
Long productId = pageReqVO.getProductId();
// 处理模块过滤条件:仅当选中具体模块(非“全部需求”)时,递归加载子模块ID进行过滤
// 处理模块过滤条件仅当选中具体模块时递归加载子模块ID进行过滤
if (moduleId != null) {
pageReqVO.setModuleIds(getAllModuleIdsWithChildren(moduleId, productId));
// 清空moduleId避免与moduleIds冲突Mapper中优先使用moduleIds做IN查询
pageReqVO.setModuleId(null);
}
// 固定只查询父需求parentId = 0L子需求通过递归加载
pageReqVO.setParentId(0L);
PageResult<ProductRequirementDO> pageResult = requirementMapper.selectPage(pageReqVO);
// 清空parentId查询所有符合条件的需求不限层级
pageReqVO.setParentId(null);
// 构建树形结构(子需求不计入分页)
List<ProductRequirementRespVO> list = pageResult.getList().stream()
.map(this::buildRequirementRespVOWithChildren)
// 第一步:查询所有符合搜索条件的需求
List<ProductRequirementDO> matchedRequirements = requirementMapper.selectList(pageReqVO);
if (matchedRequirements.isEmpty()) {
return new PageResult<>(Collections.emptyList(), 0L);
}
// 第二步找出所有匹配需求的根节点ID同时收集路径上的所有节点ID
Set<Long> rootIds = new HashSet<>();
Set<Long> pathNodeIds = new HashSet<>();
Map<Long, ProductRequirementDO> requirementCache = new HashMap<>();
for (ProductRequirementDO req : matchedRequirements) {
requirementCache.put(req.getId(), req);
pathNodeIds.add(req.getId());
Long rootId = findRootRequirementIdAndCollectPath(req, requirementCache, pathNodeIds);
rootIds.add(rootId);
}
// 第三步:查询根需求详情并按创建时间倒排
List<ProductRequirementDO> rootRequirements = requirementMapper.selectBatchIds(rootIds);
rootRequirements.sort((a, b) -> b.getCreateTime().compareTo(a.getCreateTime()));
// 第四步:对根节点列表进行内存分页
int pageNo = pageReqVO.getPageNo() != null ? pageReqVO.getPageNo() : 1;
int pageSize = pageReqVO.getPageSize() != null ? pageReqVO.getPageSize() : 10;
int total = rootRequirements.size();
int fromIndex = (pageNo - 1) * pageSize;
int toIndex = Math.min(fromIndex + pageSize, total);
if (fromIndex >= total) {
return new PageResult<>(Collections.emptyList(), (long) total);
}
List<ProductRequirementDO> pagedRootRequirements = rootRequirements.subList(fromIndex, toIndex);
// 第五步:构建树形结构(只包含路径上的节点)
List<ProductRequirementRespVO> list = pagedRootRequirements.stream()
.map(req -> buildRequirementRespVOWithPathChildren(req, pathNodeIds))
.collect(Collectors.toList());
return new PageResult<>(list, pageResult.getTotal());
return new PageResult<>(list, (long) total);
}
/**
* 向上追溯需求的根节点ID同时收集路径上的所有节点ID
* @param requirement 起始需求
* @param cache 需求缓存(避免重复查询)
* @param pathNodeIds 路径节点ID集合输出参数
* @return 根节点IDparentId = 0L 的需求ID
*/
private Long findRootRequirementIdAndCollectPath(ProductRequirementDO requirement,
Map<Long, ProductRequirementDO> cache,
Set<Long> pathNodeIds) {
if (requirement.getParentId() == null || requirement.getParentId() == 0L) {
return requirement.getId();
}
// 从缓存中查找父需求,如果没有则查询数据库
ProductRequirementDO parent = cache.get(requirement.getParentId());
if (parent == null) {
parent = requirementMapper.selectById(requirement.getParentId());
if (parent != null) {
cache.put(parent.getId(), parent);
}
}
if (parent == null) {
// 父需求不存在(数据异常),返回当前需求作为根
return requirement.getId();
}
// 收集路径上的节点ID
pathNodeIds.add(parent.getId());
return findRootRequirementIdAndCollectPath(parent, cache, pathNodeIds);
}
/**
* 构建需求响应VO只包含路径上的子需求
* @param requirement 需求
* @param pathNodeIds 路径节点ID集合
* @return 需求响应VO
*/
private ProductRequirementRespVO buildRequirementRespVOWithPathChildren(ProductRequirementDO requirement,
Set<Long> pathNodeIds) {
ProductRequirementRespVO respVO = buildRequirementRespVO(requirement);
// 查询子需求
List<ProductRequirementDO> allChildren = requirementMapper.selectListByParentId(requirement.getId());
// 只保留路径上的子需求
List<ProductRequirementDO> pathChildren = allChildren.stream()
.filter(child -> pathNodeIds.contains(child.getId()))
.toList();
if (!pathChildren.isEmpty()) {
respVO.setChildren(pathChildren.stream()
.map(child -> buildRequirementRespVOWithPathChildren(child, pathNodeIds))
.collect(Collectors.toList()));
}
return respVO;
}
/**
@@ -607,21 +688,6 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
return respVO;
}
/**
* 构建需求响应VO含子需求
*/
private ProductRequirementRespVO buildRequirementRespVOWithChildren(ProductRequirementDO requirement) {
ProductRequirementRespVO respVO = buildRequirementRespVO(requirement);
// 查询子需求
List<ProductRequirementDO> children = requirementMapper.selectListByParentId(requirement.getId());
if (!children.isEmpty()) {
respVO.setChildren(children.stream()
.map(this::buildRequirementRespVOWithChildren)
.collect(Collectors.toList()));
}
return respVO;
}
/**
* 构建模块树
*/
@@ -723,7 +789,7 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
if (existModule == null) {
return;
}
if (moduleId == null || !existModule.getId().equals(moduleId)) {
if (!existModule.getId().equals(moduleId)) {
throw exception(ErrorCodeConstants.REQUIREMENT_MODULE_NAME_DUPLICATE, moduleName.trim());
}
}