feat: PTY kubectl终端 + 侧边栏对齐修复 + 构建缓存清理
**kubectl WebShell 修复:** - 引入 github.com/creack/pty 库实现真正的伪终端 - 替换 bash --noediting + TERM=dumb 方案为 PTY-backed bash - 支持 xterm-256color、窗口自适应、readline 交互 - 修复键盘输入无响应问题 **侧边栏优化:** - 独立菜单项高度从 py-1.5 改为 h-8,与父菜单对齐 - 独立菜单图标从 h-3 w-3 改为 h-3.5 w-3.5,统一 14px **构建优化:** - run.sh docker up 增加 docker image prune -f 清理悬空镜像 - 每次部署自动清理 builder cache + dangling images **认证修复(历史):** - Token 存储:Zustand + localStorage 双写,http.ts 双源 fallback - YamlViewer/DeploymentDetail token 来源统一为 Zustand store
This commit is contained in:
1 parent
cac1414917
commit
a3cd0d3910
29 files changed
+2954
-180
No files matched your search
@@ -219,7 +219,7 @@ export const kubernetesApi = {
|
||||
// === HPA 管理 (Logan.Li) ===
|
||||
getHPAs: async (clusterCode: string, namespace?: string) => {
|
||||
if (namespace) return http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/hpas`);
|
||||
return http.get(`/kubernetes-clusters/${clusterCode}/hpas`); // fallback old route
|
||||
return http.get(`/kubernetes/${clusterCode}/hpas`); // AllNS route
|
||||
},
|
||||
createHPA: async (clusterCode: string, data: { name: string; namespace: string; targetKind: string; targetName: string; minReplicas: number; maxReplicas: number; cpuPercent: number; memPercent: number }) => {
|
||||
return http.post(`/kubernetes/${clusterCode}/namespace/${data.namespace}/hpas`, data);
|
||||
@@ -270,6 +270,76 @@ export const kubernetesApi = {
|
||||
getNamespaces: async (clusterCode: string) => {
|
||||
return http.get(`/kubernetes/${clusterCode}/namespaces`);
|
||||
},
|
||||
|
||||
// === All-namespace listing (Logan.Li) ===
|
||||
getAllDeployments: async (clusterCode: string) => {
|
||||
return http.get(`/kubernetes/${clusterCode}/deployments`);
|
||||
},
|
||||
getAllPods: async (clusterCode: string) => {
|
||||
return http.get(`/kubernetes/${clusterCode}/pods`);
|
||||
},
|
||||
|
||||
// === PVC (存储) ===
|
||||
getPVCs: async (clusterCode: string, namespace: string) => {
|
||||
return http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/pvcs`);
|
||||
},
|
||||
deletePVC: async (clusterCode: string, namespace: string, name: string) => {
|
||||
return http.delete(`/kubernetes/${clusterCode}/namespace/${namespace}/pvcs/${name}`);
|
||||
},
|
||||
|
||||
// === StatefulSet / DaemonSet ===
|
||||
getStatefulSets: async (clusterCode: string, namespace: string) => {
|
||||
return http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/statefulsets`);
|
||||
},
|
||||
getDaemonSets: async (clusterCode: string, namespace: string) => {
|
||||
return http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/daemonsets`);
|
||||
},
|
||||
|
||||
// === YAML ===
|
||||
getResourceYaml: async (clusterCode: string, namespace: string, resource: string, name: string) => {
|
||||
return http.getRaw(`/kubernetes/${clusterCode}/namespace/${namespace}/${resource}/${name}/yaml`);
|
||||
},
|
||||
updateResourceYaml: async (clusterCode: string, namespace: string, resource: string, name: string, yaml: string) => {
|
||||
return http.putRaw(`/kubernetes/${clusterCode}/namespace/${namespace}/${resource}/${name}/yaml`, yaml, 'application/yaml');
|
||||
},
|
||||
|
||||
// === Export CSV ===
|
||||
exportAsCSV: (filename: string, data: any[]) => {
|
||||
if (data.length === 0) return;
|
||||
const headers = Object.keys(data[0]);
|
||||
const csv = [headers.join(','), ...data.map((row: any) => headers.map(h => JSON.stringify(row[h] ?? '')).join(','))].join('\n');
|
||||
const blob = new Blob(['\ufeff' + csv], { type: 'text/csv;charset=utf-8;' });
|
||||
const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = filename; a.click();
|
||||
},
|
||||
exportAsJSON: (filename: string, data: any[]) => {
|
||||
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
|
||||
const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = filename; a.click();
|
||||
},
|
||||
|
||||
// === 🆕 Pod Metrics (kubectl top pods) ===
|
||||
getPodMetrics: async (clusterCode: string, namespace?: string) => {
|
||||
const params = namespace ? { namespace } : undefined;
|
||||
return http.get(`/kubernetes/${clusterCode}/metrics/pods`, params);
|
||||
},
|
||||
|
||||
// === 🆕 Events ===
|
||||
getEvents: async (clusterCode: string, namespace?: string, type?: string) => {
|
||||
const params: any = {};
|
||||
if (namespace) params.namespace = namespace;
|
||||
if (type) params.type = type;
|
||||
return http.get(`/kubernetes/${clusterCode}/events`, params);
|
||||
},
|
||||
|
||||
// === 🆕 Capacity Analysis ===
|
||||
getCapacity: async (clusterCode: string, namespace?: string) => {
|
||||
const params = namespace ? { namespace } : undefined;
|
||||
return http.get(`/kubernetes/${clusterCode}/capacity`, params);
|
||||
},
|
||||
|
||||
// === 🆕 YAML Apply ===
|
||||
applyYAML: async (clusterCode: string, yaml: string) => {
|
||||
return http.post(`/kubernetes/${clusterCode}/yaml/apply`, { yaml });
|
||||
},
|
||||
};
|
||||
|
||||
// ==================== 告警 API ====================
|
||||
|
||||
Reference in new issue
Block a user