lxr 2 mesiacov pred
rodič
commit
4bba5c2677

+ 85 - 6
src/views/accountRoleManagement/roleManagement/create.vue

@@ -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");
 };