目录
- 案例一:
- 1.1后端准备工作
- 1.2前端代码
- 2.1后端准备
- 2.2前端代码
首先官网上的树形控件教程地址为Element - The world's most popular Vue UI framework
案例一:
要实现这种类型的树控件,并且后边相关操作:
1.1后端准备工作
首先,数据库表为:
查询接口返回的实体类为:
// 有参构造 | |
// 表示以name去重写的Equals和HashCode | |
public class Department implements Serializable { | |
private static final long serialVersionUID =L; | |
private Integer id; | |
private String name; | |
private Integer parentId; | |
private String depPath; | |
private Boolean enabled; | |
private Boolean isParent; | |
private List<Department> children; | |
private Integer result; | |
} |
查询接口返回的数据格式:通过属性 children来判断是否有子节点
[ | |
{ | |
"id":, | |
"name": "股东会", | |
"parentId": -, | |
"depPath": ".", | |
"enabled": true, | |
"isParent": true, | |
"children": [ | |
{ | |
"id":, | |
"name": "董事会", | |
"parentId":, | |
"depPath": "..2", | |
"enabled": true, | |
"isParent": true, | |
"children": [ | |
{ | |
"id":, | |
"name": "总办", | |
"parentId":, | |
"depPath": "..2.3", | |
"enabled": true, | |
"isParent": true, | |
"children": [ | |
{ | |
"id":, | |
"name": "财务部", | |
"parentId":, | |
"depPath": "..2.3.4", | |
"enabled": true, | |
"isParent": false, | |
"children": [], | |
"result": null | |
}, | |
{ | |
"id":, | |
"name": "市场部", | |
"parentId":, | |
"depPath": "..2.3.5", | |
"enabled": true, | |
"isParent": true, | |
"children": [ | |
{ | |
"id":, | |
"name": "华东市场部", | |
"parentId":, | |
"depPath": ".2.3.5.6", | |
"enabled": true, | |
"isParent": true, | |
"children": [ | |
{ | |
"id":, | |
"name": "上海市场部", | |
"parentId":, | |
"depPath": ".2.3.5.6.8", | |
"enabled": true, | |
"isParent": false, | |
"children": [], | |
"result": null | |
} | |
], | |
"result": null | |
}, | |
{ | |
"id":, | |
"name": "华南市场部", | |
"parentId":, | |
"depPath": ".2.3.5.7", | |
"enabled": true, | |
"isParent": false, | |
"children": [], | |
"result": null | |
}, | |
{ | |
"id":, | |
"name": "西北市场部", | |
"parentId":, | |
"depPath": "..2.3.5.9", | |
"enabled": true, | |
"isParent": true, | |
"children": [ | |
{ | |
"id":, | |
"name": "贵阳市场", | |
"parentId":, | |
"depPath": "..2.3.5.9.10", | |
"enabled": true, | |
"isParent": true, | |
"children": [ | |
{ | |
"id":, | |
"name": "乌当区市场", | |
"parentId":, | |
"depPath": "..2.3.5.9.10.11", | |
"enabled": true, | |
"isParent": false, | |
"children": [], | |
"result": null | |
} | |
], | |
"result": null | |
} | |
], | |
"result": null | |
} | |
], | |
"result": null | |
}, | |
{ | |
"id":, | |
"name": "技术部", | |
"parentId":, | |
"depPath": "..2.3.12", | |
"enabled": true, | |
"isParent": false, | |
"children": [], | |
"result": null | |
}, | |
{ | |
"id":, | |
"name": "运维部", | |
"parentId":, | |
"depPath": "..2.3.13", | |
"enabled": true, | |
"isParent": false, | |
"children": [], | |
"result": null | |
} | |
], | |
"result": null | |
} | |
], | |
"result": null | |
}, | |
{ | |
"id":, | |
"name": "aaa", | |
"parentId":, | |
"depPath": "..150", | |
"enabled": true, | |
"isParent": true, | |
"children": [ | |
{ | |
"id":, | |
"name": "abbb", | |
"parentId":, | |
"depPath": "..150.151", | |
"enabled": true, | |
"isParent": false, | |
"children": [], | |
"result": null | |
} | |
], | |
"result": null | |
}, | |
{ | |
"id":, | |
"name": "ccc", | |
"parentId":, | |
"depPath": "..154", | |
"enabled": true, | |
"isParent": false, | |
"children": [], | |
"result": null | |
}, | |
{ | |
"id":, | |
"name": "dddd", | |
"parentId":, | |
"depPath": "..157", | |
"enabled": true, | |
"isParent": false, | |
"children": [], | |
"result": null | |
} | |
], | |
"result": null | |
} | |
] |
1.2前端代码
从官网上复制一个模板过来,搜索的话,直接往下找一个有搜索框的,把搜索框复制过来,复制好就可以开始修改,写增删改查的方法调用了。
写好的代码如下:
<template> | |
<div style="width:px;"> | |
<el-input | |
placeholder="请输入部门名称进行搜索..." | |
prefix-icon="el-icon-search" | |
v-model="filterText"> | |
</el-input> | |
<el-tree | |
:data="deps" | |
:props="defaultProps" | |
:filter-node-method="filterNode" | |
:expand-on-click-node="false" | |
ref="tree"> | |
<!-- slot-scope可以自定义树节点里的内容,node当前节点的node对象,data后端对应返回的数据 --> | |
<span class="custom-tree-node" slot-scope="{ node, data }" style="display:flex; justify-content: space-between;width:%;"> | |
<span>{{ data.name }}</span> | |
<span> | |
<el-button | |
type="primary" | |
size="mini" | |
class="depBtn" | |
@click="() => showAddDep(data)"> | |
添加部门 | |
</el-button> | |
<el-button | |
type="danger" | |
size="mini" | |
class="depBtn" | |
@click="() => deleteDep(data)"> | |
删除部门 | |
</el-button> | |
</span> | |
</span> | |
</el-tree> | |
<!-- 添加部门的弹出框 --> | |
<el-dialog | |
title="添加部门" | |
:visible.sync="dialogVisible" | |
width="%"> | |
<div> | |
<table> | |
<tr> | |
<td><el-tag>上级部门</el-tag></td> | |
<td><el-tag>{{pname}}</el-tag></td> | |
</tr> | |
<tr> | |
<td><el-tag>部门名称</el-tag></td> | |
<td><el-input v-model="dep.name" placeholder="请输入部门名称..."></el-input></td> | |
</tr> | |
</table> | |
</div> | |
<span slot="footer" class="dialog-footer"> | |
<el-button @click="dialogVisible = false">取 消</el-button> | |
<el-button type="primary" @click="doAddDep">确 定</el-button> | |
</span> | |
</el-dialog> | |
</div> | |
</template> | |
<script> | |
export default { | |
data(){ | |
return{ | |
// 树的搜索条件 | |
filterText: '', | |
// 树的数据 | |
deps: [], | |
// 树的配置 | |
defaultProps: { | |
children: 'children', | |
label: 'name' | |
}, | |
// 添加弹出框 | |
dialogVisible: false, | |
// 添加的部门数据 | |
dep:{ | |
name:'', | |
parentId: - | |
}, | |
// 上级部门名称 | |
pname: '' | |
} | |
}, | |
mounted(){ | |
this.initDeps(); | |
}, | |
methods: { | |
// 初始化数据 | |
initDeps(){ | |
this.getRequest('/system/basic/department/').then(resp=>{ | |
this.deps = resp; | |
}) | |
}, | |
// 树的搜索 | |
filterNode(value, data) { | |
if (!value) return true; | |
return data.name.indexOf(value) !== -; | |
}, | |
// 添加弹框 | |
showAddDep(data){ | |
console.log(data) | |
this.dep.parentId = data.id; | |
this.pname = data.name; | |
this.dialogVisible = 'true' | |
}, | |
// 添加 | |
doAddDep(){ | |
this.postRequest('/system/basic/department/',this.dep).then(resp=>{ | |
if(resp.code==){ | |
resp.obj.children = [] | |
this.addDepDeps(this.deps,resp.obj); | |
this.initDep(); | |
this.dialogVisible = false; | |
} | |
}) | |
}, | |
initDep(){ | |
this.dep = { | |
name: '', | |
parentId: - | |
} | |
this.panme = '' | |
}, | |
// 添加成功后手动的给树加数据 | |
addDepDeps(deps,dep){ | |
for(let i =; i<deps.length; i++){ | |
let d= deps[i]; | |
if(d.id == dep.parentId){ | |
d.children = d.children.concat(dep); | |
if(d.children.length>){ | |
d.isParent = true; | |
} | |
return; | |
}else{ | |
// 递归 | |
this.addDepDeps(d.children,dep); | |
} | |
} | |
}, | |
// 删除 | |
deleteDep(data){ | |
console.log(data) | |
if(data.isParent){ | |
this.$message.error("父部门无法删除"); | |
}else{ | |
this.$confirm('此操作将永久['+data.name+']部门, 是否继续?', '提示', { | |
confirmButtonText: '确定', | |
cancelButtonText: '取消', | |
type: 'warning' | |
}).then(() => { | |
this.deleteRequest('/system/basic/department/'+data.id).then(resp=>{ | |
if(resp.code==){ | |
this.removeDepFromDeps(null,this.deps,data.id); | |
} | |
}) | |
}).catch(() => { | |
this.$message({ | |
type: 'info', | |
message: '已取消删除' | |
}); | |
}); | |
} | |
}, | |
// 手动删除 (父部门,总部门数据,要删除的部门id) | |
removeDepFromDeps(p,deps,id){ | |
for(let i=; i<deps.length; i++){ | |
let d = deps[i]; | |
if(d.id==id){ | |
deps.splice(i,); | |
if(deps.length==){ | |
p.isParent = false; | |
} | |
return; | |
}else{ | |
this.removeDepFromDeps(d,d.children,id); | |
} | |
} | |
} | |
}, | |
watch: { | |
filterText(val) { | |
this.$refs.tree.filter(val); | |
} | |
} | |
} | |
</script> | |
<style> | |
.depBtn{ | |
padding:px; | |
} | |
</style> |
需要注意的是:
1:树组件中 :data="deps" 加载树组建的数据。:props="defaultProps" 加载树组件的配置,其中label是给个枝叶的名字对应的字段,children是子节点对应的字段。:filter-node-method="filterNode" 树组件的搜索,filterNode过滤的回调,这个官网拷贝即可。:expand-on-click-node="false" 关闭点击折叠,只有点击前面的小三角才能展开折叠。
2:搜索框绑定的数据filterText,下面监听这个数据的改变,如果改变了,就调用树的filter方法(this.$refs.tree.filter(val);),进行过滤,这个方法的回调在树组件的属性中定义:filter-node-method="filterNode" ,也就是输入框值改变了,会去掉filterNode这个方法,这个方法传入两个值,value是文本框输入值,data是树组件的数据,value为空直接返回,不为空则过滤。
3: 添加部门的时候,添加成功后不能单纯的掉接口,重新请求一次树中的数据,这样的话,每添加一个部门,整个树就会折叠起来。这时候就需要不调接口请求新的数据,在js中操作树中的数据this.deps,让它和数据库保持同步。首先在成功后调用方法: addDep2Deps(deps,dep) 这个方法第一个参数是整个树中的数据,第二个参数是新添加的树的数据(这个数据是添加成功接口回显的数据,也就是添加的这条记录信息)在这个方法中,会循环,找到对应的父节点,给它的子节点拼接数据,修改父节点isParent属性(是否有孩子),之后就一直递归,知道添加完成为止。这个数据添加成功后,清空弹出框中输入的信息,关闭弹出框。
4:删除操作,同样,删除时也要手动的在js中把这条数据删除,不能请求新数据,请求新数据会导致树整个关闭,用户体验十分不好,需要在js中把树中的数据和数据库中进行同步。
调用接口删除成功后,调用removeDepFromDeps(p,deps,id)方法,在js中进行数据删除,调用时,第一个参数传null表示从顶层节点开始往下找,第二个参数是树的数据,第三个参数是要删除部门的id。同样进行循环,添加中比较的是父节点的id,删除是,比较的就是这个叶子的id,如果相同,那就删除,同时,判断把这个叶子删掉后,这个枝下面还有没有叶子,因为有叶子的枝是不能删除的,所以要再判断一下修改isParent的状态,之后还是一样,在一层中没有查询到的话,就递归到下一层去找。
案例二
这种前面带有选择框的,进行授权操作
2.1后端准备
对应的数据库表
对应的实体类:
public class Menu implements Serializable { | |
private static final long serialVersionUID =L; | |
private Integer id; | |
private String url; | |
private String path; | |
private String component; | |
private String name; | |
private String iconCls; | |
private Boolean keepAlive; | |
private Boolean requireAuth; | |
private Integer parentId; | |
private Boolean enabled; | |
// 告诉mybatisplus这个字段不在表中,查询的时候不要去查 | |
private List<Menu> children; | |
private List<Role> roles; | |
} |
查询接口返回的数据
{ | |
"code":, | |
"message": "查询成功", | |
"obj": [ | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "所有", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": [ | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "员工资料", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": [ | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "基本资料", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "高级资料", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
} | |
], | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "人事管理", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": [ | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "员工资料", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "员工奖惩", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "员工培训", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "员工调薪", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "员工调动", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
} | |
], | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "薪资管理", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": [ | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "工资账套管理", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "员工账套设置", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "工资表管理", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "月末处理", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "工资表查询", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
} | |
], | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "统计管理", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": [ | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "综合信息统计", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "员工积分统计", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "人事信息统计", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "人事记录统计", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
} | |
], | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "系统管理", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": [ | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "基础信息设置", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "系统管理", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "操作日志管理", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "操作员管理", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "备份恢复数据库", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
}, | |
{ | |
"id":, | |
"url": null, | |
"path": null, | |
"component": null, | |
"name": "初始化数据库", | |
"iconCls": null, | |
"keepAlive": null, | |
"requireAuth": null, | |
"parentId": null, | |
"enabled": null, | |
"children": null, | |
"roles": null | |
} | |
], | |
"roles": null | |
} | |
], | |
"roles": null | |
} | |
] | |
} |
2.2前端代码
<template> | |
<div> | |
<!-- 添加角色 --> | |
<div class="permissManaTool"> | |
<el-input size="small" placeholder="请输入角色英文名" v-model="role.name"> | |
<template slot="prepend">ROLE_</template> | |
</el-input> | |
<el-input size="small" placeholder="请输入角色中文名" v-model="role.nameZh" @keydown.enter.native="addRole"></el-input> | |
<el-button size="small" type="primary" icon="el-icon-plus" @click="addRole">添加角色</el-button> | |
</div> | |
<!-- 手风琴 --> | |
<div style="margin-top:px; width:660px"> | |
<el-collapse v-model="activeName" accordion @change="change"> | |
<el-collapse-item :title="r.nameZh" :name="r.id" v-for="(r,index) in roles" :key="index"> | |
<!-- 卡片 --> | |
<el-card class="box-card"> | |
<div slot="header" class="clearfix"> | |
<span>可访问资源</span> | |
<el-button style="float: right; padding:px 0; color: #ff0000;" type="text" icon="el-icon-delete" @click="doDeleteRole(r)"></el-button> | |
</div> | |
<div> | |
<!-- 树 --> | |
<el-tree | |
show-checkbox | |
node-key="id" | |
ref="tree" | |
:key="index" | |
:default-checked-keys="selectMenus" | |
:data="allMenus" :props="defaultProps"></el-tree> | |
<div style="display:flex; justify-content: flex-end"> | |
<el-button size="mini" @click="cancelUpdate">取消修改</el-button> | |
<el-button size="mini" type="primary" @click="doUpdate(r.id,index)">确定修改</el-button> | |
</div> | |
</div> | |
</el-card> | |
</el-collapse-item> | |
</el-collapse> | |
</div> | |
</div> | |
</template> | |
<script> | |
export default { | |
data(){ | |
return{ | |
role:{ | |
name:'', | |
nameZh:'' | |
}, | |
activeName : '-', | |
roles:[], | |
allMenus: [], | |
// 树菜单的属性,children子菜单的属性,label显示出来的名字,都是后端接口返回来的字段名字 | |
defaultProps: { | |
children: 'children', | |
label: 'name' | |
}, | |
// 树中选中的节点 | |
selectMenus: [] | |
} | |
}, | |
mounted(){ | |
this.initRoles(); | |
}, | |
methods:{ | |
// 初始化所有菜单 | |
initAllMenus(){ | |
this.getRequest('/system/basic/permiss/menus').then(resp=>{ | |
if(resp.code==){ | |
this.allMenus = resp.obj; | |
} | |
}) | |
}, | |
// 根据角色id获取菜单 | |
initSelectdMenus(rid){ | |
this.getRequest('/system/basic/permiss/mid/'+rid).then(resp=>{ | |
if(resp.code==){ | |
this.selectMenus = resp.obj; | |
} | |
}) | |
}, | |
// 获取角色列表 | |
initRoles(){ | |
this.getRequest('/system/basic/permiss/').then(resp=>{ | |
if(resp.code==){ | |
this.roles = resp.obj; | |
} | |
}) | |
}, | |
// 手风琴点击事件,展开rid是每个name,name对应着后端字段id,关闭时rid为空 | |
change(rid){ | |
if(rid){ | |
this.initAllMenus(); | |
this.initSelectdMenus(rid); | |
} | |
}, | |
// 修改角色权限 | |
doUpdate(rid,index){ | |
// 拿到这个手风琴下面的树 | |
let tree = this.$refs.tree[index]; | |
// 传true只打印叶子节点的id | |
let selectedKeys = tree.getCheckedKeys(true); | |
let url = '/system/basic/permiss/?rid='+ rid; | |
selectedKeys.forEach(key => { | |
url += '&mids='+ key; | |
}); | |
this.putRequest(url).then(resp=>{ | |
if(resp.code==){ | |
this.activeName = '-' | |
} | |
}) | |
}, | |
cancelUpdate(){ | |
this.activeName = '-' | |
}, | |
// 添加角色 | |
addRole(){ | |
if(this.role.name && this.role.nameZh){ | |
this.postRequest('/system/basic/permiss/',this.role).then(resp=>{ | |
if(resp.code==){ | |
this.initRoles(); | |
this.role.name = ''; | |
this.role.nameZh = ''; | |
} | |
}) | |
}else{ | |
this.$message.error("所有字段不能为空"); | |
} | |
}, | |
// 删除角色 | |
doDeleteRole(role){ | |
this.$confirm('此操作将永久删除'+role.nameZh+'角色, 是否继续?', '提示', { | |
confirmButtonText: '确定', | |
cancelButtonText: '取消', | |
type: 'warning' | |
}).then(() => { | |
this.deleteRequest('/system/basic/permiss/role/'+r.id).then(resp => { | |
if(resp.code ==){ | |
this.initRoles(); | |
}else{ | |
this.$message.error(resp.message) | |
} | |
}) | |
}).catch(() => { | |
this.$message({ | |
type: 'info', | |
message: '已取消删除' | |
}); | |
}); | |
} | |
} | |
} | |
</script> | |
<style> | |
.permissManaTool{ | |
display: flex; | |
justify-content: flex-start; | |
} | |
.permissManaTool .el-input{ | |
width:px; | |
margin-right:px; | |
} | |
</style> |
值得注意的是:
1:每个角色下面展开的权限树列表用的是手风琴组件(折叠面板)这里还要给树加上key,因为每个手风琴下面都是一个树 折叠面板饿了吗官网
2:树要展示前面的选择框,要给树组件加上show-checkbox属性。:default-checked-keys="selectMenus" 默认选中的key,这个selectMenus需要去data中定义一个数组。
3:在添加时,可通过 let tree = this.$refs.tree[index]; 拿到整个手风琴下面的树,let selectedKeys = tree.getCheckedKeys(true) 获取选中节点的id,修改成功后,把手风琴的折叠属性,定义成-1,折叠即可,因为下次再打开的时候,会去数据库查出这个角色对应菜单的最新数据。