Spring Boot + Vue3前后端分离实战wiki知识库系统<九>--文档管理功能开发一

news2025/2/22 13:30:42

接着Spring Boot + Vue3前后端分离实战wiki知识库系统<八>--分类管理功能开发二继续往下,这次咱们则来到文档管理功能的开发学习了,对于知识库的核心功能当然得是能发表文章及查看对吧,所以接下来一步一个脚印来完成它,先来提前感受一下这个功能的样式:

功能还是挺复杂的,反正对于小白的我肯定是搞不定的,费话不多说,直接开撸。

文档表设计与代码生成:

文档表设计:

这里就直接给出sql了:

-- 文档表
drop table if exists `doc`;
create table `doc` (
                       `id` bigint not null comment 'id',
                       `ebook_id` bigint not null default 0 comment '电子书id',
                       `parent` bigint not null default 0 comment '父id',
                       `name` varchar(50) not null comment '名称',
                       `sort` int comment '顺序',
                       `view_count` int default 0 comment '阅读数',
                       `vote_count` int default 0 comment '点赞数',
                       primary key (`id`)
) engine=innodb default charset=utf8mb4 comment='文档';

insert into `doc` (id, ebook_id, parent, name, sort, view_count, vote_count) values (1, 1, 0, '文档1', 1, 0, 0);
insert into `doc` (id, ebook_id, parent, name, sort, view_count, vote_count) values (2, 1, 1, '文档1.1', 1, 0, 0);
insert into `doc` (id, ebook_id, parent, name, sort, view_count, vote_count) values (3, 1, 0, '文档2', 2, 0, 0);
insert into `doc` (id, ebook_id, parent, name, sort, view_count, vote_count) values (4, 1, 3, '文档2.1', 1, 0, 0);
insert into `doc` (id, ebook_id, parent, name, sort, view_count, vote_count) values (5, 1, 3, '文档2.2', 2, 0, 0);
insert into `doc` (id, ebook_id, parent, name, sort, view_count, vote_count) values (6, 1, 5, '文档2.2.1', 1, 0, 0);

这里表字段有一个关联电子书的字段:

因为文档是属于某个电子书的,所以这里在插入数据时,需要保证这个id是存在于电子书表记录当中的:

其它的字段都比较好理解,就不过多说明,下面将sql执行一下,然后确保表成功创建了:

代码生成:

接下来咱们就可以使用mybatis generator【如果对它木有印象的可以参考Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<二>---后端架构完善与接口开发】来生成mybatis相关的代码了,如下:

此时相关的代码就已经生成了:

相当的happy。

完成文档表基本增删改查功能:

接下来则通过CV大法快速实现文档表的增删改查功能,关于这块的技巧在之前Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<七>--分类管理功能开发分类管理时已经使用过了,有些忘了,下面则再来复习一下这整个过程。

1、DocController:

这里直接拷贝分类的代码:

接下来打开新拷贝的类,进行如下替换:

然后再换成小写替换一次:

此时替换完之后有一堆报错,不用管,因为还没整体替换完。

2、 DocService:

 然后打开类,跟Controller一样的替换规则,这里就不再重复啰嗦了,替换完之后也是一堆报错。

3、req实体:

对于分类请求实体有两个:

这里就不能无脑的CV了,先来看一下查询的:

这里倒可以直接copy,里面没有涉及到字段,如下:

而保存的实体这里由于会涉及到表字段:

很显然不能直接拷贝分类的了,这里还是直接基于文档的domain进行拷贝比较好:

然后在里面再标注非空的字段,如下:

4、resp实体:

这个也是直接从文档的domain实体进行拷贝:

这样整个后端的代码就拷贝完了,报错也没有了。

5、admin-doc.vue:

接下来回到前端进行同样的CV大法,也拷贝自分类页面:

然后进行大小写的替换:

这里就不过多说明了, 另外对于前端还需要替换一个中文:

接下来通常需要修改一下表单的内容了,毕竟业务表的字段是不一样的,凑巧这里的文档和分类目前的字段是一样的,暂时先不用改,之后等做到时再细化。

6、添加路由:

接下来则配置一下文档页面的路由:

7、电子书管理增加跳转入口:

由于文档的管理是需要从某个电子书中点击进来的,毕竟文档是隶属于电子书的,所以咱们回到电子书管理页面,在这块增加一个跳转文档管理的入口:

8、运行:

通过这么一顿CV大法之后,咱们运行看一下初步的效果:

增删改查都有了,效率还是相当高的,不过从运行效果中可以发现编辑时,目前只能选择一级分类作为父文档,照理应该是可以选择任务级文档作为当前的父文档的,关于这块的细节之后再来完善。

使用树形选择组件选择父节点:

概述:

在上面也说了现在在编辑文档时,只能选择一级文档做为父节点:

接下来咱们得将它改成树形的选择框。

实现:

1、找选择框组件:

这里可以用这个组件:

其中我们使用最基础的效果就可以了:

点开代码查看一下它的基本用法,貌似发现这个树形菜单的生成不是基于json数据:

很明显我们得根据文档树形的json数据来进行菜单的生成对吧,所以这种方式很显然不适合咱们使用,那得找使用json数据生成的,刚好在下面就有一个:

简单了解一下它是如何通过json数据来生成的:

而treeData则是定义的一个树形结构的json:

interface TreeDataItem {
  value: string;
  key: string;
  title?: string;
  slots?: Record<string, string>;
  children?: TreeDataItem[];
}

const treeData: TreeDataItem[] = [
  {
    title: 'Node1',
    value: '0-0',
    key: '0-0',
    children: [
      {
        value: '0-0-1',
        key: '0-0-1',
        slots: {
          title: 'title',
        },
      },
      {
        title: 'Child Node2',
        value: '0-0-2',
        key: '0-0-2',
      },
    ],
  },
  {
    title: 'Node2',
    value: '0-1',
    key: '0-1',
  },
];

而这个树形结构其实刚好跟咱们定义的文档树形结构是一样的,好,接下来咱们来将它集成到工程中。

2、 集成TreeSelect树选择组件:

模板代码从ant design进行拷贝,如下:

运行看一下效果:

树形结构已经有了,但是现在里面的数据没正常显示出来,其实原因是因为这个组件默认需要的json中的属性是这样的:

而咱们的树形json的key是id和name:

那这个组件有有木有转换的属性呢?答案是有的:

咱们来使用一下:

运行发现不好使。。这里其实是故意挖个坑来让自己对vue的语法理解得更加深刻一些,错误的原因是replaceFields前面没有加一个“:”导致,咱们录个动图来感受一下不加":"和加了“:”的区别:

有木有发现加了冒号之后,它设置的json的颜色都不一样了,也就是如果属性加了冒号,它里面的值是动态生成的,如果不加冒号则会将它里面的值当一个string,是一个死的值,基础巩固一下,下面再运行:

3、完成文档编辑功能:

接下来我们来完成文档的编辑功能,目前编辑功能其实是有很多问题的,下面一一来进行解决。

问题一:父节点可选择自己及子节点

这个问题其实在之前分类管理时就遇到过,下面来演示一下:

看到木有,也就是将“文档111”的父节点设置成了它的孩子“文档1.1”,这样就造成了这俩文档相互引用,在查询树形菜单时则会将这样的数据给过滤掉,造成设置之后该数据不见了,也就是该数据从树形结构中断掉了,很显然不合理,而解决这种问题思路就是不让它可以选择自己及孩子做为它的父节点,效果如下:

下面来解决一下,对于某个项不让用户点,其实只需要在树形结构中将对应的节点设置一下disabled=true既可,如官方的示例所示:

所以下面咱们来处理一下树形选择框绑定的数据:

这里需要用到递归了,因为是无限级的树形菜单,有可能有很多层,处理逻辑这里直接贴出来了:

接下来就是集中来处理setDisable,逻辑如下:

// 将某节点及其子孙节点全部置为disabled
    const setDisable = (treeSelectData: any, id: any) => {
      // 遍历数组,即遍历某一层节点
      for (let i = 0; i < treeSelectData.length; i++) {
        const node = treeSelectData[i];
        if (node.id === id) {
          // 如果当前节点就是目标节点
          console.log("disabled", node);
          // 将目标节点设置为disabled
          node.disabled = true;

          // 遍历所有子节点,将所有子节点全部都加上disabled
          const children = node.children;
          if (Tool.isNotEmpty(children)) {
            for (let j = 0; j < children.length; j++) {
              setDisable(children, children[j].id)
            }
          }
        } else {
          // 如果当前节点不是目标节点,则到其子节点再找找看。
          const children = node.children;
          if (Tool.isNotEmpty(children)) {
            setDisable(children, id);
          }
        }
      }
    }

下面来运行看一下效果,由于之前我们为了演示问题,目前列表中只展示文档2的内容了,这里到数据库中将文档1.1的父id给手动改为0让其列表中可以多显示点数据:

木问题,但是我再编辑一下文档2 ,bug就产生了:

咋文档2编辑时,全部都无法选择了,照理应该只有它和它的孩子节点才不能被选择才对,难道是写的setDisable的逻辑有问题么?其实不然,是因为我们目前编辑修改的是level1:

而对于它的修改是会破坏原数据的,所以解决之道也比较简单,每次编辑时克隆一份树形结构的数据,之后编辑所产生的修改只修改拷贝,不直接修改原数据就好了,如下:

好,关键的显示也需要进行替换了:

再运行:

其实还有个bug,就是如果我刷新一下界面,直接点新增,你会发现:

父节点没有数据了。。是因为我们现在选择组件绑定的是treeSelectData这个数据了,而目前对于添加我们没有进行任何的处理:

加一句代码既可:

再运行:

问题二:无法设置父节点为顶层节点:

接下来继续解决bug,就是现在新增文档时,是无法新建一个顶层节点的,因为父文档这块必须要选择一个现有的文档节点:

很明显是不合理的,所以有必要再增加一个自定义的结点叫“无”,如果选择父节点为“无”,那么该文档则为顶层节点,那如何在编辑或新增时给显示的下拉选项中增加一个“无”呢?这里需要用到一个新的api了,叫“unshift”,先网上了解一下它:

其实也就是使用unshift往数组的开头添加元素,所以处理如下:

此时再运行:

Vue页面参数传递完成新增文档功能:

问题描述:

现在编辑功能已经好使了,接下来则差文档的新增功能,不过目前新增功能不好使,报错了,演示一下:

为啥报电子书为空呢?我们不是很明显是从电子书的管理列表中的一项点击来查看它底下的文档列表么,是的,但是我们目前在文档列表页面并没有把电子书的id给保存起来,所以在保存时是不支持电子书id的。

实现:

1、文档管理点击增加参数:

为了能在文档管理的界面上接收到电子书的id,所以咱们需要在点击它时增加一个参数:

对应的代码如下:

很明显加一个参数是需要将它变成一个动态的值,所以此时的to需要加一个冒号了:

而对于里面不变的我们需要将它用单引号括起来:

此时再加上动态的电子书的id既可:

2、文档页面接收电子书id:

接下来咱们就可以在文档页面来读取路由传过来的电子书id的参数了,如何获取呢?如下:

接下来我们在新增的时候就可以这样来获取路由的参数了:

接下来咱们就可以这样修改一下:

其中route.query其实就是取的我们在路由传弟的这种参数:

3、运行:

接下来咱们运行看一下:

回到数据库中看一下是否插入正常:

增加删除文档功能:

需求:

接下来再来完成删除功能,目前删除功能只能删除某个文档,对于无限级的文档树来说,目前是不满足正常的业务需求的,实际的业务需求应该是这样的:

而应该将它及它下面的子孙结点全部给删除,也就是:

实现:

其实现思路其实也比较简单,这里就又要用到递归来得到当前文档及它下面的所有文档的id集合了,然后再将所有要删除的id传给后端,后端接收之后进行id的删除, 当然这里不是轮循一个个id进行删除,而是通过一个sql来删除多个id的记录。

1、调研前端传一个带逗号分隔符的string让后端进行接收:

这样试一下:

在正式改造之前,先来调个研:

后端接口也改一下:

下面运行看一下:

嗯,成功获取到前端传过来的多个id的String值了。

2、修改后端:

接下来后端增加一个删除多个id的方法,如下:

接着我们在service中需要定义一个对应参数的删除方法:

那我们通过IDE的提示改一下:

也就是改的它:

3、修改前端:

接下来咱们来将前端id的获取修改一下,先来定义一个存所有id的集合:

然后在删除时,通过递归手段来获取所有的id,然后将其存于新声明的这个集合中,这个递归逻辑跟之前文档树中子树不能选的是一样的,修改如下:

此时运行看一下效果:

此时看一下后端控制台确认是执行了删除sql了:

同时再确认一下表内容:

确实成功的删除了。 

4、优化:

由于删除可能会删除多个文档,所以这个是一个非常危险的操作,这里打算给用户一个二次确认的提示,在这个二次确认的提示中会把涉及到要删除的所有的文档名称给列出来提示给用户,这样的交互体验也大大的增强了,具体实现如下:
1、先声明一个集合响应式变量用来存储要删除的文档名称:

然后在递归时把文档名称都取出来往这个集合中塞:

2、删除时弹出二次确认框:

接着在删除时,需要加一下它:

其中二次确认框来自于Ant Design Vue的这块:

好,再来运行看一下,在运行之前,由于数据库里木有太多数据了,这里重新对表进行一个初始化,再运行:

总结:

本次实现的功能,说实话还是挺复杂的,其实倒没有什么新的技术点,主要是业务型的代码,这次先到这,下次则要开始进行文档内容的开发了,保持学习热情继续往前~~

  关注个人公众号,获得实时推送

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

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

相关文章

Linux CentOS_7.9卸载Oracle适用于多版本(亲测验证)

前言&#xff1a;近期安装测评的比较多&#xff0c;在完成使命后还是可以按部就班形成个B环&#xff0c;这里主要是记录Linux卸载Oracle&#xff0c;下述方法适用于Oracle 11g&#xff0c;Oracle 12c&#xff0c;Oracle 19g版本的数据库&#xff0c;我们这边以CentOS_7.9、Orac…

C语言进阶教程(include只能包含.h文件吗?)

文章目录 前言一、include工作原理二、include只能包含.h文件吗三、include包含文件时<>和""的区别总结 前言 include在多文件编程中是非常重要的&#xff0c;我们经常使用他来包含一些头文件&#xff0c;方便我们管理代码和项目&#xff0c;那么include是只能…

《计算机系统与网络安全》 第八章 操作系统安全基础

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

Linux文件的权限

1.Linux文件的权限 linux文件的权限可以分为四类&#xff1a;可读、可写、可执行、没有权限。分别用字符r、w、x、- 表示。 2. 用户与用户组 Linux是一个多用户多任务的操作系统&#xff0c;可以通过用户和用户组来更好的控制文件的权限。 每个文件都有一个拥有者&#xff08…

能在图片上涂鸦的软件有哪些?分享几种好用涂鸦工具

涂鸦可以增加趣味性。在照片上涂鸦可以增加趣味性&#xff0c;让照片更加有趣。无论是在旅行照片中添加一些有趣的涂鸦&#xff0c;还是在生活照片中添加一些幽默的涂鸦&#xff0c;都可以让照片更具有趣味性。很多小伙伴不清楚怎么在照片上进行涂鸦&#xff0c;下面给大家分享…

【JSP】使用 JSTL 增强 JSP 功能

本文仅供学习参考&#xff01; JSTL 代表 JavaServer Pages Standard Tag Library;它提供了一组核心网页功能&#xff0c;可以执行许多基本任务&#xff0c;例如结构元素的条件和迭代、操作 XML 文档以及支持国际化标记以更复杂的 SQL 元素处理。JSP以scriples而闻名&#xff0…

Apache Struts是什么?高效实现应用程序控制器

目录 一、Apache Struts是什么 二、如何使用Apache Struts 三、Apache Struts的优势和作用 一、Apache Struts是什么 Apache Struts是一个基于Java的Web应用程序框架&#xff0c;它通过MVC&#xff08;模型-视图-控制器&#xff09;体系结构来实现应用程序控制器。Struts框…

如何沉淀企业内部的知识体系?

在当今竞争激烈的商业环境下&#xff0c;企业内部的知识是一项宝贵的资产。有效地沉淀企业内部的知识体系&#xff0c;可以帮助企业提高创新能力、加强竞争优势&#xff0c;并为员工学习和发展提供良好的资源。本文将介绍如何在企业中建立和沉淀知识体系&#xff0c;以促进知识…

聊聊程序员必备的软技能——情绪管理

我之前经常提到一句话&#xff1a;大多数时候所谓的“技术之玻璃天花板”&#xff0c;其实只是缺乏软技能而已。 所以粉丝朋友们&#xff0c;我们除了需要关注技术&#xff0c;更需要注重软技能的提高。 今天写的这篇是情绪管理。 文章目录&#xff1a; 01 前言 其实我一开…

6.1.3 关于可执行文件路径的变量:$PATH

查阅文件属性的指令ls完整文件名为&#xff1a;/bin/ls&#xff08;绝对路径&#xff09;。 当我们在执行一个指令的时候&#xff0c;系统会依照PATH的设置去每个PATH定义的目录下搜寻文件名为ls的可可执行文件&#xff0c;如果在PATH定义的目录中含有多个文件名为ls的可可执行…

Node框架 【Egg-企业级框架】

文章目录 &#x1f31f;前言&#x1f31f;Egg.js 是什么?&#x1f31f;Egg.js 的特性:&#x1f31f;Egg.js 的历史?&#x1f31f;Egg 继承于 Koa&#x1f31f;使用脚手架搭建项目环境&#x1f31f;环境准备&#x1f31f;搭建项目环境方式&#x1f31f;无需安装egg脚手架初始化…

大型医院安全(不良)事件报告系统源码(支持二次开发)

医院安全&#xff08;不良&#xff09;事件管理系统通过规范事件上报、流转审批、数据统计、原因分析、措施制定、效果追踪的业务流程&#xff0c;全面覆盖医院所有科室&#xff0c;利用统计工具对本院不良事件数据进行深度分析&#xff0c;查找医疗安全管理的薄弱环节&#xf…

微信小程序的跨页面传参以及data-方法的相关细节

&#x1f642;博主&#xff1a;爱学习的Akali King &#x1f642;文章核心&#xff1a;微信小程序的跨页面传参以及data-方法的相关细节 目录 前言wx.navigateTo()方法微信小程序传参的几种方式通过data-属性传参关于data-方法配合点击事件传参的细节 前言 其实在学习新东西的…

phpmyadmin弱口令至getshell 漏洞复现

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 环境部署02 漏洞配置03 利用方式04 修复方案 01 环境部署 &#xff08;1&#xff09;phpStudy phpStudy 是一款用于进行 PHP 环境调试的程序集成软件包。在软件安装后便 启动了 MySQL 服务、Apache…

【容灾系统搭建】网络杂谈(1)之容灾系统如何搭建?

涉及知识点 什么是容灾&#xff0c;容灾系统的建设&#xff0c;容灾系统的结构模型&#xff0c;容灾平台。深入了解容灾技术。 原创于&#xff1a;CSDN博主-《拄杖盲学轻声码》&#xff0c;更多内容可去其主页关注下哈&#xff0c;不胜感激 文章目录 涉及知识点前言1.容灾系统…

Android Jetpack Compose - 探索 BottomSheet

Jetpack Compose 是一种现代化的、声明式的 UI 工具集&#xff0c;它使得 Android 的 UI 开发变得更加简单和直观。在这篇文章中&#xff0c;我们将要探索其中的一种常用 UI 元素 —— 底部抽屉&#xff08;BottomSheet&#xff09;。 一、什么是 BottomSheet&#xff1f; 在 …

速度与技能的较量!飞桨黑客松 OpenVINO™ 任务获奖者经验分享

点击蓝字 关注我们,让开发变得更有趣 作者 | Fisher 排版 | 李擎 速度与技能的较量&#xff01; 飞桨黑客松 OpenVINO™ 任务获奖者经验分享 前言/ 获奖经验分享&#xff0c;比赛轻松拿捏&#xff0c; 千元奖金拿到手软&#xff01; 黑客松活动介绍 飞桨黑客马拉松是一项兼具编…

Vuex —— 同步和异步请求

上一篇讲到 Vuex 状态管理的内容&#xff0c;先来简单的回顾一下 Vuex &#xff0c;Vuex 中有五个核心属性&#xff1a;state 、getter、mutation、action、module 。state: 存放数据状态&#xff0c;不能被直接的修改&#xff1b;getter: 基于 state 的计算属性&#xff1b;mu…

kaggle注册时出现一排“Captcha must be filled out.”

kaggle网址&#xff1a;Kaggle: Your Home for Data Science 想去kaggle下载一份数据&#xff0c;但是出现了一排红色的英文&#xff1a;&#xff08;真是学习之路哪哪都是阻碍哭唧唧&#xff09; ​ 出现该问题的原因&#xff1a;必须填写(图片)验证码&#xff0c;可是它没出…

长期不关路由器网速会变慢?一文读懂

如果把现代人最烦的十件事列一个清单&#xff0c;那么网速慢肯定其中一项。看剧的时候画面在转圈&#xff0c;玩游戏的时候角色在卡顿&#xff0c;真是让人非常恼火。 最近我家的网速也比刚安上网时慢了很多&#xff0c;看网上的说法是路由器太久没关了&#xff0c;应该天天关闭…