• Spring Boot+Vue3前后端分离实战wiki知识库系统之分类管理功能开发


    在这里插入图片描述

    分类表设计与代码生成

    在这里插入图片描述

    分类表设计:项目设计两级分类,表设计支持无限极分类

    在这里插入图片描述
    在这里插入图片描述

    生成持久层代码

    来到我们mybatis generator的配置文件中:
    在这里插入图片描述
    执行一下generator,生成了四个类:
    在这里插入图片描述

    完成分类基本增删改查功能

    在这里插入图片描述
    首先我们先写controller,直接复制我们之前所写的EBookController重命名为CategoryController,使用快捷键ctrl+R一键替换关键词:
    在这里插入图片描述
    再替换大写的:
    在这里插入图片描述
    这时候其实有很多类是没有的:
    在这里插入图片描述
    接下来我们来编写sevice,同样直接复制之前写好的Ebook相关service:

    在这里插入图片描述
    同样直接一键替换大写和小写:
    在这里插入图片描述
    在这里插入图片描述
    接下来我们来编写实体类
    在这里插入图片描述
    CategoryQueryReq查询分类的时候不用请求参数,直接集成我们之前的分页请求就行:

    public class  CategoryQueryReq extends PageReq {
        @Override
        public String toString() {
            return "CategoryQueryReq{} " + super.toString();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    CategorySaveReq就跟我们之前设计的表的结构一致即可:

    public class CategorySaveReq {
        private Long id;
    
        private Long parent;
    
        @NotNull(message = "【名称】不能为空")
        private String name;
    
        @NotNull(message = "【排序】不能为空")
        private Integer sort;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public Long getParent() {
            return parent;
        }
    
        public void setParent(Long parent) {
            this.parent = parent;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getSort() {
            return sort;
        }
    
        public void setSort(Integer sort) {
            this.sort = sort;
        }
    
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(getClass().getSimpleName());
            sb.append(" [");
            sb.append("Hash = ").append(hashCode());
            sb.append(", id=").append(id);
            sb.append(", parent=").append(parent);
            sb.append(", name=").append(name);
            sb.append(", sort=").append(sort);
            sb.append("]");
            return sb.toString();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    CategoryQueryResp也是跟我们的表的结构一致:

    public class CategoryQueryResp {
        private Long id;
    
        private Long parent;
    
        private String name;
    
        private Integer sort;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public Long getParent() {
            return parent;
        }
    
        public void setParent(Long parent) {
            this.parent = parent;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getSort() {
            return sort;
        }
    
        public void setSort(Integer sort) {
            this.sort = sort;
        }
    
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(getClass().getSimpleName());
            sb.append(" [");
            sb.append("Hash = ").append(hashCode());
            sb.append(", id=").append(id);
            sb.append(", parent=").append(parent);
            sb.append(", name=").append(name);
            sb.append(", sort=").append(sort);
            sb.append("]");
            return sb.toString();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    除此之外我们要在service中删掉用名字查询的条件,因为我们分类查询没有只有分页的参数:
    在这里插入图片描述
    在这里插入图片描述
    接下来我们来写前端界面,同样也是复制admin-ebook.vue,创建admin-category.vue,并进行大写和小写的替换:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    首先我们先来对比一下电子书和分类的异同:
    电子书:
    在这里插入图片描述
    分类:
    在这里插入图片描述
    所以我们要将原本的在这里插入图片描述
    改为:
    在这里插入图片描述
    表格对应的列我们也需要修改:
    由:
    在这里插入图片描述

    改为:
    在这里插入图片描述
    由:
    在这里插入图片描述
    改为:
    在这里插入图片描述
    接下来我们修改路由:
    在inex.ts中导入:
    在这里插入图片描述
    在这里插入图片描述
    header中我们要添加:
    在这里插入图片描述
    这样我们就快速地完成了分类基本增删改查功能 。

    分类表格显示优化在这里插入图片描述

    不需要分页,一次查出全部数据

    分类的数据是有限的,所以我们可以一次性查出所有数据:
    我们新增一个查询all的方法:
    在这里插入图片描述
    我们按照递增顺序返回,接着我们修改接口:
    在这里插入图片描述

    修改前端请求地址、删掉请求参数:

    在这里插入图片描述
    删掉分页信息:
    在这里插入图片描述
    在这里插入图片描述
    删掉加载列表的分页请求参数
    在这里插入图片描述
    在这里插入图片描述
    取消分页:
    在这里插入图片描述

    改为树形表格展示

    在这里插入图片描述
    在这里插入图片描述
    使用递归算法将数组变成树形JSON:

    在这里插入图片描述

          /**
           * 数据查询
           **/
          const handleQuery = () => {
            loading.value = true;
            // 如果不清空现有数据,则编辑保存重新加载数据后,再点编辑,则列表显示的还是编辑前的数据
            level1.value = [];
            axios.get("/category/all").then((response) => {
              loading.value = false;
              const data = response.data;
              if (data.success) {
                categorys.value = data.content;
                console.log("原始数组:", categorys.value);
    
                level1.value = [];
                level1.value = Tool.array2Tree(categorys.value, 0);
                console.log("树形结构:", level1);
              } else {
                message.error(data.message);
              }
            });
          };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
      /**
       * 使用递归将数组转为树形结构
       * 父ID属性为parent
       */
      public static array2Tree (array: any, parentId: number) {
        if (Tool.isEmpty(array)) {
          return [];
        }
    
        const result = [];
        for (let i = 0; i < array.length; i++) {
          const c = array[i];
          // console.log(Number(c.parent), Number(parentId));
          if (Number(c.parent) === Number(parentId)) {
            result.push(c);
    
            // 递归查看当前节点对应的子节点
            const children = Tool.array2Tree(array, c.id);
            if (Tool.isNotEmpty(children)) {
              c.children = children;
            }
          }
        }
        return result;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    分类编辑功能优化

    在这里插入图片描述
    在这里插入图片描述
    我们要实现下图的效果:
    在这里插入图片描述
    在表单中添加选择框
    在这里插入图片描述
    我们还要解决一个问题,就是自己不能选择自己:
    在这里插入图片描述

    电子书管理增加分类选择

    在这里插入图片描述
    在电子书的编辑按钮中我们要实现可以选择多级:
    在这里插入图片描述
    在这里插入图片描述
    我们这边遇到了一个问题,编辑完保存后,对于的界面发生变化,但是重新点编辑发现表单中还是刚刚未修改的值:
    在这里插入图片描述
    我们待会儿再来解决。

    级联选择组件:
    在这里插入图片描述
    选择的时候会有一个value数组就是对应着每一级的数据 。
    选项也是数组:
    在这里插入图片描述
    初始化的时候我们要加载所有的分类,所以我们可以将分类管理中的代码原封不动地复制到电子书管理来。

    添加级联选择组件:
    在这里插入图片描述
    在这里插入图片描述
    定义响应式变量:
    在这里插入图片描述
    当我们点击OK时执行以下函数,先拿到所选的级联分类:
    在这里插入图片描述
    而编辑按钮则是反过来,先获取到一级、二级分类,填入表单:
    在这里插入图片描述
    查询所有分类(跟之前分类管理的代码一致):
    在这里插入图片描述
    在这里插入图片描述
    在初始的时候我们要查到所有的分类:
    在这里插入图片描述
    我们现在想实现一个效果,将表格中的分类一和分类二合并为一个分类:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    定义一个普通变量用于js中计算,拿到所有分类的数据:
    在这里插入图片描述
    在这里插入图片描述
    使用循环通过id返回name:
    在这里插入图片描述

    这样我们就实现了分类合并展示出来了。

    现在我们来解决之前遗留的问题:
    在这里插入图片描述

    首页显示分类菜单

    同样我们初始也是要先获取到所有的分类在这里插入图片描述
    使用导航菜单组件:
    在这里插入图片描述
    利用循环展示菜单:
    在这里插入图片描述
    导入:
    在这里插入图片描述
    初始我们也是要查询所有的分类:
    在这里插入图片描述
    在这里插入图片描述
    在电子书界面会有一个小bug,我们修改一下:
    在这里插入图片描述

    点击分类菜单显示电子书

    在这里插入图片描述

    首页默认显示欢迎界面

    新增一个主页的菜单:
    在这里插入图片描述
    我们首页打开的时候需要先显示欢迎菜单栏,欢迎页要显示在a-layout-content下面:
    在这里插入图片描述
    其中欢迎页和list的内容是互斥的。所以要定义一个响应式变量判断当前a-layout-content是显示什么,初始我们要显示欢迎页面:
    在这里插入图片描述
    条件渲染:
    在这里插入图片描述

    点击某分类时,显示该分类下的电子书

    点击分类的时候该变量改为false,我们在点击菜单栏的回调函数中(只有二级分类才会触发或者就只有一个一级分类的时候会触发)去处理:
    在这里插入图片描述

    实现效果:
    在这里插入图片描述
    在这里插入图片描述添加一个变量表示当前所在的二级分类:
    在这里插入图片描述
    通过categoryId2请求后端
    在这里插入图片描述
    修改后端模仿name写一个动态查询:

    在这里插入图片描述

    总结

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    云原生下基于K8S声明式GitOps持续部署工具ArgoCD实战-上
    顺序表的折半查找法
    UTF-8字符串操作方法
    代码检查的方式有哪几种?
    YOLOv7独家改进:Multi-Dconv Head Transposed Attention注意力,效果优于MHSA| CVPR2022
    文献速递:深度学习胶质瘤诊断---通过深度学习和弥散加权成像提高胶质瘤遗传亚型的无创分类
    安全学习_开发相关_JNDI介绍(注入)&RMI&LDAP服务
    【VUE】vue程序设计----模仿网易严选
    JVM-环境准备&性能指标&基础知识
    JS网页特效实例:动态关闭页面
  • 原文地址:https://blog.csdn.net/Lbsssss/article/details/127848953