实现一个分配权限的页面,最左侧是大的权限模块的名称,左右侧是控制其是否勾选的多选框。中间部分是一级权限模块下的子权限名称及多选框。
请求此权限模块数据的接口返回的是树形结构 对象数组。
主要属性为menuName表示权限名,isHas表示是否拥有此权限,1或0字符串,parentMenuId为0表示一级,children表示子项,id唯一标识。
展示在界面的数据为一级和没有子项的末级。对象数组项中,可能没有children子项,即权限一级二级三级四级都可能出现。多选框标识是否是否有此权限。并且存在依赖关系。当界面上某模块所有子项勾选,一级多选框自动勾选,一个子项未勾选,一级多选框自动不勾选。一级多选框的勾选与否同时也能控制此模块的所有子项的勾选。
当选定权限保存时向后端传递的是界面上所有勾选项。
el-checkbox的v-model属性为选中项绑定值,可以是布尔、字符串或数字类型。用true-label和false-label标识选中和未选中值即可。
但是当使用的是否以为只能是布尔类型,就把返回的数据依赖isHas转化一下渲染.
// PermissionsType.value是被赋值的数据
for (let i = 0; i < PermissionsType.value.length; i++) {
addIsCheckedProperty(PermissionsType.value[i]);
}
//增加isChecked标识选中未选中
function addIsCheckedProperty(menu) {
if (menu.isHas === '1') {
menu.isChecked = true;
} else {
menu.isChecked = false;
}
if (menu.children && menu.children.length > 0) {
for (let i = 0; i < menu.children.length; i++) {
addIsCheckedProperty(menu.children[i]);
}
}
}
为el-checkbox绑定change事件,传递当前的项作为参数。
当parentMenuId === 0即为一级数据,检测到一级就根据一级数据更新其下所有子项isChecked 。
若为子项,则根据所有子项的isChecked状态改变一级项的isChecked 状态
//el-checkbox的change事件
const handleCheckboxChange = (item) => {
//点击一级
if (item.parentMenuId === 0) {
updateChildrenCheckedStatus(item, item.isChecked);
}
updateParentCheckedStatus(PermissionsType.value);
};
// 递归更新子菜单状态
const updateChildrenCheckedStatus = (menu, isChecked) => {
if (menu.children) {
menu.children.forEach((child) => {
child.isChecked = isChecked;
updateChildrenCheckedStatus(child, isChecked); // 继续更新孙菜单
});
}
};
// 检查并更新父菜单状态
const updateParentCheckedStatus = (menu) => {
menu.forEach((menuItem) => {
if (menuItem.children && menuItem.children.length > 0) {
menuItem.isChecked = areAllChildrenChecked(menuItem.children);
} else if (!menuItem.isChecked) {
menuItem.isChecked = false; // 只有一级的isChecked置为false
}
});
};
const areAllChildrenChecked = (children) => {
for (const child of children) {
if (child.children && child.children.length > 0) {
if (!areAllChildrenChecked(child.children)) {
return false;
}
} else {
if (!child.isChecked) {
return false;
}
}
}
return true;
};
遍历数据中所有被选择项的id得到数组。
遍历数据,只保留一级数据的id和末级数据的id,得到数组。
数组去重。
for (let i = 0; i < PermissionsType.value.length; i++) {
getCheckedIds(PermissionsType.value[i]);
}
selectIgnore();
filteredMenuIds.value = selectedMenuIds.value.filter((item) => isIgnore.value.indexOf(item) === -1);
//递归遍历被选中权限id
function getCheckedIds(menu) {
if (menu.isChecked === true) {
selectedMenuIds.value.push(menu.id);
}
if (menu.children && menu.children.length > 0) {
for (let i = 0; i < menu.children.length; i++) {
getCheckedIds(menu.children[i]);
}
}
}
//有三级项时忽略掉二级项 有四级项时忽略三级项
const selectIgnore = () => {
PermissionsType.value.forEach((item) => {
if (item.children) {
item.children.forEach((child) => {
if (child.children) {
isIgnore.value.push(child.id);
child.children.forEach((childThird) => {
if (childThird.children) {
isIgnore.value.push(childThird.id);
}
});
}
});
}
});
};