11.人力资源管理项目 -_角色管理==>RBAC 设计思想、 组间通信、 数据铺设、默认选择
当页数不确定时如何获取所有页面的数据==>>先随便发一次请求,然后利用第一次请求返回的数据中的total确定总页数。
父传子时,通过watch监听props中的值的变化,给子组件中data的值进行实时赋值,便可以实现子组件data中的数据与父组件的传值实时绑定
01.权限管理-RBAC的权限设计思想
目标
- 了解传统的权限设计
- 了解 RBAC 权限设计思想
分析
- 传统权限说明
从上面的图中,我们发现,传统的权限设计是对每个人进行单独的权限设置,
但这种方式已经不适合目前企业的高效管控权限的发展需求,因为每个人都要单独去设置权限
- RBAC 权限设计思想说明
因此传统的诸多缺点,RBAC的权限模型就应运而生了,RBAC(Role-Based Access Control) ,也就是基于角色的权限分配解决方案,相对于传统方案,RBAC提供了中间层Role(角色),其权限模式如下:
RBAC 实现了用户和权限点的分离,想对某个用户设置权限,只需要对该用户设置相应的角色即可,而该角色就拥有了对应的权限,这样一来,权限的分配和设计就做到了极简,高效,当想对用户收回权限时,只需要收回角色即可,接下来,我们就在该项目中实施这一设想。
小结
-
以前我们怎么管理用户的权限, 现在怎么做的?
答案- 以前是给每个用户设置可以访问的路由页面路径列表, 或者权限来管理, 现在我们关心的是角色(类)能访问的权限, 而用户分发的是角色的身份
02.角色管理-员工分配角色弹框
目标
实现给员工分配角色的弹框展示
分析
目前系统中已经有一些角色,我们下面要将这些角色分配给不同的员工,让他们进入系统后,做不同的事情。
用户和角色是**1对多
**的关系:一个用户可以拥有多个角色,这样他就会具有这多个角色的权限了。比如公司的董事长可以查看全部的员工、可以对公司进行设置、也可以查看员工考勤
例如: 老王是董事长
方式1:
老王这个员工, 分配角色的时候, 可以分配多个角色(人事专员-权限1和2, 薪资专员-权限1和3, 考勤专员-权限4和5…) -> 老王就有很多功能
上面的分配有点麻烦, 所以更好的做法
方式2:
新建角色 -> 董事长 -> 分配权限点(1, 2, 3, 4, 5) -> 给老王设置角色就不需要上面那些小的了, 直接设置一个董事长就全有了
因为功能比较复杂,因此我们需要按照如下步骤进行开发
- 把具体的功能给拆分出去(角色的功能比较复杂,拆分组件会减轻工作量)
- 通过 Element 提供的 Dialog 组件实现弹层
实现
-
创建
src\views\employees\components\assignRoleDialog.vue
组件 -
初始化页面结构
<template>
<div>
<!-- 渲染角色列表 -->
<el-row class="footer" type="flex" justify="center">
<el-col :span="6">
<el-button type="primary" size="small">确定</el-button>
<el-button size="small" @click="cancleDialog">取消</el-button>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: 'AssignRole',
props: {
// 用户的id 用来查询当前用户的角色信息
userId: {
type: String,
default: null
}
},
data() {
return {}
},
methods: {
// 取消弹框
cancleDialog() {
this.$emit('close')
}
}
}
</script>
<style lang="scss" scoped>
.footer {
margin-top: 30px;
}
</style>
- 导入组件,在
src/views/employees/index.vue
并放置到弹框中
import AssignRoleDialog from './components/assignRoleDialog.vue'
components: {
AssignRoleDialog
}
<!-- 员工-分配角色权限 - 弹窗 -->
<el-dialog title="分配角色" :visible="showRoleDialog" @close="cancleDialog">
<!-- 设置角色组件 -->
<assign-role-dialog @close="showRoleDialog = false" />
</el-dialog>
// 关闭分配角色弹框
cancleDialog() {
this.showRoleDialog = false
}
- 点击分配角色绑定事件处理程序,并传递 ID
<el-button type="text" size="small" @click="setEmp(scope.row.id)">分配角色</el-button>
- 在对应的事件处理中
- 接收 ID,并传递给组件
- 让弹框展示
- data里定义userId: ‘’ 变量
// 分配角色
setEmp(id) {
this.userId = id
this.showRoleDialog = true
}
<!-- 设置角色组件 -->
<assign-role-dialog :user-id="userId" @close="showRoleDialog = false" />
-
子组件内接收userId变量, 在
src/views/employees/components/assignRoleDialog.vue
中其实这一步已经在上面埋伏好了
props: { // 用户的id 用来查询当前用户的角色信息 userId: { type: String, default: null } }
小结
-
角色分配我们要做什么效果?
答案- 弄一个弹框, 把内部的内容单独封装一个组件
03.角色管理-获取角色列表并用渲染
目标
- 学习 Checkbox 多选框 组件的使用
- 获取角色列表数据
- Checkbox + 列表数据,渲染角色列表结构
分析
- 学习 Checkbox 多选框 的使用
- 准备 api 接口发送请求获取后端数据
- 开始渲染角色列表的结构
组件学习
- 页面结构
- v-model的值是数组(表示多选)
- 它的子元素el-checkbox的label属性决定了选中这一项之后值
<!-- 渲染角色列表 -->
<el-checkbox-group v-model="roleIdArr">
<el-checkbox label="复选框 A" />
<el-checkbox label="复选框 B" />
<el-checkbox label="复选框 C" />
</el-checkbox-group>
<script>
export default {
data () {
return {
roleIdArr: [] // 保存当前选中的权限列表
}
}
}
</script>
实现
-
导入获取角色列表的方法, 在
src/views/employees/index.vue
引入使用, 然后传值进入到弹窗组件在api/setting.js中已经定义过了, 直接导入使用
import { getRolesAPI } from '@/api'
-
调用该方法,获取角色列表数据
data() { return { roleIds: [], // 被选中项 roleList: [] // 角色列表数据 } }, created() { // ...其他 // 获取所有角色信息 this.getRoleListFn() }, methods: { // 获取角色列表 async getRoleListFn() { const res = await getRolesAPI() this.roleList = res.data.rows } }
-
向子组件传值进入
<!-- 员工-分配角色权限 - 弹窗 --> <el-dialog title="分配角色" :visible="showRoleDialog" @close="cancleDialog"> <!-- 设置角色组件 --> <assign-role-dialog :user-id="userId" :role-list="roleList" @close="showRoleDialog = false" /> </el-dialog>
-
在
views/employees/components/assignRoleDialog.vue
中接收传递过来的角色数组数据props: { // ... // 接收所有角色数据 roleList: { type: Array, required: true } }
小结
-
我们为何要把数组定义在逻辑页面, 传入, 写子组件里也行, 那为何还要写在外面?
答案- 组件一般接收数据展示, 或者有一些事件, 触发传回到逻辑页面, 而且我们在用一些第三方封装的组件也是这个思想, 组件只负责展示数据和一些简单的交互
04.角色管理-获取员工已有角色数据并回填
目标
获取员工已有的数据,将获取到的数据回填到复选框内
分析
- 首先需要获取到当前员工已有的权限
- 将获取到的员工数据中的 roleIds 权限字段赋值给 data 中的 roleIds
实现
-
在
api/employees.js
里其实已经定义过了, 改个注释/** * @description: 获取用户详细信息 * @param {*} id 用户id * @return {*} */ export function getUserDetailByIdAPI(id) { return request({ url: `/sys/user/${id}` }) }
-
导入获取员工详情的 API
import { getUserDetailByIdAPI } from '@/api'
-
调用获取员工详情数据的方法
methods: { // 调用员工详情数据 async getUserRoles() { const infoRes = await getUserDetailByIdAPI(this.userId) if (!infoRes.success) return this.$message.error(infoRes.message) this.roleIds = infoRes.data.roleIds }, // ...其他 // 分配角色-按钮点击事件 // 分配角色 setEmp(id) { this.userId = id this.showRoleDialog = true // 获取员工详细数据 this.getUserRoles() } }
小结
-
为什么我们一直在请求准备数据, 不在组件内渲染呢?
答案- 因为根据需求发现, 我们需要全部的角色信息列表, 还需要当前登录的这个用户的角色信息, 所以先准备好2个数组的数据, 再去铺设, 还可以设置默认选中哪些. 所以先准备好数据, 一会儿铺设
05.角色管理-数据铺设和默认选择
目标
把角色信息, 在弹窗组件中显示, 并接收用户选择的数据
讲解
-
在子组件
employees/components/assignRoleDialog.vue
中, 铺设数据<!-- 渲染角色列表 --> <el-checkbox-group v-model="roleIdArr"> <el-checkbox v-for="obj in roleList" :key="obj.id" :label="obj.name" :value="obj.id" /> </el-checkbox-group>
-
设置默认的选择
在内部监听外面传入值的变化, 同步给子组件内私有变量, 影响上面多选框的选择
watch: { roleIds() { this.roleIdArr = this.roleIds } },
小结
-
默认选择如何做的?
答案- 复选框v-model设置数组, 默认和每个value匹配上, 默认就选中了
06.角色管理-完成角色管理的分配
目标
给员工选定角色,同步到服务器,实现角色管理的分配
分析
- 封装角色管理分配的 API
- 点击确定,调用接口,完成角色分配
实现
- 在
src\api\employees.js
文件中封装角色管理分配的 API
/**
* @description: 为员工分配角色
* @param {*} data { id:当前用户id, roleIds:选中的角色id组成的数组 }
* @return {*}
*/
export function assignRolesAPI(data) {
return request({
url: '/sys/user/assignRoles',
data,
method: 'put'
})
}
-
点击确定,调用接口,完成角色分配, 把数组返回给父组件, 在子组件
employees/components/assignRoleDialog.vue
实现<el-button type="primary" size="small" @click="confirmFn">确定</el-button>
-
对应点击事件的方法
// 确定-点击事件 confirmFn() { this.$emit('confirm', this.roleIdArr) }
-
在父级
src/employees/index.vue
中, 接收事件和选择的角色id的数组<!-- 员工-分配角色权限 - 弹窗 --> <el-dialog title="分配角色" :visible="showRoleDialog" @close="cancleDialog"> <!-- 设置角色组件 --> <assign-role-dialog :user-id="userId" :role-list="roleList" :role-ids="roleIds" @close="showRoleDialog = false" @confirm="addRoleFn" /> </el-dialog>
-
对应父级的事件方法
import { assignRolesAPI } from '@/api'
methods: { // 子组件弹窗 - 点击确定 - 员工角色分配 async addRoleFn(roleIds) { // 调用 API,传入参数 const res = await assignRolesAPI({ id: this.userId, roleIds: roleIds }) if (!res.success) return this.$message.error(res.message) // 员工分配成功,给用户提示 this.$message.success(res.message) // 关闭弹框 this.showRoleDialog = false // 重新获取当前当前列表数据 this.getEmployeeList() } }
小结
-
角色管理-角色分配传递什么类型数据给后台
答案- 外层是对象, 里面是角色id的数组给后台, 但其实会被axios转成json字符串发给后台