VUE-ELEMENT-Tree-全加载树,后端排序

本文介绍了一种使用Java实现的企业组织结构树构建方法,通过整合公司、站点和设备信息,形成一个多层次的企业组织结构树。文章详细展示了如何利用递归算法设置节点之间的父子关系,并提供了前端展示树形结构的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


/**
 * 树类
 *
 */
@Data
public class TreeInfoVO extends BaseVO {
	/**节点ID*/
	private String id;
	/**父ID*/
	private String parentId;
	/**名称*/
	private String name;

	private List<TreeInfoVO> children;

}

//业务层
package com.jysoft.service;

import com.jysoft.dao.entity.Company;
import com.jysoft.dao.entity.Device;
import com.jysoft.dao.entity.Station;
import com.jysoft.dao.mapper.CompanyMapper;
import com.jysoft.dao.mapper.DeviceMapper;
import com.jysoft.dao.mapper.StationMapper;
import com.jysoft.dao.mapper.VoiceprintMapper;
import com.jysoft.entity.company.vo.CompanyVO;
import com.jysoft.entity.company.vo.TreeInfoVO;
import com.jysoft.resp.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class CompanyService {

    @Autowired
    CompanyMapper companyMapper;
    @Autowired
    StationMapper stationMapper;
    @Autowired
    DeviceMapper deviceMapper;
    @Autowired
    VoiceprintMapper voicePrintMapper;

    public ResponseResult<?> queryCompanyTreeMainInfo() {
        Device device = new Device();
        Station station = new Station();
        List<Company> companyList = companyMapper.queryAllCompany();
        List<Station> stationList = stationMapper.queryAllStations(station);
        List<Device> deviceList = deviceMapper.queryDevices(device);
        List<TreeInfoVO> treeInfoVOListFromComany = companyBuildEntity(companyList);
        List<TreeInfoVO> treeInfoVOListFromStation = stationBuildEntity(stationList);
        List<TreeInfoVO> treeInfoVOListFromDevice = deviceBuildEntity(deviceList);
        int lengthNumberOne = treeInfoVOListFromComany.size();
        for (int i = 0; i < treeInfoVOListFromStation.size(); i++) {
            treeInfoVOListFromComany.add(lengthNumberOne + i - 1, treeInfoVOListFromStation.get(i));
        }
        int lengthNumberTwo = treeInfoVOListFromComany.size();
        for (int i = 0; i < treeInfoVOListFromDevice.size(); i++) {
            treeInfoVOListFromComany.add(lengthNumberTwo + i - 1, treeInfoVOListFromDevice.get(i));
        }
        // 把所有的数据都放到map中
        Map<String, TreeInfoVO> treeMap = new HashMap<>();
        for (int i = 0; i < treeInfoVOListFromComany.size() && !treeInfoVOListFromComany.isEmpty(); i++) {
            // 元素的id为键,元素本身为值
            treeMap.put(treeInfoVOListFromComany.get(i).getId(), treeInfoVOListFromComany.get(i));
        }
        // 将所有顶层节点存入result中
        List<TreeInfoVO> result = new ArrayList<>();
        // 遍历map得到顶层节点或者游离节点
        for (TreeInfoVO treeInfoVO : treeInfoVOListFromComany) {
            if (!treeMap.containsKey(treeInfoVO.getParentId())) {
                result.add(treeInfoVO);
            }
        }
        setParentChildRelative(treeInfoVOListFromComany, treeMap);
        return ResponseResult.success(result);
    }

    private List<TreeInfoVO> companyBuildEntity(List<Company> companyList) {
        List<TreeInfoVO> treeInfoVOList = new ArrayList<>();
        companyList.forEach(company -> {
            TreeInfoVO treeInfoVO = new TreeInfoVO();
            treeInfoVO.setId(company.getId());
            treeInfoVO.setName(company.getName());
            treeInfoVO.setChildren(new ArrayList<>());
            treeInfoVO.setParentId(company.getParentId());
            treeInfoVOList.add(treeInfoVO);
        });
        return treeInfoVOList;

    }

    private List<TreeInfoVO> stationBuildEntity(List<Station> stationList) {
        List<TreeInfoVO> treeInfoVOList = new ArrayList<>();
        stationList.forEach(station -> {
            TreeInfoVO treeInfoVO = new TreeInfoVO();
            treeInfoVO.setId(station.getId());
            treeInfoVO.setName(station.getName());
            treeInfoVO.setChildren(new ArrayList<>());
            treeInfoVO.setParentId(station.getCompanyId());
            treeInfoVOList.add(treeInfoVO);
        });
        return treeInfoVOList;
    }

    private List<TreeInfoVO> deviceBuildEntity(List<Device> deviceList) {
        List<TreeInfoVO> treeInfoVOList = new ArrayList<>();
        deviceList.forEach(device -> {
            TreeInfoVO treeInfoVO = new TreeInfoVO();
            treeInfoVO.setId(device.getId());
            treeInfoVO.setName(device.getDeviceName());
            treeInfoVO.setChildren(new ArrayList<>());
            treeInfoVO.setParentId(device.getStationId());
            treeInfoVOList.add(treeInfoVO);
        });
        return treeInfoVOList;
    }


    public void setParentChildRelative(List<TreeInfoVO> list, Map<String, TreeInfoVO> treeMap) {
        for (int i = 0; i < list.size() && !list.isEmpty(); i++) {
            TreeInfoVO treeInfoVO = treeMap.get(list.get(i).getParentId());
            if (treeInfoVO != null) {
                if (treeInfoVO.getChildren() == null) {
                    treeInfoVO.setChildren(new ArrayList<>());
                }
                treeInfoVO.getChildren().add(list.get(i));
            }
        }
    }

}

思路:
将所有结果集先转换为TreeInfo类,再将集合合并为一个集合,并转换为Map类;并且循环集合,根据对象的parentId来设置父子关系

前端代码

  <el-tree
              ref="treeBox"
              :data="treeList"
              :props="defaultProps"
              accordion
              :default-expanded-keys="expandedKeys"
              node-key="id"
          >
          </el-tree>


  • treeBox ||this.$refs可以直接指向该标签
  • treeLisrt || 后端传过来的数据 注意是个集合 不能直接将树的根类传过来
  • defaultProps
    id: ‘id’, //标识每个结点
    label: ‘name’, //结点的文本展示
    children: ‘children’ //结点的子节点
<think>好的,用户想了解在Vue3和Element-Plus中使用状图组件的方法或示例。我需要先回顾一下Element-Plus的文档,确认形组件的基本用法和属性。记得用户提到了状图,可能是指形控件,即Tree组件。 首先,需要确保用户正确安装并引入了Element-Plus。根据引用[1]和[2],他们的项目是基于Vue3、Element Plus等技术栈的,所以应该已经配置好了环境。但可能需要指导用户如何单独引入ElTree组件。 接下来,基本用法部分,应该展示一个最简单的结构,使用data属性传入数据。数据格式通常是包含label和children的数组。同时,要说明如何通过props配置字段别名,比如使用label作为节点名称,children表示子节点。 然后,用户可能需要节点选择的功能。这里需要介绍show-checkbox属性,以及如何通过v-model绑定选中的节点。此外,事件处理也很重要,比如node-click事件,可以演示如何在点击节点时触发方法。 高级功能方面,比如懒加载Element-Plus的Tree组件支持load属性,可以动态加载子节点。需要提供一个示例函数,说明如何按需加载数据。另外,自定义节点内容可以通过插槽实现,使用#default插槽来定制显示内容,比如添加图标或按钮。 引用中的项目如vue3-element-admin和vue-element-plus-admin可能在实际使用中有更复杂的例子,可以参考他们的实现方式。例如,引用[3]提到的最佳实践可能包括形组件在后台管理系统中的应用,比如菜单管理或权限配置。这时候可能需要结合后端接口动态渲染结构,或者实现节点的增删改查。 另外,注意用户可能需要代码示例,所以需要提供Vue3的语法,比如使用<script setup>和组合式API。同时,确保代码中的ElTree组件正确引入,并展示数据绑定的方式。 最后,相关问题部分需要考虑用户可能遇到的进一步需求,比如如何与后端API对接、如何实现拖拽排序、如何展开特定节点等。这些问题可以帮助用户深入使用形组件。 总结步骤:安装引入组件、基本数据渲染、复选框和事件处理、懒加载、自定义内容、实际应用示例,以及相关问题的扩展。需要确保所有代码示例符合Vue3和Element-Plus的语法,并引用提供的参考资料,特别是在实际项目中的应用场景。</think>### Vue3 Element-Plus 状图组件使用教程 #### 一、环境准备 确保已正确安装 Element-Plus(Vue3 版本): ```bash npm install element-plus ``` 在入口文件局引入: ```javascript import { createApp } from 'vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' const app = createApp(App) app.use(ElementPlus) app.mount('#app') ``` #### 二、基础形结构 ```html <template> <el-tree :data="treeData" /> </template> <script setup> const treeData = [ { label: '一级节点', children: [ { label: '二级节点-1' }, { label: '二级节点-2' } ] } ] </script> ``` *通过 `data` 属性传递形数据,默认使用 `label` 显示节点名称,`children` 表示子节点[^2]* #### 三、核心功能实现 1. **节点选择与事件** ```html <el-tree :data="treeData" show-checkbox node-key="id" :props="defaultProps" @node-click="handleNodeClick" v-model:checked-keys="checkedKeys" /> <script setup> const defaultProps = { children: 'children', label: 'label' } const handleNodeClick = (nodeData) => { console.log('点击节点:', nodeData) } </script> ``` 2. **懒加载模式** ```html <el-tree :props="lazyProps" :load="loadNode" lazy /> <script setup> const lazyProps = { label: 'name', isLeaf: 'leaf' } const loadNode = (node, resolve) => { if (node.level === 0) { return resolve([{ name: '根节点' }]) } // 模拟异步加载 setTimeout(() => { resolve([{ name: '动态子节点', leaf: true }]) }, 500) } </script> ``` #### 四、高级功能示例 1. **自定义节点内容** ```html <el-tree :data="treeData"> <template #default="{ node }"> <span class="custom-node"> <el-icon><document /></el-icon> {{ node.label }} <el-button size="mini" @click="appendNode(node)">+</el-button> </span> </template> </el-tree> ``` 2. **完整功能示例** ```html <template> <el-tree ref="treeRef" :data="data" show-checkbox default-expand-all :expand-on-click-node="false" > <template #default="{ node, data }"> <span>{{ node.label }}</span> <el-button-group> <el-button size="small" @click="append(data)">添加</el-button> <el-button size="small" @click="remove(node, data)">删除</el-button> </el-button-group> </template> </el-tree> </template> <script setup> import { ref } from 'vue' const treeRef = ref() const data = ref([...]) // 形数据结构 const append = (data) => { if (!data.children) data.children = [] data.children.push({ label: '新节点' }) } const remove = (node, data) => { const parent = node.parent const children = parent.data.children || parent.data const index = children.findIndex(d => d === data) children.splice(index, 1) } </script> ``` #### 五、实际应用场景 在后台管理系统中,状图常用于: 1. 权限管理系统中的多级权限分配 2. 组织架构展示(部门-子部门结构) 3. 文件目录管理系统 4. 分类多级选择器(如商品分类)[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值