refactor(frontend): API 子模块化、大组件拆分与 TanStack Query hooks
P1: kubernetes/system API 拆为子目录模块,导出工具下沉到 lib/export-utils,
http 统一 buildApiUrl/getWsBase;HostMonitor、DeploymentEdit* 拆至子组件。
P2: 新增 hooks/api(queryKeys、useTerminalSessions、useHostMonitor),
TerminalSessionsTab 与 HostMonitor 接入 TanStack Query。
P3: 保留 services/api 路径,未迁移至 api/ 目录。
This commit is contained in:
1 parent
7fb2236b4d
commit
0b404b4611
226 files changed
+3040
-2596
No files matched your search
@@ -0,0 +1,11 @@
|
||||
// TanStack Query key 工厂 — 统一缓存键 // Logan.Li
|
||||
|
||||
export const queryKeys = {
|
||||
terminalSessions: (params?: Record<string, unknown>) => ['terminal-sessions', params] as const,
|
||||
hostMonitor: {
|
||||
hosts: () => ['host-monitor', 'hosts'] as const,
|
||||
history: (hostname: string, hours: number) => ['host-monitor', 'history', hostname, hours] as const,
|
||||
probes: (hostname: string) => ['host-monitor', 'probes', hostname] as const,
|
||||
portPolicy: (hostname: string) => ['host-monitor', 'port-policy', hostname] as const,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
// 主机监控数据 — TanStack Query // Logan.Li
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { agentApi } from '@/services/api';
|
||||
import { queryKeys } from './queryKeys';
|
||||
|
||||
function unwrapList<T>(data: unknown): T[] {
|
||||
if (Array.isArray(data)) return data;
|
||||
if (data && typeof data === 'object') {
|
||||
const obj = data as Record<string, unknown>;
|
||||
if (Array.isArray(obj.list)) return obj.list as T[];
|
||||
if (Array.isArray(obj.data)) return obj.data as T[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function useHostList() {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.hostMonitor.hosts(),
|
||||
queryFn: async () => {
|
||||
const data = await agentApi.getLatest();
|
||||
return unwrapList<Record<string, unknown>>(data);
|
||||
},
|
||||
staleTime: 30_000,
|
||||
});
|
||||
}
|
||||
|
||||
export function useHostHistory(hostname: string, hours: number) {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.hostMonitor.history(hostname, hours),
|
||||
queryFn: async () => {
|
||||
if (!hostname) return [];
|
||||
const data = await agentApi.getHistory(hostname, hours);
|
||||
return unwrapList<Record<string, unknown>>(data);
|
||||
},
|
||||
enabled: !!hostname,
|
||||
staleTime: 30_000,
|
||||
});
|
||||
}
|
||||
|
||||
export function useHealthProbes(hostname: string) {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.hostMonitor.probes(hostname),
|
||||
queryFn: async () => {
|
||||
if (!hostname) return [];
|
||||
const data = await agentApi.getHealthProbes({ hostname });
|
||||
return unwrapList<Record<string, unknown>>(data);
|
||||
},
|
||||
enabled: !!hostname,
|
||||
});
|
||||
}
|
||||
|
||||
export function usePortPolicy(hostname: string) {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.hostMonitor.portPolicy(hostname),
|
||||
queryFn: async () => {
|
||||
if (!hostname) return { port_filter_mode: 'whitelist', port_whitelist: [] as number[] };
|
||||
const data = await agentApi.getPortPolicy(hostname) as { data?: { port_filter_mode?: string; port_whitelist?: number[] } };
|
||||
return {
|
||||
port_filter_mode: data?.data?.port_filter_mode || 'blacklist',
|
||||
port_whitelist: data?.data?.port_whitelist || [],
|
||||
};
|
||||
},
|
||||
enabled: !!hostname,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// 终端会话列表 — TanStack Query // Logan.Li
|
||||
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { terminalSessionApi } from '@/services/api';
|
||||
import { queryKeys } from './queryKeys';
|
||||
|
||||
export interface TerminalSession {
|
||||
id: number;
|
||||
user_id?: number;
|
||||
username: string;
|
||||
server_id: number;
|
||||
server_name: string;
|
||||
server_ip: string;
|
||||
server_port: number;
|
||||
client_ip: string;
|
||||
status: string;
|
||||
duration: number;
|
||||
record_size: number;
|
||||
start_time: string;
|
||||
end_time?: string | null;
|
||||
}
|
||||
|
||||
type ListParams = {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
server_id?: number;
|
||||
username?: string;
|
||||
status?: string;
|
||||
};
|
||||
|
||||
function unwrapList<T>(data: unknown): T[] {
|
||||
if (Array.isArray(data)) return data;
|
||||
if (data && typeof data === 'object' && 'list' in data) {
|
||||
return (data as { list: T[] }).list ?? [];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function useTerminalSessions(params: ListParams = { page: 1, page_size: 100 }) {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.terminalSessions(params),
|
||||
queryFn: async () => {
|
||||
const resp = await terminalSessionApi.list(params);
|
||||
return unwrapList<TerminalSession>(resp);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useTerminalSessionMutations() {
|
||||
const qc = useQueryClient();
|
||||
|
||||
const invalidate = () => qc.invalidateQueries({ queryKey: ['terminal-sessions'] });
|
||||
|
||||
const killMutation = useMutation({
|
||||
mutationFn: (id: number) => terminalSessionApi.kill(id),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: (id: number) => terminalSessionApi.delete(id),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
|
||||
const batchDeleteMutation = useMutation({
|
||||
mutationFn: (ids: number[]) => terminalSessionApi.batchDelete(ids),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
|
||||
return { killMutation, deleteMutation, batchDeleteMutation, invalidate };
|
||||
}
|
||||
Reference in new issue
Block a user