|
|
@@ -117,7 +117,8 @@ const roleFormRules: FormRules = {
|
|
|
// 树形组件配置
|
|
|
const treeProps = {
|
|
|
children: "children",
|
|
|
- label: "label"
|
|
|
+ label: "label",
|
|
|
+ disabled: "disabled"
|
|
|
};
|
|
|
|
|
|
// 权限树数据
|
|
|
@@ -253,10 +254,9 @@ const extractMenuIdsFromPermissions = (permissionList: RolePermissionItem[], men
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 处理二级权限
|
|
|
- // 由于 checkStrictly 为 true,父子节点独立,所以无论是否有三级权限,都可以安全地添加二级权限ID
|
|
|
- if (permission.level2Permission) {
|
|
|
- const menuId = findMenuIdByName(menuTree, permission.level2Permission);
|
|
|
+ // 处理二级权限:必须在对应的一级权限下查找,避免「编辑」「查看」等多处重名时取错节点
|
|
|
+ if (permission.level2Permission && permission.level1Permission) {
|
|
|
+ const menuId = findChildMenuIdByName(menuTree, permission.level1Permission, permission.level2Permission);
|
|
|
if (menuId !== null && !addedIds.has(menuId)) {
|
|
|
menuIds.push(menuId);
|
|
|
addedIds.add(menuId);
|
|
|
@@ -268,6 +268,8 @@ const extractMenuIdsFromPermissions = (permissionList: RolePermissionItem[], men
|
|
|
// 只有当 level3Permission 不为 null 且不为空字符串时才处理
|
|
|
// 重要:必须在对应的二级权限下查找三级权限,避免跨范围匹配
|
|
|
if (permission.level3Permission && permission.level3Permission.trim() && permission.level2Permission) {
|
|
|
+ // 保存 level2Permission 到局部变量,确保类型安全
|
|
|
+ const level2Permission = permission.level2Permission;
|
|
|
// 将 level3Permission 按空格拆分为多个权限名称
|
|
|
const level3PermissionNames = permission.level3Permission
|
|
|
.split(/\s+/) // 按一个或多个空白字符拆分
|
|
|
@@ -277,7 +279,7 @@ const extractMenuIdsFromPermissions = (permissionList: RolePermissionItem[], men
|
|
|
// 对每个权限名称分别在对应的二级权限下进行精确匹配
|
|
|
level3PermissionNames.forEach(permissionName => {
|
|
|
// 在对应的二级权限下查找三级权限,避免在其他二级权限下误匹配
|
|
|
- const menuId = findChildMenuIdByName(menuTree, permission.level2Permission, permissionName);
|
|
|
+ const menuId = findChildMenuIdByName(menuTree, level2Permission, permissionName);
|
|
|
// 只有精确匹配到菜单项时才添加,避免误匹配
|
|
|
if (menuId !== null && !addedIds.has(menuId)) {
|
|
|
menuIds.push(menuId);
|
|
|
@@ -323,6 +325,8 @@ const loadRoleData = async () => {
|
|
|
// 更新权限列表
|
|
|
const finalCheckedKeys = permissionTreeRef.value?.getCheckedKeys() || [];
|
|
|
roleForm.permissions = finalCheckedKeys;
|
|
|
+ // 更新节点的禁用状态
|
|
|
+ updateNodeDisabledState(permissionTreeData.value, finalCheckedKeys);
|
|
|
}
|
|
|
});
|
|
|
} else {
|
|
|
@@ -364,6 +368,52 @@ const hasOtherCheckedSiblings = (currentNode: any, checkedKeys: number[]): boole
|
|
|
});
|
|
|
};
|
|
|
|
|
|
+// 检查节点是否有子节点被选中(通过数据源检查)
|
|
|
+const hasCheckedChildrenInData = (nodeData: any, checkedKeys: number[]): boolean => {
|
|
|
+ // 如果是叶子节点,返回 false
|
|
|
+ if (!nodeData.children || nodeData.children.length === 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 递归检查所有子节点是否有被选中的
|
|
|
+ const checkChildren = (children: any[]): boolean => {
|
|
|
+ return children.some((child: any) => {
|
|
|
+ // 如果子节点本身被选中,返回 true
|
|
|
+ if (checkedKeys.includes(child.id)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ // 如果子节点还有子节点,递归检查
|
|
|
+ if (child.children && child.children.length > 0) {
|
|
|
+ return checkChildren(child.children);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ return checkChildren(nodeData.children);
|
|
|
+};
|
|
|
+
|
|
|
+// 更新树节点数据中的 disabled 状态
|
|
|
+const updateNodeDisabledState = (treeData: any[], checkedKeys: number[]) => {
|
|
|
+ const updateNode = (nodes: any[]): void => {
|
|
|
+ nodes.forEach((node: any) => {
|
|
|
+ // 如果是叶子节点,不禁用
|
|
|
+ if (!node.children || node.children.length === 0) {
|
|
|
+ node.disabled = false;
|
|
|
+ } else {
|
|
|
+ // 如果节点有子节点被选中,则禁用该节点
|
|
|
+ node.disabled = hasCheckedChildrenInData(node, checkedKeys);
|
|
|
+ // 递归更新子节点
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ updateNode(node.children);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ updateNode(treeData);
|
|
|
+};
|
|
|
+
|
|
|
// 权限选择变化
|
|
|
const handlePermissionCheck = (data: any, checked: any) => {
|
|
|
// 如果正在自动勾选"查看"权限,直接返回,避免递归
|
|
|
@@ -429,9 +479,30 @@ const handlePermissionCheck = (data: any, checked: any) => {
|
|
|
nextTick(() => {
|
|
|
const updatedCheckedKeys = permissionTreeRef.value?.getCheckedKeys() || [];
|
|
|
roleForm.permissions = updatedCheckedKeys;
|
|
|
+ // 更新节点的禁用状态
|
|
|
+ updateNodeDisabledState(permissionTreeData.value, updatedCheckedKeys);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ // 如果尝试取消勾选父节点,但该父节点有子节点被选中,则阻止取消
|
|
|
+ if (!isChecked && currentNode && currentNode.data.children && currentNode.data.children.length > 0) {
|
|
|
+ // 使用最新的选中状态检查
|
|
|
+ const latestCheckedKeys = permissionTreeRef.value?.getCheckedKeys() || [];
|
|
|
+ const hasChecked = hasCheckedChildrenInData(currentNode.data, latestCheckedKeys);
|
|
|
+ if (hasChecked) {
|
|
|
+ // 如果有子节点被选中,阻止取消勾选父节点,重新勾选
|
|
|
+ nextTick(() => {
|
|
|
+ permissionTreeRef.value?.setChecked(currentNode.data.id, true, false);
|
|
|
+ const updatedCheckedKeys = permissionTreeRef.value?.getCheckedKeys() || [];
|
|
|
+ roleForm.permissions = updatedCheckedKeys;
|
|
|
+ // 更新节点的禁用状态
|
|
|
+ updateNodeDisabledState(permissionTreeData.value, updatedCheckedKeys);
|
|
|
+ ElMessage.warning("当子级权限被选中时,父级权限不能取消");
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 如果勾选的是三级权限(叶子节点),自动勾选同级的"查看"权限
|
|
|
if (isChecked && isLeafNode && data.label !== "查看" && currentNode) {
|
|
|
if (currentNode.parent) {
|
|
|
@@ -456,6 +527,8 @@ const handlePermissionCheck = (data: any, checked: any) => {
|
|
|
// 更新权限列表
|
|
|
const updatedCheckedKeys = permissionTreeRef.value?.getCheckedKeys() || [];
|
|
|
roleForm.permissions = updatedCheckedKeys;
|
|
|
+ // 更新节点的禁用状态
|
|
|
+ updateNodeDisabledState(permissionTreeData.value, updatedCheckedKeys);
|
|
|
|
|
|
// 重置标志位
|
|
|
nextTick(() => {
|
|
|
@@ -468,6 +541,12 @@ const handlePermissionCheck = (data: any, checked: any) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 更新节点的禁用状态(每次权限变化后都更新)
|
|
|
+ nextTick(() => {
|
|
|
+ const finalCheckedKeys = permissionTreeRef.value?.getCheckedKeys() || [];
|
|
|
+ updateNodeDisabledState(permissionTreeData.value, finalCheckedKeys);
|
|
|
+ });
|
|
|
+
|
|
|
// 触发表单验证
|
|
|
roleFormRef.value?.validateField("permissions");
|
|
|
};
|