feat(k8s): A1 K8s 双路由体系统一 — code 路由为主, ID 路由标记 deprecated

后端:
- 新增 4 条 all-NS code 路由: services/ingresses/cronjobs/nodes
- ListNodes 改用 getK8sClientByCode (兼容 ID+code)
- ID 域资源路由标记 // Deprecated

前端:
- clusterApi/nodeApi/workloadApi 资源方法迁移到 code 路由
- KubernetesClusterDetail/TopologyView/KubernetesNodes 组件从 cluster.id 迁移到 cluster.code
- 修复潜在 bug: ClusterOverviewPage 曾将 code 传给 ID-based getNodes

验证: 16/16 API 测试通过 (7 新 code 路由 + 3 旧 ID 兼容 + 6 回归)
go build=✅ tsc -b=✅ npm build=✅
This commit is contained in:
attacker committed 2026-06-27 04:50:58 +08:00
1 parent bb2b91ebe0
commit 00a98e210d
13 files changed
+241 -39

No files matched your search

@@ -67,15 +67,16 @@ export function KubernetesClusterDetail({ cluster, onClose }: { cluster?: JsonDa
];
}, [clusterMetrics]);
const loadClusterDetail = async (clusterId: string) => {
const loadClusterDetail = async (clusterCode: string) => {
try {
// 后端 ListNodes/ListPods/etc 返回 data 直接为数组(非 {list,total})
// 统一使用 Kuboard code 路由 (ROADMAP A1)
const [nodesRes, podsRes, depRes, svcRes, ingRes] = await Promise.all([
kubernetesApi.getNodes(clusterId).catch(() => []),
kubernetesApi.getPods(clusterId).catch(() => []),
kubernetesApi.getDeployments(clusterId).catch(() => []),
kubernetesApi.getServices(clusterId).catch(() => []),
kubernetesApi.getIngresses(clusterId).catch(() => []),
kubernetesApi.getNodes(clusterCode).catch(() => []),
kubernetesApi.getPods(clusterCode).catch(() => []),
kubernetesApi.getDeployments(clusterCode).catch(() => []),
kubernetesApi.getServices(clusterCode).catch(() => []),
kubernetesApi.getIngresses(clusterCode).catch(() => []),
]);
const toArray = (v: JsonData) => (Array.isArray(v) ? v : (v?.list || []));
setNodes(toArray(nodesRes));
@@ -89,10 +90,10 @@ export function KubernetesClusterDetail({ cluster, onClose }: { cluster?: JsonDa
};
useEffect(() => {
if (cluster?.id) {
loadClusterDetail(cluster.id);
if (cluster?.code) {
loadClusterDetail(cluster.code);
}
}, [cluster?.id]);
}, [cluster?.code]);
return (
<Card className="bg-slate-900 border-slate-800">
@@ -26,7 +26,7 @@ export function KubernetesNodes() {
const res: JsonData = await kubernetesApi.getClusters();
const list = res?.list || [];
setClusters(list);
if (list.length > 0 && !selectedCluster) setSelectedCluster(String(list[0].id));
if (list.length > 0 && !selectedCluster) setSelectedCluster(String(list[0].code || list[0].id));
} catch { setClusters([]); }
}, []);
@@ -72,7 +72,7 @@ export function KubernetesNodes() {
</SelectTrigger>
<SelectContent className="bg-slate-800 border-slate-700">
{clusters.map((c) => (
<SelectItem key={c.id} value={String(c.id)}>{c.name}</SelectItem>
<SelectItem key={c.id} value={String(c.code || c.id)}>{c.name}</SelectItem>
))}
</SelectContent>
</Select>
@@ -96,14 +96,16 @@ export function TopologyView() {
setLoading(true);
try {
const toArray = ( v: any) => (Array.isArray(v) ? v : (v?.list || []));
const [nodesRes, svcRes, depRes, ingRes, podRes] = await Promise.all([
kubernetesApi.getNodes(selectedClusterId).catch(() => []),
kubernetesApi.getServices(selectedClusterId).catch(() => []),
kubernetesApi.getDeployments(selectedClusterId).catch(() => []),
kubernetesApi.getIngresses(selectedClusterId).catch(() => []),
kubernetesApi.getPods(selectedClusterId).catch(() => []),
]);
const cluster = clusters.find((c) => String(c.id) === selectedClusterId) || {};
// 统一使用 Kuboard code 路由获取资源 (ROADMAP A1)
const clusterCode = (cluster as any).code || selectedClusterId;
const [nodesRes, svcRes, depRes, ingRes, podRes] = await Promise.all([
kubernetesApi.getNodes(clusterCode).catch(() => []),
kubernetesApi.getServices(clusterCode).catch(() => []),
kubernetesApi.getDeployments(clusterCode).catch(() => []),
kubernetesApi.getIngresses(clusterCode).catch(() => []),
kubernetesApi.getPods(clusterCode).catch(() => []),
]);
const built = buildTopology(cluster, toArray(ingRes), toArray(svcRes), toArray(depRes), toArray(nodesRes), toArray(podRes));
// 合并已保存布局