这里写自定义目录标题
- 需要实现的效果
 - 前端需要的json格式:一定是一个完整的树结构
 - 错误
 - 错误的返回格式
 - 错误的返回格式实现的效果
 
- 正确
 - 正确的返回格式
 - 正确的展示画面
 
- 后端
 - 逻辑分析
 - 代码总览
 
- 数据库表结构
 
需要实现的效果

前端需要的json格式:一定是一个完整的树结构
错误
错误的返回格式

错误的返回格式实现的效果

正确
正确的返回格式

正确的展示画面

后端
逻辑分析
1. 根据搜索条件,查出符合的数据
List<ReproductiveCycleInfo> list = reproductiveCycleInfoMapper.selectReproductiveCycleInfoList(reproductiveCycleInfo);
 

 这一步不能直接返回给前端的,因为前端的组件是需要完整的一个树结构。
 从图中可以看到,我们 id in(70,71,72)的父节点 id = 17 没有找到,所以 这就不是一个完整的树结构。
2. 符合的数据里面我们需要发现还需要找到几个父节点数据
// parentId = 0,表示他已经没有父节点了
Set<Long> collect = list.stream().filter(x -> x.getParentId() != 0).map(ReproductiveCycleInfo::getParentId).collect(Collectors.toSet());
 

 3. 开始找父节点的信息
        if (StringUtils.isNotEmpty(collect)) {
            for (Long x : collect) {
                getParentInfoByParentId(x, list);
            }
        }
 
3.1 根据节点的id找到节点
    /**
     * 根据节点id找出节点,并添加到结果集里面
     *
     * @param nodeId 当前需要找的节点id
     * @param list 返回的结果集
     */
    private void getNodeByParentId(Long nodeId, List<ReproductiveCycleInfo> list) {
        // 1. 如果当前需要找的节点
        if (nodeId != 0) {
            // 2. 为了避免父节点也已经出现在 所有的节点信息 里面
            // 2.1 找出当前所有的节点信息
            List<Long> ids = list.stream().map(ReproductiveCycleInfo::getId).collect(Collectors.toList());
            // 2.2 当前所有的节点信息不包含当前需要找的节点
            if (!ids.contains(nodeId)) {
                // 3. 从数据库里面,根据父节点的id,找到父节点信息
                ReproductiveCycleInfo one = reproductiveCycleInfoMapper.selectReproductiveCycleInfoById(nodeId);
                // 4. 把当前节点放到所有节点里面
                list.add(one);
                // 5. 如果当前节点还存在父节点
                if (one.getParentId() != 0) {
                    // 6. 递归去找父节点信息
                    getNodeByParentId(one.getParentId(), list);
                }
            }
        }
    }
 
以找17节点为例子:
 
代码总览
从这里也可以看出我这里其实代码已经有逻辑耦合了。毕竟 node != 0 判断了两次了,这其实没必要。还可以优化一下。
    @Override
    public List<ReproductiveCycleInfo> selectReproductiveCycleInfoListByName(ReproductiveCycleInfoDto reproductiveCycleInfo) {
        List<ReproductiveCycleInfo> list = reproductiveCycleInfoMapper.selectReproductiveCycleInfoList(reproductiveCycleInfo);
        Set<Long> collect = list.stream().filter(x -> x.getParentId() != 0).map(ReproductiveCycleInfo::getParentId).collect(Collectors.toSet());
        if (StringUtils.isNotEmpty(collect)) {
            for (Long x : collect) {
                getNodeByParentId(x, list);
            }
        }
        return list;
    }
    /**
     * 根据节点id找出节点,并添加到结果集里面
     *
     * @param nodeId 当前需要找的节点id
     * @param list 返回的结果集
     */
    private void getNodeByParentId(Long nodeId, List<ReproductiveCycleInfo> list) {
        // 1. 如果当前需要找的节点
        if (nodeId != 0) {
            // 2. 为了避免父节点也已经出现在 所有的节点信息 里面
            // 2.1 找出当前所有的节点信息
            List<Long> ids = list.stream().map(ReproductiveCycleInfo::getId).collect(Collectors.toList());
            // 2.2 当前所有的节点信息不包含当前需要找的节点
            if (!ids.contains(nodeId)) {
                // 3. 从数据库里面,根据父节点的id,找到父节点信息
                ReproductiveCycleInfo one = reproductiveCycleInfoMapper.selectReproductiveCycleInfoById(nodeId);
                // 4. 把当前节点放到所有节点里面
                list.add(one);
                // 5. 如果当前节点还存在父节点
                if (one.getParentId() != 0) {
                    // 6. 递归去找父节点信息
                    getNodeByParentId(one.getParentId(), list);
                }
            }
        }
    }
 
数据库表结构
起码得满足有这些极端并约定 parentId = 0 是表示是首节点了.
 



















