feat(wavelet): 侧栏新增网站管理折叠组

使用 shadcn Collapsible 与 SidebarMenuSub 收纳网站、证书、DNS、源站入口。
This commit is contained in:
ryan
2026-06-18 19:48:30 +08:00
parent 8b3d220d73
commit 1208f7ee94
5 changed files with 193 additions and 37 deletions
@@ -22,24 +22,25 @@ export interface OpenFlareNavItem {
childUrls?: string[];
}
export interface OpenFlareNavSubItem {
title: string;
url: string;
childUrls?: string[];
}
export interface OpenFlareNavGroup {
title: string;
icon: LucideIcon;
items: OpenFlareNavSubItem[];
}
/** OpenFlare 业务控制台侧栏导航(子页面通过父级入口或页内链接访问) */
export const openflareNavItems: OpenFlareNavItem[] = [
{title: '总览', url: '/', icon: LayoutDashboard},
{title: '节点', url: '/nodes', icon: Server, childUrls: ['/nodes/detail']},
{title: '规则', url: '/proxy-routes', icon: Route, childUrls: ['/proxy-routes/detail']},
{title: 'Pages', url: '/pages', icon: FileText, childUrls: ['/pages/detail']},
{
title: '网站',
url: '/websites',
icon: Globe,
childUrls: [
'/websites/detail',
'/websites/certificates',
'/websites/dns-accounts',
],
},
{title: 'WAF', url: '/waf', icon: Shield, childUrls: ['/waf/ip-groups']},
{title: '源站', url: '/origins', icon: MapPin, childUrls: ['/origins/detail']},
{title: '发布', url: '/config-versions', icon: GitBranch},
{title: '访问日志', url: '/access-logs', icon: ScrollText},
{title: '应用日志', url: '/apply-logs', icon: ClipboardList},
@@ -47,6 +48,18 @@ export const openflareNavItems: OpenFlareNavItem[] = [
{title: '关于', url: '/about', icon: Info},
];
/** 网站管理折叠组 */
export const openflareWebsiteNavGroup: OpenFlareNavGroup = {
title: '网站管理',
icon: Globe,
items: [
{title: '网站', url: '/websites', childUrls: ['/websites/detail']},
{title: '证书', url: '/websites/certificates'},
{title: 'DNS', url: '/websites/dns-accounts'},
{title: '源站', url: '/origins', childUrls: ['/origins/detail']},
],
};
/** 网站模块页内二级导航 */
export const openflareWebsiteSubNav = [
{title: '网站列表', url: '/websites'},
@@ -56,16 +69,37 @@ export const openflareWebsiteSubNav = [
const nonConsoleRoutePrefixes = ['/admin', '/settings', '/files', '/home', '/login', '/register', '/docs'];
export function matchesNavPath(
pathname: string,
url: string,
childUrls?: string[],
): boolean {
if (url === '/') {
return pathname === '/';
}
if (pathname === url || pathname.startsWith(`${url}/`)) {
return true;
}
return (childUrls ?? []).some(
(childUrl) => pathname === childUrl || pathname.startsWith(`${childUrl}/`),
);
}
export function isNavGroupActive(pathname: string, group: OpenFlareNavGroup): boolean {
return group.items.some((item) => matchesNavPath(pathname, item.url, item.childUrls));
}
/** 判断当前路径是否属于 OpenFlare 业务控制台(用于顶栏版本入口等) */
export function isOpenFlareConsoleRoute(pathname: string): boolean {
if (nonConsoleRoutePrefixes.some((prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`))) {
return false;
}
return openflareNavItems.some((item) => {
if (item.url === '/') {
return pathname === '/';
}
return pathname === item.url || pathname.startsWith(`${item.url}/`);
});
if (isNavGroupActive(pathname, openflareWebsiteNavGroup)) {
return true;
}
return openflareNavItems.some((item) => matchesNavPath(pathname, item.url, item.childUrls));
}