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 @@