refactor(frontend): P1-P2 续 — API 子模块化、大组件拆分、Query 铺开

- api/server/ 与 api/cloud/ 子目录拆分,保持 @/api 导入不变
- hooks/api 新增 useCredentials、usePromDatasources,增强 useServers
- 拆分 CredentialManager、DeploymentWorkload、PrometheusDatasourceManager
- ServerManager、CredentialManager、PromDs 接入 TanStack Query
This commit is contained in:
Logan.Li committed 2026-06-26 00:22:50 +08:00
1 parent f45e203e21
commit 480e677042
32 files changed
+2280 -1940

No files matched your search

+3 -1
View File
@@ -4,7 +4,9 @@ export { queryKeys } from './queryKeys';
export { unwrapList, unwrapTotal } from './unwrap';
export { useTerminalSessions, useTerminalSessionMutations, type TerminalSession } from './useTerminalSessions';
export { useHostList, useHostHistory, useHealthProbes, usePortPolicy } from './useHostMonitor';
export { useServers, useServerMutations } from './useServers';
export { useServers, useServerMutations, type ServerRecord } from './useServers';
export { useCredentials, useCredentialDetail, useCredentialMutations, type CredentialRecord } from './useCredentials';
export { usePromDatasources, usePromDatasourceMutations, type PromDatasource } from './usePromDatasources';
export { usePipelines, usePipelineRuns, usePipelineMutations } from './usePipelines';
export { useAlertRules, useAlerts, useAlertMutations } from './useAlerts';
export { useAuditLogs } from './useAuditLogs';
+3
View File
@@ -16,4 +16,7 @@ export const queryKeys = {
auditLogs: (params?: Record<string, unknown>) => ['audit-logs', params] as const,
sessionCommands: (params?: Record<string, unknown>) => ['session-commands', params] as const,
k8sClusters: () => ['k8s-clusters'] as const,
credentials: (params?: Record<string, unknown>) => ['credentials', params] as const,
credentialDetail: (id: number | null) => ['credential-detail', id] as const,
promDatasources: () => ['prom-datasources'] as const,
};
+77
View File
@@ -0,0 +1,77 @@
// 凭据管理 — TanStack Query // Logan.Li
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { credentialApi } from '@/api';
import { queryKeys } from './queryKeys';
import { unwrapList } from './unwrap';
export type CredentialRecord = {
id: number;
name: string;
variable_name: string;
secret_type: string;
summary: string;
tags: string[];
description: string;
expires_at: string | null;
is_active: boolean;
env_prefix: string;
created_at: string;
updated_at: string;
};
type ListParams = {
page?: number;
page_size?: number;
secret_type?: string;
search?: string;
};
export function useCredentials(params: ListParams = { page_size: 100 }) {
return useQuery({
queryKey: queryKeys.credentials(params),
queryFn: async () => {
const resp = await credentialApi.list(params);
return unwrapList<CredentialRecord>(resp);
},
staleTime: 30_000,
});
}
export function useCredentialDetail(id: number | null, enabled = true) {
return useQuery({
queryKey: queryKeys.credentialDetail(id),
queryFn: () => credentialApi.get(id!),
enabled: !!id && enabled,
staleTime: 10_000,
});
}
export function useCredentialMutations() {
const qc = useQueryClient();
const invalidate = () => qc.invalidateQueries({ queryKey: ['credentials'] });
const createMutation = useMutation({
mutationFn: (data: Record<string, unknown>) => credentialApi.create(data),
onSuccess: invalidate,
});
const updateMutation = useMutation({
mutationFn: ({ id, data }: { id: number | string; data: Record<string, unknown> }) =>
credentialApi.update(id, data),
onSuccess: invalidate,
});
const deleteMutation = useMutation({
mutationFn: (id: number | string) => credentialApi.delete(id),
onSuccess: invalidate,
});
const toggleActiveMutation = useMutation({
mutationFn: ({ id, isActive }: { id: number | string; isActive: boolean }) =>
credentialApi.toggleActive(id, isActive),
onSuccess: invalidate,
});
return { createMutation, updateMutation, deleteMutation, toggleActiveMutation, invalidate };
}
@@ -0,0 +1,72 @@
// Prometheus 数据源 — TanStack Query // Logan.Li
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { promDatasourceApi } from '@/api';
import { queryKeys } from './queryKeys';
import { unwrapList } from './unwrap';
export type PromDatasource = {
id: number;
name: string;
url: string;
access: string;
basic_auth: boolean;
basic_auth_user: string;
basic_auth_pass: string;
with_credentials: boolean;
tls_client_auth: boolean;
with_ca_cert: boolean;
ca_cert: string;
skip_tls_verify: boolean;
custom_headers: string;
enable_alerting: boolean;
alertmanager_ds: string;
scrape_interval: number;
query_timeout: number;
http_method: string;
disable_metrics_lookup: boolean;
custom_query_params: string;
is_default: boolean;
status: number;
created_at: string;
updated_at: string;
};
export function usePromDatasources() {
return useQuery({
queryKey: queryKeys.promDatasources(),
queryFn: async () => {
const resp = await promDatasourceApi.list();
return unwrapList<PromDatasource>(resp);
},
staleTime: 30_000,
});
}
export function usePromDatasourceMutations() {
const qc = useQueryClient();
const invalidate = () => qc.invalidateQueries({ queryKey: ['prom-datasources'] });
const createMutation = useMutation({
mutationFn: (data: Record<string, unknown>) => promDatasourceApi.create(data),
onSuccess: invalidate,
});
const updateMutation = useMutation({
mutationFn: ({ id, data }: { id: number | string; data: Record<string, unknown> }) =>
promDatasourceApi.update(id, data),
onSuccess: invalidate,
});
const deleteMutation = useMutation({
mutationFn: (id: number | string) => promDatasourceApi.delete(id),
onSuccess: invalidate,
});
const setDefaultMutation = useMutation({
mutationFn: (id: number | string) => promDatasourceApi.setDefault(id),
onSuccess: invalidate,
});
return { createMutation, updateMutation, deleteMutation, setDefaultMutation, invalidate };
}
+31 -4
View File
@@ -3,7 +3,15 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { serverApi } from '@/api';
import { queryKeys } from './queryKeys';
import { unwrapList } from './unwrap';
import { unwrapList, unwrapTotal } from './unwrap';
export type ServerRecord = Record<string, unknown> & {
id: number | string;
hostname?: string;
ip?: string;
status?: string;
has_auth?: boolean;
};
type ListParams = {
page?: number;
@@ -12,12 +20,20 @@ type ListParams = {
status?: string;
};
type ServerListResult = {
list: ServerRecord[];
total: number;
};
export function useServers(params: ListParams = { page: 1, page_size: 100 }) {
return useQuery({
queryKey: queryKeys.servers(params),
queryFn: async () => {
queryFn: async (): Promise<ServerListResult> => {
const resp = await serverApi.getServers(params);
return unwrapList<Record<string, unknown>>(resp);
return {
list: unwrapList<ServerRecord>(resp),
total: unwrapTotal(resp),
};
},
staleTime: 30_000,
});
@@ -27,6 +43,17 @@ export function useServerMutations() {
const qc = useQueryClient();
const invalidate = () => qc.invalidateQueries({ queryKey: ['servers'] });
const createMutation = useMutation({
mutationFn: (data: Record<string, unknown>) => serverApi.createServer(data),
onSuccess: invalidate,
});
const updateMutation = useMutation({
mutationFn: ({ id, data }: { id: number | string; data: Record<string, unknown> }) =>
serverApi.updateServer(id, data),
onSuccess: invalidate,
});
const deleteMutation = useMutation({
mutationFn: (id: number | string) => serverApi.deleteServer(id),
onSuccess: invalidate,
@@ -37,5 +64,5 @@ export function useServerMutations() {
onSuccess: invalidate,
});
return { deleteMutation, batchDeleteMutation, invalidate };
return { createMutation, updateMutation, deleteMutation, batchDeleteMutation, invalidate };
}