需求
构建tree,要求查询节点关键字时要携带所有直属上级节点。
思路
1.先查询全部节点数据,过滤出带关键字的节点数据。然后通过过滤出来的节点进行递归查找直属上级,最后根据结果构建tree
2.先查询所有节点,构建成tree,然后通过递归对tree过滤出带关键字的节点
代码
这里针对第2种思路进行实现
controller
@ApiOperation(value = "根据项目名称搜索tree")
@GetMapping("/searchTree")
public R<List<AppraiseItemTreeVo>> searchTree(String projectName) {
return R.ok(iAppraiseItemService.treeList(projectName));
}
IService
/**
* 根据项目名称获取tree,查询子集关键字时要携带所有直属上级结构
*
* @param projectName
* @return
*/
List<AppraiseItemTreeVo> treeList(String projectName);
ServiceImpl
/**
* 根据项目名称获取tree,查询子集关键字时要携带所有上级结构
*
* @param projectName
* @return
*/
@Override
public List<AppraiseItemTreeVo> treeList(String projectName) {
// 查询所有节点
LambdaQueryWrapper<AppraiseItem> queryWrapper = new LambdaQueryWrapper<>();
List<AppraiseItem> appraiseItemList = baseMapper.selectList(queryWrapper);
// 查询所有父节点
queryWrapper.eq(AppraiseItem::getParentId, 0);
List<AppraiseItem> parentList = baseMapper.selectList(queryWrapper);
List<AppraiseItemTreeVo> result = new ArrayList<>();
if (CollectionUtils.isEmpty(parentList)) {
return result;
}
// 先构建树
parentList.forEach(item -> result.add(buildChildren(item, appraiseItemList)));
// 关键字检索
return doSearch(result, projectName);
}
/**
* 构建树状结构
*
* @param item
* @param list
* @return
*/
private AppraiseItemTreeVo buildChildren(AppraiseItem item, List<AppraiseItem> list) {
List<AppraiseItemTreeVo> children = new ArrayList<>();
for (AppraiseItem appraiseItem : list) {
if (Objects.equals(item.getId(), appraiseItem.getParentId())) {
children.add(buildChildren(appraiseItem, list));
}
}
AppraiseItemTreeVo vo = new AppraiseItemTreeVo();
vo.setId(String.valueOf(item.getId()));
vo.setParentId(String.valueOf(item.getParentId()));
vo.setUnit(item.getUnit());
vo.setOrderBy(item.getOrderBy());
vo.setProjectName(item.getProjectName());
vo.setIsHasSon(item.getIsHasSon());
// 对子集合排序,排序字段为null的排在第一位
children = children.stream().sorted(Comparator.comparing(AppraiseItemTreeVo::getOrderBy, Comparator.nullsFirst(String::compareTo))).collect(Collectors.toList());
vo.setChildren(children);
return vo;
}
/**
* tree 关键字搜索
*
* @param searchList
* @param keyWord
* @return
*/
private List<AppraiseItemTreeVo> doSearch(List<AppraiseItemTreeVo> searchList, String keyWord) {
List<AppraiseItemTreeVo> resultList = new ArrayList<>();
for (AppraiseItemTreeVo treeVo : searchList) {
// 判断是否包括keyWord
String projectName = treeVo.getProjectName();
if (projectName.contains(keyWord)) {
// 如果存在关键字继续递归子集
treeVo.setChildren(doSearch(treeVo.getChildren(), keyWord));
resultList.add(treeVo);
} else {
// 继续递归
List<AppraiseItemTreeVo> children = doSearch(treeVo.getChildren(), keyWord);
if (!CollectionUtils.isEmpty(children)) {
// 把子节点列表加到节点上
treeVo.setChildren(children);
resultList.add(treeVo);
}
}
}
// 对最外层排序,排序字段为null的排在第一位
resultList = resultList.stream().sorted(Comparator.comparing(AppraiseItemTreeVo::getOrderBy, Comparator.nullsFirst(String::compareTo))).collect(Collectors.toList());
return resultList;
}
mapper 和 vo就不展示了
如图效果: