商城-学习整理-基础-商品服务API-三级分类(五)

目录

一、启动之前创建的环境

1、启动虚拟机

2、启动mysql

3、启动redis

4、启动nacos

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

5、导入三级分类测试数据

将三级分类的数据导入mysql中,在pms库中的pms_category表。
在这里插入图片描述
造一些数据方便开发,正常开发的时候,开发完功能再造数据,先写新增功能。

二、开发商品服务三级分类列表

1、后台模块

1)书写商品三级分类表后台业务逻辑

找到我们的商品模块代码:zhenyanmall-product
刚才我们导入的是pms_category商品三级分类表,因此打开CategoryController.java,然后自己写后台业务逻辑,以父子结构查询出三级分类列表。
在这里插入图片描述

2、前端模块

1)启动renren-fast前后端项目

找到我们的reneren-fast-vue项目,启动前端之前,需要启动renren-fast后端项目
npm run dev
在这里插入图片描述
默认账号和密码都是admin/admin
在这里插入图片描述

2)在系统管理-》菜单管理-》新增目录-》商品系统

在这里插入图片描述

3)新增分类维护

在这里插入图片描述

4)查看角色管理

此时我们在系统管理-》角色管理,由此可以看到路径http://localhost:8001/#/sys-role

在这里插入图片描述
且sys-role代码在
在这里插入图片描述
重启前端项目
在这里插入图片描述

5)创建商品目录vue文件

因此我们只需要在src/views/modules目录下创建product目录对应商品系统分类维护。并创建category.vue文件,在这里写分类维护代码。
在这里插入图片描述
因为改项目已经设置了样式,所以需要下载一些样式,或者去掉style
在这里插入图片描述

扫描二维码关注公众号,回复: 16097813 查看本文章

6)从element UI 官网引入Tree树形控件

我们使用的是element ui因此,我们可以从官网:https://element.eleme.cn/#/zh-CN/component/installation

在这里插入图片描述
搜索tree 组件,然后拷贝使用。

7)参考role.vue模块写商品目录模块

里面写的是静态数据,我们可以把静态数据模块换掉,写成请求后台的方法获取数据,放到data里面。
可以参考role.vue模块的获取数据的写法。
写好代码之后,请求后台接口。

8)修改接口请求地址

打开控制台,发现并没有获取到数据,请求的地址不是商品项目,而是http://localhost:8080/renren-fast/product/category/list/tree,(而8080是renren-fast后台端口)请求的地址应该是http://localhost:20001/product/category/list/tree
在这里插入图片描述

9)网关配置

其实我们需要配置的是网关的地址,让网关去转发到对应的服务地址,而不是直接请求对应服务地址。http://localhost:8080/renren-fast这个地址其实就是renren-fast配置的请求后台转发地址,全局搜索改配置,看看改配置在哪里,然后配置为网关地址,发现配置在static/config/index.js 在这里插入图片描述

改为:http://localhost:88
在这里插入图片描述
此时我们把请求api地址改了,那么也就不能请求到renren-fast后台了,

10)需要将renren-fast注册到网关。

renren-fast引入common,并添加注册中心注解,添加服务名和注册中心地址(因为spring版本冲突问题,可以不用引入common,可以单独引入注册中心和配置中心)

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

在这里插入图片描述
然后重启RenrenApplication

11)遇到的问题:找不到类定义

org.springframework.cloud.context.properties包下的
ConfigurationPropertiesBeans类报错:

Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
	at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
	at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3166)
	at java.base/java.lang.Class.getDeclaredMethods(Class.java:2309)
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:467)
	... 37 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 41 common frames omitted

分析:
1:查看
ConfigurationPropertiesBeans存在相同名类共有三个
2:去掉 nacos服务注册中心和配置中心的依赖则不报错,此时存在

ConfigurationPropertiesBeans类共有两个(其他项目存在一个版本2.2.0RELEASE,人人开源项目存在3.1.5版本)

3:依赖冲突,在nacos的依赖中去掉依赖:

spring-cloud-context
4:nacos本身也需要去掉依赖

spring-cloud-starter-netflix-ribbon
解决方案:修改pom文件

 <!--注册中心  服务注册/发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.1.0.RELEASE</version>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.cloud</groupId>
					<artifactId>spring-cloud-context</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework.cloud</groupId>
					<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
				</exclusion>
			</exclusions>

        </dependency>

        <!--配置中心  管理配置-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2.1.0.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-context</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

12)然后还会报错,报配置不存在,

因为我们引入了配置中心,但是没有配置配置中心的配置,索引会报错,但是不影响,后续添加配置中心的配置即可
在这里插入图片描述

13)修改网关路由

后面就可以修改网关的路由,然后当前端请求api的时候,如果是renren-fast后台,则转到renren-fast,如果是商品服务,转到商品服务后台。

在这里插入图片描述
在这里插入图片描述
根据路径去匹配,当匹配到该路径时,转到对应的uri。
在这里插入图片描述
在前端项目+API,所有的请求都走API
在这里插入图片描述

14)验证码报错

请求登录,发现验证码还会报错
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

从前端项目发送:http://localhost:88/api/captcha.jpg 请求 发给网关,网关看到前缀是api满足断言,转到renren-fast,请求:http://renren-fast:8080/api/captcha.jpg,还是会报错。(实际应该访问的是:http://localhost:8080/renren-fast/captcha.jpg)应该进行重定向
在这里插入图片描述

15)重写转发路径

因此需要将http://localhost:88/api/captcha.jpg 转发给 http://localhost:8080/renren-fast/captcha.jpg 使用网关的路径重写
在这里插入图片描述
可以正常获取验证码

在这里插入图片描述

16)登录报错,跨域

然后登录,发现报如下错误:
在这里插入图片描述

17)端口号发生了变化

403Forbidden被拒绝,从’http://localhost:8001’ 访问’http://localhost:88/api/sys/login’ ,请求被cors策略阻塞,也就是跨域,浏览器安全限制期间,拒绝跨域请求。浏览器检查有一个请求头:Access-Control-Allow-Origin,不在请求头里面。
因为从http://localhost:8001访问http://localhost:88/api/sys/login 端口号发生了变化

18)跨域含义

在这里插入图片描述

19)预检请求

在这里插入图片描述
options:跨域请求的预请求
在这里插入图片描述

20)跨域解析网址

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

简单请求不会跨域,
在这里插入图片描述
而我们的登录是POST,Application/json的请求,
不是简单请求的都需要发送一个预检请求
在这里插入图片描述
在这里插入图片描述

21)解决跨域方法

有以下几种方案可以解决跨域问题,跨域的根本原因就是以上三种原因:协议、域名、端口号不同,解决这三种情况即可。

22)线上部署环境使用nginx

在这里插入图片描述

23)开发中使用以下方式(因为开发中不好配置nginx):

在这里插入图片描述

24)配置跨域

每次请求都要给响应头添加以上字段,因此我们可以写一个filter,我们所有的请求进来,返回给浏览器之前,添加那些响应头,filter不用写在每一个项目,每一个项目都会远程访问跨域,可以直接写在网关里面,因为是网关代理给其他的服务,在网关里面配置统一跨域解决问题。
将网关里面的配置都写到config里面
在这里插入图片描述

25)同源策略多个值

重新启动网关服务,登录,预检请求没问题,真正请求登录接口报错,报同源策略多个值,只希望一个,是因为renren-fast脚手架工程后台也配置了跨域,将renren-fast那个跨域注释掉。
在这里插入图片描述
在这里插入图片描述

3、查询

1)配置product的路由

在这里插入图片描述

在这里插入图片描述

2)配置路由顺序

要注意,路由配置顺序,范围小的精确的在前面(高优先级),范围大的在后面(低优先级),要不然会被前面给匹配。

3)直接请求网关,测试查询接口:

在这里插入图片描述
修改category.vue文件。

在这里插入图片描述

4、删除

1)element ui自定义节点内容

编写菜单删除功能,没有子菜单,且未被引用的,可参考element ui自定义节点内容,有两种方式,render-content和 scoped slot,我们在此使用scoped slot,只需要引入span标签即可。(使用的是vue的插槽机制)
然后修改其中的append和remove方法,需要给后台发送请求
在这里插入图片描述
在这里插入图片描述

2)删除完展开内容 :expand-on-click-node=“true”

从element ui找到对应控件的自定义节点内容,引入添加删除功能,修改内容展开为flase,这样只有点击箭头才能展开内容 :expand-on-click-node=“false”
// 3、去掉单击函数 @node-click=“handleNodeClick”
// 4、我们要做的效果是,只有没有子菜单和引用才显示Delete按钮,只有一级、二级菜单才能显示Append按钮 使用v-if进行判断
// 5、在使用remove方法时,会传入节点参数,几级节点
在这里插入图片描述
批量删除
在这里插入图片描述
// 7、添加树中唯一节点标识,node-key 每一个节点都有一个catId

2)后端编写删除功能接口

配置mybatis逻辑删除,参考MyBatis-Plus文档
在这里插入图片描述

1、逻辑删除

  • 1)、配置全局的逻辑删除规则(省略)

  • 2)、配置逻辑删除的组件Bean(省略)
    在这里插入图片描述

  • 3)、给Bean加上逻辑删除注解@TableLogic 当实际的逻辑删除值和全局配置的不一致,可以指定对应的逻辑删除值
    在这里插入图片描述

  • 4)、打印sql语句,调整日志级别为debug
    在这里插入图片描述
    根据日志发现删除实际是修改标记字段。
    在这里插入图片描述
    可以使用postman进行测试。
    在这里插入图片描述

3)参照role.vue的请求删除接口

在这里插入图片描述
// 8、请求后台删除接口,要有删除弹出确认框,删除完,更新menus,并且列表还是展开的状态
// 9、使用Message Box弹框,确认删除
// 10、使用Message 消息提示,确定删除成功
在这里插入图片描述
// 11、删除之后列表是展开的状态 default-expanded-keys 默认展开的节点的 key 的数组

在这里插入图片描述

5、新增

1)前端的一些简单配置

使用element ui中的对话框,使用自定义内容的打开嵌套表单的
在这里插入图片描述

在这里插入图片描述
.sync修饰符是用来实现父子组件中的数据进行双向绑定功能的。

在这里插入图片描述

如果用多个组件,必须有一个根元素

包含所有的组件
在这里插入图片描述
初始的时候,对话框为false,进行add时,设置为true

然后使用表单,model绑定数据对象

在这里插入图片描述

// 12、新增三级分类 引入element ui 的 el-dialog对话框,使用自定义内容的打开嵌套表单的
// 13、修改model的值,表单数据双向绑定
// 14、添加addCategory 方法
// 15、在category中添加对象的属性 在append方法中获取一些数据属性放到category对象中
// 16、在addCategory()方法中请求后台接口 然后 关闭对话框this.dialogVisible = false 刷新出新的菜单this.getMenus() 设置需要默认展开的菜单

2)编写后端新增三级目录接口

可以直接掉逆向生成工程里面的新增三级菜单接口
在这里插入图片描述

6、修改

// 17、添加修改按钮,直接拷贝新增的即可,且去掉if,任何时候修改按钮都是存在的
// 18、在edit方法中 设置弹出对话框 设置修改的名称 分类ID
// 19、需要在点击确认的时候到底请求的是添加还是修改,添加标识 dialogType: ‘’, // edit,add
// 20、title提示也需要修改一下,到底是添加还是修改
在这里插入图片描述
在这里插入图片描述

// 21、添加图标和计量单位
// 22、回显内容修改,多个人修改,应该发送请求获取节点最新数据
// 23、设置修改时,对话框通过点击关闭 close-on-click-modal
// 24、点击添加时,清空回显的值

在这里插入图片描述

7、修改-拖拽效果

查看element ui文档,根据tree树型控件的拖拽功能。
// 25、拖拽效果,目前只有三级目录,需要判断是否可以放置该位置 draggable 是否开启拖拽节点功能 allow-drop 拖拽时判定目标节点能否被放置。type 参数有三种情况:‘prev’、‘inner’ 和 ‘next’,分别表示放置在目标节点前、插入至目标节点和放置在目标节点后 Function(draggingNode, dropNode, type)
// 26、被拖动的当前节点以及所在的父节点总层数不能大于3
在这里插入图片描述

8、修改-获取拖拽数据集

// 27、拖拽数据收集,将修改节点的位置保存到后台 监听拖拽成功事件 Events 的node-drop 拖拽成功完成时触发的事件 共四个参数,依次为:被拖拽节点对应的 Node、结束拖拽时最后进入的节点、被拖拽节点的放置位置(before、after、inner)、event

在这里插入图片描述

后台编写批量修改功能。

9、批量拖拽效果

// 28、添加批量拖拽按钮 使用组件switch
在这里插入图片描述
在这里插入图片描述

// 29、添加保存按钮,当全部拖拽成功后,将所有的修改一次性提交后台进行修改,当拖拽按钮为开启的时候,显示,不开启时隐藏 并且从节点本身获取级别,因为拖拽一直在变化

在这里插入图片描述

10、批量删除

// 30、使用button进行批量删除 获取选中的节点 看一下tree组件的方法
// 31、要调一个组件提供的一个方法,首先要写一个ref给组件起一个唯一标识,要调el-tree封装的方法的时候,要this. r e f . t r e e . f i l t e r ( v a l ) t h i s 是 v u e 实例, ref.tree.filter(val) this是vue实例, ref.tree.filter(val)thisvue实例,ref当前vue实例所有的组件,tree是对应组件的标识名称,filter对应组件的方法
// 32、this.$confirm 弹出确定提示框,将菜单ID转为名称
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

11、总结

// 1、从element ui找到tree树型控件,引入其中,参考role.vue请求后台远程接口,获取data数据
// 2、从element ui找到对应控件的自定义节点内容,引入添加删除功能,修改内容展开为flase,这样只有点击箭头才能展开内容 :expand-on-click-node=“false”
// 3、去掉单击函数 @node-click=“handleNodeClick”
// 4、我们要做的效果是,只有没有子菜单和引用才显示Delete按钮,只有一级、二级菜单才能显示Append按钮 使用v-if进行判断
// 5、在使用remove方法时,会传入节点参数,几级节点
// 6、批量删除,只需要添加 show-checkbox
// 7、添加树中唯一节点标识,node-key 每一个节点都有一个catId
// 8、请求后台删除接口,要有删除弹出确认框,删除完,更新menus,并且列表还是展开的状态
// 9、使用Message Box弹框 确认删除
// 10、使用Message 消息提示,确定删除成功
// 11、删除之后列表是展开的状态 default-expanded-keys 默认展开的节点的 key 的数组
// 12、新增三级分类 引入element ui 的 el-dialog对话框,使用自定义内容的打开嵌套表单的
// 13、修改model的值,表单数据双向绑定
// 14、添加addCategory 方法
// 15、在category中添加对象的属性 在append方法中获取一些要添加菜单的上级菜单的数据属性放到category对象中
// 16、在addCategory()方法中请求后台接口 然后 关闭对话框this.dialogVisible = false 刷新出新的菜单this.getMenus() 设置需要默认展开的菜单
// 17、添加修改按钮,直接拷贝新增的即可,且去掉if,任何时候修改按钮都是存在的
// 18、在edit方法中 设置弹出对话框 设置修改的名称 分类ID
// 19、需要在点击确认的时候到底请求的是添加还是修改,添加标识 dialogType: ‘’, // edit,add
// 20、title提示也需要修改一下,到底是添加还是修改
// 21、添加图标和计量单位
// 22、回显内容修改,多个人修改,应该发送请求获取节点最新数据
// 23、设置修改时,对话框通过点击关闭 close-on-click-modal
// 24、点击添加时,清空回显的值
// 25、拖拽效果,目前只有三级目录,需要判断是否可以放置该位置 draggable 是否开启拖拽节点功能 allow-drop 拖拽时判定目标节点能否被放置。type 参数有三种情况:‘prev’、‘inner’ 和 ‘next’,分别表示放置在目标节点前、插入至目标节点和放置在目标节点后 Function(draggingNode, dropNode, type)
// 26、被拖动的当前节点以及所在的父节点总层数不能大于3
// 27、拖拽数据收集,将修改节点的位置保存到后台 监听拖拽成功事件 Events 的node-drop 拖拽成功完成时触发的事件 共四个参数,依次为:被拖拽节点对应的 Node、结束拖拽时最后进入的节点、被拖拽节点的放置位置(before、after、inner)、event
// 28、添加批量拖拽按钮 使用组件switch
// 29、添加保存按钮,当全部拖拽成功后,将所有的修改一次性提交后台进行修改,当拖拽按钮为开启的时候,显示,不开启时隐藏 并且从节点本身获取级别,因为拖拽一直在变化
// 30、使用button进行批量删除 获取选中的节点 看一下tree组件的方法
// 31、要调一个组件提供的一个方法,首先要写一个ref给组件起一个唯一标识,要调el-tree封装的方法的时候,要this. r e f . t r e e . f i l t e r ( v a l ) t h i s 是 v u e 实例, ref.tree.filter(val) this是vue实例, ref.tree.filter(val)thisvue实例,ref当前vue实例所有的组件,tree是对应组件的标识名称,filter对应组件的方法
// 32、this.$confirm 弹出确定提示框,将菜单ID转为名称

猜你喜欢

转载自blog.csdn.net/qq_44696532/article/details/131975333
今日推荐