前言
目录
一、权限管理的设计思想
我们项目使用的是RBAC的权限模型,RBAC(Role-Based Access control) ,也就是基于角色的权限分配解决方案,相对于传统方案,RBAC提供了中间层Role(角色),其权限模式如下:
RBAC实现了用户和权限点的分离,想对某个用户设置权限,只需要对该用户设置相应的角色即可,而该角色就拥有了对应的权限,这样一来,权限的分配和设计就做到了极简,高效,当想对用户收回权限时,只需要收回角色即可
二、给员工分配角色
2.1 分配角色弹窗效果图
2.1 新建分配角色对话框组件
用户和角色是1对多的关系,即一个用户可以拥有多个角色
在src/views/employees/components/目录下新建assign-role.vue组件:
<template>
<el-dialog title="分配角色" :visible="showRoleDialog">
<!-- el-checkbox-group选中的是 当前用户所拥有的角色 需要绑定 当前用户拥有的角色-->
<el-checkbox-group>
<!-- 选项 -->
</el-checkbox-group>
<el-row slot="footer" type="flex" justify="center">
<el-col :span="6">
<el-button type="primary" size="small">确定</el-button>
<el-button size="small">取消</el-button>
</el-col>
</el-row>
</el-dialog>
</template>
<script>
export default {
props: {
showRoleDialog: {
type: Boolean,
default: false
}
}
}
</script>
2.2 获取角色列表
在src/views/employees/components/assign-role.vue中添加如下代码:
<!-- 分配角色 -->
<el-checkbox-group v-model="roleIds">
<el-checkbox v-for="item in list" :key="item.id" :label="item.id">
{
{
item.name
}}
</el-checkbox>
</el-checkbox-group>
import {
getRoleList } from '@/api/setting'
export default {
props: {
showRoleDialog: {
type: Boolean,
default: false
},
userId: {
type: String,
default: null
}
},
data() {
return {
list: [], // 角色列表
}
},
created() {
this.getRoleList()
},
methods: {
// 获取所有角色
async getRoleList() {
const {
rows } = await getRoleList()
this.list = rows
}
}
}
2.3 获取当前用户的角色信息
首先,在src/views/employees/components/assign-role.vue中定义获取角色信息的方法:
import {
getUserDetailById } from '@/api/user'
async getUserDetailById(id) {
const {
roleIds } = await getUserDetailById(id)
this.roleIds = roleIds // 赋值本用户的角色
}
然后,在src/views/employees/index.vue中调用子组件方法:
<el-button type="text" size="small" @click="editRole(row.id)">角色</el-button>
<!-- 放置角色分配组件 -->
<assign-role ref="assignRole" :show-role-dialog.sync="showRoleDialog" :user-id="userId" />
// 编辑角色
async editRole(id) {
this.userId = id // props传值 是异步的
await this.$refs.assignRole.getUserDetailById(id) // 父组件调用子组件方法
this.showRoleDialog = true
},
2.4 点击确定按钮给用户分配角色
首先,在src/api/employees.js中封装分配角色的请求:
/** *
* 给用户分配角色
* ***/
export function assignRoles(data) {
return request({
url: '/sys/user/assignRoles',
data,
method: 'put'
})
}
然后,在src/views/employees/components/assign-role.vue中绑定按钮点击事件:
<el-button type="primary" size="small" @click="btnOK">确定</el-button>
<el-button size="small" @click="btnCancel">取消</el-button>
async btnOK() {
await assignRoles({
id: this.userId, roleIds: this.roleIds })
// 关闭窗体
this.$emit('update:showRoleDialog', false)
},
//点击取消或关闭对话框时调用
btnCancel() {
this.roleIds = [] // 清空原来的数组
this.$emit('update:showRoleDialog', false)
}
三、权限管理页面
3.1 权限管理页面效果图
3.2 权限管理页面的基础布局
在src/views/permission/index.vue中添加如下代码:
<template>
<div class="dashboard-container">
<div class="app-container">
<!-- 靠右的按钮 -->
<page-tools>
<template v-slot:after>
<el-button type="primary" size="small">添加权限</el-button>
</template>
</page-tools>
<!-- 表格 -->
<el-table border>
<el-table-column align="center" label="名称" />
<el-table-column align="center" label="标识" />
<el-table-column align="center" label="描述" />
<el-table-column align="center" label="操作">
<template>
<el-button type="text">添加</el-button>
<el-button type="text">编辑</el-button>
<el-button type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
3.3 封装权限管理相关请求
在src/api/permisson.js中添加如下代码:
// 获取权限
export function getPermissionList(params) {
return request({
url: '/sys/permission',
params
})
}
// 新增权限
export function addPermission(data) {
return request({
url: '/sys/permission',
method: 'post',
data
})
}
// 更新权限
export function updatePermission(data) {
return request({
url: `/sys/permission/${
data.id}`,
method: 'put',
data
})
}
// 删除权限
export function delPermission(id) {
return request({
url: `/sys/permission/${
id}`,
method: 'delete'
})
}
// 获取权限详情
export function getPermissionDetail(id) {
return request({
url: `/sys/permission/${
id}`
})
}
3.4 获取权限数据
我们通过树形操作方法,将列表转化成层级数据,这里需要给el-table配置row-key属性 id才可显示树形结构
在src/views/permission.js中添加如下代码:
<el-table :data="list" border="" row-key="id">
<el-table-column label="名称" prop="name" />
<el-table-column label="标识" prop="code" />
<el-table-column label="描述" prop="description" />
<el-table-column label="操作">
<template slot-scope="{ row }">
<el-button type="text" >添加</el-button>
<el-button type="text" >编辑</el-button>
<el-button type="text" >删除</el-button>
</template>
</el-table-column>
</el-table>
<script>
import {
getPermissionList } from '@/api/permission'
import {
transListToTreeData } from '@/utils'
export default {
data() {
return {
list: [],
}
},
created() {
this.getPermissionList()
},
methods: {
async getPermissionList() {
this.list = transListToTreeData(await getPermissionList(), '0')
}
}
}
</script>
3.5 新增、编辑和删除权限
在src/views/permission.js中新建新增和编辑权限对话框:
<!-- 靠右的按钮 -->
<page-tools>
<template v-slot:after>
<el-button type="primary" size="small" @click="addPermission(1, '0')">添加权限</el-button>
</template>
</page-tools>
<!-- 添加按钮只在 访问权的层级显示 当type==1 时才显示添加按钮 -->
<el-button v-if="row.type === 1" type="text" @click="addPermission(2, row.id)">添加</el-button>
<el-button type="text" @click="editPermission(row.id)">编辑</el-button>
<el-button type="text" @click="delPermission(row.id)">删除</el-button>
<!-- 放置一个弹层 用来编辑新增节点 -->
<el-dialog :title="`${showText}权限点`" :visible="showDialog" @close="btnCancel">
<!-- 表单 -->
<el-form ref="perForm" :model="formData" :rules="rules" label-width="120px">
<el-form-item label="权限名称" prop="name">
<el-input v-model="formData.name" style="width:90%" />
</el-form-item>
<el-form-item label="权限标识" prop="code">
<el-input v-model="formData.code" style="width:90%" />
</el-form-item>
<el-form-item label="权限描述">
<el-input v-model="formData.description" style="width:90%" />
</el-form-item>
<el-form-item label="开启">
<el-switch
v-model="formData.enVisible"
active-value="1"
inactive-value="0"
/>
</el-form-item>
</el-form>
<el-row slot="footer" type="flex" justify="center">
<el-col :span="6">
<el-button size="small" type="primary" @click="btnOK">确定</el-button>
<el-button size="small" @click="btnCancel">取消</el-button>
</el-col>
</el-row>
</el-dialog>
绑定数据:
import {
updatePermission, addPermission, getPermissionDetail, delPermission, getPermissionList } from '@/api/permission'
data() {
return {
list: [],
showDialog: false,
formData: {
name: '', // 名称
code: '', // 标识
description: '', // 描述
type: '', // 类型 该类型 不需要显示 因为点击添加的时候已经知道类型了
pid: '', // 因为做的是树 需要知道添加到哪个节点下了
enVisible: '0' // 开启
},
rules: {
name: [{
required: true, message: '权限名称不能为空', trigger: 'blur' }],
code: [{
required: true, message: '权限标识不能为空', trigger: 'blur' }]
}}
},
computed: {
showText() {
return this.formData.id ? '编辑权限' : '新增权限'
}
},
methods: {
delPermission(id) {
this.$confirm('确认删除该权限点吗').then(() => {
return delPermission(id)
}).then(() => {
this.$message.success('删除成功')
// 重新拉取数据
this.getPermissionList()
})
},
addPermission(type, pid) {
// 访问权的type = 1 按钮操作的权type =2
// pid表示当前数据的父节点的标识
// 记录当前添加的类型和父标识
this.formData.type = type
this.formData.pid = pid
this.showDialog = true
},
async editPermission(id) {
this.formData = await getPermissionDetail(id)
this.showDialog = true
}
btnOK() {
this.$refs.permForm.validate().then(() => {
// 校验成功
if (this.formData.id) {
// 认为是编辑
return updatePermission(this.formData)
}
return addPermission(this.formData) // 新增接口
}).then(() => {
// 添加成功
this.$message.success('操作成功')
this.getPermissionList()
this.showDialog = false
})
},
btnCancel() {
// 重置数据
this.formData = {
name: '', // 名称
code: '', // 标识
description: '', // 描述
type: '', // 类型 该类型 不需要显示 因为点击添加的时候已经知道类型了
pid: '', // 因为做的是树 需要知道添加到哪个节点下了
enVisible: '0' // 开启
}
// 移除校验
this.$refs.permForm.resetFields() // 移除校验
this.showDialog = false
},
}
四、给角色分配权限
4.1 分配权限效果图
4.2 封装分配权限的请求
在src/api/setting.js中添加如下代码:
// 给角色分配权限
export function assignPerm(data) {
return request({
url: '/sys/role/assignPrem',
method: 'put',
data
})
}
4.3 新建分配权限弹窗
在src/views/settings/index.vue中添加弹窗基本布局:
<!-- 点击分配权限按钮 -->
<el-button size="small" type="success" @click="assignPerm(row.id)">分配权限</el-button>
<!-- 放置一个弹层 -->
<el-dialog title="分配权限" :visible="showPermDialog" @close="btnPermCancel">
<!-- 权限是一颗树 -->
<!-- 将数据绑定到组件上 -->
<!-- check-strictly 如果为true 那表示父子勾选时 不互相关联 如果为false就互相关联 -->
<!-- id作为唯一标识 -->
<el-tree
ref="permTree"
:data="permData"
:props="defaultProps"
:show-checkbox="true"
:check-strictly="true"
:default-expand-all="true"
:default-checked-keys="selectCheck"
node-key="id"
/>
<!-- 确定 取消 -->
<el-row slot="footer" type="flex" justify="center">
<el-col :span="6">
<el-button type="primary" size="small" @click="btnPermOK">确定</el-button>
<el-button size="small" @click="btnPermCancel">取消</el-button>
</el-col>
</el-row>
</el-dialog>
绑定数据:
import {
getRoleDetail, assignPerm } from '@/api/setting'
import {
transListToTreeData } from '@/utils'
import {
getPermissionList } from '@/api/permission'
data() {
return {
showPermDialog: false, // 控制分配权限弹层的显示或者隐藏
permData: [], // 接收权限数据
defaultProps: {
label: 'name'
}, // 定义显示字段的名称 和 子属性的字段名称
roleId: null, // 用来记录当前分配权限的id
selectCheck: [] // 用来记录当前的权限点的标识
}
},
methods: {
// 点击分配权限
// 获取权限点数据 在点击的时候调用 获取权限点数据
async assignPerm(id) {
this.permData = tranListToTreeData(await getPermissionList(), '0') // 转化list到树形数据
this.roleId = id
// 应该去获取 这个id的 权限点
// 有id 就可以 id应该先记录下来
const {
permIds } = await getRoleDetail(id) // permIds是当前角色所拥有的权限点数据
this.selectCheck = permIds // 将当前角色所拥有的权限id赋值
this.showPermDialog = true
},
async btnPermOK() {
// 调用el-tree的方法
await assignPerm({
permIds: this.$refs.permTree.getCheckedKeys(), id: this.roleId })
this.$message.success('分配权限成功')
this.showPermDialog = false
},
btnPermCancel() {
this.selectCheck = [] // 重置数据
this.showPermDialog = false
}
}