+
+
+
路由管理
+
宿主机分配给 LXC 的 NAT4 端口和 IPv6 地址
+
+
+
+
+
+ }
+ remaining={routing?.nat4.remaining || '0'}
+ total={routing?.nat4.total || '0'}
+ used={routing?.nat4.used || 0}
+ label="剩余端口 / 端口总数"
+ />
+ }
+ remaining={formatCapacity(routing?.ipv6.remaining || '0')}
+ total={formatCapacity(routing?.ipv6.total || '0')}
+ used={routing?.ipv6.used || 0}
+ label={`剩余地址 / 地址总数 · ${ipv6Prefix}`}
+ />
+
+
+
+
+
NAT4 端口分配
+
共 {nat4Mappings.length} 条映射
+
+ {nat4Mappings.length === 0 ? (
+
} text="暂无 NAT4 端口映射" />
+ ) : (
+ <>
+
+
+
+
+ | 容器 |
+ LXC 名称 |
+ 容器 IPv4 |
+ 宿主机端口 |
+ 容器端口 |
+ 协议 |
+ 说明 |
+ 状态 |
+
+
+
+ {pagedNat4Mappings.map((mapping, index) => (
+
+ |
+
+ |
+ {mapping.lxc_name} |
+ {mapping.ip || '-'} |
+ {mapping.host_port} |
+ {mapping.container_port} |
+ {mapping.protocol || '-'} |
+ {mapping.description || '-'} |
+ |
+
+ ))}
+
+
+
+
+ >
+ )}
+
+
+
+
+
IPv6 地址分配
+
共 {ipv6Assignments.length} 个地址
+
+ {ipv6Assignments.length === 0 ? (
+
} text="暂无 IPv6 地址分配" />
+ ) : (
+ <>
+
+
+
+
+ | 容器 |
+ LXC 名称 |
+ IPv6 地址 |
+ 前缀 |
+ 出口网卡 |
+ 状态 |
+
+
+
+ {pagedIPv6Assignments.map((item) => (
+
+ |
+
+ |
+ {item.lxc_name} |
+ {item.address} |
+ /{item.prefix_len || '-'} |
+ {item.interface || '-'} |
+ |
+
+ ))}
+
+
+
+
+ >
+ )}
+
+
+ )
+}
+
+function Pagination({ page, totalPages, totalItems, pageSize, onPageChange }: {
+ page: number
+ totalPages: number
+ totalItems: number
+ pageSize: number
+ onPageChange: (page: number) => void
+}) {
+ if (totalPages <= 1) return null
+
+ const start = (page - 1) * pageSize + 1
+ const end = Math.min(page * pageSize, totalItems)
+
+ return (
+
+
+ 显示 {start}-{end},共 {totalItems} 条
+
+
+
+
+ {page} / {totalPages}
+
+
+
+
+ )
+}
+
+function CapacityCard({ title, icon, remaining, total, used, label }: {
+ title: string
+ icon: React.ReactNode
+ remaining: string
+ total: string
+ used: number
+ label: string
+}) {
+ return (
+