import { Server, Copy, Check, Gauge, Network, Clock3, FileText, } from 'lucide-react' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Separator } from '@/components/ui/separator' import { Skeleton } from '@/components/ui/skeleton' import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from '@/components/ui/sheet' import { formatNanoDelay } from '@/lib/format' export interface SheetNodeInfo { id: string address: string compressedAddress?: string isSelf: boolean deviceName?: string } export interface SheetNeighborInfo { address: string deviceName?: string delay: number cost: number } interface NodeDetailSheetProps { open: boolean onOpenChange: (open: boolean) => void node: SheetNodeInfo | null neighbors: SheetNeighborInfo[] copiedId: string | null onCopy: (text: string) => void /** 设备描述(来自 /api/node-info 查询) */ description?: string | null descriptionLoading?: boolean } export function NodeDetailSheet({ open, onOpenChange, node, neighbors, copiedId, onCopy, description, descriptionLoading, }: NodeDetailSheetProps) { if (!node) return null const isCopied = copiedId === node.address return (
{node.deviceName || '未命名节点'} {node.isSelf && ( 本机 )} {node.compressedAddress || node.address}
{/* Device Description */}
设备描述 {descriptionLoading ? (
) : ( {description ? description : '无描述信息'} )}
{/* Full Address */}
完整 SRv6 地址 (SID)
{node.address}
{/* Stats */}
邻居数量
{neighbors.length}
平均时延
{neighbors.length > 0 ? formatNanoDelay( neighbors.reduce((acc, n) => acc + n.delay, 0) / neighbors.length ) : '--'}
{/* Neighbor list */}
邻居链路 {neighbors.length === 0 ? (
暂无可达邻居节点
) : ( neighbors.map((nb) => (
{nb.deviceName || '未命名节点'} {nb.address}
{formatNanoDelay(nb.delay)}
)) )}
{/* Reserved for Kperf speed test */}
) }