Java后端 || ElementUI 显示后端树形表格数据

文章目录

  • 1、前端源码
  • 2、数据库设计
  • 3、后端设计
    • 3.1、实体类
    • 3.2、Controller层
    • 3.3、具体树形列表后端代码实现

1、前端源码

ElementUI Table 链接

在此链接中找到 树形数据与懒加载

在这里插入图片描述
查看其JS源码,可知,每个菜单节点的子节点存放于children字段中,

const tableData: User[] = [
  {
    id: 1,
    date: '2016-05-02',
    name: 'wangxiaohu',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    id: 2,
    date: '2016-05-04',
    name: 'wangxiaohu',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    id: 3,
    date: '2016-05-01',
    name: 'wangxiaohu',
    address: 'No. 189, Grove St, Los Angeles',
    children: [
      {
        id: 31,
        date: '2016-05-01',
        name: 'wangxiaohu',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        id: 32,
        date: '2016-05-01',
        name: 'wangxiaohu',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ],
  },
  {
    id: 4,
    date: '2016-05-03',
    name: 'wangxiaohu',
    address: 'No. 189, Grove St, Los Angeles',
  },
]

将示例代码复制到项目中,此处根据源码做了符合自己项目的修改,主要复制el-table中的内容

<el-table
        :data="list"
        style="width: 100%; margin-bottom: 20px"
        row-key="id"
        border
        default-expand-all
    >
    <el-table-column prop="title" label="菜单标题" />
    <el-table-column prop="component" label="路由名称" />
    <el-table-column prop="sortValue" label="排序" />
    <el-table-column prop="status" label="状态" #default="scope">
      {{ scope.row.status == 1 ? '正常' : '停用' }}
    </el-table-column>
    <el-table-column prop="createTime" label="创建时间" />

    <el-table-column label="操作" align="center" width="280" #default="scope" >
        <el-button type="success" size="small" @click="addShow(scope.row)">
            添加下级节点
        </el-button>
        <el-button type="primary" size="small" @click="editShow(scope.row)">
            修改
        </el-button>
        <el-button type="danger" size="small" @click="remove(scope.row.id)">
            删除
        </el-button>
    </el-table-column>
  </el-table>

<script setup>
import { ref , onMounted } from "vue"

// 定义表格数据模型
const list = ref([])
//页面表单数据
const defaultForm = {
    id: '',
    parentId: 0,
    title: '',
    url: '',
    component: '',
    icon: '',
    sortValue: 1,
    status: 1,
}

// 钩子函数
onMounted(() => {
    fetchData()
})

const fetchData = async () => {
    const { code, data, message } = await FindNodes()
    list.value = data
}
</script>

前端js配置文件

import request from '@/utils/request'
const api_name = '/admin/system/sysMenu'

export const FindNodes = () => {
    return request({
        url: `${api_name}/findNodes`,
        method: 'get',
    })
}

2、数据库设计

每个菜单有自己的id,还有其父节点的parent_id(用于表示父子关系,双亲表示法)
在这里插入图片描述
给出SQL DDL 注:基于MySQL 8.0.30

CREATE TABLE `sys_menu` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
  `parent_id` bigint NOT NULL DEFAULT '0' COMMENT '所属上级',
  `title` varchar(20) NOT NULL DEFAULT '' COMMENT '菜单标题',
  `component` varchar(100) DEFAULT NULL COMMENT '组件名称',
  `sort_value` int NOT NULL DEFAULT '1' COMMENT '排序',
  `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态(0:禁止,1:正常)',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `is_deleted` tinyint NOT NULL DEFAULT '0' COMMENT '删除标记(0:不可用 1:可用)',
  PRIMARY KEY (`id`),
  KEY `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='菜单表'

3、后端设计

3.1、实体类

这边先把公共的属性抽取出来 组成BaseEntity类,然后将菜单的属性定义在SysMenu类,并继承BaseEntity

// BaseEntity 类

@Data
public class BaseEntity implements Serializable {

    @Schema(description = "唯一标识")
    private Long id;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "创建时间")
    private Date createTime;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "修改时间")
    private Date updateTime;

    @Schema(description = "是否删除")
    private Integer isDeleted;

}
// SysMenu 类

@Data
public class SysMenu extends BaseEntity {

	@Schema(description = "父节点id")
	private Long parentId;

	@Schema(description = "节点标题")
	private String title;

	@Schema(description = "组件名称")
	private String component;

	@Schema(description = "排序值")
	private Integer sortValue;

	@Schema(description = "状态(0:禁止,1:正常)")
	private Integer status;

	// 下级列表
	@Schema(description = "子节点")
	private List<SysMenu> children;

}

3.2、Controller层

常规调用,注意"/findNodes"路径与前端js文件中保持一致

// 显示菜单列表方法
@GetMapping("/findNodes")
public Result findNodes(){
    List<SysMenu> sysMenuList = sysMenuService.findNodes();
    return Result.build(sysMenuList, ResultCodeEnum.SUCCESS);
}

3.3、具体树形列表后端代码实现

代码3.1为实现类中的方法,此代码中sysMenuMapper.findAll() 用于查询所有菜单,其SQL如下
select * from sys_menu where is_deleted = 0 order by sort_value

此外,其中的MenuHelper为自定义的一个类,在代码3.2中给出,该类的静态方法buildTree为具体的递归构造树形菜单的方法(该方法的参数为:菜单列表数据)。

buildTree方法调用了递归函数findChildren(该递归函数的参数为:已知的父节点,菜单列表数据),其思路是:已知的父节点为N0,再找出子节点N1,并递归地为N1节点的children属性赋值,然后将N1添加至N0的children中。

代码3.1:

// 递归查找列表
@Override
public List<SysMenu> findNodes() {
    // 1.先查询所有菜单,返回所有list集合
    List<SysMenu> sysMenuList = sysMenuMapper.findAll();
    if (CollectionUtils.isEmpty(sysMenuList)){
        return null;
    }

    // 2.调用工具类中的方法,返回树形数据结构列表
    List<SysMenu> treeList = MenuHelper.buildTree(sysMenuList);
    return treeList;
}

代码3.2:

public class MenuHelper {

    // 递归实现封装
    public static List<SysMenu> buildTree(List<SysMenu> sysMenuList){
        // TODO 完成封装过程
        List<SysMenu> trees = new ArrayList<>();

        for (SysMenu sysMenu : sysMenuList) {
            // 找到递归入口
            if (sysMenu.getParentId().longValue()==0){
                // 根据第一层,找下一层的数据
                trees.add(findChildren(sysMenu, sysMenuList));
            }
        }

        return trees;
    }


    // 返回已经封装好children字段的 菜单节点
    private static SysMenu findChildren(SysMenu sysMenu, List<SysMenu> sysMenuList) {
        // 初始化
        sysMenu.setChildren(new ArrayList<>());

        for (SysMenu menu : sysMenuList) {
            if(menu.getParentId().longValue()==sysMenu.getId().longValue()){
                sysMenu.getChildren().add(findChildren(menu, sysMenuList));
            }
        }

        return sysMenu;
    }
}

最终效果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

天润融通助力立升净水,AI技术打造全天候智能客服体系

水&#xff0c;作为生命之源&#xff0c;其纯净度直接关系到人类的健康与社会的可持续发展。 在工业化和城市化进程的不断推进中&#xff0c;我们面临着土壤、空气等环境因素对饮用水质量的挑战。近期的公共卫生事件更是将饮用水安全问题推到了公众视野的中心&#xff0c;引发…

【论文阅读】-- Temporal Summary Images:通过交互式注释生成和放置实现叙事可视化的方法

Temporal Summary Images: An Approach to Narrative Visualization via Interactive Annotation Generation and Placement 摘要1 引言2 背景及相关工作2.1 叙事可视化和讲故事2.2 显示面向时间的数据2.3 小倍数和漫画2.4 注释可视化 3 设计要求和工作流程3.1 工作流程3.2 TSI…

科技未来·无限可能“2024世亚智博会”

随着科技的飞速发展&#xff0c;人类社会正以前所未有的速度迈向一个全新的时代。科学技术作为第一生产力&#xff0c;不仅极大地推动了经济和社会的发展&#xff0c;更在不断地改变着我们的生活方式和思维方式。特别是在人工智能、物联网等前沿科技领域&#xff0c;其创新和应…

搜索引擎的妙用:掌握这些技巧,让你的搜索更高效!

搜索引擎是我们日常生活中不可或缺的工具&#xff0c;它帮助我们快速找到所需的信息。但是&#xff0c;你真的知道如何高效地使用搜索引擎吗&#xff1f;下面&#xff0c;我将分享一些高级搜索技巧&#xff0c;让你的搜索更加精准和高效。 1. 完全匹配搜索 当你想要搜索一个特…

OutOfMemoryError能被catch(Exception)捕获吗?

背景 写了一个 Kafka 消费者程序&#xff0c;Kafka 集群中数据量过大时&#xff0c;消费线程无故退出了&#xff0c;日志打印了心跳 OOM 异常信息&#xff1a; 但是消费线程里面的 run 方法里面明明包含了 catch (Exception e) &#xff0c;结尾信息没有打印异常&#xff0c;…

钢筋计在工程项目中的关键应用与优势

在长期工程项目中&#xff0c;如大型桥梁、高层建筑或深基坑工程中&#xff0c;钢筋是承载结构的重要组成部分。为确保工程质量和安全&#xff0c;监测与管理钢筋的状态至关重要。钢筋计作为一种先进的监测工具&#xff0c;在长期工程项目中发挥着不可替代的作用。 1. 钢筋计的…

Python-井字棋

井字棋 1.设计登录界面1.1导入需要的工具包1.2窗口显示1.3登录界面图片显示1.6标签按钮输入框显示 2.登录功能实现2.1用户数据存储 2.2登录和注册2.2.1登录功能实现2.2.2注册功能实现 3.井字棋游戏3.1 导入需要的工具包3.2 窗口显示3.2 按钮标签显示3.3 棋盘设置初始状态3.4 游…

Adobe AIR是什么?能做什么?

Flash&#xff08;Animate&#xff09;软件能制作二维动画以及普通的互动课件是多数人了解的&#xff0c;其实Adobe还有一个AIR平台&#xff0c;可以用来开发更多不同的内容&#xff0c;这里就自己理解和掌握的信息分享一下AIR平台。 基本介绍 Adobe AIR是和Flash制作软件相依…

基于UDP的网络聊天室(多线程实现收和发消息)

要求&#xff1a;1.有新用户登录&#xff0c;其他在线的用户可以收到登录信息 2.有用户群聊&#xff0c;其他在线的用户可以收到群聊信息 3.有用户退出&#xff0c;其他在线的用户可以收到退出信息 4.服务器可以发送系统信息 效果图&#xff1a; service.c #include <head…

Day5:有效的字母异位词 242 两个数组的交集 349 快乐数 202 两数之和1

题目242. 有效的字母异位词 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool isAnagram(string s, string t) {//把数组当成哈希表&#xff0c;用两个数组来存储取模后的字母对应的数量//26个字母&#xff0c; 模25 0~25int arrs[26];int arrt[26];for(…

<电力行业> - 《第4课:什么是电力?什么是发输变配用5环节?》

1 什么是电力&#xff1f; 我们对于平日生活中离不开的电很熟悉&#xff0c;但是电力是什么&#xff1f; 其实&#xff0c;电力就是电能作为动力的能源。电力就是我们说的电&#xff0c;不过更多了系统化。 19世纪70年代&#xff0c;电力的发明和应用掀起了第二次工业化高潮。…

MySQL之可扩展性(四)

可扩展性 向外扩展 分片?还是不分片&#xff1f; 这是一个问题&#xff0c;对吧&#xff1f;答案很简单:如非必要&#xff0c;尽量不分片。首先看是否能通过性能调优或者更好的应用或数据库设计来推迟分片。如果能足够长时间地推迟分片&#xff0c;也许可以直接购买更大地服…

springcloud第4季 springcloud-alibaba之openfegin+sentinel整合案例

一 介绍说明 1.1 说明 1.1.1 消费者8081 1.1.2 openfegin接口 1.1.3 提供者9091 9091微服务满足&#xff1a; 1 openfegin 配置fallback逻辑&#xff0c;作为统一fallback服务降级处理。 2.sentinel访问触发了自定义的限流配置&#xff0c;在注解sentinelResource里面配置…

吴恩达机器学习 第三课 week2 推荐算法(下)

目录 01 学习目标 02 基于内容的过滤算法 03 实现“电影推荐系统” 3.1 问题描述 3.2 算法实现 04 大项目&#xff08;数据很大&#xff09;的推荐方法※ 4.1 方法原理 4.2 实施示例 05 总结 01 学习目标 &#xff08;1&#xff09;理解基于内容的过滤算法&#xff08…

(四十六)Vue Router组件所独有的两个钩子activate、deactivated

文章目录 activated钩子函数deactivated钩子函数demo 上一篇&#xff1a;&#xff08;四十五&#xff09;Vue Router之编程式路由导航 Vue Router提供了两个钩子函数&#xff0c;分别是activated和deactivated。 这两个钩子函数可以用于在路由组件的激活状态发生变化时执行相…

前端开发实战项目:实时天气预报应用

引言 在本实战项目中&#xff0c;我们将开发一个实时天气预报应用。这个项目将帮助你掌握前端开发的核心技能&#xff0c;包括HTML、CSS、JavaScript&#xff0c;以及如何使用API来获取实时数据。通过这个项目&#xff0c;你将学会如何构建用户界面、处理用户交互、以及与第三…

HarmonyOS Next开发学习手册——通过startAbility拉起文件处理类应用

使用场景 开发者可以通过调用startAbility接口&#xff0c;由系统从已安装的应用中寻找符合要求的应用来实现打开特定文件的意图&#xff0c;例如&#xff1a;浏览器下应用下载PDF文件&#xff0c;可以调用此接口选择文件处理应用打开此PDF文件。开发者需要在请求中设置待打开…

IO-Link ISDU

目录 一、引言 二、ISDU定义与功能 三、ISDU指令构成 四、ISDU应用场景 五、ISDU优势 六、总结 一、引言 IO-Link技术作为工业自动化领域的创新通信标准&#xff0c;通过单一电缆实现了设备层级的透明化通信。其中&#xff0c;Indexed Service Data Unit&#xff08;ISDU…

目标检测mAP

【目标检测】目标检测算法评估指标(性能度量) AP&#xff0c;mAP 详细介绍_ap和map的区别-CSDN博客 目标检测中的mAP | Clouds Blog 目标检测AP如何理解&#xff1f;_置信度与ap-CSDN博客 一、IOU (Intersection Over Union, 交并比) 二、查准率和查全率 True Positive (TP…

力扣随机一题 6/26 哈希表 数组 思维

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 题目一&#xff1a; 2869.收集元素的最少操作次数【简单】 题目&#xff…