From e1cdc26697d3d5859a28b5879fe3ccfefad52b23 Mon Sep 17 00:00:00 2001 From: chenxing Date: Tue, 15 Sep 2026 16:51:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(auth):=20=E6=A0=91=E5=8B=BE=E9=80=89?= =?UTF-8?q?=E7=BA=A7=E8=81=94+=E7=82=B9=E5=87=BB=E6=96=87=E5=AD=97?= =?UTF-8?q?=E5=8B=BE=E9=80=89+=E6=A0=91=E9=BB=98=E8=AE=A4=E9=97=AD?= =?UTF-8?q?=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增共享级联工具 utils/treeCascade.ts:勾选子->祖先全部勾选;勾选父->子孙全部勾选/取消;取消子->父/祖不受影响(zTree 侧 chkboxType 置空,由代码级联) - GroupAuth.vue:接入代码级联,模块明细按 diff 提交(追加/删除),取消时同步清理子组继承标记 - AppModuleCheckTree.vue:角色授权接入同一套级联逻辑 - 组/角色授权树与应用节点默认闭合,点击文字等价勾选框(MyTree onClick 同步触发 onCheck) - PermissionView.vue「已授权应用」应用一级默认不展开模块 --- src/utils/treeCascade.ts | 100 +++++++++++++++++ src/views/GroupAuth.vue | 114 ++++++++++---------- src/views/PermissionView.vue | 2 +- src/views/role-authz/AppModuleCheckTree.vue | 55 +++------- 4 files changed, 172 insertions(+), 99 deletions(-) create mode 100644 src/utils/treeCascade.ts diff --git a/src/utils/treeCascade.ts b/src/utils/treeCascade.ts new file mode 100644 index 0000000..6e1319f --- /dev/null +++ b/src/utils/treeCascade.ts @@ -0,0 +1,100 @@ +/** + * 树勾选级联工具 + * + * 规则(与 zTree chkboxType {Y:"ps", N:"s"} 语义一致,由代码实现,zTree 侧保持 {Y:"",N:""}): + * 1. 勾选子节点 -> 其所有父/祖先节点全部勾选 + * 2. 勾选父节点 -> 其所有子孙节点全部勾选 + * 3. 取消父节点 -> 其所有子孙节点全部取消 + * 4. 取消子节点 -> 父/祖先保持原状(不受影响) + * 取消任意节点时,同时清除其 inheritFlag(子组继承标记),并向下传播清除,避免残留。 + */ + +export type ModuleVo = { + id?: number; + name?: string; + checked?: boolean; + inheritFlag?: boolean; + children?: ModuleVo[]; +}; + +export function walkModules(nodes: ModuleVo[] | undefined, fn: (n: ModuleVo) => void): void { + (nodes || []).forEach((n) => { + fn(n); + walkModules(n.children, fn); + }); +} + +function findModuleWithPath( + nodes: ModuleVo[] | undefined, + moduleId: number, + ancestors: ModuleVo[] = [] +): { node: ModuleVo; ancestors: ModuleVo[] } | null { + for (const n of nodes || []) { + if (Number(n.id) === moduleId) return { node: n, ancestors }; + const hit = findModuleWithPath(n.children, moduleId, [...ancestors, n]); + if (hit) return hit; + } + return null; +} + +/** + * 本地数据(AppItem.modules 嵌套结构)级联。 + * 勾选:自身 + 祖先链 + 子孙全部勾选;取消:自身 + 子孙全部取消(祖先不动)。 + */ +export function applyModuleCascade(app: { modules?: ModuleVo[] } | null | undefined, moduleId: number, checked: boolean): void { + if (!app?.modules) return; + const hit = findModuleWithPath(app.modules, moduleId); + if (!hit) return; + const { node, ancestors } = hit; + node.checked = checked; + if (checked) { + ancestors.forEach((a) => { + a.checked = true; + }); + walkModules(node.children, (c) => { + c.checked = true; + }); + } else { + walkModules([node], (c) => { + c.checked = false; + c.inheritFlag = false; + }); + } +} + +/** 应用整级勾选/取消:全部模块同步(取消时清除 inheritFlag) */ +export function setAppModulesChecked(app: { modules?: ModuleVo[] } | null | undefined, checked: boolean): void { + walkModules(app?.modules, (n) => { + n.checked = checked; + if (!checked) n.inheritFlag = false; + }); +} + +/** + * zTree 节点级联(仅同步视觉状态,checkTypeFlag / callbackFlag 均传 false,不触发 onCheck、不重复走 chkboxType)。 + * 勾选:自身 + 祖先链 + 子孙;取消:自身 + 子孙(祖先不动)。 + */ +export function checkNodeWithCascade(treeObj: any, node: any, checked: boolean): void { + if (!treeObj || !node) return; + const set = (n: any, v: boolean) => { + n.checked = v; + if (!v && n.inheritFlag !== undefined) n.inheritFlag = false; + treeObj.checkNode(n, v, false, false); + }; + set(node, checked); + if (checked) { + let parent: any = node.getParentNode ? node.getParentNode() : null; + while (parent) { + set(parent, true); + parent = parent.getParentNode ? parent.getParentNode() : null; + } + } + walkZtreeChildren(node, (c) => set(c, checked)); +} + +function walkZtreeChildren(node: any, fn: (n: any) => void): void { + (node.children || []).forEach((c: any) => { + fn(c); + walkZtreeChildren(c, fn); + }); +} \ No newline at end of file diff --git a/src/views/GroupAuth.vue b/src/views/GroupAuth.vue index 9cae28e..59e2bc9 100644 --- a/src/views/GroupAuth.vue +++ b/src/views/GroupAuth.vue @@ -42,7 +42,7 @@ 子组继承
-
@@ -62,11 +62,11 @@