首先创建权限管理页面,然后在router中注册好路由,实现了跳转之后,就在权限管理页面实现获取数据,然后把数据存起来,然后把数据展示出来
<template>
<div>
<!-- 面包屑区域 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>权限管理</el-breadcrumb-item>
<el-breadcrumb-item>权限列表</el-breadcrumb-item>
</el-breadcrumb>
<el-card>
<el-table :data="rights" border script>
<el-table-column label="id" type="index" width="120px"></el-table-column>
<el-table-column label="权限说明" prop="authName"></el-table-column>
<el-table-column label="权限层次" prop="level">
<template slot-scope="scope">
<el-tag type="info" v-if="scope.row.level === '0'">等级一</el-tag>
<el-tag type="warning" v-else-if="scope.row.level === '1'">等级二</el-tag>
<el-tag type="danger" v-else>等级三</el-tag>
</template>
</el-table-column>
<el-table-column label="路径" prop="path"></el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
export default {
data() {
return {
rights: []
}
},
created () {
this.getRights()
},
methods: {
async getRights() {
const { data: res } = await this.$http.get('rights/list')
if (res.meta.status !== 200) return this.$message.error('获权限列表失败')
this.rights = res.data
}
}
}
</script>
<style>
</style>
现在设计权限分层的特效
第一步,使用作用域插槽,因为压要数据,把权限进行好布局,使用layout布局,前面使用row占5个部分,然后循环把一级权限取出来
<!-- 展开列 -->
<el-table-column type="expand"> //使用这个type可以实现点击那个箭头会在行下面展开一个空白页面
<template slot-scope="scope">
<el-row v-for="item in scope.row.children" :key="item.id">
<el-col :span="5">
<el-tag>{{item.authName}}</el-tag>
</el-col>
<el-col :span="19"></el-col>
</el-row>
</template>
</el-table-column>
<el-table-column type="expand">
<!-- 通过作用域获取数据 -->
<template slot-scope="scope">
<!-- 通过分行布局 class是为了使每一个权限上面有边框线 -->
<el-row v-for="(item, index) in scope.row.children" :key="item.id" :class="['dbbottom',index === 0 ? 'bdtop' : '']">
<!-- 一级权限使用5个部分 -->
<el-col :span="5">
<el-tag >{{item.authName}}</el-tag>
<i class="el-icon-caret-right"></i>
</el-col>
<!-- 二级权限 -->
<el-col :span="19">
<!-- 再创建一个row来分二级和三级权限 -->
<el-row v-for="(item2, index2) in item.children" :key="item2.id" :class="[index2 === 0 ? '' : 'bdtop']">
<!-- 二级权限 -->
<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>
</el-row>
</template>
</el-table-column>
然后进行优化,如果缩小敞口大小,权限布局会乱掉,所以需要加一个最小的宽度
下面代码的效果就是如果宽度不够的话,会强制把把宽度变成设置的大小
然后想要居中
.venter{
display: flex;
align-items: center;
}
然后想要给tag设置一个可以删除的样子
加了closable 还有在关闭的时候产生的close事件,然后这个close事件就对应删除权限的方法,然后传删除角色的信息和删除权限的id
<!-- 三级权限 -->
<el-col :span="18">
<el-tag closable type="warning" v-for="item3 in item2.children" :key="item3.id" @close="removeTag(scope.row, item3.id)">{{item3.authName}}</el-tag>
</el-col>
然后
/* 删除权限 */
async removeTag(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('删除失败')
// this.getuserRoles() 直接使用请求来获取最新的数据会产生刷新一样的bug,就是把expand关上
// 由于文档里说会响应返回最新的data,只需要把datad的数据放到role的孩子权限那里就可以了就可以了
role.children = res.data
}
现在来实现权限的树形结构
首先把一个对话框放在card外面,然后在点击分配权限的时候拿出来,并且获取到所有权限的数据
/* 分配权限 */
async showsetRight() {
/* 获取权限数据 */
const { data: res } = await this.$http.get('rights/tree')
if (res.meta.status !== 200) return this.$message.error('获取失败')
//把数据存储起来
this.rightsTree = res.data
/* 展示框 */
this.setRightdialogVisible = true
}
然后把树形控件复制进来,并且去elementui插件哪里声明和使用一下
树形控件中,data绑定的是所有权限数据,比如上面获取到的数据,然后prop绑定的是如何分配权限
<!-- 分配权限对话框 -->
<el-dialog
title="分配权限"
:visible.sync="setRightdialogVisible"
width="50%">
<!-- 树形控件 -->
<el-tree :data="rightsTree" :props="treeProps" ></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>
prop绑定的数据要在data生声明一下
data () {
return {
userRoles: [],
setRightdialogVisible: false,
rightsTree: [],
treeProps: { //绑定这里
label: 'authName', //这里的是展示权限的名字
children: 'children' //这里是展示权限的地方
}
}
},
<!-- 树形控件 show-checkbox表示可以选择 node-key表示绑定id这个值 default-expand-all表示默认展开 -->
<el-tree :data="rightsTree" :props="treeProps" show-checkbox node-key="id" default-expand-all></el-tree>
下面来实现点开上面的树状图时,默认选手角色拥有的权限
这里使用到的就是tree控件的, :default-checked-keys = defKey
,通过绑定defkey数组里面的权限的id来实现哪一个权限被选中
首先使用
<!-- 树形控件 show-checkbox表示可以选择 node-key表示绑定id这个值 default-expand-all表示默认展开 -->
<el-tree :data="rightsTree"
:props="treeProps"
show-checkbox
node-key="id"
default-expand-all
:default-checked-keys = defKey //这里这个属性
></el-tree>
然后定义完那个数组之后,写一个递归方法,通过递归把三级权限拿出来,然后存到数组里面就可以实现了
/* 递归方法来把角色拥有的权限通过递归把第三级权拿出来 */
getLearfKeys(node, arr) {
if (!node.children) return arr.push(node.id)
node.children.forEach(item => {
this.getLearfKeys(item, arr)
})
}
然后在点击的时候
/* 分配权限 */
async showsetRight(role) {
/* 获取权限数据 */
const { data: res } = await this.$http.get('rights/tree')
if (res.meta.status !== 200) return this.$message.error('获取失败')
this.rightsTree = res.data
/* 展示框 */
this.setRightdialogVisible = true
/* 调用递归方法,把角色拥有的权限存到defkey数组里面 */
this.getLearfKeys(role, this.defKey) //把值传进去用就可以了
},
但是这个时候会产生一个bug,每一个点击这个按钮都会填充defkey数组,所以点其他角色的时候会把没有他权限也展示出来,所以在关闭对话框的时候,就清空一下数组就可以了
然后下面真的来是实现分配权限,在选中的权限都从新分配给角色
首先就是拿到选中和半选中的权限,然后把他们的id放到一个数组里面,然后拿到当前点击的是哪一个角色的id,然后通过当前角色的id和权限的id发送请求就可以实现更改用户权限了
首先在对话框绑定一个点击事件,然后创一个数组,数组里面使用tree控件的两个方法把全选中和半选中的权限id放到数组里
/* 点击确定的时候分配权限 */
async setRight() {
/* getCheckedKeys拿到全选中的权限的id,getHalfCheckedKeys半选中的id */
/* 通过ref拿到树控件放到数组里 */
const treeId = [
...this.$refs.trees.getCheckedKeys(),
...this.$refs.trees.getHalfCheckedKeys()
]
/* 因为对应的是字符串所以要改成字符串 */
const tId = treeId.join(',')
const { data: res } = await this.$http.post(`roles/${this.roleId}/rights`, { rids: tId })
if (res.meta.status !== 200) return this.$message.error('分配错误')
this.$message.success('分配成功')
this.getuserRoles()
this.setRightdialogVisible = false
}