fix(产品需求): 修复产品需求查询的问题、修复产品需求树返回数据的问题
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 根节点ID(parentId = 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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user