# 业务开发-基础业务-分类管理 启动renren-fast如果出现如下错误 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/1d48e1d389314ed6a23aa3906a70d635.png) > -Djps.track.ap.dependencies=false 添加相关配置即可 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/4dfbd643eb504e5f9b003548bc4e9ee3.png) ## 分类管理 ### 1.后端分类接口 JDK8特性:https://blog.csdn.net/qq_38526573/category_11113126.html 在后端服务中我们需要查询出所有的三级分类信息,并将这些信息组合为有父子关系的数据,所以首先我们需要在对应的entity中添加关联字段 `childrens` ```java /** * 当前类别所拥有的所有的子类 */ @TableField(exist = false) private List childrens; ``` 然后我们在service中完成对应的数据处理的逻辑,具体实现逻辑参考注释 ```java /** * 查询所有的类别数据,然后将数据封装为树形结构,便于前端使用 * * @param params * @return */ @Override public List queryPageWithTree(Map params) { // 1.查询所有的商品分类信息 List categoryEntities = baseMapper.selectList(null); // 2.将商品分类信息拆解为树形结构【父子关系】 // 第一步遍历出所有的大类 parent_cid = 0 List list = categoryEntities.stream().filter(categoryEntity -> categoryEntity.getParentCid() == 0) .map(categoryEntity -> { // 根据大类找到多有的小类 递归的方式实现 categoryEntity.setChildrens(getCategoryChildrens(categoryEntity,categoryEntities)); return categoryEntity; }).sorted((entity1, entity2) -> { return (entity1.getSort() == null ? 0 : entity1.getSort()) - (entity2.getSort() == null ? 0 : entity2.getSort()); }).collect(Collectors.toList()); // 第二步根据大类找到对应的所有的小类 return list; } /** * 查找该大类下的所有的小类 递归查找 * @param categoryEntity 某个大类 * @param categoryEntities 所有的类别数据 * @return */ private List getCategoryChildrens(CategoryEntity categoryEntity , List categoryEntities) { List collect = categoryEntities.stream().filter(entity -> { // 根据大类找到他的直属的小类 return entity.getParentCid() == categoryEntity.getCatId(); }).map(entity -> { // 根据这个小类递归找到对应的小小类 entity.setChildrens(getCategoryChildrens(entity, categoryEntities)); return entity; }).sorted((entity1, entity2) -> { return (entity1.getSort() == null ? 0 : entity1.getSort()) - (entity2.getSort() == null ? 0 : entity2.getSort()); }).collect(Collectors.toList()); return collect; } ``` CategoryService中同步定义对应的接口方法 ```java public interface CategoryService extends IService { PageUtils queryPage(Map params); List queryPageWithTree(Map params); } ``` 然后在CategoryController中新增对应处理的方法 ```java @GetMapping("/listTree") public R listTree(@RequestParam Map params){ List list = categoryService.queryPageWithTree(params); return R.ok().put("data", list); } ``` 启动服务访问测试 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/a9a7ea6c73e045fbbda8b46da7c2a728.png) ### 2. 前端服务串联 #### 2.1 新增菜单 首先我们新增一个 `商品系统`的目录 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/a840495293af4a4d9c63ace48c98c0cf.png) 按照上图的操作完成即可 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/57c20806d3a847b2a41c7bd726ff7756.png) 然后在商品系统下添加 `类别管理`的菜单 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/fb3ef682fe894b1d86108c8789f7cb89.png) 对应的三级分类的页面 product/catagory--> src/views/modules/product/category.vue ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/71ff00256fb045ef9bc8d1b0fecaed81.png) #### 2.2 类别数据 ElementUI官网:https://element.eleme.cn/#/zh-CN 第一步:展示静态的数据,直接从ElementUI官网拷贝Tree相关案例代码 ```html ``` 页面效果 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/c09d8df688bd4cc7829d91449339128c.png) 第二步:动态获取后台服务的数据 ```html ``` 访问三级分类数据并没有得到我们期望的结果。出现了404错误:`http://localhost:8080/renren-fast/product/category/listTree` ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/eaf443630b344d62bee2860640570e11.png) 针对这个错误提示我们需要通过网关服务来实现统一的路由处理 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/5ff7e802a4fc49c2962955ccb8419e35.png) 修改了前端统一的后端服务地址为路由服务后 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/01ca56cfcff3424b9a7e7592062fab39.png) 访问后这个验证码出不来了 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/96ef047456104c9ea03db7d04053669c.png) 验证码出不来的原因是请求的地址:`http://localhost:8070/captcha.jpg?uuid=a496be9e-d916-4f3e-813d-d396c13a8b87` 跑到网关服务获取验证码了,这里网关服务就应该要将这个请求路由到renren-fast服务中。 首先renren-fast服务没有在注册中心中注册,网关发现不了,先注册renren-fast服务 在renren-fast中依赖commons ```xml com.msb.mall mall-commons 0.0.1-SNAPSHOT ``` 添加注册中心和配置中心相关的信息 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/601413e8170f4c83b303890692fbd88b.png) ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/02701c98317545e8a1988010447d6aa0.png) 然后放开注册中心 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/d3ead1be16684b1198e999cb941d6373.png) 最后启动服务提示如下错误 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/0da303100335438d938ca152efe534eb.png) 原因是因为SpringBoot我们把版本升级到了2.4.12那么validation默认被移除了,我们需要收到的添加依赖 ```xml org.springframework.boot spring-boot-starter-validation 2.4.12 ``` 启动服务,注册成功 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/f3c731e5c2114afea7ea7b241e1a20e4.png) 解决验证码图片不显示的问题,我们需要在网关服务中添加对renren-fast服务访问的路由 ```yml # 注册中心的信息 spring: application: name: mall-gateway cloud: nacos: discovery: server-addr: 192.168.56.100:8848 gateway: routes: - id: route1 uri: http://www.baidu.com predicates: - Query=url,baidu - id: route2 uri: http://www.jd.com predicates: - Query=url,jd - id: app_route uri: lb://renren-fast predicates: - Path=/app/** filters: - RewritePath=/app/(?/?.*), /renren-fast/$\{segment} # localhost:8070/app/captcha.jpg --> # localhost:8080/app/captcha.jpg localhost:8080/renren-fast/captcha.jpg # 指定注册中心的服务端口 server: port: 8070 ``` 然后测试访问验证码出现了503的错误 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/884cfbd6f2a24eb28f44fbb88161959a.png) 出现503错误的原因是Gateway网关服务中会根据loadbanlance负载均衡路由到renren-fast但是缺少了对应的依赖,在Gateway服务中添加即可 ```xml org.springframework.cloud spring-cloud-starter-loadbalancer ``` #### 2.3 跨域问题 同源策略 > 由于浏览器的同源策略,即属于不同域的页面之间不能相互访问各自的页面内容 > `注`:同源策略,单说来就是同协议,同域名,同端口 ```xml URL 说明 是否允许通信 http://www.a.com/a.js http://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.js http://www.a.com/script/b.js 同一域名下不同文件夹 允许 http://www.a.com:8000/a.js http://www.a.com/b.js 同一域名,不同端口 不允许 http://www.a.com/a.js https://www.a.com/b.js 同一域名,不同协议 不允许 http://www.a.com/a.js http://70.32.92.74/b.js 域名和域名对应ip 不允许 http://www.a.com/a.js http://script.a.com/b.js 主域相同,子域不同 不允许 http://www.a.com/a.js http://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问) http://www.cnblogs.com/a.js http://www.a.com/b.js 不同域名 不允许 ``` 跨域网站介绍:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/ed7a4937cb7c4bff8d3391994762c18f.png) ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/8cb50f6ea7274bb888f345e0d9701dc1.png) 对于跨域问题的解决我们统一在Gateway中设定。注意删除掉在renren-fast中配置的跨域问题 ```java package com.msb.mall.gateway.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsConfigurationSource; import org.springframework.web.cors.reactive.CorsWebFilter; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; @Configuration public class MallCorsConfiguration { @Bean public CorsWebFilter corsWebFilter(){ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration configuration = new CorsConfiguration(); // 配置跨域的信息 configuration.addAllowedHeader("*"); configuration.addAllowedMethod("*"); // SpringBoot升级到2.4.0 之后需要使用该配置 configuration.addAllowedOriginPattern("*"); configuration.setAllowCredentials(true); source.registerCorsConfiguration("/**",configuration); return new CorsWebFilter(source); } } ``` 然后登录操作即可 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/5c541e1f2aa040fe95b10c18e9464020.png) #### 2.4 查看类别数据 首先需要在Gateway中配置商品服务的路由信息,同时要注意配置规则的先后顺序 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/6b5e0ce0412c43ef9406bcc12a5be8ce.png) 然后服务端响应的数据的字段要在Vue文件中显示的对应,才能正确的显示 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/c878cb4097c74531b11ce0183891eb20.png) 访问测试 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/d7c8a3b11dae4bec83ced283ecff415b.png) ### 3 删除类别 1> 先完成类型页面的基础处理 添加相关的 `添加` , `删除`按钮和复选框按钮以及相关的代码逻辑 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/1a7a8a99a3914b93b9df158c0295fc62.png) 对应的Vue代码 ```html ``` 2> 实现后台服务逻辑删除的操作 在实际开发中针对数据删除这块我们一般都会采用逻辑删除的方法来操作。在本项目中我们可以通过mybatis-Puls中提供的逻辑删除方式来实现 mybatis-plus:https://mp.baomidou.com/guide/ 首先配置全局的逻辑删除逻辑 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/403a7263cc934aa28d84fe75475bd623.png) 然后在entity的字段中显示的标明: ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/95f292c5780a423286472638a19a6448.png) 然后我们就可以在service中继续使用delete相关的方法来操作了 ```java /** * 逻辑批量删除操作 * @param ids */ @Override public void removeCategoryByIds(List ids) { // TODO 1.检查类别数据是否在其他业务中使用 // 2.批量逻辑删除操作 baseMapper.deleteBatchIds(ids); } ``` 然后通过postman测试 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/19605e51b8dc44909b878a6fb2a1b3aa.png) 然后在数据库中反应的效果 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/fea4812cd2f54445b858e1fcb8c1d993.png) 3> 串联前后端的逻辑 要实现该效果,首先需要通过ajax异步的来提交请求到后端服务 ```javascript this.$http({ url: this.$http.adornUrl("/product/category/delete"), method: "post", data: this.$http.adornData(ids, false), }).then(({ data }) => { if (data && data.code === 0) { this.$message({ message: "操作成功", type: "success", }); // 重新加载所有的菜单数据 this.getCategory(); // 设置默认展开的父节点信息 this.expandKeys=[node.parent.data.catId] } else { this.$message.error(data.msg); } ``` 然后删除需要必要的提示信息 ```javascript this.$confirm(`是否确认删除【${data.name}】记录?`, "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", }) .then(() => { // 传递的数据 let ids = [data.catId]; // 把删除的请求提交到后台服务 this.$http({ url: this.$http.adornUrl("/product/category/delete"), method: "post", data: this.$http.adornData(ids, false), }).then(({ data }) => { if (data && data.code === 0) { this.$message({ message: "操作成功", type: "success", }); // 重新加载所有的菜单数据 this.getCategory(); // 设置默认展开的父节点信息 this.expandKeys=[node.parent.data.catId] } else { this.$message.error(data.msg); } }); }) .catch(() => { this.$message({ type: "info", message: "已取消删除", }); }); console.log("删除", data, node); ``` ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/ee3feda8d14645a7a078858d1d3d5cbf.png) ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/b6771cadc21748139d462ef80901fbf4.png) 最后删除成功数据后Tree数据刷新及对应的Tree的默认展示父节点信息 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/32c340907a3845b0b5ba8d8e2f0aa772.png) ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/1734048d725d4dc9a195d365d3e20f60.png) ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/2764953ded1648bfbf320442fa83c041.png) 到此,三级分类数据的删除操作搞定 ### 4.新增类别 后台的添加逻辑已经有了,我们只需要在前端项目中完成新增的相关页面逻辑就可以了 对话框页面 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/e65831992bf9461ebaefdcc3b624579d.png) 点击后弹出页面 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/e4f4c6240136421a8ef98bbdb11862b7.png) 修改新增类别相关的数据 ```javascript append(data) { this.dialogVisible = true; // 打开弹出窗口 // console.log("添加", data); this.categoryForm.parentCid = data.catId;// 添加的类别对应的父菜单 this.categoryForm.catLevel = data.catLevel + 1; // 设置添加类别的层级 this.categoryForm.showStatus = 1; // 菜单的显示状态 1 显示 0 被删除 this.categoryForm.sort = 0; // 排序 默认给 0 } ``` 完成表单数据提交的ajax请求 ```javascript addDialog(){ // 添加三级分类的类别信息 this.$http({ url: this.$http.adornUrl("/product/category/save"), method: "post", data: this.$http.adornData(this.categoryForm, false), }).then(({ data }) => { if (data && data.code === 0) { this.$message({ message: "数据添加成功", type: "success", }); this.dialogVisible = false; // 关闭弹出窗口 // 重新加载所有的菜单数据 this.getCategory(); // 设置默认展开的父节点信息 this.expandKeys = [this.categoryForm.parentCid]; } else { this.$message.error(data.msg); } }); } ``` 页面效果 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/d2bb484be9044feda4545d930a4a3cab.png) 添加信息隐藏了一个Bug,如果在二级分类下面添加三级分类,然后添加的三级分类不能显示。原因在Java后端中的Long类型数据的比较。只需要修改相关代码即可 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/9c5be3474cbf487cb48355aa6a58bdda.png) 原因 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/baf2b3d53691403aa6224dd3b4c4007c.png) ### 5.修改类别 同样的后台逻辑已经实现,我们只需要完善前端业务即可 添加修改按钮 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/8a22d836ad704a3399f32f01238bb0d5.png) 点击更新的按钮弹出对话框 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/43c653a8ffaa43109b8ec4f3d0960a5f.png) 然后修改数据后的更新提交 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/6266a59c40b04c0cb4dd13e34afd82eb.png) ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/96c290b512b94da0ac7bf651a90a545d.png) ### 6. 拖拽功能 首先实现拖拽效果 1> 放开拖拽的功能 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/798f3d33cf054fb880387c398187e70d.png) 也就是我们只需要将 draggable设置为TRUE即可 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/fae3c04d533a40819365c4bacfb436a9.png) 然后就是要控制拖拽的位置是否可行,因为我们不能破坏三级分类的规则,我们不能拖拽后整个分类变成了4级5级分类等,控制的条件是在ElementUI中给你我们提供了一个allow-drop属性,该属性接收一个方法,方法返回true表示可放置,返回false表示不可放置,我们要做的就是在这个方法中添加我们的放置逻辑 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/4deca037819e430aac2a95e6576c12d6.png) ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/83950d0da8c64906b2a4c527a90db982.png) ```javascript // draggingNode 要拖拽的节点 // dropNode 目标节点 // type 参数有三种情况:'prev'、'inner' 和 'next' allowDrop(draggingNode, dropNode, type){ // 判断拖拽的节点是否可以在该位置放置 console.log("--->",draggingNode, dropNode, type) // 1.获取当前被拖拽的节点的最大的level this.countNodeLevel(draggingNode); let deep = Math.abs(this.maxLevel - draggingNode.level ) + 1; if(type == 'inner'){ return deep + dropNode.level <= 3; } return deep + dropNode.parent.level <= 3; }, countNodeLevel(node){ // 找到所有子节点,最大的level if(node.childNodes != null && node.childNodes.length > 0){ for(let i = 0; i < node.childNodes.length; i ++){ if(node.childNodes[i].level > this.maxLevel){ this.maxLevel = node.childNodes[i].level } this.countNodeLevel(node.childNodes[i]); } } } ``` 然后实现拖拽后台数据更新,我们需要在后台添加批量更新的方法: ```java /** * 批量修改 */ @RequestMapping("/updateBatch") //@RequiresPermissions("product:category:update") public R updateBatch(@RequestBody CategoryEntity[] category){ //categoryService.updateById(category); categoryService.updateBatchById(Arrays.asList(category)); return R.ok(); } ``` 前端的数据调整,需要更新的数据保存在了this.updateNodes中。注意push方法的使用。添加对应的提交操作的方法 ```javascript editSort(parentId){ // 获取最新的数据回写 this.$http({ url: this.$http.adornUrl(`/product/category/updateBatch`), method: "post", data: this.$http.adornData(this.updateNodes, false), }).then(({ data }) => { if (data && data.code === 0) { this.$message({ message: "拖拽操作成功", type: "success", }); // 重新加载所有的菜单数据 this.getCategory(); // 设置默认展开的父节点信息 this.expandKeys = [parentId]; } else { this.$message.error(data.msg); } }); } ``` 针对拖拽相关的开关设置,还是非常有必要的。通过ElementUI中的Switch就可以搞定。 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/1a45a39368c5421db8be41cf973dda24.png) 现在是每次拖拽都需要调用后端的接口来处理,如果拖拽的比较频繁那么对系统的性能肯定会有影响,这时我们可以通过批量提交的方式来实现。先添加批量添加的按钮。 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/c68dee11818a46eebbfb62b76a164bf3.png) 然后拖拽确定后点击“批量保存”按钮来实现后端数据处理,点击触发相关的方法: ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/1c6fe39c94354f50a9ac67c252210df2.png) ```javascript ,editSort(){ // 获取最新的数据回写 this.$http({ url: this.$http.adornUrl(`/product/category/updateBatch`), method: "post", data: this.$http.adornData(this.updateNodes, false), }).then(({ data }) => { if (data && data.code === 0) { this.$message({ message: "拖拽操作成功", type: "success", }); // 重新加载所有的菜单数据 this.getCategory(); // 设置默认展开的父节点信息 this.expandKeys = this.pCid; // 提交更新的数据后,重新相关的数据 this.updateNodes=[]; this.maxLevel=0; console.log("parentCid:",this.pCid) this.parentCid=[]; } else { this.$message.error(data.msg); } }); } ``` 这样整个更新分类的操作就完成了,完整的vue代码如下: ```html ``` ### 7.批量删除 因为类别比较多,在操作的时候也可以能面临批量删除的操作。我们在案例中来实现,首先创建批量删除的按钮,同时绑定操作的方法。 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/49c552148da744719e2f5fc21a881a37.png) 然后就是触发删除的方法后,我们需要找到所有的被选中的节点。结合ElementUI官方的信息来获取。 ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/689b0b23a33c40c38aa3fe6e9bb6cbb6.png) 然后批量删除的方法 ```javascript batchDelete() { let catIds = []; // 批量的删除类别 let checkedNodes = this.$refs.tree.getCheckedNodes(false, false); // console.log("被选中的节点:",checkedNodes); for (let i = 0; i < checkedNodes.length; i++) { catIds.push(checkedNodes[i].catId); } // 给出一个删除的提示信息 this.$confirm(`是否确认删除【${catIds}】记录?`, "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", }) .then(() => { // 把删除的请求提交到后台服务 this.$http({ url: this.$http.adornUrl("/product/category/delete"), method: "post", data: this.$http.adornData(catIds, false), }).then(({ data }) => { if (data && data.code === 0) { this.$message({ message: "操作成功", type: "success", }); // 重新加载所有的菜单数据 this.getCategory(); } else { this.$message.error(data.msg); } }); }) .catch(() => { this.$message({ type: "info", message: "已取消删除", }); }); }, ``` ![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1462/1637300624000/5ea6e1ce71634e97b3082a7936a24420.png)