尚品汇后台管理系统
尚品汇后台管理系统
- 1、登录(退出登录)
- 2、路由设置(***)
- 路由表component属性
- 3、品牌列表模块
- 3.1 el-pagination layout属性
- 3.2 封装四个模块api
- 3.3 this滥用和参数解构
- 3.4 品牌列表展示(插槽)
- 3.5 品牌信息新增和修改
- 3.6 表单验证
- 3.7 删除品牌信息
- 4、商品属性
- 4.1 三级联动
- 4.2 商品属性展示
1、登录(退出登录)
后台接口swagger在线文档:
后台接口1
后台接口2
1、将所有的api接口url更换为和swagger在线文档相同的url。
2、跨域解决
devServer部分(proxy代理解决跨域)
记得重启项目
3、切记将请求拦截器的X-Token改为token,否则后台会返回jwt空错误。
config.headers['token'] = getToken()
退出登录部分可以不做修改。
2、路由设置(***)
路由部分代码
export const constantRoutes = [{path: '/login',component: () => import('@/views/login/index'),hidden: true},{path: '/404',component: () => import('@/views/404'),hidden: true},{path: '/',component: Layout,redirect: '/dashboard',children: [{path: 'dashboard',name: 'Dashboard',component: () => import('@/views/dashboard/index'),meta: { title: '首页', icon: 'dashboard' }}]},{path: '/product',name: 'Product',component: Layout,meta: { title: '商品管理', icon: 'el-icon-goods' },children: [{path: 'trademark',name: 'TradeMark',component: () => import('@/views/tradeMark'),meta: { title: '品牌管理' }}, {path: 'attr',name: 'Attr',component: () => import('@/views/Attr'),meta: { title: '平台属性管理' }}, {path: 'sku',name: 'Sku',component: () => import('@/views/Sku'),meta: { title: 'Sku管理' }}, {path: 'spu',name: 'Spu',component: () => import('@/views/Spu'),meta: { title: 'Spu管理' }}]},// 404 page must be placed at the end !!!{ path: '*', redirect: '/404', hidden: true } ]路由表component属性
component用法一:
path: 'trademark', name: 'TradeMark', component: () => import('@/views/tradeMark'),当访问path为trademark时,会显示tradeMark这个组件。上面只是component最简单的应用。
component用法二
如果一个路由只是一个菜单项,并不对应相应的组件,那么此时的component为本菜单项所在的路由组件。
例如:上面代码中product只是一个菜单项,并不对应相应组件。所以他的component应该为他所在的组件,即component: Layout。trademark为子菜单项,有具体对应的组件,所以component: () => import('@/views/tradeMark'),trademark的component原理就是用法一。
前端菜单栏显示的实现具体如下:
遍历路由信息数组,将路由项渲染为菜单项。菜单项的信息在路由信息中获取。
(1)如果路由项只有一个子路由,则将该子路由信息作为作为菜单项信息。
(2)如果路由项有多个子路由,将父路由信息作为一级菜单项信息。然后,遍历所有的子路由,生成相应的二级菜单项。
这个前端菜单项显示代码值得研究,写的非常好。
3、品牌列表模块
3.1 el-pagination layout属性
layout是指分页器各组件的排列方式,例如:
layout=" prev, pager, next, jumper,->,sizes,total"
->后面的组件会被放在页面的最右边。如下图所示:
3.2 封装四个模块api
四个模块分别为attr、sku、spu、tradeMark。
每个模块的api封装为对应的js文件,如下图所示:
为了方便使用,将四个模块再次封装到一个js文件中,然后统一暴露。
这样如果我们使用时,只需要import这个js文件就可以使用了,但是为了更加简介,我们可以将这个js文件在main.js中注册,将其是设置为全局属性。
之后在组件中使用四个模块的api函数时,可直接通过this.$API.函数名调用。
3.3 this滥用和参数解构
data中的数据十分常用,当我们使用时可能会频繁的通过this.使用data中的数据,这样容易发生滥用this去读取data中数据,程序性能会下降。具体原因链接描述
解决方法:ES6允许我们通过参数解构来避免this的滥用。
例如,getPageList函数需要使用page, limit两个属性。直接const { page, limit } = this解构出这两个属性。
export default {name: 'TradeMark',data() {return {page: 1,limit: 3}},mounted() {this.getPageList()},methods: {getPageList() {const { page, limit } = thisthis.$API.trademark.getTradeMarkInfo(page, limit)}} }3.4 品牌列表展示(插槽)
1、获取数据函数
设置了pager = 1参数,调用时,如果传值就会将值赋给pager ,如果不传pager = 1。即默认获取的是第一页数据。
2、需要注意的是插槽的使用。我们需要通过插槽获取父组件数据。
el-table插槽使用方法:
品牌logo列使用了插槽。所以通过一下代码探究插槽的使用
下面三个箭头分别对应slot-scope="{row, column, $index}中的row, column, $ index。
row表示表格当前一行的全部信息;
column表示当前列的一些属性;
$index表示当前行数据在整个数据数组中的下标。
这里我们只需要用到当前行所包含的品牌logo图片链接,所以只需要使用row,完整代码如下:
3、分页器修改页面大小和修改当前页码都比较简单,直接贴代码。
// 修改当前页码handleCurrentChange(current) {this.getPageList(current)},// 修改页面大小handleSizeChange(size) {this.limit = sizethis.getPageList()},注意:handleSizeChange中的getPageList需要带参数,因为getPageList定义了默认参数pager=1,如果不传入current,则getPageList的默认参数pager=1就会生效,就会一直请求第一页数据。
3.5 品牌信息新增和修改
1、头像上传组件
新增中比较重要的时头像上传组件,代码如下
图片数据不能用v-model绑定,
action 必选参数,上传的地址。这里的 action取值是上传图片的接口,是后台提供好的接口。
before-upload表示上传成功前的函数
on-success表示上传成功后的函数
handleAvatarSuccess(res, file) {// res是上传成功后返回给前端的数据// file是上传成功后服务器返回给前端的数据this.tmFrom.logoUrl = URL.createObjectURL(file.raw)}上面两个函数饿了吗UI官网都以给出,理解即可。
2、新增和修改函数
新增和修改按钮使用的是同一个弹窗。
(1)点击添加按钮显示弹窗
记得清空上次操作的数据
(2)点击修改按钮显示弹窗(浅拷贝问题)
this.$tmFrom = row会使得二者同时指向数据的引用,当修改tmFrom表单项时,表格中数据也会改变,如果修改后点了取消按钮,表格中数据会发生改变。所以,要解决浅拷贝
当赋值的对象row中还有对象元素时,又会出现上面的问题,所以可以通过深拷贝JSON.parse(JSON.stringfy())实现。
(3)击弹窗的确定按钮实现数据的修改或新增
新增和修改成功后,需要再次获取品牌信息。需要注意,如果时新增则刷新后显示第一页,如果是修改,则要在当前页刷新显示。
新增或修改品牌API函数
// 新增或修改品牌 export const addOrUpdateTradeMark = (tradeMark) => {// 有id则为修改if (tradeMark.id) {return request({ url: 'admin/product/baseTrademark/update', method: 'put', data: tradeMark })}// 无id则为新增return request({ url: 'admin/product/baseTrademark/save', method: 'post', data: tradeMark }) }3.6 表单验证
表单验证,主要分以下几步:
(1)定义rules
(2)表单绑定rules,表单项prop绑定验证属性
(3)提交表单时触发的函数内,先进行表单验证,如果成功执行后续操作,否则弹出失败。
3.7 删除品牌信息
(1)气泡确认框
@onConfirm="deleteTradeMark(row)"绑定的是删除函数
(2)删除函数
删除成功后要刷新页面。
示例:
4、商品属性
4.1 三级联动
(1)三级联动静态组件
示例
由于多个页面都使用到了上面的el-card,所以将其封装为全局组件。
main.js
注意:虽然该全局组件的名字是CategorySelect ,但是在使用时最好用后面的形式<category-select></category-select>。
原因:html不区分大小写,会将大写字母转换为小写,并在前面加-。即CategorySelect 转换为category-select
(2)三级联动数据展示
示例:
html静态代码
data属性
data() {return {category1List: [],category2List: [],category3List: [],formList: {category1: '',category2: '',category3: ''}}注意:formList内容是三个选择框选中属性的id。后续也是通过id去查询。
针对于选中一级属性后,自动获取二级属性列表,选中二级属性后,再自动获取三级属性列表问题。
最初思路:通过computed或者watch去实现,但都没有成功。
老师的方法:通过给选择框添加@change属性,再回调函数内去获取下一级属性列表。
@change绑定的获取三级列表函数都比较简单,这里就不过多描述。
// 获取一级分类// 获取一级分类async getCategory1List() {const result = await this.$API.attr.reqCategory1List()if (result.code === 200) {this.category1List = result.data} else {alert(result.message)}},// 通过选中一级属性id获取二级属性列表async getCategory2List() {// 当一级分类改变时,上一次选择的二级和三级分类应设置为空this.category2List = []this.category3List = []this.formList.category2 = ''this.formList.category3 = ''const result = await this.$API.attr.reqCategory2List(this.formList.category1)if (result.code === 200) {this.category2List = result.data} else {alert(result.message)}},// 通过选中二级属性id获取三级属性列表async getCategory3List() {// 当二级分类改变时,上一次选择的三级分类应设置为空this.category3List = []this.formList.category3 = ''const result = await this.$API.attr.reqCategory3List(this.formList.category2)if (result.code === 200) {this.category3List = result.data} else {alert(result.message)}},(3)将选中的三级分类id传递给父组件
这里是通过点击查询按钮实现的父子组件通信
查询按钮绑定的回调
父组件
<category-select @getCategoryId="getCategoryId"></category-select>父组件data
data() {return {category1Id: '',category2Id: '',category3Id: ''}},父子组件通信,父组件的接收函数:getCategoryId函数
只有当三级id不为空时,才发请求。
4.2 商品属性展示
通过三级联动获取到要展示的属性id后,接下来就是通过该id请求数据,然后展示。
总结
- 上一篇: Java8新特性Stream
- 下一篇: 计算机组成原理—— 指令系统