diff --git a/src/app/panel/components/PanelSidebarContent.tsx b/src/app/panel/components/PanelSidebarContent.tsx
index 3f78050..08e2199 100644
--- a/src/app/panel/components/PanelSidebarContent.tsx
+++ b/src/app/panel/components/PanelSidebarContent.tsx
@@ -4,21 +4,24 @@ import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { useMemo, type ComponentType } from 'react'
+import { Plus, type LucideIcon } from 'lucide-react'
+
import { getExtensionRegistry } from '@extensions/loader'
import { useLanguage } from '@i18n/LanguageProvider'
import { translations } from '@i18n/translations'
import { resolveAccess } from '@lib/accessControl'
import { useUserStore } from '@lib/userStore'
-import { SidebarHeader, SidebarContent } from '../../../components/layout/SidebarRoot'
+import { SidebarHeader, SidebarContent, SidebarFooter } from '../../../components/layout/SidebarRoot'
const registry = getExtensionRegistry()
const PlaceholderIcon: ComponentType<{ className?: string }> = () => null
interface NavItem {
+ id?: string
href: string
label: string
description: string
- Icon: ComponentType<{ className?: string }>
+ Icon: ComponentType<{ className?: string }> | LucideIcon
disabled: boolean
}
@@ -68,6 +71,7 @@ export function PanelSidebarContent({ onNavigate, collapsed = false }: PanelSide
const Icon = route.icon ?? PlaceholderIcon
return {
+ id: route.id,
href: route.path,
label: route.label,
description: route.description ?? '',
@@ -75,7 +79,7 @@ export function PanelSidebarContent({ onNavigate, collapsed = false }: PanelSide
disabled,
}
})
- .filter((value): value is NavItem => Boolean(value))
+ .filter((value) => Boolean(value)) as NavItem[]
if (items.length === 0) {
return null
@@ -87,7 +91,7 @@ export function PanelSidebarContent({ onNavigate, collapsed = false }: PanelSide
items,
}
})
- .filter((value): value is NavSection => Boolean(value))
+ .filter((value) => Boolean(value)) as NavSection[]
}, [requiresSetup, user])
return (
@@ -193,7 +197,9 @@ export function PanelSidebarContent({ onNavigate, collapsed = false }: PanelSide
- {item.label}
+
+ {(item.id && translations[language].userCenter.items[item.id as keyof typeof translations.en.userCenter.items]) || item.label}
+
{item.description}
@@ -218,6 +224,18 @@ export function PanelSidebarContent({ onNavigate, collapsed = false }: PanelSide
)
})}
+
+
+
+
>
)
}
diff --git a/src/app/services/Material3Layout.tsx b/src/app/services/Material3Layout.tsx
index 1ee708e..fde1266 100644
--- a/src/app/services/Material3Layout.tsx
+++ b/src/app/services/Material3Layout.tsx
@@ -1,7 +1,6 @@
'use client'
import React from 'react'
-import { Sidebar } from '../../components/Sidebar'
import { Header } from '../../components/Header'
interface Material3LayoutProps {
@@ -11,7 +10,6 @@ interface Material3LayoutProps {
export function Material3Layout({ children }: Material3LayoutProps) {
return (
-
diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts
index e3a5f2a..8562d1a 100644
--- a/src/i18n/translations.ts
+++ b/src/i18n/translations.ts
@@ -478,9 +478,25 @@ type UserCenterTranslation = {
sections: {
workspace: string
productivity: string
+ infra: string
management: string
preferences: string
}
+ items: {
+ dashboard: string
+ mail: string
+ agents: string
+ apis: string
+ accounts: string
+ subscription: string
+ ldp: string
+ appearance: string
+ deployments: string
+ resources: string
+ apiKeys: string
+ logs: string
+ settings: string
+ }
overview: UserCenterOverviewTranslation
mfa: UserCenterMfaTranslation
}
@@ -950,9 +966,25 @@ export const translations: Record<'en' | 'zh', Translation> = {
sections: {
workspace: 'Workspace',
productivity: 'Productivity Tools',
+ infra: 'Infrastructure',
management: 'Accounts & Access',
preferences: 'Preferences',
},
+ items: {
+ dashboard: 'Dashboard',
+ mail: 'Mail',
+ agents: 'Agents',
+ apis: 'APIs',
+ accounts: 'Accounts',
+ subscription: 'Subscription',
+ ldp: 'LDP',
+ appearance: 'Appearance',
+ deployments: 'Deployments',
+ resources: 'Resources',
+ apiKeys: 'API Keys',
+ logs: 'Logs',
+ settings: 'Settings',
+ },
overview: {
heading: 'User Center',
loading: 'Loading your personalized space…',
@@ -1702,9 +1734,25 @@ export const translations: Record<'en' | 'zh', Translation> = {
sections: {
workspace: '工作台',
productivity: '生产力工具',
+ infra: '资源运维',
management: '账户与权限',
preferences: '偏好设置',
},
+ items: {
+ dashboard: '仪表盘',
+ mail: '邮箱服务',
+ agents: '运行节点',
+ apis: '接口集成',
+ accounts: '账户中心',
+ subscription: '订阅计划',
+ ldp: '身份平面',
+ appearance: '个性化',
+ deployments: '部署管理',
+ resources: '资源列表',
+ apiKeys: '接口密钥',
+ logs: '运行日志',
+ settings: '系统设置',
+ },
overview: {
heading: '用户中心',
loading: '正在加载你的专属空间…',
diff --git a/src/modules/extensions/builtin/index.ts b/src/modules/extensions/builtin/index.ts
index bd4488c..b64dc50 100644
--- a/src/modules/extensions/builtin/index.ts
+++ b/src/modules/extensions/builtin/index.ts
@@ -1,5 +1,9 @@
import type { DashboardExtension } from '../types'
import { userCenterExtension } from './user-center'
+import { infraExtension } from './infra'
-export const builtinExtensions: DashboardExtension[] = [userCenterExtension]
+export const builtinExtensions: DashboardExtension[] = [
+ userCenterExtension,
+ infraExtension,
+]
diff --git a/src/modules/extensions/builtin/infra/index.ts b/src/modules/extensions/builtin/infra/index.ts
new file mode 100644
index 0000000..48b50e3
--- /dev/null
+++ b/src/modules/extensions/builtin/infra/index.ts
@@ -0,0 +1,66 @@
+import { Database, History, Key, Rocket, Settings } from 'lucide-react'
+
+import type { DashboardExtension } from '../../types'
+
+export const infraExtension: DashboardExtension = {
+ id: 'builtin.infra',
+ meta: {
+ title: '基础设施管理',
+ description: '云基础设施、部署、资源与日志管理。',
+ version: '1.0.0',
+ author: 'Cloud-Neutral',
+ keywords: ['infrastructure', 'deployments', 'resources', 'logs'],
+ },
+ routes: [
+ {
+ id: 'deployments',
+ path: '/panel/deployments',
+ label: 'Deployments',
+ description: '部署任务与运行状态',
+ icon: Rocket,
+ loader: () => import('./routes/placeholder'),
+ guard: { requireLogin: true },
+ sidebar: { section: 'infra', order: 0 },
+ },
+ {
+ id: 'resources',
+ path: '/panel/resources',
+ label: 'Resources',
+ description: '云资源与数据库实例',
+ icon: Database,
+ loader: () => import('./routes/placeholder'),
+ guard: { requireLogin: true },
+ sidebar: { section: 'infra', order: 1 },
+ },
+ {
+ id: 'apiKeys',
+ path: '/panel/api-keys',
+ label: 'API Keys',
+ description: '接口密钥与访问凭证',
+ icon: Key,
+ loader: () => import('./routes/placeholder'),
+ guard: { requireLogin: true },
+ sidebar: { section: 'infra', order: 2 },
+ },
+ {
+ id: 'logs',
+ path: '/panel/logs',
+ label: 'Logs',
+ description: '系统流水与审计日志',
+ icon: History,
+ loader: () => import('./routes/placeholder'),
+ guard: { requireLogin: true },
+ sidebar: { section: 'infra', order: 3 },
+ },
+ {
+ id: 'settings',
+ path: '/panel/settings',
+ label: 'Settings',
+ description: '全局系统配置',
+ icon: Settings,
+ loader: () => import('./routes/placeholder'),
+ guard: { requireLogin: true, roles: ['admin', 'operator'] },
+ sidebar: { section: 'preferences', order: 99 },
+ },
+ ],
+}
diff --git a/src/modules/extensions/builtin/infra/routes/placeholder.tsx b/src/modules/extensions/builtin/infra/routes/placeholder.tsx
new file mode 100644
index 0000000..d183f10
--- /dev/null
+++ b/src/modules/extensions/builtin/infra/routes/placeholder.tsx
@@ -0,0 +1,22 @@
+'use client'
+
+import React from 'react'
+import { usePathname } from 'next/navigation'
+
+export default function PlaceholderPage() {
+ const pathname = usePathname()
+ const title = pathname.split('/').pop()?.replace(/-/g, ' ') || 'Page'
+
+ return (
+
+
+ {title.charAt(0)}
+
+
{title}
+
+ This feature is currently under active development.
+ It will soon provide a powerful interface for managing your {title.toLowerCase()}.
+
+
+ )
+}
diff --git a/src/modules/extensions/builtin/user-center/index.ts b/src/modules/extensions/builtin/user-center/index.ts
index 06b4948..45cbdbb 100644
--- a/src/modules/extensions/builtin/user-center/index.ts
+++ b/src/modules/extensions/builtin/user-center/index.ts
@@ -13,6 +13,7 @@ export const userCenterExtension: DashboardExtension = {
},
routes: [
{
+ id: 'dashboard',
path: '/panel',
label: 'Dashboard',
description: '专属于你的信息总览',
@@ -24,6 +25,7 @@ export const userCenterExtension: DashboardExtension = {
sidebar: { section: 'workspace', order: 0 },
},
{
+ id: 'mail',
path: '/panel/mail',
label: 'Mail',
description: '租户邮件与 AI 助理',
@@ -34,6 +36,7 @@ export const userCenterExtension: DashboardExtension = {
sidebar: { section: 'workspace', order: 1 },
},
{
+ id: 'agents',
path: '/panel/agent',
label: 'Agents',
description: '管理运行节点',
@@ -51,6 +54,7 @@ export const userCenterExtension: DashboardExtension = {
},
},
{
+ id: 'apis',
path: '/panel/api',
label: 'APIs',
description: '洞察后端服务',
@@ -68,6 +72,7 @@ export const userCenterExtension: DashboardExtension = {
},
},
{
+ id: 'accounts',
path: '/panel/account',
label: 'Accounts',
description: '目录与多因素设置',
@@ -78,6 +83,7 @@ export const userCenterExtension: DashboardExtension = {
sidebar: { section: 'management', order: 20 },
},
{
+ id: 'subscription',
path: '/panel/subscription',
label: 'Subscription',
description: '订阅方案与计费规则',
@@ -95,6 +101,7 @@ export const userCenterExtension: DashboardExtension = {
},
},
{
+ id: 'ldp',
path: '/panel/ldp',
label: 'LDP',
description: '低时延身份平面',
@@ -112,6 +119,7 @@ export const userCenterExtension: DashboardExtension = {
},
},
{
+ id: 'appearance',
path: '/panel/appearance',
label: 'Appearance',
description: '个性化主题设置',
diff --git a/src/modules/extensions/types.ts b/src/modules/extensions/types.ts
index 05c5859..9ad4d9c 100644
--- a/src/modules/extensions/types.ts
+++ b/src/modules/extensions/types.ts
@@ -27,6 +27,7 @@ export interface ExtensionMenuItem {
}
export interface ExtensionRoute {
+ id?: string
path: string
label: string
description?: string