lxr 2 місяців тому
батько
коміт
c4f12efb83
1 змінених файлів з 75 додано та 29 видалено
  1. 75 29
      src/views/accountRoleManagement/roleManagement/create.vue

+ 75 - 29
src/views/accountRoleManagement/roleManagement/create.vue

@@ -149,9 +149,8 @@ const saveLoading = ref(false);
 const isAutoCheckingView = ref(false);
 
 // 控制父子节点是否严格独立(false表示父子关联,true表示严格独立)
-// 在设置初始选中状态时使用true,避免因为父子关联导致所有子节点被选中
-// 设置完成后改为false,允许用户操作时的父子关联
-const checkStrictly = ref(false);
+// 设置为true,使父子节点独立,选择某一级时不会自动勾选下级
+const checkStrictly = ref(true);
 
 // 加载菜单树数据
 const loadMenuTree = async () => {
@@ -202,6 +201,42 @@ const findMenuIdByName = (menuList: any[], permissionName: string): number | nul
   return null;
 };
 
+// 在指定的父节点下查找子节点ID(用于查找三级权限)
+const findChildMenuIdByName = (parentMenuList: any[], parentName: string, childName: string): number | null => {
+  // 先找到父节点
+  const parentMenu = findMenuNodeByName(parentMenuList, parentName);
+  if (!parentMenu) {
+    return null;
+  }
+
+  // 在父节点的子节点中查找
+  if (parentMenu.children && parentMenu.children.length > 0) {
+    for (const child of parentMenu.children) {
+      if (child.menuName === childName || child.label === childName) {
+        return child.menuId || child.id;
+      }
+    }
+  }
+
+  return null;
+};
+
+// 通过权限名称匹配菜单节点(返回节点对象,用于查找子节点)
+const findMenuNodeByName = (menuList: any[], permissionName: string): any | null => {
+  for (const menu of menuList) {
+    if (menu.menuName === permissionName || menu.label === permissionName) {
+      return menu;
+    }
+    if (menu.children && menu.children.length > 0) {
+      const found = findMenuNodeByName(menu.children, permissionName);
+      if (found !== null) {
+        return found;
+      }
+    }
+  }
+  return null;
+};
+
 // 从权限详情数据中提取所有菜单ID
 // 规则:一级权限只要有数据就勾选,二级和三级权限按需添加
 const extractMenuIdsFromPermissions = (permissionList: RolePermissionItem[], menuTree: MenuItem[]): number[] => {
@@ -219,8 +254,8 @@ const extractMenuIdsFromPermissions = (permissionList: RolePermissionItem[], men
     }
 
     // 处理二级权限
-    // 注意:如果存在三级权限,不要单独添加二级权限ID,避免因为父子关联导致所有子节点被选中
-    if (permission.level2Permission && !permission.level3Permission) {
+    // 由于 checkStrictly 为 true,父子节点独立,所以无论是否有三级权限,都可以安全地添加二级权限ID
+    if (permission.level2Permission) {
       const menuId = findMenuIdByName(menuTree, permission.level2Permission);
       if (menuId !== null && !addedIds.has(menuId)) {
         menuIds.push(menuId);
@@ -230,16 +265,19 @@ const extractMenuIdsFromPermissions = (permissionList: RolePermissionItem[], men
 
     // 处理三级权限
     // 注意:level3Permission 可能包含多个权限名称(用空格分隔),需要拆分处理
-    if (permission.level3Permission) {
+    // 只有当 level3Permission 不为 null 且不为空字符串时才处理
+    // 重要:必须在对应的二级权限下查找三级权限,避免跨范围匹配
+    if (permission.level3Permission && permission.level3Permission.trim() && permission.level2Permission) {
       // 将 level3Permission 按空格拆分为多个权限名称
       const level3PermissionNames = permission.level3Permission
         .split(/\s+/) // 按一个或多个空白字符拆分
         .map(name => name.trim()) // 去除首尾空格
         .filter(name => name.length > 0); // 过滤空字符串
 
-      // 对每个权限名称分别进行精确匹配
+      // 对每个权限名称分别在对应的二级权限下进行精确匹配
       level3PermissionNames.forEach(permissionName => {
-        const menuId = findMenuIdByName(menuTree, permissionName);
+        // 在对应的二级权限下查找三级权限,避免在其他二级权限下误匹配
+        const menuId = findChildMenuIdByName(menuTree, permission.level2Permission, permissionName);
         // 只有精确匹配到菜单项时才添加,避免误匹配
         if (menuId !== null && !addedIds.has(menuId)) {
           menuIds.push(menuId);
@@ -278,29 +316,13 @@ const loadRoleData = async () => {
       defaultCheckedKeys.value = menuIds;
 
       // 设置树形组件的选中状态
-      // 临时使用精确模式(check-strictly="true"),避免因为父子关联导致所有子节点被选中
+      // 由于 checkStrictly 为 true,父子节点独立,直接设置选中状态即可
       nextTick(() => {
         if (permissionTreeRef.value) {
-          // 临时切换到精确模式
-          checkStrictly.value = true;
-
-          // 等待DOM更新后设置选中状态
-          nextTick(() => {
-            if (permissionTreeRef.value) {
-              permissionTreeRef.value.setCheckedKeys(menuIds);
-
-              // 设置完成后,切换回父子关联模式
-              nextTick(() => {
-                checkStrictly.value = false;
-
-                // 更新权限列表(在父子关联模式下,父节点会被自动勾选)
-                nextTick(() => {
-                  const finalCheckedKeys = permissionTreeRef.value?.getCheckedKeys() || [];
-                  roleForm.permissions = finalCheckedKeys;
-                });
-              });
-            }
-          });
+          permissionTreeRef.value.setCheckedKeys(menuIds);
+          // 更新权限列表
+          const finalCheckedKeys = permissionTreeRef.value?.getCheckedKeys() || [];
+          roleForm.permissions = finalCheckedKeys;
         }
       });
     } else {
@@ -386,6 +408,30 @@ const handlePermissionCheck = (data: any, checked: any) => {
   // 更新权限列表
   roleForm.permissions = checkedKeys;
 
+  // 如果勾选了子节点,自动勾选所有父节点
+  if (isChecked && currentNode && currentNode.parent) {
+    // 递归向上查找并勾选所有父节点
+    let parent = currentNode.parent;
+    while (parent && parent.data) {
+      const parentId = parent.data.id;
+      const parentNode = permissionTreeRef.value?.getNode(parentId);
+
+      // 如果父节点存在且未被勾选,则勾选它
+      if (parentNode && !parentNode.checked) {
+        permissionTreeRef.value?.setChecked(parentId, true, false);
+      }
+
+      // 继续向上查找
+      parent = parent.parent;
+    }
+
+    // 更新权限列表(包含新勾选的父节点)
+    nextTick(() => {
+      const updatedCheckedKeys = permissionTreeRef.value?.getCheckedKeys() || [];
+      roleForm.permissions = updatedCheckedKeys;
+    });
+  }
+
   // 如果勾选的是三级权限(叶子节点),自动勾选同级的"查看"权限
   if (isChecked && isLeafNode && data.label !== "查看" && currentNode) {
     if (currentNode.parent) {