1 权限列表

1.1 通过路由展示权限列表组件
- 创建页面:
../components/power/Rights.vue
<template>
<div>
<!-- 面包屑导航 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/welcome' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>权限管理</el-breadcrumb-item>
<el-breadcrumb-item>权限列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片区域 -->
<el-card> 权限列表表单</el-card>
</div>
</template>
<script>
export default {};
</script>
<style lang="less" scoped>
</style>
import Rights from '../components/power/Rights.vue'
Vue.use(Router)
const router = new Router({
routes: [
...
{
path: '/home', component: Home, redirect: '/welcome', children: [
...,
{ path: '/rights', component: Rights }
]
}
]
})

1.2 调用API获取权限列表的数据
<script>
export default {
data() {
return {
rightsList: [],
};
},
created() {
this.getRightsList();
},
methods: {
async getRightsList() {
const { data: res } = await this.$http.get("rights/list");
if (res.meta.status !== 200) {
return this.$message.error("获取权限列表失败!");
}
this.rightsList = res.data;
console.log(this.rightsList);
},
},
};
</script>
1.3 渲染权限列表UI结构
<el-table :data="rightsList" stripe border>
<el-table-column type="index" label="序号"> </el-table-column>
<el-table-column prop="authName" label="权限名称">
</el-table-column>
<el-table-column prop="path" label="路径">
</el-table-column>
<el-table-column prop="level" label="权限等级">
<!-- 作用域插槽 -->
<template slot-scope="scope">
<el-tag v-if="scope.row.level === '0'">一级</el-tag>
<el-tag type="success" v-else-if="scope.row.level === '1'">二级</el-tag>
<el-tag type="warning" v-else>三级</el-tag>
</template>
</el-table-column>
</el-table>
2 权限管理

2.1 绘制基本布局结构并获取列表数据
- 创建页面:
../components/power/Roles.vue
<template>
<div>
<!-- 面包屑导航 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/welcome' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>权限管理</el-breadcrumb-item>
<el-breadcrumb-item>角色列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片视图 -->
<el-card>
<!-- 添加角色按钮 -->
<el-row>
<el-col>
<el-button type="primary">添加角色</el-button>
</el-col>
</el-row>
<!-- 角色列表区域 -->
</el-card>
</div>
</template>
<script>
export default {};
</script>
<style lang="less" scoped>
</style>
import Roles from '../components/power/Roles.vue'
Vue.use(Router)
const router = new Router({
routes: [
...
{
path: '/home', component: Home, redirect: '/welcome', children: [
...
{ path: '/roles', component: Roles },
]
}
]
})
1.5.1. 角色列表接口
<script>
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);
},
},
};
</script>
2.2 渲染角色列表数据
<!-- 角色列表区域 -->
<el-table :data="rolesList" stripe border>
<!-- 展开列 -->
<el-table-column type="expand"> </el-table-column>
<!-- 索引列 -->
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="roleName" label="角色名称"> </el-table-column>
<el-table-column prop="roleDesc" label="角色描述"> </el-table-column>
<el-table-column label="操作">
<!-- 作用域插槽 -->
<template slot-scope="scope">
<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>

2.3 通过第一层for循环渲染一级权限
<!-- 展开列 -->
<el-table-column type="expand">
<template slot-scope="scope">
<el-row
:class="['bdbottom', i1 === 0 ? 'bdtop' : '']"
v-for="(item1, i1) in scope.row.children"
:key="item1.id"
>
<!-- 渲染一级权限 -->
<el-col :span="5">
<el-tag>{{ item1.authName }}</el-tag>
<i class="el-icon-caret-right"></i>
</el-col>
<!-- 渲染二级和三级权限 -->
<el-col :span="19"></el-col>
</el-row>
</template>
</el-table-column>
<style lang="less" scoped>
.el-tag {
margin: 7px;
}
.bdtop {
border-top: 1px solid #eee;
}
.bdbottom {
border-bottom: 1px solid #eee;
}
</style>

2.4 渲染二级和三级权限
<!-- 渲染二级和三级权限 -->
<el-col :span="19">
<!-- 二级 -->
<el-row
:class="[i2 === 0 ? '' : 'bdtop']"
v-for="(item2, i2) in item1.children"
:key="item2.id"
>
<el-col :span="6">
<el-tag type="success">{{ item2.authName }}</el-tag>
<i class="el-icon-caret-right"></i>
</el-col>
<!-- 三级 -->
<el-col :span="18">
<el-tag type="warning" v-for="item3 in item2.children" :key="item3.id">{{item3.authName}}</el-tag>
</el-col>
</el-row>
</el-col>

2.5 美化角色下权限的UI结构
解决页面过窄时,页面变形
html,
body,
#app {
...
min-width: 1366px;
}
.vcenter{
display: flex;
align-items: center;
}
绑定样式
<el-row
:class="['bdbottom', i1 === 0 ? 'bdtop' : '','vcenter']"
v-for="(item1, i1) in scope.row.children"
:key="item1.id"
>
<!-- 二级 -->
<el-row
:class="[i2 === 0 ? '' : 'bdtop','vcenter']"
v-for="(item2, i2) in item1.children"
:key="item2.id"
>

2.6 完成删除角色下指定权限的功能
<!-- 渲染一级权限 -->
<el-col :span="5">
<el-tag closable
@close="removeRightById(scope.row, item1.id)">{{ item1.authName }}</el-tag>
<i class="el-icon-caret-right"></i>
</el-col>
<!-- 渲染二级和三级权限 -->
<el-col :span="19">
<!-- 二级 -->
<el-row
:class="[i2 === 0 ? '' : 'bdtop', 'vcenter']"
v-for="(item2, i2) in item1.children"
:key="item2.id"
>
<el-col :span="6">
<el-tag
type="success"
closable
@close="removeRightById(scope.row, item2.id)"
>{{ item2.authName }}</el-tag
>
<i class="el-icon-caret-right"></i>
</el-col>
<!-- 三级 -->
<el-col :span="18">
<el-tag
type="warning"
v-for="item3 in item2.children"
:key="item3.id"
closable
@close="removeRightById(scope.row, item3.id)"
>{{ item3.authName }}</el-tag
>
</el-col>
async removeRightById(role, rightId) {
const confirmResult = await this.$confirm(
"此操作将永久删除该权限, 是否继续?",
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
).catch((err) => err);
if (confirmResult !== "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;
},
3 分配权限
3.1 弹出分配权限对话框并请求权限数据
- 在
分配权限 按钮绑定点击事件showSetRightDialog ,并实权限列表的数据获取:
async showSetRightDialog() {
const { data: res } = await this.$http.get("rights/tree");
if (res.meta.status !== 200) {
return this.$message.error("获取权限列表失败!");
}
this.rightsList = res.data;
console.log(this.rightsList);
this.setRightDialogVisible = true;
},
<!-- 分配权限对话框 -->
<el-dialog
title="分配权限"
:visible.sync="setRightDialogVisible"
width="50%"
>
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="setRightDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="setRightDialogVisible = false"
>确 定</el-button
>
</span>
</el-dialog>
3.2 配置并使用el-tree树形控件
使用element-ui中的[tree树形控件](https://element.eleme.cn/#/zh-CN/component/tree) 来展示权限列表数据。
属性show-checkbox :节点是否可被选择 属性render-after-expand :是否在第一次展开某个树节点后才渲染其子节点 属性node-key : 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的
<el-tree
:data="rightsList"
:props="treeProps"
show-checkbox
default-expand-all
node-key="id"
></el-tree>
treeProps: {
children: "children",
label: "authName",
},

3.3 加载当前角色已有的权限
在展开角色的权限弹窗时,需要将对应的权限
- 树形控件加上
default-checked-keys 属性,展示默认选中的项
<!-- 分配权限对话框 -->
<el-dialog
title="分配权限"
:visible.sync="setRightDialogVisible"
width="50%"
@close="closeRightDialog()"
>
<!-- 树形控件 -->
<el-tree
:data="rightsList"
:props="treeProps"
show-checkbox
default-expand-all
node-key="id"
:default-checked-keys="defKeys"
></el-tree>
<span slot="footer" class="dialog-footer">
<el-button @click="setRightDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="setRightDialogVisible = false"
>确 定</el-button
>
</span>
</el-dialog>
getLeafKeys(node, arr) {
if (!node.children) {
return arr.push(node.id);
}
node.children.forEach((item) => {
this.getLeafKeys(item, arr);
});
},
async showSetRightDialog(role) {
const { data: res } = await this.$http.get("rights/tree");
if (res.meta.status !== 200) {
return this.$message.error("获取权限列表失败!");
}
this.rightsList = res.data;
this.getLeafKeys(role, this.defKeys);
this.setRightDialogVisible = true;
},
closeRightDialog() {
this.defKeys = [];
},
3.4 调用API完成分配权限的功能
- 给树形结构绑定
ref 属性,并给弹窗的确定按钮,绑定allotRights() 方法
<el-tree
:data="rightsList"
:props="treeProps"
show-checkbox
default-expand-all
node-key="id"
:default-checked-keys="defKeys"
ref="treeRef"
></el-tree>
- 实现
allotRights() 方法:
- 通过
角色授权(roles/:roleId/rights) 接口来给用户分配相关权限。 - 该接口的post传参需要传递
权限 ID 列表 。 - 通过树形结构的方法
getCheckedNodes() 和getHalfCheckedKeys() 来获取选中和半选中的权限的id。
知识点: 1、ref 属性:ref 被用来给DOM元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。如果在普通的DOM元素上使用,引用信息就是元素; 如果用在子组件上,引用信息就是组件实例。(注意:只要想要在Vue中直接操作DOM元素,就必须用ref属性进行注册) 2、getCheckedKeys :若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点所组成的数组。 3、getHalfCheckedKeys :若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点的 key 所组成的数组。
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 }
);
if (res.meta.status !== 200) {
return this.$message.error("分配权限列表失败!");
}
this.$message.success("分配权限成功");
this.getRolesList();
this.setRightDialogVisible = false;
},
分配角色
完成用户列表操作栏的分配角色的功能
setRoleDialogVisible: false,
userInfo: {},
rolesList: [],
selectRoleId: "",
- 分配按钮绑定
setRole 方法,实现点击后,获取角色列表信息,并且展示出来弹框
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;
},
知识点: select控件循环展示数据
<!-- 分配角色弹窗 -->
<el-dialog
title="提示"
:visible.sync="setRoleDialogVisible"
width="50%"
@close="setRoleDialogClosed()"
>
<div>
<p>当前的用户:{{ userInfo.username }}</p>
<p>当前的角色:{{ userInfo.role_name }}</p>
<p>
分配新角色:
<el-select v-model="selectRoleId" placeholder="请选择">
<el-option
v-for="item in rolesList"
:key="item.id"
:label="item.roleName"
:value="item.id"
>
</el-option>
</el-select>
</p>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="setRoleDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="saveRoleInfo()">确 定</el-button>
</span>
</el-dialog>

- 实现在点击分配角色弹窗的确定按钮后,设置该用户的角色
async saveRoleInfo() {
if (!this.selectRoleId) {
return this.$message.error("请选择角色!");
}
const { data: res } = await this.$http.put(
`users/${this.userInfo.id}/role`,
{
rid: this.selectRoleId,
}
);
if (res.meta.status !== 200) {
return this.$message.error("分配角色失败!");
}
this.getUserList();
this.setRoleDialogVisible = false;
},
setRoleDialogClosed() {
this.selectRoleId = "";
this.userInfo = {};
},
|