feat(web): Home page ui upgrade

This commit is contained in:
zhaoying
2026-03-07 12:20:55 +08:00
parent 0b3b241436
commit e2b6c713e7
22 changed files with 1016 additions and 1000 deletions

View File

@@ -33,92 +33,72 @@ export const useNavigationBreadcrumbs = (source: 'space' | 'manage' = 'manage')
const currentPath = location.pathname;
const menus = allMenus[source] || [];
/** Find matching menu item and build key path */
const findMenuKeyPath = (menuList: any[], parentKeys: string[] = []): string[] | null => {
let bestMatch: { path: string; parentId?: string; score: number } | null = null;
for (const menu of menuList) {
/** Check submenus */
if (menu.subs && menu.subs.length > 0) {
const menuPath = menu.path ? (menu.path[0] !== '/' ? '/' + menu.path : menu.path) : '';
for (const sub of menu.subs) {
if (sub.path) {
const subPath = sub.path[0] !== '/' ? '/' + sub.path : sub.path;
/** Exact match has priority */
if (subPath === currentPath) {
return [sub.path, `${menu.id}`];
}
console.log('menuPath', menuPath)
/** Dynamic route matching */
if (subPath.includes(':')) {
/** Check if under parent menu */
if (menuPath && currentPath.startsWith(menuPath + '/')) {
const relativePath = currentPath.replace(menuPath, '');
const pathSegments = subPath.split('/');
const relativeSegments = relativePath.split('/');
if (pathSegments.length === relativeSegments.length) {
const pathPattern = subPath.replace(/:[\w-]+/g, '[^/]+').replace(/\[[\w-]+\]/g, '[^/]+');
const regex = new RegExp(`^${pathPattern}$`);
if (regex.test(relativePath)) {
return [sub.path, `${menu.id}`];
}
}
}
/** Direct match submenu path */
const pathSegments = subPath.split('/');
const currentSegments = currentPath.split('/');
if (pathSegments.length === currentSegments.length) {
const pathPattern = subPath.replace(/:[\w-]+/g, '[^/]+').replace(/\[[\w-]+\]/g, '[^/]+');
const regex = new RegExp(`^${pathPattern}$`);
if (regex.test(currentPath)) {
return [sub.path, `${menu.id}`];
}
}
}
}
}
}
/** Check main menu */
if (menu.path) {
const menuPath = menu.path[0] !== '/' ? '/' + menu.path : menu.path;
/** Exact match has priority */
if (menuPath === currentPath) {
return [menu.path, ...parentKeys].reverse();
}
/** Dynamic route matching */
if (menuPath.includes(':')) {
const pathSegments = menuPath.split('/');
const currentSegments = currentPath.split('/');
if (pathSegments.length === currentSegments.length) {
const pathPattern = menuPath.replace(/:[\w-]+/g, '[^/]+').replace(/\[[\w-]+\]/g, '[^/]+');
const regex = new RegExp(`^${pathPattern}$`);
if (regex.test(currentPath)) {
const score = menuPath.split('/').length;
if (!bestMatch || score > bestMatch.score) {
bestMatch = { path: menu.path, score };
}
}
}
} else if (currentPath.startsWith(menuPath + '/')) {
const score = menuPath.split('/').length;
if (!bestMatch || score > bestMatch.score) {
bestMatch = { path: menu.path, score };
}
}
}
const pathMatches = (pattern: string, path: string): boolean => {
const normalized = pattern[0] !== '/' ? '/' + pattern : pattern;
if (normalized === path) return true;
if (normalized.includes(':')) {
const regex = new RegExp('^' + normalized.replace(/:[\\w-]+/g, '[^/]+') + '$');
return regex.test(path);
}
if (bestMatch) {
return bestMatch.parentId ? [bestMatch.path, bestMatch.parentId] : [bestMatch.path];
return false;
};
/**
* Recursively search menu tree, returns keyPath or null.
* keyPath format:
* - 1-level: [path]
* - 2-level: [subPath, parentId]
* - 3-level: [subSubPath, subId, parentId]
*/
/**
* parentId: the group's id when recursing into group subs
* keyPath format:
* - 1-level: [path]
* - 2-level: [subPath, parentId]
* - 3-level: [subSubPath, subId, parentId]
*/
const findKeyPath = (menuList: any[], groupId?: string): string[] | null => {
for (const menu of menuList) {
/** Group menus: recurse into subs, passing group id */
if (menu.type === 'group' && menu.subs?.length) {
const result = findKeyPath(menu.subs, `${menu.id}`);
if (result) return result;
continue;
}
if (menu.subs?.length) {
for (const sub of menu.subs) {
/** Check third-level subs */
if (sub.subs?.length) {
for (const subSub of sub.subs) {
if (subSub.path && pathMatches(subSub.path, currentPath)) {
return [subSub.path, `${sub.id}`, `${menu.id}`];
}
}
}
/** Second-level match: sub is a leaf under menu */
if (sub.path && pathMatches(sub.path, currentPath)) {
/** If menu is inside a group, return 3-level: [subPath, menuId, groupId] */
return groupId
? [sub.path, `${menu.id}`, groupId]
: [sub.path, `${menu.id}`];
}
}
}
/** First-level / group-child match */
if (menu.path && pathMatches(menu.path, currentPath)) {
return groupId ? [menu.path, groupId] : [menu.path];
}
}
return null;
};
const keyPath = findMenuKeyPath(menus);
const keyPath = findKeyPath(menus);
console.log('keyPath', keyPath)
if (keyPath) {
updateBreadcrumbs(keyPath, source);
}
}, [location.pathname, allMenus, source, updateBreadcrumbs]);
};
};