【202】Java8从数据库表中读取树形结构示例

数据库准备工作

数据库表结构如下:

CREATE TABLE `t_menu` (`c_id` varchar(80) NOT NULL COMMENT '主键',`c_name` varchar(15) NOT NULL COMMENT '菜单名称',`c_parent_id` varchar(80) NOT NULL COMMENT '父级菜单id',`c_icon` text COMMENT '图标',`c_type` tinyint(1) NOT NULL COMMENT '类型,字段menu_type',`c_create_id` varchar(80) NOT NULL COMMENT '创建者ID',`c_create_time` timestamp NOT NULL COMMENT '创建时间',`c_update_id` varchar(80) NOT NULL COMMENT '更新者ID',`c_update_time` timestamp NOT NULL COMMENT '更新时间',`c_no` int(10) DEFAULT NULL COMMENT '顺序',`c_del_flag` tinyint(1) NOT NULL COMMENT '是否删除',PRIMARY KEY (`c_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜单'

插入数据:


INSERT INTO `t_menu` (`c_id`, `c_name`,`c_parent_id`, `c_icon`,`c_type`, `c_create_id`, `c_create_time`,`c_update_id`, `c_update_time`, `c_no`, `c_del_flag`
) 
VALUES('0_0_01ec9a90f6b34439bb979e4fad37852b','百叶箱数据','0_0_61379d8d12b3456797188a9044d14f3c',NULL, 2,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 22:43:30','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 22:43:30', 1,0),('0_0_090d3da1301841f6b43e3a3ff2b44f68', '删除','0_0_c982f477026541848405484f08ff1dfa', NULL, 2,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-20 11:04:09','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-20 11:07:34', 3, 0),('0_0_0ab19e321a5f490e9015f6e4cd496d27','分配菜单','0_0_e7b9049e8ad34a78af90286b63f4759c', NULL, 3,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 10:08:44','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 10:08:44',4, 0),('0_0_3983284d54104f359b8406a50fa45632','4444','0_0_f887ea1dc38341559285926c54123516', NULL, 3,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-22 11:00:16','0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-22 11:00:16', 1, 0),('0_0_3de80520f6f74b2386b8381a564c4e09', '删除','0_0_99cad34fd9814ff4a8c88e72d60a552d', NULL, 3,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:54:43','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:54:43', 3, 0),('0_0_545fb128881f462f8bc828b54e19e034','删除', '0_0_da9e85f955f44e16bfa8a20659de30d7', NULL, 3,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:38:27','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:38:27', 3, 0),('0_0_61379d8d12b3456797188a9044d14f3c', '智慧农业', '-1', NULL, 1,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 21:31:47', '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:31:47', 2, 0),('0_0_634317d8797e4aacb467e348a1ac8924','添加','0_0_c982f477026541848405484f08ff1dfa', NULL, 2,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-20 11:03:33','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-20 11:06:46', 1,0),('0_0_661824d0f33441aba8236d5be366434f','系统管理','-1', NULL, 1,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:02:49','0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:02:49',1,0),('0_0_6a71439c4de84eb19f99648df760c9c0','修改','0_0_e7b9049e8ad34a78af90286b63f4759c',NULL,3,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 10:08:21','0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 10:08:21',2,0),('0_0_729b70ba39144dbb930547d39e4700b0', '添加','0_0_e7b9049e8ad34a78af90286b63f4759c', NULL, 3,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 10:08:13','0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 10:08:13',1, 0),('0_0_843138ca616b466b8904c53c31b1bd2e','添加','0_0_da9e85f955f44e16bfa8a20659de30d7',NULL,3,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:38:10','0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:38:10',1,0),('0_0_99cad34fd9814ff4a8c88e72d60a552d', '用户管理','0_0_661824d0f33441aba8236d5be366434f', NULL, 2,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:04:43','0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:04:43', 1,0),('0_0_a3486bd0026f47c298b5d2d55db6f733', '重置密码','0_0_99cad34fd9814ff4a8c88e72d60a552d', NULL, 3,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:54:58','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:54:58', 4, 0),('0_0_a695d1d7a5c243379ceae6560855496e', '删除','0_0_e7b9049e8ad34a78af90286b63f4759c', NULL, 3,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 10:08:28','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 10:08:28',3, 0),('0_0_a88b254640f94f3c9afab62ef10dbedb', '分配角色','0_0_99cad34fd9814ff4a8c88e72d60a552d',  NULL, 3,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:55:20','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:55:20', 5, 0),('0_0_acf36bbee31541ad874af0b78de92ff5', '删除','0_0_01ec9a90f6b34439bb979e4fad37852b', NULL, 3,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:35:33','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:35:33', 1,0),('0_0_bf244c78e686400db9808cd5fb0c3c91','修改','0_0_c982f477026541848405484f08ff1dfa', NULL,2,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-20 11:04:02','0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-20 11:07:19', 2,0),('0_0_c8085841164547a5834d51eb7d3f566f','修改','0_0_99cad34fd9814ff4a8c88e72d60a552d', NULL,3,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:54:34','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:54:34',2,0),('0_0_c982f477026541848405484f08ff1dfa','接口权限','0_0_661824d0f33441aba8236d5be366434f', NULL, 2,'0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:16:20','0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-20 10:58:32', 4,0),('0_0_d00f45f79a1941ad9adc0567352e6670', '修改','0_0_da9e85f955f44e16bfa8a20659de30d7', NULL, 3,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:38:18','0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:38:18', 2, 0),('0_0_da9e85f955f44e16bfa8a20659de30d7', '菜单管理','0_0_661824d0f33441aba8236d5be366434f', NULL, 2,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 21:05:38','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 21:05:38', 2, 0),('0_0_e7b9049e8ad34a78af90286b63f4759c', '角色管理','0_0_661824d0f33441aba8236d5be366434f', NULL, 2,'0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 21:04:57','0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 21:04:57', 3, 0),('0_0_f887ea1dc38341559285926c54123516', '添加','0_0_99cad34fd9814ff4a8c88e72d60a552d', NULL, 3, '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:54:26', '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:54:26', 1, 0) ;

代码实现

Menu实体类,每个属性对应数据库的字段:


import java.sql.Timestamp;public class Menu {
private String id;     // 主键private String name;   // 菜单名称private String parentId;      // 父级菜单idprivate String icon;          // 图标private Integer type;         // 类型 1=目录,2=菜单,3=按钮private String createId;      // 创建者IDprivate Timestamp createTime; // 创建时间private String updateId;      // 更新者IDprivate Timestamp updateTime; // 更新时间private Integer no;           // 顺序private Integer delFlag;      // 是否删除// getter/setters 忽略
}

Menu的DTO类,用来保存树形结构:

private String id;     // 主键private List<String> ids;private String name;   // 菜单名称private String parentId;      // 父级菜单idprivate List<String> parentIds;private String icon;          // 图标private Integer code;         // 菜单编码private Integer type;         // 类型 字典menu_typeprivate String createId;      // 创建者IDprivate Timestamp createTime; // 创建时间private String updateId;      // 更新者IDprivate Timestamp updateTime; // 更新时间private Integer no;           // 顺序private Integer delFlag;      // 是否删除private List<MenuDto> children = new ArrayList<>();private String orderBy;private String asc;
// getter/setters 忽略

mybatis的MenuMapper接口:

package zhangchao.readdbtree;import java.util.List;
import org.apache.ibatis.annotations.Param;public interface MenuMapper {Menu selectById(@Param("id") String id);List<Menu> selectList(MenuDto menuDto);
}

MenuMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="zhangchao.readdbtree.MenuMapper"><resultMap id="rm" type="zhangchao.readdbtree.Menu"><id property="id" column="c_id"/><result property="name" column="c_name"/><result property="parentId" column="c_parent_id"/><result property="icon" column="c_icon"/><result property="type" column="c_type"/><result property="createId" column="c_create_id"/><result property="createTime" column="c_create_time"/><result property="updateId" column="c_update_id"/><result property="updateTime" column="c_update_time"/><result property="no" column="c_no"/><result property="delFlag" column="c_del_flag"/></resultMap><select id="selectById" resultMap="rm">select * from t_menu where c_id=#{id}</select><select id="selectList" resultMap="rm">select * from t_menu where 1=1<if test="name != null">and c_name like concat('%', #{name}, '%')</if><if test="parentId != null">and c_parent_id = #{parentId}</if><if test="parentIds != null and parentIds.size() > 0">and c_parent_id in<foreach collection="parentIds" open="(" close=")" separator="," item="item">#{item}</foreach></if><if test="type != null">and c_type = #{type}</if><if test="delFlag != null">and c_del_flag = #{delFlag}</if><if test="ids != null and ids.size() > 0">and c_id in<foreach collection="ids" open="(" close=")" separator="," item="item">#{item}</foreach></if><if test="orderBy != null and asc != null">order by ${orderBy} ${asc}</if></select>
</mapper>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><mappers><mapper resource="mapper/CityMapper.xml"/><mapper resource="mapper/MenuMapper.xml"/>
<!--        <mapper resource="mapper/LogMapper.xml"/>--></mappers>
</configuration>

加载mybatis的类DBFactory

package zhangchao.common.db;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;public class DBFactory {private static SqlSessionFactory sqlSessionFactory = null;static {String resource = "mybatis-config.xml";InputStream inputStream = null;try {inputStream = Resources.getResourceAsStream(resource);} catch (IOException e) {e.printStackTrace();}sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}public static SqlSessionFactory getInstance(){return sqlSessionFactory;}}

整个算法的核心类MenuService,该类包含了三个算法:

  1. 查找整棵树的树形结构
  2. 根据若干ID查找对应的树节点,并按照树形结构返回结果。
  3. 传入某个节点的ID,把以该节点为根的子树都查找出来

具体代码如下:

package zhangchao.readdbtree;import org.apache.ibatis.session.SqlSession;
import zhangchao.common.db.DBFactory;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author zhangchao*/
public class MenuService {private void menuToDto(Menu menu, MenuDto menuDto) {menuDto.setId(menu.getId());menuDto.setName(menu.getName());menuDto.setParentId(menu.getParentId());menuDto.setIcon(menu.getIcon());menuDto.setType(menu.getType());menuDto.setNo(menu.getNo());}/*** 查找整棵树的树形结构* @return 整棵树的树形结构*/public List<MenuDto> allMenuTree() {List<MenuDto> result = new ArrayList<>();MenuDto sqlParam = new MenuDto();sqlParam.setParentId("-1");sqlParam.setDelFlag(0);sqlParam.setOrderBy("c_no");sqlParam.setAsc("asc");SqlSession sqlSession = DBFactory.getInstance().openSession(true);MenuMapper menuMapper = sqlSession.getMapper(MenuMapper.class);try {// 先把顶层加入resultList<Menu> menuList_1 = menuMapper.selectList(sqlParam);for (Menu menu_1 : menuList_1) {MenuDto menuDto_1 = new MenuDto();this.menuToDto(menu_1, menuDto_1);result.add(menuDto_1);}List<MenuDto> currentLevel = result;while (currentLevel != null && !currentLevel.isEmpty()) {List<String> parentIds = new ArrayList<>();Map<String, MenuDto> map = new HashMap<>();for (MenuDto dto : currentLevel) {String id = dto.getId();parentIds.add(id);map.put(id, dto);if (dto.getChildren() == null) {dto.setChildren(new ArrayList<>());}}sqlParam.setParentId(null);sqlParam.setParentIds(parentIds);List<Menu> dbNextLevel = menuMapper.selectList(sqlParam);List<MenuDto> nextLevel = new ArrayList<>();if (dbNextLevel != null && !dbNextLevel.isEmpty()) {for (Menu menu : dbNextLevel) {MenuDto menuDto = new MenuDto();this.menuToDto(menu, menuDto);map.get(menu.getParentId()).getChildren().add(menuDto);nextLevel.add(menuDto);}}currentLevel = nextLevel;}} finally {sqlSession.close();}return result;}/*** 根据若干ID查找对应的树节点,并按照树形结构返回结果。* @param ids 树节点ID列表* @return 树形结构*/public List<MenuDto> selectMenuTreeByIds(List<String> ids) {List<MenuDto> result = new ArrayList<>();MenuDto sqlParam = new MenuDto();sqlParam.setIds(ids);sqlParam.setParentId("-1");sqlParam.setDelFlag(0);sqlParam.setOrderBy("c_no");sqlParam.setAsc("asc");SqlSession sqlSession = DBFactory.getInstance().openSession(true);MenuMapper menuMapper = sqlSession.getMapper(MenuMapper.class);try {// 先把顶层加入resultList<Menu> menuList_1 = menuMapper.selectList(sqlParam);for (Menu menu_1 : menuList_1) {MenuDto menuDto_1 = new MenuDto();this.menuToDto(menu_1, menuDto_1);result.add(menuDto_1);}List<MenuDto> curentLevel = result;while (curentLevel != null && !curentLevel.isEmpty()) {List<String> parentIds = new ArrayList<>();Map<String, MenuDto> map = new HashMap<>();// 这个for循环是为了给 parentIds 和 map 添加元素。for (MenuDto dto : curentLevel) {String id = dto.getId();parentIds.add(id);map.put(id, dto);if (dto.getChildren() == null) {dto.setChildren(new ArrayList<>());}}// 设置查询下一级节点的参数。sqlParam.setParentId(null);sqlParam.setParentIds(parentIds);// 从数据库中查询下一级节点。List<Menu> dbNextLevel = menuMapper.selectList(sqlParam);// 下一级节点的dto列表。List<MenuDto> nextLevel = new ArrayList<>();if (dbNextLevel != null && !dbNextLevel.isEmpty()) {for (Menu menu : dbNextLevel) {MenuDto menuDto = new MenuDto();this.menuToDto(menu, menuDto);map.get(menu.getParentId()).getChildren().add(menuDto);nextLevel.add(menuDto);}}curentLevel = nextLevel;}} finally {sqlSession.close();}return result;}/*** 传入某个节点的ID,把以该节点为根的子树都查找出来* @param subRootId 节点ID* @return 以传入节点为根的子树*/public List<MenuDto> subTree(String subRootId) {List<MenuDto> result = new ArrayList<>();SqlSession sqlSession = DBFactory.getInstance().openSession(true);MenuMapper menuMapper = sqlSession.getMapper(MenuMapper.class);try {Menu root = menuMapper.selectById(subRootId);// 先把顶层加入resultList<Menu> menuList_1 = new ArrayList<>();if (root != null && root.getDelFlag() == 0) {menuList_1.add(root);}for (Menu menu_1 : menuList_1) {MenuDto menuDto_1 = new MenuDto();this.menuToDto(menu_1, menuDto_1);result.add(menuDto_1);}MenuDto sqlParam = new MenuDto();sqlParam.setDelFlag(0);sqlParam.setOrderBy("c_no");sqlParam.setAsc("asc");List<MenuDto> curentLevel = result;while (curentLevel != null && !curentLevel.isEmpty()) {List<String> parentIds = new ArrayList<>();Map<String, MenuDto> map = new HashMap<>();// 这个for循环是为了给 parentIds 和 map 添加元素。for (MenuDto dto : curentLevel) {String id = dto.getId();parentIds.add(id);map.put(id, dto);if (dto.getChildren() == null) {dto.setChildren(new ArrayList<>());}}// 设置查询下一级节点的参数。sqlParam.setParentId(null);sqlParam.setParentIds(parentIds);// 从数据库中查询下一级节点。List<Menu> dbNextLevel = menuMapper.selectList(sqlParam);// 下一级节点的dto列表。List<MenuDto> nextLevel = new ArrayList<>();if (dbNextLevel != null && !dbNextLevel.isEmpty()) {for (Menu menu : dbNextLevel) {MenuDto menuDto = new MenuDto();this.menuToDto(menu, menuDto);map.get(menu.getParentId()).getChildren().add(menuDto);nextLevel.add(menuDto);}}curentLevel = nextLevel;}} finally {sqlSession.close();}return result;}
}

调用类TestReadDbTree:

package zhangchao.readdbtree;import com.google.gson.Gson;import java.util.ArrayList;
import java.util.List;public class TestReadDbTree {public static void main(String[] args) {MenuService menuService = new MenuService();List<MenuDto> allTree = menuService.allMenuTree();Gson gson = new Gson();// 整棵树System.out.println(gson.toJson(allTree));// 选中的部分树节点List<String> ids = new ArrayList<>();ids.add("0_0_661824d0f33441aba8236d5be366434f");ids.add("0_0_99cad34fd9814ff4a8c88e72d60a552d");ids.add("0_0_61379d8d12b3456797188a9044d14f3c");ids.add("0_0_01ec9a90f6b34439bb979e4fad37852b");ids.add("0_0_acf36bbee31541ad874af0b78de92ff5");List<MenuDto> selectedTree = menuService.selectMenuTreeByIds(ids);System.out.println(gson.toJson(selectedTree));// 传入某个节点的ID,把以该节点为根的子树都查找出来List<MenuDto> subTree = menuService.subTree("0_0_99cad34fd9814ff4a8c88e72d60a552d");System.out.println(gson.toJson(subTree));}
}

输出结果

整棵树形结构:

[{"id": "0_0_661824d0f33441aba8236d5be366434f","name": "系统管理","parentId": "-1","type": 1,"no": 1,"children": [{"id": "0_0_99cad34fd9814ff4a8c88e72d60a552d","name": "用户管理","parentId": "0_0_661824d0f33441aba8236d5be366434f","type": 2,"no": 1,"children": [{"id": "0_0_f887ea1dc38341559285926c54123516","name": "添加","parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d","type": 3,"no": 1,"children": []},{"id": "0_0_c8085841164547a5834d51eb7d3f566f","name": "修改","parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d","type": 3,"no": 2,"children": []},{"id": "0_0_3de80520f6f74b2386b8381a564c4e09","name": "删除","parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d","type": 3,"no": 3,"children": []},{"id": "0_0_a3486bd0026f47c298b5d2d55db6f733","name": "重置密码","parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d","type": 3,"no": 4,"children": []},{"id": "0_0_a88b254640f94f3c9afab62ef10dbedb","name": "分配角色","parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d","type": 3,"no": 5,"children": []}]},{"id": "0_0_da9e85f955f44e16bfa8a20659de30d7","name": "菜单管理","parentId": "0_0_661824d0f33441aba8236d5be366434f","type": 2,"no": 2,"children": [{"id": "0_0_843138ca616b466b8904c53c31b1bd2e","name": "添加","parentId": "0_0_da9e85f955f44e16bfa8a20659de30d7","type": 3,"no": 1,"children": []},{"id": "0_0_d00f45f79a1941ad9adc0567352e6670","name": "修改","parentId": "0_0_da9e85f955f44e16bfa8a20659de30d7","type": 3,"no": 2,"children": []},{"id": "0_0_545fb128881f462f8bc828b54e19e034","name": "删除","parentId": "0_0_da9e85f955f44e16bfa8a20659de30d7","type": 3,"no": 3,"children": []}]},{"id": "0_0_e7b9049e8ad34a78af90286b63f4759c","name": "角色管理","parentId": "0_0_661824d0f33441aba8236d5be366434f","type": 2,"no": 3,"children": [{"id": "0_0_729b70ba39144dbb930547d39e4700b0","name": "添加","parentId": "0_0_e7b9049e8ad34a78af90286b63f4759c","type": 3,"no": 1,"children": []},{"id": "0_0_6a71439c4de84eb19f99648df760c9c0","name": "修改","parentId": "0_0_e7b9049e8ad34a78af90286b63f4759c","type": 3,"no": 2,"children": []},{"id": "0_0_a695d1d7a5c243379ceae6560855496e","name": "删除","parentId": "0_0_e7b9049e8ad34a78af90286b63f4759c","type": 3,"no": 3,"children": []},{"id": "0_0_0ab19e321a5f490e9015f6e4cd496d27","name": "分配菜单","parentId": "0_0_e7b9049e8ad34a78af90286b63f4759c","type": 3,"no": 4,"children": []}]},{"id": "0_0_c982f477026541848405484f08ff1dfa","name": "接口权限","parentId": "0_0_661824d0f33441aba8236d5be366434f","type": 2,"no": 4,"children": [{"id": "0_0_634317d8797e4aacb467e348a1ac8924","name": "添加","parentId": "0_0_c982f477026541848405484f08ff1dfa","type": 2,"no": 1,"children": []},{"id": "0_0_bf244c78e686400db9808cd5fb0c3c91","name": "修改","parentId": "0_0_c982f477026541848405484f08ff1dfa","type": 2,"no": 2,"children": []},{"id": "0_0_090d3da1301841f6b43e3a3ff2b44f68","name": "删除","parentId": "0_0_c982f477026541848405484f08ff1dfa","type": 2,"no": 3,"children": []}]}]},{"id": "0_0_61379d8d12b3456797188a9044d14f3c","name": "智慧农业","parentId": "-1","type": 1,"no": 2,"children": [{"id": "0_0_01ec9a90f6b34439bb979e4fad37852b","name": "百叶箱数据","parentId": "0_0_61379d8d12b3456797188a9044d14f3c","type": 2,"no": 1,"children": [{"id": "0_0_acf36bbee31541ad874af0b78de92ff5","name": "删除","parentId": "0_0_01ec9a90f6b34439bb979e4fad37852b","type": 3,"no": 1,"children": []}]}]}
]

选中的节点

[{"id": "0_0_661824d0f33441aba8236d5be366434f","name": "系统管理","parentId": "-1","type": 1,"no": 1,"children": [{"id": "0_0_99cad34fd9814ff4a8c88e72d60a552d","name": "用户管理","parentId": "0_0_661824d0f33441aba8236d5be366434f","type": 2,"no": 1,"children": []}]},{"id": "0_0_61379d8d12b3456797188a9044d14f3c","name": "智慧农业","parentId": "-1","type": 1,"no": 2,"children": [{"id": "0_0_01ec9a90f6b34439bb979e4fad37852b","name": "百叶箱数据","parentId": "0_0_61379d8d12b3456797188a9044d14f3c","type": 2,"no": 1,"children": [{"id": "0_0_acf36bbee31541ad874af0b78de92ff5","name": "删除","parentId": "0_0_01ec9a90f6b34439bb979e4fad37852b","type": 3,"no": 1,"children": []}]}]}
]

某棵子树

[{"id": "0_0_99cad34fd9814ff4a8c88e72d60a552d","name": "用户管理","parentId": "0_0_661824d0f33441aba8236d5be366434f","type": 2,"no": 1,"children": [{"id": "0_0_f887ea1dc38341559285926c54123516","name": "添加","parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d","type": 3,"no": 1,"children": [{"id": "0_0_3983284d54104f359b8406a50fa45632","name": "4444","parentId": "0_0_f887ea1dc38341559285926c54123516","type": 3,"no": 1,"children": []}]},{"id": "0_0_c8085841164547a5834d51eb7d3f566f","name": "修改","parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d","type": 3,"no": 2,"children": []},{"id": "0_0_3de80520f6f74b2386b8381a564c4e09","name": "删除","parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d","type": 3,"no": 3,"children": []},{"id": "0_0_a3486bd0026f47c298b5d2d55db6f733","name": "重置密码","parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d","type": 3,"no": 4,"children": []},{"id": "0_0_a88b254640f94f3c9afab62ef10dbedb","name": "分配角色","parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d","type": 3,"no": 5,"children": []}]}
]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/825325.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot实现信息化在线教学平台设计【项目源码+论文说明】计算机毕业设计

基于springboot实现信息化在线教学平台设计演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了信息化在线教学平台的开发全过程。通过分析信息化在线教学平台管理的不足&#xff0c;创建了一个计算机管理信息…

【OpenGL开发】PyQt在关闭应用程序时没有运行析构函数的问题

PyQt在关闭应用程序时没有运行析构函数的问题 目录 一、说明二、python的析构函数三、通用版QT5 存在一些问题四、python版PyQt5 存在一些问题五、OpenGL的析构问题5.1 OpenGL很脆弱,这不是危言耸听5.2 以上OpenGL问题解决方法六、一些保留意见一、说明 应用QT做程序界面,在…

电视盒子哪个牌子好?博主总结网络电视盒子推荐

电视盒子是我们使用最多的产品&#xff0c;追剧、游戏、上网课都离不开电视盒子&#xff0c;但很多朋友不知道电视盒子哪个牌子好&#xff0c;我这周共计测评了18款不同品牌的电视盒子&#xff0c;今天整理了五款网络电视盒子推荐&#xff0c;想买电视盒子可以看看下面这些。 第…

vscode 配置go环境

https://www.zhihu.com/question/486786946/answer/2723663432 注意一定要安装最新版,否则不容易debug //main.go package main //说明hello.go这个文件在main这个包中import "fmt" //导入内置包&#xff0c;可以使用其中函数等func main() {fmt.Println("Hello…

java 红黑树

01.红黑树的定义&#xff1a; 每一个结点有五个属性&#xff1a;

Computer Organization/Architecture 计算机组织/架构/结构 重要观念和笔记(陆续更新中,2024/04/17周三,已更新)

前情提要&#xff1a;我的说法比较白话&#xff0c;希望可以更好理解其中一些观念&#xff0c;这篇会以中文为主&#xff0c;专有名词还是用英文&#xff0c;好吧应该会中英穿插&#xff0c;自己学的时候感觉听中文会吸收比较快&#xff0c;也可能是我英文比较烂的关系&#xf…

Eagle for Mac v1.9.13注册版:强大的图片管理工具

Eagle for Mac是一款专为Mac用户设计的图片管理工具&#xff0c;旨在帮助用户更高效、有序地管理和查找图片资源。 Eagle for Mac v1.9.13注册版下载 Eagle支持多种图片格式&#xff0c;包括JPG、PNG、GIF、SVG、PSD、AI等&#xff0c;无论是矢量图还是位图&#xff0c;都能以清…

Solaris安装Oracle RAC配置手册

一. Oracle RAC安装前的系统准备工作 检查安装包 ​pkginfo –i SUNWarc SUNWbtool SUNWhea SUNWlibC SUNWlibm SUNWlibms SUNWsprotSUNWtoo pkg install SUNWarc SUNWbtool SUNWhea SUNWlibC SUNWlibm SUNWlibms SUNWsprotSUNWtoo 1.1 创建系统用户和组(两节点都要执行 ro…

通付盾APP尽职调查报告:守护移动应用安全新篇章

在数字化浪潮席卷全球的今天&#xff0c;移动应用程序已经成为我们生活中不可或缺的一部分。无论是购物、社交、娱乐还是工作&#xff0c;我们几乎每天都在与各种各样的APP打交道。然而&#xff0c;随着APP的广泛应用&#xff0c;其安全问题也日益凸显&#xff0c;成为开发者和…

BEV| lift-splat-shoot 运行配置

Lift, splat, shoot: Encoding images from arbitrary camera rigs by implicitly unprojecting to 3d

基于imx6ull的LCD驱动移植

移植思路&#xff1a; LCD除了显示之外&#xff0c;它的表面通常还贴有一个触摸屏。 所以我们移植的是2个设备的驱动&#xff1a;LCD、触摸屏。 LCD驱动在内核中已经有了&#xff0c;并且很完善&#xff0c;我们只需要修改设备树就可以&#xff1a;修改时序等LCD参数&#x…

GPT国内怎么用

2022年11月&#xff0c;OpenAI发布了ChatGPT&#xff0c;这标志着大型语言模型在自然语言处理领域迈出了巨大的一步。ChatGPT不仅在生成文本方面表现出了惊人的流畅度和连贯性&#xff0c;更为人工智能应用开启了全新的可能性。 ChatGPT的推出促进了人工智能技术在多个领域的广…

No spring.config.import property has been defined

运行Springcloud项目出现下面错误&#xff1a; Description: No spring.config.import property has been defined Action: Add a spring.config.importnacos: property to your configuration. If configuration is not required add spring.config.importoptional:nac…

mac电脑mysql下载与安装

mysql下载地址 历史下载地址 MySQL :: Download MySQL Community Server (Archived Versions) mac 版下载 mac版本分为 Intel 处理器 和 M系列处理器。 从 8.0.26开始&#xff0c; mysql 支持M系列处理器。 以前的都只有Intel 处理器的。 Intel 处理器选择 x86_64 M 系列处理…

内置管线升级到SBP,如何复用之前打包的AssetBundle

1&#xff09;内置管线升级到SBP&#xff0c;如何复用之前打包的AssetBundle 2&#xff09;安卓真机&#xff0c;在Unity 2021.3.31版本下Buffer数据异常 3&#xff09;URP里CullResults.CreateSharedRendererScene下面的消耗 4&#xff09;移动端是否支持曲面细分着色 这是第3…

Seaborn:推荐一个好用的Python可视化工具

1. 引言 Seaborn 是建立在 matplotlib 基础上的数据可视化库&#xff0c;并与 Python 中的 pandas 数据结构紧密结合。可视化是 Seaborn 的核心部分&#xff0c;有助于直观的理解数据。 闲话少说&#xff0c;我们直接开始吧&#xff01; 2. 安装 Seaborn库主要提供以下功能…

羊大师解析,夏天羊奶有什么搭配,可以解暑吗?

羊大师解析&#xff0c;夏天羊奶有什么搭配,可以解暑吗&#xff1f; 羊大师发现夏天羊奶的搭配方式多样&#xff0c;不仅可以提供丰富的营养&#xff0c;还有助于解暑。以下是一些推荐的搭配方式&#xff1a; 羊奶蜂蜜&#xff1a;蜂蜜的清甜口感可以改善羊奶的膻味&#xff…

学习笔记<2024.4.15-2024.4.21>:Attention Is All You Need

Transformer中Self-Attention以及Multi-Head Attention详解 (https://www.bilibili.com/video/BV15v411W78M/?spm_id_from333.337.search-card.all.click&vd_sourcef32decb03075b4a1833fe5c47c11ba94)

网络变压器(网络隔离变压器)是如何影响网通设备的传输速率的呢?

Hqst华轩盛(石门盈盛)电子导读&#xff1a;今天介绍网络变压器&#xff08;网络隔离变压器/网络滤波器&#xff09;是如何影响网通设备的传输速率的 一、网络变压器&#xff08;网络隔离变压器/网络滤波器&#xff09;的工作原理 网络变压器&#xff08;网络隔离变压器/网络滤…

【网络运维知识】—路由器与交换机区别

【网络运维知识】—路由器与交换机区别 一、路由器&#xff08;Router&#xff09;和交换机&#xff08;Switch&#xff09;对比1.1 功能1.2 转发方式1.3 范围1.4 处理方式 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 路由器&#xff08…