mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-09 10:57:03 +08:00
218 lines
6.6 KiB
TypeScript
218 lines
6.6 KiB
TypeScript
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
|
import type { LucideIcon } from 'lucide-vue-next'
|
|
import {
|
|
Activity,
|
|
BarChart3,
|
|
Box,
|
|
Cog,
|
|
CreditCard,
|
|
Database,
|
|
FileUp,
|
|
FolderTree,
|
|
Gift,
|
|
Gauge,
|
|
Home,
|
|
Key,
|
|
KeyRound,
|
|
Layers,
|
|
Package,
|
|
Puzzle,
|
|
Send,
|
|
Server,
|
|
Shield,
|
|
SlidersHorizontal,
|
|
Users,
|
|
Wallet,
|
|
Zap,
|
|
Megaphone,
|
|
} from 'lucide-vue-next'
|
|
import type { NavigationGroup } from '@/components/layout/SidebarNav.vue'
|
|
import type { ModuleStatus } from '@/api/modules'
|
|
import { BUILTIN_TOOL_BREADCRUMBS } from '@/config/builtin-tools'
|
|
import type { MessageKey } from '@/i18n'
|
|
|
|
type ModuleRecord = Record<string, ModuleStatus>
|
|
type Translate = (key: MessageKey) => string
|
|
|
|
export interface BreadcrumbItem {
|
|
label: string
|
|
href?: string
|
|
}
|
|
|
|
type NavItem = NavigationGroup['items'][number]
|
|
|
|
const moduleIconMap: Record<string, LucideIcon> = {
|
|
Key,
|
|
KeyRound,
|
|
FileUp,
|
|
Shield,
|
|
Puzzle,
|
|
Server,
|
|
Send,
|
|
SlidersHorizontal,
|
|
CreditCard,
|
|
Gift,
|
|
}
|
|
|
|
function activeModuleItems(modules: ModuleRecord, group: string): NavItem[] {
|
|
return Object.values(modules)
|
|
.filter(m => m.active && m.admin_route && m.admin_menu_group === group)
|
|
.sort((a, b) => a.admin_menu_order - b.admin_menu_order)
|
|
.map(m => ({
|
|
name: m.display_name,
|
|
href: m.admin_route ?? '',
|
|
icon: moduleIconMap[m.admin_menu_icon || ''] || Puzzle
|
|
}))
|
|
}
|
|
|
|
export function buildNavigation(options: {
|
|
canAccessAdmin: boolean
|
|
modules: ModuleRecord
|
|
isModuleActive: (name: string) => boolean
|
|
t?: Translate
|
|
}): NavigationGroup[] {
|
|
const { canAccessAdmin, modules, isModuleActive } = options
|
|
const t = options.t ?? ((key: MessageKey) => key)
|
|
|
|
if (!canAccessAdmin) {
|
|
return [
|
|
{
|
|
title: t('nav.group.overview'),
|
|
items: [
|
|
{ name: t('nav.dashboard'), href: '/dashboard', icon: Home },
|
|
{ name: t('nav.healthMonitor'), href: '/dashboard/endpoint-status', icon: Activity },
|
|
]
|
|
},
|
|
{
|
|
title: t('nav.group.resources'),
|
|
items: [
|
|
{ name: t('nav.modelCatalog'), href: '/dashboard/models', icon: Box },
|
|
{ name: t('nav.apiKeys'), href: '/dashboard/api-keys', icon: Key },
|
|
]
|
|
},
|
|
{
|
|
title: t('nav.group.account'),
|
|
items: [
|
|
{ name: t('nav.walletCenter'), href: '/dashboard/wallet', icon: Wallet },
|
|
{ name: t('nav.billingCenter'), href: '/dashboard/billing', icon: Package },
|
|
...(isModuleActive('referral') ? [{ name: t('nav.myReferral'), href: '/dashboard/referral', icon: Gift }] : []),
|
|
{ name: t('nav.usageStats'), href: '/dashboard/usage', icon: BarChart3 },
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
const systemItems: NavItem[] = [
|
|
{ name: t('nav.announcements'), href: '/admin/announcements', icon: Megaphone },
|
|
{ name: t('nav.cacheMonitoring'), href: '/admin/cache-monitoring', icon: Gauge },
|
|
...activeModuleItems(modules, 'system'),
|
|
{ name: t('nav.moduleManagement'), href: '/admin/modules', icon: Puzzle },
|
|
{ name: t('nav.systemSettings'), href: '/admin/system', icon: Cog },
|
|
]
|
|
|
|
return [
|
|
{
|
|
title: t('nav.group.overview'),
|
|
items: [
|
|
{ name: t('nav.dashboard'), href: '/admin/dashboard', icon: Home },
|
|
{ name: t('nav.operations'), href: '/admin/operations', icon: Activity },
|
|
{ name: t('nav.healthMonitor'), href: '/admin/health-monitor', icon: Activity },
|
|
{ name: t('nav.userStats'), href: '/admin/user-stats', icon: BarChart3 },
|
|
{ name: t('nav.costAnalysis'), href: '/admin/cost-analysis', icon: Gauge },
|
|
{ name: t('nav.performanceAnalysis'), href: '/admin/performance-analysis', icon: Activity },
|
|
]
|
|
},
|
|
{
|
|
title: t('nav.group.management'),
|
|
items: [
|
|
{ name: t('nav.userManagement'), href: '/admin/users', icon: Users },
|
|
{ name: t('nav.providers'), href: '/admin/providers', icon: FolderTree },
|
|
{ name: t('nav.modelManagement'), href: '/admin/models', icon: Layers },
|
|
{ name: t('nav.routing'), href: '/admin/routing', icon: SlidersHorizontal },
|
|
{ name: t('nav.pool'), href: '/admin/pool', icon: Database },
|
|
{ name: t('nav.standaloneKeys'), href: '/admin/keys', icon: Key },
|
|
{ name: t('nav.walletManagement'), href: '/admin/wallets', icon: Wallet },
|
|
{ name: t('nav.billingManagement'), href: '/admin/billing-plans', icon: Package },
|
|
...activeModuleItems(modules, 'management'),
|
|
{ name: t('nav.asyncTasks'), href: '/admin/async-tasks', icon: Zap },
|
|
{ name: t('nav.usageRecords'), href: '/admin/usage', icon: BarChart3 },
|
|
]
|
|
},
|
|
{
|
|
title: t('nav.group.system'),
|
|
items: systemItems
|
|
}
|
|
]
|
|
}
|
|
|
|
export function buildBreadcrumbs(options: {
|
|
route: RouteLocationNormalizedLoaded
|
|
navigation: NavigationGroup[]
|
|
modules: ModuleRecord
|
|
isNavActive: (href: string) => boolean
|
|
t?: Translate
|
|
}): BreadcrumbItem[] {
|
|
const { route, navigation, modules, isNavActive } = options
|
|
const t = options.t ?? ((key: MessageKey) => key)
|
|
|
|
if (route.path === '/dashboard/settings') {
|
|
return [
|
|
{ label: t('nav.group.account') },
|
|
{ label: t('breadcrumb.personalSettings') }
|
|
]
|
|
}
|
|
|
|
if (route.meta?.module) {
|
|
const moduleName = route.meta.module as string
|
|
const moduleStatus = modules[moduleName]
|
|
const displayName = moduleStatus?.display_name || moduleName
|
|
return [
|
|
{ label: t('nav.group.system') },
|
|
{ label: t('nav.moduleManagement'), href: '/admin/modules' },
|
|
{ label: displayName }
|
|
]
|
|
}
|
|
|
|
if (BUILTIN_TOOL_BREADCRUMBS[route.path]) {
|
|
return [
|
|
{ label: t('nav.group.system') },
|
|
{ label: t('nav.moduleManagement'), href: '/admin/modules' },
|
|
{ label: BUILTIN_TOOL_BREADCRUMBS[route.path] }
|
|
]
|
|
}
|
|
|
|
if (route.path.startsWith('/admin/routing/') && route.path !== '/admin/routing') {
|
|
return [
|
|
{ label: t('nav.group.management') },
|
|
{ label: t('nav.routing'), href: '/admin/routing' },
|
|
{
|
|
label: route.name === 'RoutingProfileCreate'
|
|
? t('breadcrumb.routingCreate')
|
|
: t('breadcrumb.routingConfig')
|
|
}
|
|
]
|
|
}
|
|
|
|
for (const group of navigation) {
|
|
const activeItem = group.items.find(item => isNavActive(item.href))
|
|
if (activeItem) {
|
|
return [
|
|
{ label: group.title || '' },
|
|
{ label: activeItem.name }
|
|
]
|
|
}
|
|
}
|
|
|
|
const currentModule = Object.values(modules).find(
|
|
m => m.admin_route && route.path === m.admin_route
|
|
)
|
|
if (currentModule) {
|
|
return [
|
|
{ label: t('nav.moduleManagement'), href: '/admin/modules' },
|
|
{ label: currentModule.display_name }
|
|
]
|
|
}
|
|
|
|
return [{ label: t('nav.dashboard') }]
|
|
}
|