fix(产品需求): 修复产品需求查询的问题、修复产品需求树返回数据的问题
This commit is contained in:
@@ -20,6 +20,22 @@ public interface ProductRequirementMapper extends BaseMapperX<ProductRequirement
|
|||||||
* 分页查询需求列表
|
* 分页查询需求列表
|
||||||
*/
|
*/
|
||||||
default PageResult<ProductRequirementDO> selectPage(ProductRequirementPageReqVO reqVO) {
|
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<>();
|
LambdaQueryWrapperX<ProductRequirementDO> queryWrapper = new LambdaQueryWrapperX<>();
|
||||||
// 标题模糊搜索
|
// 标题模糊搜索
|
||||||
if (StringUtils.hasText(reqVO.getTitle())) {
|
if (StringUtils.hasText(reqVO.getTitle())) {
|
||||||
@@ -46,7 +62,7 @@ public interface ProductRequirementMapper extends BaseMapperX<ProductRequirement
|
|||||||
// 按排序值升序,再按创建时间降序
|
// 按排序值升序,再按创建时间降序
|
||||||
.orderByAsc(ProductRequirementDO::getSort)
|
.orderByAsc(ProductRequirementDO::getSort)
|
||||||
.orderByDesc(ProductRequirementDO::getCreateTime);
|
.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.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception;
|
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",
|
@CheckObjectPermission(objectType = PRODUCT_OBJECT_TYPE, objectId = "#pageReqVO.productId",
|
||||||
permission = PRODUCT_QUERY_PERMISSION)
|
permission = PRODUCT_QUERY_PERMISSION)
|
||||||
public PageResult<ProductRequirementRespVO> getRequirementTree(ProductRequirementPageReqVO pageReqVO) {
|
public PageResult<ProductRequirementRespVO> getRequirementTree(ProductRequirementPageReqVO pageReqVO) {
|
||||||
System.out.println("--------------");
|
|
||||||
System.out.println(pageReqVO);
|
|
||||||
// 查询当前产品下的所有顶级需求
|
|
||||||
Long moduleId = pageReqVO.getModuleId();
|
Long moduleId = pageReqVO.getModuleId();
|
||||||
Long productId = pageReqVO.getProductId();
|
Long productId = pageReqVO.getProductId();
|
||||||
|
|
||||||
// 处理模块过滤条件:仅当选中具体模块(非“全部需求”)时,才递归加载子模块ID进行过滤
|
// 处理模块过滤条件:仅当选中具体模块时,递归加载子模块ID进行过滤
|
||||||
if (moduleId != null) {
|
if (moduleId != null) {
|
||||||
pageReqVO.setModuleIds(getAllModuleIdsWithChildren(moduleId, productId));
|
pageReqVO.setModuleIds(getAllModuleIdsWithChildren(moduleId, productId));
|
||||||
// 清空moduleId,避免与moduleIds冲突(Mapper中优先使用moduleIds做IN查询)
|
|
||||||
pageReqVO.setModuleId(null);
|
pageReqVO.setModuleId(null);
|
||||||
}
|
}
|
||||||
// 固定只查询父需求(parentId = 0L),子需求通过递归加载
|
// 清空parentId,查询所有符合条件的需求(不限层级)
|
||||||
pageReqVO.setParentId(0L);
|
pageReqVO.setParentId(null);
|
||||||
PageResult<ProductRequirementDO> pageResult = requirementMapper.selectPage(pageReqVO);
|
|
||||||
|
|
||||||
// 构建树形结构(子需求不计入分页)
|
// 第一步:查询所有符合搜索条件的需求
|
||||||
List<ProductRequirementRespVO> list = pageResult.getList().stream()
|
List<ProductRequirementDO> matchedRequirements = requirementMapper.selectList(pageReqVO);
|
||||||
.map(this::buildRequirementRespVOWithChildren)
|
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());
|
.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;
|
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) {
|
if (existModule == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (moduleId == null || !existModule.getId().equals(moduleId)) {
|
if (!existModule.getId().equals(moduleId)) {
|
||||||
throw exception(ErrorCodeConstants.REQUIREMENT_MODULE_NAME_DUPLICATE, moduleName.trim());
|
throw exception(ErrorCodeConstants.REQUIREMENT_MODULE_NAME_DUPLICATE, moduleName.trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user