refactor(frontend): services/api 迁至 src/api,http 迁至 utils/request

对齐 Vue 后台惯例:
- src/api/          域 API(原 services/api)
- src/utils/request.ts  HTTP 封装(原 services/http.ts)
- src/utils/export.ts  客户端导出工具
- src/utils/index.ts   工具统一出口

全局导入改为 @/api 与 @/utils/request,tsc + build 通过。
This commit is contained in:
Logan.Li committed 2026-06-26 00:09:07 +08:00
1 parent 9bf35b369c
commit d19a03d427
145 files changed
+156 -142

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
// Kubernetes 集群管理 API // Logan.Li
import { http, type ListResponse } from '@/utils/request';
export const clusterApi = {
getClusters: async () => http.get<ListResponse>('/kubernetes-clusters'),
getClusterDetail: async (id: number | string) => http.get(`/kubernetes-clusters/${id}/detail`),
createCluster: async (data: Record<string, unknown>) => http.post('/kubernetes-clusters', data),
updateCluster: async (id: number | string, data: Record<string, unknown>) => http.put(`/kubernetes-clusters/${id}`, data),
deleteCluster: async (id: number | string) => http.delete(`/kubernetes-clusters/${id}`),
getPods: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/pods`),
getDeployments: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/deployments`),
getServices: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/services`),
getIngresses: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/ingresses`),
syncCluster: async (clusterId: number | string) => http.post(`/kubernetes-clusters/${clusterId}/sync`),
exportAllResources: async (clusterCode: string) =>
http.download(`/kubernetes/${clusterCode}/export`, `cluster-${clusterCode}-resources.tar.gz`),
getTopology: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/topology`),
saveTopology: async (clusterId: number | string, layoutData: string) =>
http.put(`/kubernetes-clusters/${clusterId}/topology`, { layout_data: layoutData }),
getMultiClusterComparison: async () => http.get('/kubernetes/compare'),
};
+94
View File
@@ -0,0 +1,94 @@
// Kubernetes API 辅助:流式 URL / WebSocket / 导出 // Logan.Li
import { buildApiUrl, getAuthToken, getWsBase, http } from '@/utils/request';
import { exportAsCSV, exportAsJSON } from '@/utils/export';
export { exportAsCSV, exportAsJSON };
export function buildPodLogsStreamUrl(
clusterCode: string,
namespace: string,
podName: string,
opts: {
container?: string;
tailLines?: number;
previous?: boolean;
sinceTime?: string;
} = {},
): string {
const params = new URLSearchParams();
params.set('stream', 'true');
if (opts.container) params.set('container', opts.container);
if (opts.tailLines && opts.tailLines > 0) params.set('tailLines', String(opts.tailLines));
if (opts.previous) params.set('previous', 'true');
if (opts.sinceTime) params.set('sinceTime', opts.sinceTime);
return buildApiUrl(
`/kubernetes/${clusterCode}/namespace/${namespace}/pods/${podName}/logs`,
params,
);
}
export function buildPodExecWsUrl(
clusterId: number | string,
namespace: string,
podName: string,
container?: string,
command?: string,
): string {
const params = new URLSearchParams();
if (container) params.set('container', container);
if (command) params.set('command', command);
const token = getAuthToken();
if (token) params.set('token', token);
const qs = params.toString();
const wsBase = getWsBase();
return `${wsBase}/ws/kubernetes-exec/${clusterId}/namespaces/${namespace}/pods/${podName}${qs ? `?${qs}` : ''}`;
}
export function buildPodFileDownloadUrl(
clusterCode: string,
namespace: string,
podName: string,
path: string,
container?: string,
): string {
const params = new URLSearchParams({ path });
if (container) params.set('container', container);
const token = getAuthToken();
if (token) params.set('token', token);
return buildApiUrl(
`/kubernetes/${clusterCode}/namespace/${namespace}/pods/${podName}/files/download`,
params,
);
}
export async function readPodFileText(
clusterCode: string,
namespace: string,
podName: string,
path: string,
container?: string,
): Promise<string> {
const url = buildPodFileDownloadUrl(clusterCode, namespace, podName, path, container);
const resp = await fetch(url);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
return resp.text();
}
export async function uploadPodFile(
clusterCode: string,
namespace: string,
podName: string,
targetPath: string,
file: File,
container?: string,
): Promise<unknown> {
const formData = new FormData();
formData.append('file', file);
formData.append('path', targetPath);
if (container) formData.append('container', container);
return http.upload(
`/kubernetes/${clusterCode}/namespace/${namespace}/pods/${podName}/files/upload`,
formData,
);
}
+20
View File
@@ -0,0 +1,20 @@
// Kubernetes API 聚合出口 // Logan.Li
import { clusterApi } from './cluster';
import { nodeApi } from './node';
import { podApi } from './pod';
import { workloadApi } from './workload';
import { namespaceApi } from './namespace';
import { resourceApi } from './resource';
import { exportAsCSV, exportAsJSON } from './helpers';
export const kubernetesApi = {
...clusterApi,
...nodeApi,
...podApi,
...workloadApi,
...namespaceApi,
...resourceApi,
exportAsCSV,
exportAsJSON,
};
+14
View File
@@ -0,0 +1,14 @@
// Kubernetes Namespace API // Logan.Li
import { http } from '@/utils/request';
export const namespaceApi = {
getNamespaces: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/namespaces`),
getNamespacesDetail: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/namespaces/detail`),
getNamespaceDetail: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/detail`),
createNamespace: async (clusterCode: string, name: string, labels?: Record<string, string>) =>
http.post(`/kubernetes/${clusterCode}/namespaces`, { name, labels: labels || {} }),
deleteNamespace: async (clusterCode: string, namespace: string) =>
http.delete(`/kubernetes/${clusterCode}/namespaces/${namespace}`),
};
+10
View File
@@ -0,0 +1,10 @@
// Kubernetes 节点 API // Logan.Li
import { http } from '@/utils/request';
export const nodeApi = {
getNodes: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/nodes`),
getClusterNodes: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/nodes`),
getNodeDetail: async (clusterCode: string, nodeName: string) =>
http.get(`/kubernetes/${clusterCode}/nodes/${encodeURIComponent(nodeName)}`),
};
+69
View File
@@ -0,0 +1,69 @@
// Kubernetes Pod API(日志 / Exec / 文件 / 指标) // Logan.Li
import { http } from '@/utils/request';
import {
buildPodExecWsUrl,
buildPodFileDownloadUrl,
buildPodLogsStreamUrl,
readPodFileText,
uploadPodFile,
} from './helpers';
export const podApi = {
getPodLogs: async (
clusterCode: string,
namespace: string,
podName: string,
tail = 200,
container?: string,
) => {
const params = new URLSearchParams({ tail: String(tail) });
if (container) params.set('container', container);
return http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/pods/${podName}/logs?${params}`);
},
getPodLogsEnhanced: async (
clusterCode: string,
namespace: string,
podName: string,
opts: {
container?: string;
tailLines?: number;
previous?: boolean;
sinceTime?: string;
} = {},
) => {
const params = new URLSearchParams();
if (opts.container) params.set('container', opts.container);
if (opts.tailLines && opts.tailLines > 0) params.set('tailLines', String(opts.tailLines));
if (opts.previous) params.set('previous', 'true');
if (opts.sinceTime) params.set('sinceTime', opts.sinceTime);
const qs = params.toString();
return http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/pods/${podName}/logs${qs ? `?${qs}` : ''}`);
},
buildPodLogsStreamUrl,
execPod: async (
clusterCode: string,
namespace: string,
podName: string,
command: string[],
container?: string,
) => http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/pods/${podName}/exec`, { command, container }),
buildPodExecWsUrl,
listPodFiles: async (
clusterCode: string,
namespace: string,
podName: string,
path: string,
container?: string,
) => http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/pods/${podName}/files/list`, { path, container }),
buildPodFileDownloadUrl,
readPodFileText,
uploadPodFile,
getPodMetrics: async (clusterCode: string, namespace?: string) => {
const params = namespace ? { namespace } : undefined;
return http.get(`/kubernetes/${clusterCode}/metrics/pods`, params);
},
getAllPods: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/pods`),
getNamespacePods: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/pods`),
};
+48
View File
@@ -0,0 +1,48 @@
// Kubernetes 命名空间资源 / YAML / 事件 / 容量 API // Logan.Li
import { http } from '@/utils/request';
export const resourceApi = {
getNamespaceServices: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/services`),
getNamespaceIngresses: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/ingresses`),
getNamespaceConfigMaps: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/configmaps`),
getNamespaceSecrets: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/secrets`),
getPVCs: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/pvcs`),
deletePVC: async (clusterCode: string, namespace: string, name: string) =>
http.delete(`/kubernetes/${clusterCode}/namespace/${namespace}/pvcs/${name}`),
getServiceAccounts: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/serviceaccounts`),
getRoles: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/roles`),
getRoleBindings: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/rolebindings`),
getResourceYaml: async (clusterCode: string, namespace: string, resource: string, name: string) =>
http.getRaw(`/kubernetes/${clusterCode}/namespace/${namespace}/${resource}/${name}/yaml`),
updateResourceYaml: async (clusterCode: string, namespace: string, resource: string, name: string, yaml: string) =>
http.putRaw(`/kubernetes/${clusterCode}/namespace/${namespace}/${resource}/${name}/yaml`, yaml, 'application/yaml'),
deleteResourceYaml: async (clusterCode: string, namespace: string, resource: string, name: string) =>
http.delete(`/kubernetes/${clusterCode}/namespace/${namespace}/${resource}/${name}/yaml`),
getEvents: async (clusterCode: string, namespace?: string, type?: string) => {
const params: Record<string, string> = {};
if (namespace) params.namespace = namespace;
if (type) params.type = type;
return http.get(`/kubernetes/${clusterCode}/events`, params);
},
getEventsSummary: async (clusterCode: string, namespace?: string, hours?: number) => {
const params: Record<string, string | number> = {};
if (namespace) params.namespace = namespace;
if (hours) params.hours = hours;
return http.get(`/kubernetes/${clusterCode}/events/summary`, params);
},
getCapacity: async (clusterCode: string, namespace?: string) => {
const params = namespace ? { namespace } : undefined;
return http.get(`/kubernetes/${clusterCode}/capacity`, params);
},
applyYAML: async (clusterCode: string, yaml: string) =>
http.post(`/kubernetes/${clusterCode}/yaml/apply`, { yaml }),
};
+91
View File
@@ -0,0 +1,91 @@
// Kubernetes 工作负载 API(Deployment / StatefulSet / HPA / CronJob) // Logan.Li
import { http } from '@/utils/request';
export const workloadApi = {
scaleDeployment: async (clusterCode: string, namespace: string, name: string, replicas: number) =>
http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/deployments/${name}/scale`, { replicas }),
restartDeployment: async (clusterCode: string, namespace: string, name: string) =>
http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/deployments/${name}/restart`),
pauseDeployment: async (clusterCode: string, namespace: string, name: string) =>
http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/deployments/${name}/pause`),
resumeDeployment: async (clusterCode: string, namespace: string, name: string) =>
http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/deployments/${name}/resume`),
updateDeploymentImage: async (
clusterCode: string,
namespace: string,
name: string,
image: string,
containerName?: string,
) => http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/deployments/${name}/update-image`, {
image,
container_name: containerName,
}),
getHPAs: async (clusterCode: string, namespace?: string) => {
if (namespace) return http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/hpas`);
return http.get(`/kubernetes/${clusterCode}/hpas`);
},
createHPA: async (
clusterCode: string,
data: {
name: string;
namespace: string;
targetKind: string;
targetName: string;
minReplicas: number;
maxReplicas: number;
cpuPercent: number;
memPercent: number;
},
) => http.post(`/kubernetes/${clusterCode}/namespace/${data.namespace}/hpas`, data),
deleteHPA: async (clusterCode: string, namespace: string, name: string) =>
http.delete(`/kubernetes/${clusterCode}/namespace/${namespace}/hpas/${name}`),
getCronJobs: async (clusterCode: string, namespace?: string) => {
if (namespace) return http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/cronjobs`);
return http.get(`/kubernetes-clusters/${clusterCode}/cronjobs`);
},
createCronJob: async (
clusterCode: string,
data: { name: string; namespace: string; schedule: string; image: string; command: string[] },
) => http.post(`/kubernetes/${clusterCode}/namespace/${data.namespace}/cronjobs`, data),
suspendCronJob: async (clusterCode: string, namespace: string, name: string, suspend: boolean) =>
http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/cronjobs/${name}/suspend`, { suspend }),
triggerCronJob: async (clusterCode: string, namespace: string, name: string) =>
http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/cronjobs/${name}/trigger`),
deleteCronJob: async (clusterCode: string, namespace: string, name: string) =>
http.delete(`/kubernetes/${clusterCode}/namespace/${namespace}/cronjobs/${name}`),
getNamespaceDeployments: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/deployments`),
getAllDeployments: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/deployments`),
getStatefulSets: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/statefulsets`),
getDaemonSets: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/daemonsets`),
getStatefulSetDetail: async (clusterCode: string, namespace: string, name: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/statefulsets/${name}`),
getDaemonSetDetail: async (clusterCode: string, namespace: string, name: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/daemonsets/${name}`),
scaleStatefulSet: async (clusterCode: string, namespace: string, name: string, replicas: number) =>
http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/statefulsets/${name}/scale`, { replicas }),
restartStatefulSet: async (clusterCode: string, namespace: string, name: string) =>
http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/statefulsets/${name}/restart`, {}),
restartDaemonSet: async (clusterCode: string, namespace: string, name: string) =>
http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/daemonsets/${name}/restart`, {}),
getReplicaSets: async (clusterCode: string, namespace: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/replicasets`),
getDeploymentRevisions: async (clusterCode: string, namespace: string, name: string) =>
http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/deployments/${name}/revisions`),
rollbackDeployment: async (clusterCode: string, namespace: string, name: string, revision: number) =>
http.post(`/kubernetes/${clusterCode}/namespace/${namespace}/deployments/${name}/rollback`, { revision }),
getDeployment: async (clusterCode: string, namespace: string, name: string) => {
try {
return await http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/deployments/${name}`);
} catch {
const res: Record<string, unknown> = await http.get(
`/kubernetes/${clusterCode}/namespace/${namespace}/deployments`,
);
const list = Array.isArray(res) ? res : (res?.list || res?.items || res?.data || []);
return (list as { name: string }[]).find((d) => d.name === name) || null;
}
},
};