问题描述:
在写后台管理是 遇到用el-tree展示权限列表的情况,给角色分配权限时,选择了某一项目前全有的权限,如图:
但是如果之后 我再新增一个子权限 这个子权限也会被默认选中,如图:
首先新增一个 但是我并没有去给任何角色分配此权限
但是:!!what the f**k??
产生原因:当我们在全部选中某一项权限时 权限的父级id也会被加入到我们已选择的权限中 当我们把含有父级id的权限数组传给后端,再请求权限列表时,el-tree检测到里面包含的父级权限的id,就会默认勾选上该父级权限及他下面的所有子权限。
解决办法:
办法1:取消父子级联动效果 使用 check-strictly 属性,
<el-tree
ref="tree"
:data="listPermission"
:props="props"
node-key="permissionId"
show-checkbox
default-expand-all
:default-checked-keys="hadPermissionIdList"
getCheckedKeys
check-strictly
></el-tree>
办法2,在添加权限和显示已有权限时 过滤掉父级id
第一步,在上传id的时候 过滤掉父级id 这样在之后请求权限列表时就不会有父级id存在,上述问题就不会存在了。但是,会有一个新的bug,如果有一个权限,情况一:他有子级,但是目前子级目前还没有添加上去,也就是他的haveChildFlag 为true,但是目前childList为[ ],或者,情况二:原本是子级,haveChildFlag 为false,后来子级变为父级,haveChildFlag 为true。那么这样的父级我们都应该先视为子级,等他变为父级之后,取消他的选中状态,等待管理员重新分配角色,否则,还是会出现有了父级id,子级(不论是否是新增)被全部选中的情况。
具体实现思路:在提交选中的权限的时候,过滤掉childList.length>0的父级。在请求到权限之后,过滤掉已有权限中childList.length>0的父级。
<template>
<div>
<el-button type="warning" @click="showDialog">分配权限</el-button>
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%">
<el-tree
ref="tree"
:data="listPermission"
:props="props"
node-key="permissionId"
show-checkbox
default-expand-all
:default-checked-keys="hadPermissionIdList"
getCheckedKeys
></el-tree>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="handleSubmit">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { updateUser,getlistPermission, appointPermissionToRole,} from "@/network/systemManage";//这是我封装的网络请求 用的axios
export default {
props: ["row"],
data() {
return {
dialogVisible: false,
data: [],
selectedRole: [],
props: {
label: "permissionName",
children: "childList",
},
count: 1,
listPermission: [], //权限列表(所有)
hadPermissionIdList: [], //已有的权限
permissionIdList: [], //要选择的权限
toDeletePermissionIdList: [], //被删掉的权限
lock: false//防止重复点击的锁
};
},
created() {},
methods: {
showDialog() {//打开弹窗
this.dialogVisible = true;
this.lock = false;
const config = {
pageIndex: 1,
pageSize: 10,
roleId: this.row.id,
};
getlistPermission(config).then((res) => { //获取某用户权限列表
const data = res.data;
if (data.code == 100) {
//全部权限
this.listPermission = data.content.allPermissionList;
//该用户已有权限
if (data.content.hadPermissionIdList) {
this.hadPermissionIdList = data.content.hadPermissionIdList;
//过滤父级id
let newArr = [];
let item = "";
this.hadPermissionIdList.forEach((item) => {
this.checked(item, this.listPermission, newArr);
}); //item是已有的id,将已有的id与全部id进行匹配 找出父id然后删除
this.hadPermissionIdList = newArr; //将删除了父级id的数据赋值过去,这样就不会选中父id下面的东西了。
}
}
});
},
checked(id, data, newArr) {//这个函数是在检查id是否是父级id 将子级id过滤出来 运用到了递归
data.forEach((item) => {
if (item.permissionId == id) { //在数组的第一层中查找属于这个id的item
if (!item.haveChildFlag || item.childList.length < 1) {//如果item没有子级或者子级为空就说明他不是父节点或者暂时不是父节点 因为也存在有子级但是子级还没有添加进去的情况 如果直接过滤掉haveChildFlag 为true的item 会导致判断不精准
newArr.push(item.permissionId);
}
} else {
if (item.haveChildFlag && item.childList.length != 0) {
// 查找第二层 第三层 检查这个id是否是子节点的id
this.checked(id, item.childList, newArr);
}
}
});
},
handleSubmit() {
//点击确定 发送配置权限时
//获取选中的角色
if (!this.lock) {//这个lock是为防止重复点击
var selectedRoleAll = [];
this.selectedRole = [];
this.lock = true;
//获取所有被选中的权限
selectedRoleAll = this.$refs.tree.getCheckedNodes();
//将是子级 或者是父级但是还没有添加子级(这种要暂时将他视为子级 等他真正添加了子级之后 再删除)的id过滤出来
selectedRoleAll.forEach((item) => {
if (item.childList.length === 0) {
this.selectedRole.push(item);
}
});
let arr = [];
//拿到他们的id
this.selectedRole.map((item) => {
arr.push(item.permissionId);
});
// console.log("已选择" + arr);
// 对比原本有的和现在选择的 筛选出原来有的现在没有的//这是个人需求 后端要求我在传送选择了哪些权限时将原本有现在没有了的权限一起返给他
this.toDeletePermissionIdList = this.hadPermissionIdList.filter(
(item) => {
return arr.indexOf(item) == -1;
}
);
// console.log("被删掉" + this.toDeletePermissionIdList);
const config = {
permissionIdList: arr,
roleId: this.row.id,
toDeletePermissionIdList: this.toDeletePermissionIdList,
};
// 发送请求
appointPermissionToRole(config).then((res) => {
const code = res.data.code;
if (code == 100) {
this.dialogVisible = false;
this.$message({
message: res.data.message,
type: "success",
});
} else {
this.$message.error(res.data.message);
}
});
} else {
return;
}
},
},
};
</script>
<style>
</style>
另一种需求
如果后端要求在上传权限id时,不能过滤掉父级id,那么应该对代码做出修改。
经过调试发现,使用
var selectedRoleAll = this.$refs.tree.getCheckedNodes();
el-tree只有在子节点全选中时,父节点才是选中状态,selectedRoleAll 中才会有父节点id,当取消一个子节点,父节点就变成了半选状态,此时,应当使用:
var parentArr = this.$refs.tree.getHalfCheckedNodes()
来获取子父节点,然后将两者的id提出来,进行拼接,再将拼接后的数据上传
[半选节点(父级)id].concat([子节点id]),
注意再看一遍我的属性配置
<el-tree
ref="tree"
:data="listPermission"
:props="props"
node-key="permissionId"
show-checkbox
default-expand-all
:default-checked-keys="hadPermissionIdList"
getCheckedKeys
@check-change="checkChange"
></el-tree>
这样就能在子元素非全选的情况下将父节点id上传,但是这样在请求到以后权限的时候,为了避免出现之前的bug,需要将父节点id过滤出来再绑定到
default-checked-keys上,方法与第一种情况中给的一样,不再赘述。
数据:
"content":{
"allPermissionList":[
{
"childList":[
{
"childList":[],//子级列表
"haveChildFlag":false,///根据这个字段判断是不是有没有子级
"menuFlag":true,
"modelAction":"admin/listRole",
"parentLevelId":1,
"permissionId":2,
"permissionName":"角色管理"
},
{
"childList":[],
"haveChildFlag":true,
"menuFlag":true,
"modelAction":"admin/listPermission",
"parentLevelId":1,
"permissionId":8,
"permissionName":"菜单管理"
},
],
"haveChildFlag":true,
"menuFlag":true,
"modelAction":"admin",
"parentLevelId":0,
"permissionId":1,
"permissionName":"系统管理"
},
{
"childList":[
{
"childList":[],
"haveChildFlag":false,
"menuFlag":false,
"modelAction":"terminal/listTerminal",
"parentLevelId":6,
"permissionId":7,
"permissionName":"设备列表"
},
],
"haveChildFlag":true,
"menuFlag":true,
"modelAction":"terminal",
"parentLevelId":0,
"permissionId":6,
"permissionName":"设备管理"
},
{
"childList":[
{
"childList":[
{
"childList":[],
"haveChildFlag":false,
"menuFlag":true,
"modelAction":"dispathTask/yinliu/follow",
"parentLevelId":61,
"permissionId":63,
"permissionName":"关注功能"
}
],
"haveChildFlag":true,
"menuFlag":true,
"modelAction":"executeTask/yinliu",
"parentLevelId":59,
"permissionId":61,
"permissionName":"引流功能"
},
{
"childList":[],
"haveChildFlag":false,
"menuFlag":true,
"modelAction":"dispathTask/danxiang",
"parentLevelId":59,
"permissionId":66,
"permissionName":"单项功能"
},
],
"haveChildFlag":true,
"menuFlag":true,
"modelAction":"dispathTask",
"parentLevelId":0,
"permissionId":59,
"permissionName":"任务下发"
},
{
"childList":[],
"haveChildFlag":false,
"menuFlag":false,
"modelAction":"admin/getCurrentUserInfo",
"parentLevelId":0,
"permissionId":78,
"permissionName":"获取当前用户信息"
},
]
},