refactor(sidebar): 提取侧边栏项目解析逻辑到工具函数复用

This commit is contained in:
Oscar
2025-12-11 17:14:02 +08:00
parent 7e43cca134
commit 2387abe570
2 changed files with 82 additions and 80 deletions
@@ -121,7 +121,8 @@ import sidebarItems from '@/layouts/full/vertical-sidebar/sidebarItem';
import {
getSidebarCustomization,
setSidebarCustomization,
clearSidebarCustomization
clearSidebarCustomization,
resolveSidebarItems
} from '@/utils/sidebarCustomization';
const { t } = useI18n();
@@ -133,52 +134,12 @@ const draggedItem = ref(null);
function initializeItems() {
const customization = getSidebarCustomization();
const all = new Map();
const defaultMain = [];
const defaultMore = [];
sidebarItems.forEach(item => {
if (item.children) {
item.children.forEach(child => {
all.set(child.title, child);
defaultMore.push(child.title);
});
} else {
all.set(item.title, item);
defaultMain.push(item.title);
}
});
if (customization) {
const used = new Set([...(customization.mainItems || []), ...(customization.moreItems || [])]);
mainItems.value = (customization.mainItems || [])
.map(title => all.get(title))
.filter(Boolean);
// 追加新增默认主区项
defaultMain.forEach(title => {
if (!used.has(title)) {
const item = all.get(title);
if (item) mainItems.value.push(item);
}
});
moreItems.value = (customization.moreItems || [])
.map(title => all.get(title))
.filter(Boolean);
// 追加新增默认更多区项
defaultMore.forEach(title => {
if (!used.has(title)) {
const item = all.get(title);
if (item) moreItems.value.push(item);
}
});
} else {
// Load default structure
mainItems.value = sidebarItems.filter(item => !item.children);
const moreGroup = sidebarItems.find(item => item.title === 'core.navigation.groups.more');
moreItems.value = moreGroup ? [...moreGroup.children] : [];
}
const { mainItems: resolvedMain, moreItems: resolvedMore } = resolveSidebarItems(
sidebarItems,
customization
);
mainItems.value = resolvedMain;
moreItems.value = resolvedMore;
}
function openDialog() {
+74 -33
View File
@@ -41,56 +41,97 @@ export function clearSidebarCustomization() {
}
/**
* Apply customization to sidebar items
* @param {Array} defaultItems - Default sidebar items array
* @returns {Array} Customized sidebar items array (new array, doesn't mutate input)
* 解析侧边栏默认项与用户定制,返回主区/更多区及可选的合并结果
* @param {Array} defaultItems - 默认侧边栏结构
* @param {Object|null} customization - 用户定制(mainItems/moreItems
* @param {Object} options
* @param {boolean} [options.cloneItems=false] - 是否克隆条目以避免外部引用被修改
* @param {boolean} [options.assembleMoreGroup=false] - 是否组装带更多分组的整体数组
* @returns {{ mainItems: Array, moreItems: Array, merged?: Array }}
*/
export function applySidebarCustomization(defaultItems) {
const customization = getSidebarCustomization();
if (!customization) {
return defaultItems;
}
export function resolveSidebarItems(defaultItems, customization, options = {}) {
const { cloneItems = false, assembleMoreGroup = false } = options;
const { mainItems = [], moreItems = [] } = customization;
const all = new Map();
const defaultMain = [];
const defaultMore = [];
// 收集所有条目,按 title 建索引
defaultItems.forEach(item => {
if (item.children) {
item.children.forEach(child => {
all.set(child.title, { ...child });
all.set(child.title, cloneItems ? { ...child } : child);
defaultMore.push(child.title);
});
} else {
all.set(item.title, { ...item });
all.set(item.title, cloneItems ? { ...item } : item);
defaultMain.push(item.title);
}
});
const customizedItems = [];
const used = new Set([...mainItems, ...moreItems]);
// 按用户顺序还原主区
mainItems.forEach(title => all.get(title) && customizedItems.push(all.get(title)));
// 追加新增的默认主区项
defaultMain.forEach(title => !used.has(title) && customizedItems.push(all.get(title)));
const hasCustomization = Boolean(customization);
const mainKeys = hasCustomization ? customization.mainItems || [] : defaultMain;
const moreKeys = hasCustomization ? customization.moreItems || [] : defaultMore;
const used = hasCustomization ? new Set([...mainKeys, ...moreKeys]) : new Set(defaultMain.concat(defaultMore));
// 更多区:用户配置 + 新增默认
const mergedMore = [...moreItems];
defaultMore.forEach(title => { if (!used.has(title)) mergedMore.push(title); });
const mainItems = mainKeys
.map(title => all.get(title))
.filter(Boolean);
if (mergedMore.length > 0) {
const moreGroup = {
title: 'core.navigation.groups.more',
icon: 'mdi-dots-horizontal',
children: []
};
mergedMore.forEach(title => all.get(title) && moreGroup.children.push(all.get(title)));
customizedItems.push(moreGroup);
if (hasCustomization) {
// 补充新增默认主区项
defaultMain.forEach(title => {
if (!used.has(title)) {
const item = all.get(title);
if (item) mainItems.push(item);
}
});
}
return customizedItems;
const moreItems = moreKeys
.map(title => all.get(title))
.filter(Boolean);
if (hasCustomization) {
// 补充新增默认更多区项
defaultMore.forEach(title => {
if (!used.has(title)) {
const item = all.get(title);
if (item) moreItems.push(item);
}
});
}
let merged;
if (assembleMoreGroup) {
const children = cloneItems ? moreItems.map(item => ({ ...item })) : [...moreItems];
if (children.length > 0) {
merged = [
...mainItems,
{
title: 'core.navigation.groups.more',
icon: 'mdi-dots-horizontal',
children
}
];
} else {
merged = [...mainItems];
}
}
return { mainItems, moreItems, merged };
}
/**
* 应用侧边栏定制,返回包含更多分组的完整结构
* @param {Array} defaultItems - 默认侧边栏结构
* @returns {Array} 自定义后的结构(新数组,不修改入参)
*/
export function applySidebarCustomization(defaultItems) {
const customization = getSidebarCustomization();
const { merged } = resolveSidebarItems(defaultItems, customization, {
cloneItems: true,
assembleMoreGroup: true
});
return merged || defaultItems;
}