A.添加角色列表路由 添加角色列表子组件(power/Roles.vue),并添加对应的规则 B.添加面包屑导航 在Roles.vue中添加面包屑组件展示导航路径
<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-row->el-col->el-button--> <!-- 分配权限的对话框 el-dialog--> </div> </template>栅格布局使用row和col组件设置添加角色按钮的位置
<!-- 卡片视图 el-card--> <el-card> <!-- 添加角色按钮区域 --> <el-row> <el-col> <el-button type="primary">添加角色</el-button> </el-col> </el-row>C.显示数据 在data中添加一个roleList数据,在methods中提供一个getRoleList方法发送请求获取权限列表数据,在created中调用这个方法获取数据
<!-- 角色列表区域 --> <!-- row-key="id" 是2019年3月提供的新特性, if there's nested data, rowKey is required. 如果这是一个嵌套的数据,rowkey 是必须添加的属性 --> <el-table row-key="id" :data="roleList" border> <!-- 添加展开列 --> <el-table-column type="expand"> <!-- 插槽中放置权限列表 --> </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="450px"> <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> <script> export default { data(){ return { roleList:[] } },created(){ this.getRoleList(); },methods:{ async getRoleList(){ const {data:res} = await this.$http.get('roles') console.log(res.data) this.roleList = res.data; } } } </script>D 生成权限列表 增加展开列type设置为expand即可,放置作用域插槽; 使用三重嵌套for循环生成权限下拉列表 栅格布局,在v-row中v-for;col代表列; 共2列;设置一级宽span为5;二列19; 第一列渲染一级权限 第二列渲染二级和三级权限,再分成两列,列宽设置为6,19 使用tag标签渲染存放信息,i标签小向右三角形图标
<!-- 添加展开列 --> <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"> <!-- 通过for循环嵌套渲染二级权限 --> <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> </el-row> </template> </el-table-column>F.美化样式 1.通过设置global.css中的#app样式min-width:1366px 解决三级权限换行的问题 2.通过给一级权限el-row添加display:flex,align-items:center的方式解决一级权限垂直居中的问题,二级权限也类似添加,因为需要给多个内容添加,可以将这个样式设置为一个.vcenter{display:flex;align-items:center} 3.<el-row :class="[‘bdbottom’, i1 === 0 ? ‘bdtop’ : ‘’, ‘vcenter’]" 定义两个类名:分别是上边框和底边框,以数组方式动态绑定类名(2 or 3个元素),三目表达式判断第一行,数组第二个元素,即索引为0才加上边框
<style lang="less" scoped> .el-tag { margin: 7px; } .bdtop { border-top: 1px solid #eee; } .bdbottom { border-bottom: 1px solid #eee; } .vcenter { display: flex; align-items: center; } </style>G.添加权限删除功能 给每一个权限的el-tag添加closable属性,是的权限右侧出现“X”图标 再给el-tag添加绑定close事件处理函数removeRightById(scope.row,item1.id) removeRightById(scope.row,item2.id) removeRightById(scope.row,item3.id)
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('删除权限失败!') } // this.getRolesList() role.children = res.data },解决删除操作后展开列闭合的问题 原,删除成功后重新渲染列表:// this.getRolesList() 改为将请求返回res.data赋值给role.children
H.完成权限分配功能
先给分配权限按钮添加事件
<el-button size="mini" type="warning" icon="el-icon-setting" @click="showSetRightDialog">分配权限</el-button>在showSetRightDialog函数中请求权限树数据并显示对话框
// 展示分配权限的对话框 async showSetRightDialog(role) { this.roleId = role.id // 获取所有权限的数据 const { data: res } = await this.$http.get('rights/tree') if (res.meta.status !== 200) { return this.$message.error('获取权限数据失败!') } // 把获取到的权限数据保存到 data 中 this.rightslist = res.data console.log(this.rightslist) // 递归获取三级节点的Id this.getLeafKeys(role, this.defKeys) //显示对话框 this.setRightDialogVisible = true },I.完成树形结构弹窗 在element.js中引入Tree,注册Tree,按钮放在span中
<!-- 分配权限的对话框 el-dialog--> <el-dialog title="分配权限" :visible.sync="setRightDialogVisible" width="50%" @close="setRightDialogClosed"> <!-- 树形控件 --> <el-tree :data="rightslist" :props="treeProps" show-checkbox node-key="id" default-expand-all :default-checked-keys="defKeys" ref="treeRef"></el-tree> <span slot="footer" class="dialog-footer"> <el-button @click="setRightDialogVisible = false">取 消</el-button> <el-button type="primary" @click="allotRights">确 定</el-button> </span> </el-dialog>【组件】Tree树形控件 基本用法:
<el-tree :data="rightsList" :props="TreeProps"></el-tree> data() { return { ... //权限树数据 rightsList: [], //树形控件的属性绑定对象 treeProps: { //通过label设置树形节点文本展示authName label: 'authName', //设置通过children属性展示子节点信息 children: 'children' }, //设置树形控件中默认选中的内容 defKeys: [], //保存正在操作的角色id roleId:'' } },添加控件:show-checkbox属性,控件与id值关联(node-key属性=“id”);默认展开所有节点default-expand-all;默认勾选上已有的权限(:default-checked-keys=“defKeys”)
G.获取所有三级权限的id 定义一个函数(角色,数组)//所以点击函数中应该传递角色 递归的形式:判断是不是第三级(只获取三级id), node.children.forEach((item) => this.getLeafKeys(item, arr)) 函数的调用位置在设置权限对话框为true的前面this.getLeafKeys(role, this.defKeys)
//通过递归,获取角色下所有三级权限的id,保存到 defKeys 数组中 getLeafKeys(node, arr) { // 如果当前 node 节点不包含 children 属性,则是三级节点 if (!node.children) { return arr.push(node.id) } node.children.forEach(item => this.getLeafKeys(item, arr)) }, // 展示分配权限的对话框 async showSetRightDialog(role) { this.roleId = role.id // 获取所有权限的数据 const { data: res } = await this.$http.get('rights/tree') if (res.meta.status !== 200) { return this.$message.error('获取权限数据失败!') } this.rightslist = res.data // 递归获取三级节点的Id this.getLeafKeys(role, this.defKeys) this.setRightDialogVisible = true },K. 角色分配权限
// 监听分配权限对话框的关闭事件 setRightDialogClosed() { this.defKeys = [] }, // 点击为角色分配权限 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 }1.解决bug(数组数据累加):监听对话框关闭事件setRightDialogClosed,每次关闭清空数组this.defKeys = [] 2.获取选中和半选中的节点 组件中有提供两个方法getCheckedKeys、getHalfCheckedKeys 给tree添加引用属性ref,根据引用实例调用上面的方法,用数组接收,join转格式;(之前需要id,应在会话框展示时保存在data中,供以后使用)
