项目仓库:https://github.com/changeclass/vue-shop

创建子分支并推送

1
2
git checkout -b rights
git push -u origin rights

权限管理标签

根据不同等级分配不同颜色的标签。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<el-table :data="rightsList" border stripe>
<el-table-column type="index"></el-table-column>
<el-table-column label="权限名称" prop="authName"></el-table-column>
<el-table-column label="路径" prop="path"></el-table-column>
<el-table-column label="权限等级" prop="level">
<template v-slot="scoped">
<el-tag v-if="scoped.row.level == 0">一级</el-tag>
<el-tag type="success" v-else-if="scoped.row.level == 1"
>二级</el-tag
>
<el-tag type="warning" v-else>三级</el-tag>
</template>
</el-table-column>
</el-table>

权限管理列表

将权限赋予某个角色,再将角色赋予给用户。

image-20201107102200891

权限列表使用了展开列,将el-table-columntype值改为expand即可。在展开列通过三个v-for嵌套循环三中权限。

html布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<el-table :data="rolesList" border stripe>
<!-- 展开列 -->
<el-table-column type="expand">
<template v-slot="scoped">
<el-row
:class="['bdbottom', i1 === 0 ? 'bdtop' : '', 'vcenter']"
v-for="(item1, i1) in scoped.row.children"
:key="item1.id"
>
<!-- 渲染一级权限 -->
<el-col :span="4">
<el-tag closable @close="removeRightById(scoped.row, item1.id)">
{{ item1.authName }}</el-tag
>
<i class="el-icon-caret-right"></i>
</el-col>
<!-- 渲染二级和三级权限 -->
<el-col :span="19">
<!-- 通过for循环嵌套渲染二级权限 -->
<el-row
:class="[i2 === 0 ? '' : 'bdtop', 'vcenter']"
v-for="(item2, i2) in item1.children"
:key="item2.key"
>
<!-- 二级权限 -->
<el-col :span="6">
<el-tag
closable
type="success"
@close="removeRightById(scoped.row, item2.id)"
>{{ item2.authName }}</el-tag
>
<i class="el-icon-caret-right"></i>
</el-col>
<!-- 三级权限 -->
<el-col :span="18">
<el-tag
v-for="item3 in item2.children"
:key="item3.id"
type="warning"
closable
@close="removeRightById(scoped.row, item3.id)"
>{{ item3.authName }}</el-tag
>
</el-col>
</el-row>
</el-col>
</el-row>
</template>
</el-table-column>
<!-- 索引列 -->
<el-table-column type="index"></el-table-column>
<el-table-column label="角色名称" prop="roleName"></el-table-column>
<el-table-column label="角色描述" prop="roleDesc"></el-table-column>
<el-table-column label="操作" width="300px">
<template>
<el-button size="mini" type="primary" icon="el-icon-edit"
>编辑</el-button
>
<el-button size="mini" type="danger" icon="el-icon-delete"
>删除</el-button
>
<el-button size="mini" type="warning" icon="el-icon-setting"
>分配权限</el-button
>
</template>
</el-table-column>
</el-table>

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
export default {
data () {
return {
// 角色列表
rolesList: []
}
},
created () {
// 获取所有权限
this.getRolesList()
},
methods: {
async getRolesList () {
const { data: res } = await this.$http.get('/roles')
if (res.meta.status !== 200) {
return this.$message.error('获取权限列表失败')
}
this.rolesList = res.data
console.log(this.rolesList)
},
// 移除权限
async removeRightById (role, rightId) {
// 弹窗提示用户
const confirmRuselt = await this.$confirm('此操作将移除权限, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).catch(err => err)
console.log(confirmRuselt)
if (confirmRuselt !== 'confirm') {
return this.$message.info('取消了删除!')
}
const { data: res } = await this.$http.delete(`roles/${role.id}/rights/${rightId}`)
if (res.meta.status !== 200) {
return this.$message.error('删除权限失败')
}
role.children = res.data
}
}
}

分配权限

UI实现

首先是点击按钮后弹出对话框,主要核心功能是树形组件。

1
2
3
4
5
6
7
8
<el-tree
:data="rightsList"
:props="treeProps"
show-checkbox
node-key="id"
default-expand-all
:default-checked-keys="defKeys"
></el-tree>
  • show-checkbox

    显示复选框

  • node-key

    每一个选项的key为数据中的id字段

  • :props

    用于配置显示的名以及子级属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    data () {
    return {
    // 所有权限的数据
    rightsList: [],
    // 树形控件属性绑定对象
    treeProps: {
    label: 'authName',
    children: 'children'
    },
    // 默认选中的节点ID值
    defKeys: []
    }
    },
  • default-expand-all

    默认展开全部

  • :default-checked-keys="defKeys"

    默认勾选的项

对话框打开时应发起请求获取数据,并将权限填充到数据供html进行渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 展示分配权限的对话框
async showSetRightDialog (role, arr) {
const { data: res } = await this.$http.get('rights/tree')
if (res.meta.status !== 200) {
return this.$message.error('获取权限失败')
}
// 获取到的数据保存到data中
this.rightsList = res.data
// 获取权限
this.getLeafKeys(role, this.defKeys)
// 获取所有权限列表
this.setRightDialogVisible = true
},
// 通过递归的形式,获取角色下所有三级权限的ID,并保存到defKeys数组中
getLeafKeys (node, arr) {
// 如果当前node节点不好含children属性,则是三级节点
if (!node.children) {
return arr.push(node.id)
}
node.children.forEach(element => {
this.getLeafKeys(element, arr)
})
},
// 情况权限列表
setRightDialogClosed () {
this.defKeys = []
}

修改权限

修改权限只需要将权限ID以数组形式进行传入,并将角色ID进行传入即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 点击为角色分配权限
async allotRights () {
const keys = [
...this.$refs.treeRef.getCheckedKeys(),
...this.$refs.treeRef.getHalfCheckedKeys()
]
const idStr = keys.join(',')
const { data: res } = await this.$http.post(`roles/${this.roleId}/rights`, { rids: idStr })
console.log(res)
if (res.meta.status !== 200) {
return this.$message.error('更新权限失败')
}
this.$message.success('更新权限成功')
this.getRolesList()
this.setRightDialogVisible = false
}

在对话框内无法获取角色ID,因此当点击按钮时就对数据进行设置当前的角色ID。

1
2
3
async showSetRightDialog (role) {
this.roleId = role.id
}

分配角色

点击分配角色后也会弹出一个对话框,对话框使用了selectoption组件。

1
2
3
4
5
6
7
8
9
<el-select v-model="selectedRoleId" placeholder="请选择">
<el-option
v-for="item in rolesList"
:key="item.id"
:label="item.roleName"
:value="item.id"
>
</el-option>
</el-select>
  • selectedRoleId

    已经选中的ID值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 展示分配角色的对话框
async setRole (userinfo) {
// 将角色信息保存到数据
this.userInfo = userinfo
// 展示对话框前,获取角色的列表
const { data: res } = await this.$http.get('roles')
if (res.meta.status !== 200) {
return this.$message.error('获取角色列表')
}
this.rolesList = res.data
// 显示对话框
this.setRoleDialogVisible = true
},
// 点击按钮分配角色
async saveRoleInfo () {
if (!this.selectedRoleId) {
return this.$message.error('请选择要分配的角色')
}

const { data: res } = await this.$http.put(`users/${this.userInfo.id}/role`, { rid: this.selectedRoleId })
if (res.meta.status !== 200) {
return this.$message.error('更新失败')
}
this.$message.success('更新角色列表成功')
this.getUserList()
this.setRoleDialogVisible = false
},
// 监听关闭对话框事件
setRoleDialogClosed () {
this.selectedRoleId = ''
this.userinfo = ' '
}

数据值

1
2
3
4
5
6
7
8
data(){
// 需要被分配权限的用户信息
userInfo: {},
// 所有角色的数据列表
rolesList: [],
// 已经选中的ID值
selectedRoleId: ''
}