'use client'; import Link from 'next/link'; import { usePathname, useRouter, useSearchParams } from 'next/navigation'; import { type ReactNode, useCallback, useMemo } from 'react'; import type { LucideIcon } from 'lucide-react'; import { ArrowLeft } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { cn } from '@/lib/utils'; import { NodeKpiCard } from './node-detail-primitives'; import { NodeStatusBadge } from './node-status-badge'; import type { StatusTone } from './node-utils'; export type NodeDetailTabId = 'overview' | 'dashboard' | 'manage'; export type NodeDetailTabConfig = { id: NodeDetailTabId; label: string; icon?: LucideIcon; }; export type NodeDetailKpi = { label: string; value: ReactNode; icon?: LucideIcon; }; const TAB_CONFIGS: NodeDetailTabConfig[] = [ { id: 'overview', label: '概览', }, { id: 'dashboard', label: '数据看板', }, { id: 'manage', label: '配置与部署', }, ]; function isValidTab(value: string | null): value is NodeDetailTabId { return value === 'overview' || value === 'dashboard' || value === 'manage'; } export function NodeDetailShell({ title, typeLabel, typeTone = 'info', statusBadges, actions, kpis, overview, dashboard, manage, defaultTab = 'overview', }: { title: string; typeLabel: string; typeTone?: StatusTone; statusBadges: Array<{ label: string; tone: StatusTone }>; actions: ReactNode; kpis: NodeDetailKpi[]; overview: ReactNode; dashboard: ReactNode; manage: ReactNode; defaultTab?: NodeDetailTabId; }) { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); const activeTab = useMemo(() => { const tab = searchParams.get('tab'); return isValidTab(tab) ? tab : defaultTab; }, [defaultTab, searchParams]); const setActiveTab = useCallback( (tab: NodeDetailTabId) => { const params = new URLSearchParams(searchParams.toString()); params.set('tab', tab); router.replace(`${pathname}?${params.toString()}`, { scroll: false }); }, [pathname, router, searchParams], ); return (

{title}

{statusBadges.map((badge) => ( ))}
{actions}
{kpis.length > 0 ? (
{kpis.map((kpi) => ( ))}
) : null}
{ if (isValidTab(value)) { setActiveTab(value); } }} className='w-full gap-0' >
{TAB_CONFIGS.map((tab) => ( {tab.label} ))}
{activeTab === 'overview' ? overview : null} {activeTab === 'dashboard' ? dashboard : null} {activeTab === 'manage' ? manage : null}
); }