feat: 修复菜单管理 菜单配置 菜单初始化问题
This commit is contained in:
parent
968c68efba
commit
94e93a53e5
|
@ -68,12 +68,16 @@ import {
|
|||
drop,
|
||||
select,
|
||||
getMaxDepth,
|
||||
mergeArr,
|
||||
} from './utils';
|
||||
import BaseMenu from '@/views/init-home/data/baseMenu';
|
||||
import type { AntTreeNodeDropEvent } from 'ant-design-vue/es/tree';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
import { MESSAGE_SUBSCRIBE_MENU_CODE, USER_CENTER_MENU_CODE } from '@/utils/consts'
|
||||
import {
|
||||
MESSAGE_SUBSCRIBE_MENU_CODE,
|
||||
USER_CENTER_MENU_CODE,
|
||||
} from '@/utils/consts';
|
||||
|
||||
const selectedKeys: any = ref([]);
|
||||
const treeData = ref<any>([]);
|
||||
|
@ -104,54 +108,34 @@ const params = {
|
|||
],
|
||||
};
|
||||
|
||||
// 过滤子级空children
|
||||
const filterAndClean = (data: any) => {
|
||||
// 如果 data 是一个数组,则对每个元素递归调用此函数
|
||||
if (Array.isArray(data)) {
|
||||
return data
|
||||
.filter((item) => item !== null) // 过滤掉 null 元素
|
||||
.map((item: any) => filterAndClean(item)); // 递归调用此函数
|
||||
}
|
||||
|
||||
// 如果 data 是一个对象,则递归调用此函数来清除其子元素
|
||||
if (typeof data === 'object') {
|
||||
let cleanedChildren = filterAndClean(data.children); // 递归清除子元素
|
||||
if (Array.isArray(cleanedChildren)) {
|
||||
cleanedChildren = cleanedChildren.filter((i) => i);
|
||||
function filterTree(nodes: Array<any>, selectedKeys: Array<any>) {
|
||||
const filtered = [];
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i];
|
||||
if (!node.code) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cleanedChildren !== undefined) {
|
||||
data.children = cleanedChildren;
|
||||
} else {
|
||||
delete data.children; // 如果 children 是 undefined,则将其删除
|
||||
if (selectedKeys.indexOf(node.code) !== -1) {
|
||||
filtered.push(node);
|
||||
if (node.children) {
|
||||
node.children = filterTree(node.children, selectedKeys);
|
||||
}
|
||||
} else if (node.children) {
|
||||
node.children = filterTree(node.children, selectedKeys);
|
||||
if (node.children.length > 0) {
|
||||
filtered.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
return filtered;
|
||||
}
|
||||
|
||||
const handleOk = async () => {
|
||||
const { arrMap, rootSet } = developArrToMap(
|
||||
cloneDeep(treeData.value),
|
||||
false,
|
||||
true,
|
||||
);
|
||||
const dataMap = new Map();
|
||||
// 过滤选中菜单的map
|
||||
selectedKeys.value.forEach((item: string) => {
|
||||
if (arrMap.has(item)) {
|
||||
dataMap.set(item, arrMap.get(item));
|
||||
}
|
||||
});
|
||||
|
||||
const _saveDataMap = {
|
||||
arrMap: dataMap,
|
||||
rootSet,
|
||||
};
|
||||
|
||||
const dataArr = filterAndClean(mergeMapToArr(_saveDataMap, _saveDataMap));
|
||||
const _dataArr = filterTree(cloneDeep(treeData.value), selectedKeys.value);
|
||||
|
||||
loading.value = true;
|
||||
const res = await updateMenus(dataArr).catch(() => {});
|
||||
const res = await updateMenus(_dataArr).catch(() => {});
|
||||
if (res?.status === 200) {
|
||||
onlyMessage('操作成功', 'success');
|
||||
}
|
||||
|
@ -163,7 +147,7 @@ const handleCancel = () => {
|
|||
};
|
||||
|
||||
const onSelect = (selecteds: Array<string>, e: any) => {
|
||||
selectedKeys.value = select(selecteds, e);
|
||||
selectedKeys.value = select(selecteds, e, cloneDeep(treeData.value));
|
||||
};
|
||||
|
||||
const onDrop = (info: AntTreeNodeDropEvent) => {
|
||||
|
@ -186,12 +170,20 @@ onMounted(() => {
|
|||
);
|
||||
getMenuTree_api(params).then((resp: any) => {
|
||||
if (resp.status == 200) {
|
||||
systemMenu.value = resp.result?.filter((item: { code: string }) => ![USER_CENTER_MENU_CODE, MESSAGE_SUBSCRIBE_MENU_CODE].includes(item.code));
|
||||
systemMenu.value = resp.result?.filter(
|
||||
(item: { code: string }) =>
|
||||
![
|
||||
USER_CENTER_MENU_CODE,
|
||||
MESSAGE_SUBSCRIBE_MENU_CODE,
|
||||
].includes(item.code),
|
||||
);
|
||||
//初始化菜单
|
||||
const baseMenuData = developArrToMap(baseMenu.value);
|
||||
const systemMenuData = developArrToMap(systemMenu.value, true);
|
||||
selectedKeys.value = systemMenuData.checkedKeys;
|
||||
AllMenu.value = mergeMapToArr(baseMenuData, systemMenuData);
|
||||
// AllMenu.value = mergeMapToArr(baseMenuData, systemMenuData);
|
||||
AllMenu.value = mergeArr(cloneDeep(BaseMenu), systemMenu.value);
|
||||
|
||||
treeData.value = cloneDeep(AllMenu.value);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -22,6 +22,71 @@ export const filterMenu = (permissions: string[], menus: any[]) => {
|
|||
});
|
||||
};
|
||||
|
||||
// 拖拽跨级 存在顺序错乱,重复code todo
|
||||
/**
|
||||
* 合并数组(合并菜单)
|
||||
* @param oldData Array 默认菜单
|
||||
* @param newData Array 当前系统菜单
|
||||
* @returns Array 合并后的菜单
|
||||
*/
|
||||
|
||||
export const mergeArr = (oldData: Array<any>, newData: Array<any>) => {
|
||||
const mergedData = [];
|
||||
|
||||
const mergeItem: any = (oldItem: any, newItem: any) => {
|
||||
if (!oldItem) {
|
||||
return newItem;
|
||||
}
|
||||
|
||||
if (!oldItem.children && newItem.children) {
|
||||
oldItem.children = newItem.children;
|
||||
return oldItem;
|
||||
}
|
||||
|
||||
if (oldItem.children && !newItem.children) {
|
||||
return oldItem;
|
||||
}
|
||||
|
||||
if (oldItem.children && newItem.children) {
|
||||
const mergedChildren = [];
|
||||
const newChildren = [...newItem.children];
|
||||
for (const oldChild of oldItem.children) {
|
||||
const index = newChildren.findIndex(
|
||||
(child) => child.code === oldChild.code,
|
||||
);
|
||||
if (index !== -1) {
|
||||
mergedChildren.push(
|
||||
mergeItem(oldChild, newChildren[index]),
|
||||
);
|
||||
newChildren.splice(index, 1);
|
||||
} else {
|
||||
mergedChildren.push(oldChild);
|
||||
}
|
||||
}
|
||||
return {
|
||||
...oldItem,
|
||||
children: mergedChildren.concat(newChildren),
|
||||
};
|
||||
}
|
||||
|
||||
return oldItem;
|
||||
};
|
||||
|
||||
for (const newItem of newData) {
|
||||
const oldItem = oldData.find((item) => item.code === newItem.code);
|
||||
mergedData.push(mergeItem(oldItem, newItem));
|
||||
}
|
||||
|
||||
for (const oldItem of oldData) {
|
||||
const newItem = newData.find((item) => item.code === oldItem.code);
|
||||
if (!newItem) {
|
||||
mergedData.push(oldItem);
|
||||
}
|
||||
}
|
||||
|
||||
return mergedData;
|
||||
};
|
||||
|
||||
/**
|
||||
* 合并Map菜单转成Arr菜单
|
||||
* @param baseMenuData baseMenu developArrToMap平铺后的数据
|
||||
|
@ -89,31 +154,84 @@ export const developArrToMap = (Menu: any, checked = false, save = false) => {
|
|||
return { arrMap, rootSet, checkedKeys };
|
||||
};
|
||||
|
||||
/**
|
||||
* 查找父级、子级code
|
||||
* @param data 当前完整的菜单
|
||||
* @param code 当前点击的code
|
||||
* @returns result = {
|
||||
parents: [], //当前code的全部父级code
|
||||
children: [],//当前code的全部子级code
|
||||
};
|
||||
*/
|
||||
|
||||
function findAllParentsAndChildren(data: any, code: any) {
|
||||
const result = {
|
||||
parents: [],
|
||||
children: [],
|
||||
};
|
||||
|
||||
function findParentsAndChildrenRecursive(node: any) {
|
||||
if (node.code === code) {
|
||||
if (node.children) {
|
||||
result.children = node.children.flatMap((child: any) => {
|
||||
if (child.children) {
|
||||
return [
|
||||
child.code,
|
||||
...findChildrenRecursive(child.children),
|
||||
];
|
||||
}
|
||||
return [child.code];
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (node.children) {
|
||||
for (let child of node.children) {
|
||||
if (findParentsAndChildrenRecursive(child)) {
|
||||
result.parents.push(node.code);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function findChildrenRecursive(children: any) {
|
||||
return children.flatMap((child: any) => {
|
||||
if (child.children) {
|
||||
return [child.code, ...findChildrenRecursive(child.children)];
|
||||
}
|
||||
return [child.code];
|
||||
});
|
||||
}
|
||||
|
||||
for (let node of data) {
|
||||
if (findParentsAndChildrenRecursive(node)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* 选择功能
|
||||
* @param selecteds onSelect事件默认参数
|
||||
* @param e onSelect事件默认参数
|
||||
* @returns 处理后的keys
|
||||
*/
|
||||
export const select = (selecteds: Array<string>, e: any) => {
|
||||
const { node } = e;
|
||||
const childKeys: Array<string> = [];
|
||||
const getChildKeys = (data: any) => {
|
||||
data.forEach((item: any) => {
|
||||
childKeys.push(item.code);
|
||||
if (item?.children) {
|
||||
getChildKeys(item?.children);
|
||||
}
|
||||
});
|
||||
};
|
||||
if (node?.children) {
|
||||
getChildKeys(node.children);
|
||||
}
|
||||
|
||||
export const select = (selecteds: Array<string>, e: any, treeData: any) => {
|
||||
const { node, selected } = e;
|
||||
const { parents, children } = findAllParentsAndChildren(
|
||||
treeData,
|
||||
node.code,
|
||||
);
|
||||
const Keys = new Set(selecteds);
|
||||
const selectedAllKeys = [...[node.key, ...childKeys]];
|
||||
const selectedAllKeys = selected
|
||||
? [...[...parents, ...children]]
|
||||
: [...children];
|
||||
selectedAllKeys.forEach((item: string) => {
|
||||
Keys[e.selected ? 'add' : 'delete'](item);
|
||||
Keys[selected ? 'add' : 'delete'](item);
|
||||
});
|
||||
return [...Keys];
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue