权限管理
- 权限管理是后台管理系统的核⼼功能,要给不同⼯作岗位的⽤户分配不同的操作权限,就需要进⾏权限管理。
- 权限管理内部⼜划分为以下⼏个部分:菜单权限、资源权限、⻆⾊。
菜单权限
控制登录到后台的用户能访问到哪些后台菜单页面,如负责课程的人员只能看到课程管理,负责广告的人员只能看到广告管理,就需要进行不同的菜单权限分配。
资源权限
- 资源对应的就是接口,资源权限用于控制用户能操作哪些接口功能,例如分配资源权限时没有🈲用用户权限,指的是没有操作这个接口的权限。
- 资源权限与菜单权限不冲突,例如有的用户能看到用户管理页面,也可以添加用户(有权限操作新增用户接口),但无法进行禁用用户操作(无禁用用户的接口权限)
角色
- 代表了菜单权限和资源权限的一种组合方式,例如设置多个用户需要相同的菜单权限与资源权限,就可以将这些权限组合起来,设置为:角色,再将角色分配给用户以简化操作。
- 所以在项目中,不会直接对某个用户进行菜单权限和资源权限的分配,而是提前根据岗位清空设定不同的角色,再将角色分配给用户。
功能关系
- 用户需要分配角色,角色需要分配菜单权限和资源权限。
- 由于功能之间存在依赖,因此先从菜单权限与资源权限功能开始制作,后面再依次完成角色与用户功能。
添加菜单布局与数据绑定
- 使用form表单,进行布局
- Postman测试接口,数据传递成功后,复制到项目中进行运行
- 注意
<!-- 此处的 :label 的值,会随着用户的选择动态的传递给form.shown -->
<el-form-item label="是否显示">
<el-radio-group v-model="form.shown">
<el-radio :label="true">是</el-radio>
<el-radio :label="false">否</el-radio>
</el-radio-group>
</el-form-item>
- 提交表单(先验证数据,再提交表单)
- 封装请求在serives/menu.js文件中
- utils/request.js是全局都可以使用的请求文件
上级菜单处理
- 上级菜单需要请求真实的数据
- 分析:上级菜单数据需要请求接口得到,并渲染在模板中
- 用于获取菜单的接口有两个,获取所有菜单和获取编辑菜单页面信息。观察功能示例发现菜单只有一级和二级。而二级菜单无法作为“上一级菜单”使用,所以这里使用第二个接口进行操作。
- 注解
// parentId=-1 表示当前为一级菜单,没有上级菜单
// parentId = 1 表示当前为二级菜单,上级菜单为一级菜单
添加菜单中的显示上级菜单功能
- 主要看
- 因此这里新增菜单功能中的id可以传入-1,重要的不是获取新增菜单本身的信息,而是在于获取所有上一级菜单页面信息parentMenuList
- parentMenuList字段信息,内部的每个元素均为⼀级菜单,元素如具有subMenuList 则说明存在⼦菜单(⼆级菜单)。
编辑菜单中的显示上级菜单功能
- 主要看
- 因此这里需要注重的是查看当前编辑菜单的信息,在menuInfo中获取其上级菜单id,再进行显示。
展示菜单列表
- 区别开:菜单整体用的是card卡片组件,而下方用的是table表格组件
- 注意:每次接收请求后,都要判断“处理结果code”是否正确,再将数据进行赋值
菜单删除
- 无法删除默认的菜单
- 功能分析:记录当前内容的id,在后台数据库中删除,需要请求接口
- 注意两种参数书写方式
编辑菜单
- 通过观察发现,添加菜单和编辑菜单的组件结构几乎相同,可以封装为create-or-edit.vue组件进行使用
- 1.引入子组件
import CreateOrEdit from './components/create-or-edit' - 2.注册子组件
export default { name: 'MenuEdit', components: { // 2.注册子组件 CreateOrEdit } } - 3.使用子组件
<template> <div class="menu-edit"> <!-- 3.使用子组件 --> <create-or-edit></create-or-edit> </div> </template>
- 1.引入子组件
布局处理(新思路)
- 创建 menu/components/create-or-edit.vue组件,将 menu/create.vue 内容复制到 create-or-edit.vue 中
- 通过不同页面的引入,更改标题name('添加菜单'or'编辑菜单')
<span>{{ isEdit ? '编辑菜单' : '添加菜单' }}</span>- create-or-edit 组件通过 prop 接收⽗组件数据isEdit 来判断要展示哪种结构
// 接收⽗组件传值,判断是添加还是编辑功能 props: { isEdit: { // 要求类型为布尔,默认值 false type: Boolean, default: false } } - 将菜单编辑添加到路由表中。由于编辑为某个菜单的编辑,应设置动态路由展示菜单项id。
path: '/menu/:id/edit'
逻辑处理(重要)
- 编辑功能中,create-or-edit 的表单不需要重置按钮,通过v-if 判断。
- 编辑时,将要编辑的菜单项信息展示在表单中。
- 之前操作中分析过,getEditMenuInfo 接⼝在编辑功能时可以获取到菜单信息,添加时为空。
- 这⾥需要将动态路由参数传⼊,并给添加功能设置默认值-1。将响应数据中的 menuInfo 赋值给 data 中的 data.form 即可(属性名是对应的)。
async loadMenuInfo () { // 因为添加了编辑功能,所以需要合并 const id = this.$route.params.id || -1 // 通过请求数据获取到上级菜单信息 const { data } = await getEditMenuInfo(id) if (data.code === '000000') { // 分情况,编辑 显示当前id的菜单内容 || 添加不显示 if (data.data.menuInfo) { // 编辑菜单 this.form = data.data.menuInfo } this.parentMenuList = data.data.parentMenuList } } - 由于添加与编辑是同⼀个接⼝,区别在于编辑时多了参数 id ,由于提交时传⼊的为 form 数据,编辑提交时就会⾃动包含id,所以提交操作⽆需处理,编辑功能完成。
回顾 动态路由
回顾 模板字符串
回顾slot组件插槽
- 应用:父组件便捷的给子组件内部插入数据
- 组件两标签内部是不能书写内容的,会被忽略
单个插槽
-
当在子组件内部添加
<slot></slot>,就可以在组件的内部书写内容,而且可以每次的内容不同 -
子组件的数据是无法在父组件中展示的。
-
父组件视图模板,只能加载父组件的数据。(全部加载完成后,在传给子组件)
-
-
后备内容:当父组件没有传值时,就可以展示默认内容
具名插槽
- 没有名字的slot标签,默认为default
- template只是一个占位符,标记某一块区域做统一处理。
<!-- 父组件 -->
<div class="container">
<header>
<slot name="header"></slot>
</header>
</div>
<!-- 子组件 -->
<!-- v-slot只能在template中使用 -->
<com-a>
<template v-slot:header>
<h1>组件头部内容</h1>
</template>
</com-a>
<!-- 简写 -->
<com-a>
<template #header >
<h1>组件头部内容</h1>
</template>
</com-a>
作用域插槽
- 解决:使用插槽时,父组件视图模板,不能加载子组件的数据问题。
- 如果只存在默认插槽,同时又需要接收数据,可以进行简写
<!-- 简写,唯一一种将v-slot写在不是template之上,只适用于有一个插槽的情况 -->
<div id="app">
<com-a v-slot:default="dataObj">
{{ dataObj.value }}
</com-a>
</div>
<!-- 最终简化 -->
<div id="app">
<com-a v-slot="dataObj">
{{ dataObj.value }}
</com-a>
</div>
<!-- 根据ES6解构还可以进行简写 -->
<div id="app">
<com-a v-slot="{ value, num }">
{{ value }}
{{ num }}
</com-a>
</div>