feat(web): 整合 IwoooS 安全合規菜單
All checks were successful
Ansible Lint / lint (push) Successful in 30s
CD Pipeline / tests (push) Successful in 1m18s
Code Review / ai-code-review (push) Successful in 13s
CD Pipeline / build-and-deploy (push) Successful in 5m15s
CD Pipeline / post-deploy-checks (push) Successful in 2m43s

This commit is contained in:
Your Name
2026-05-31 15:03:32 +08:00
parent 872d1aa5e4
commit 50c9d51df9
5 changed files with 77 additions and 8 deletions

View File

@@ -54,6 +54,7 @@ type NavItemConfig = {
href: string
labelKey: string
Icon: typeof LayoutDashboard
aliases?: string[]
badge?: boolean // 是否顯示動態徽章
}
@@ -71,7 +72,7 @@ type NavSection = {
// 可觀測性 /observability → 整合: 監控 + APM + 錯誤 + 應用 + 服務 (5 Tab) [暫指 /monitoring]
// 自動化 /automation → 整合: 自動修復 + 神經指揮 + Drift (3 Tab) [暫指 /auto-repair]
// 營運 /operations → 整合: 部署 + 工單 + 成本 + 行動日誌 + 計費 (5 Tab) [暫指 /deployments]
// 安全合規 /security-compliance → 整合: 安全 + 合規 (2 Tab) [暫指 /security]
// IwoooS 安全合規 /iwooos → 整合: IwoooS + 安全合規;/security-compliance 保留相容高亮
// 知識 /knowledge → 知識庫 [暫指 /knowledge-base]
// ============================================================
@@ -84,8 +85,7 @@ const NAV_SECTIONS: NavSection[] = [
{ id: 'observability', href: '/observability', labelKey: 'observability', Icon: Monitor },
{ id: 'automation', href: '/automation', labelKey: 'automation', Icon: Wrench },
{ id: 'operations', href: '/operations', labelKey: 'operations', Icon: Package },
{ id: 'security-compliance', href: '/security-compliance', labelKey: 'securityCompliance',Icon: Shield },
{ id: 'iwooos', href: '/iwooos', labelKey: 'iwooos', Icon: Radar },
{ id: 'iwooos-security', href: '/iwooos', labelKey: 'iwooosSecurityCompliance', Icon: Radar, aliases: ['/security-compliance'] },
{ id: 'knowledge', href: '/knowledge', labelKey: 'knowledge', Icon: BookOpen },
{ id: 'governance', href: '/governance', labelKey: 'governance', Icon: ShieldCheck },
{ id: 'awooop', href: '/awooop/work-items', labelKey: 'awooop', Icon: BrainCircuit },
@@ -132,7 +132,7 @@ export function Sidebar({
setMounted(true)
}, [])
const isActive = (href: string) => {
const isRouteActive = (href: string) => {
const fullHref = `/${locale}${href === '/' ? '' : href}`
if (href === '/') {
return pathname === `/${locale}` || pathname === `/${locale}/`
@@ -140,6 +140,10 @@ export function Sidebar({
return pathname === fullHref || pathname.startsWith(fullHref + '/')
}
const isActive = (item: NavItemConfig) => (
isRouteActive(item.href) || item.aliases?.some(alias => isRouteActive(alias)) === true
)
return (
<aside
className={cn(
@@ -178,7 +182,7 @@ export function Sidebar({
</div>
)}
{section.items.map(item => {
const active = isActive(item.href)
const active = isActive(item)
const count = item.badge && mounted ? pendingCount : 0
return (
<Link
@@ -226,7 +230,7 @@ export function Sidebar({
{/* 底部菜單 */}
{BOTTOM_NAV_ITEMS.map(item => {
const active = isActive(item.href)
const active = isActive(item)
return (
<Link
key={item.id}