Files

200 lines
5.6 KiB
TypeScript
Raw Permalink Normal View History

2026-09-14 20:31:06 +08:00
import { apiFetch, apiFetchBlob, downloadBlob } from "@/lib/api";
/**
* NL2SQL 查询(/nl2sql/*)与管理(/nl2sql/admin/*)适配层。
* 按本次约定:页面以只读展示为主,运维类接口(jobs / refresh / kill / cache-invalidate)
* 提供触发按钮,权限类接口只做列表展示,不建增删改表单。
*/
export interface Nl2SqlQueryResult {
query_id?: string;
question?: string;
generated_sql?: string | null;
columns?: string[];
rows?: Record<string, unknown>[];
row_count?: number;
truncated?: boolean;
summary?: string;
answer?: string;
elapsed_ms?: number | null;
trace_id?: string;
[key: string]: unknown;
}
export interface QueryHistoryItem {
query_id: string;
user_id?: number;
session_id?: string | null;
caller_agent?: string | null;
question?: string;
generated_sql?: string | null;
access_tables?: string[];
status?: string;
error_code?: string | null;
error_message?: string | null;
row_count?: number;
truncated?: boolean;
elapsed_ms?: number | null;
trace_id?: string | null;
create_time?: string | null;
}
export interface Nl2SqlHealth {
[component: string]: unknown;
}
export interface QueryRole {
id?: number;
employee_role?: string;
max_rows?: number;
active?: boolean;
[key: string]: unknown;
}
export interface TablePermission {
id?: number;
table_name?: string;
active?: boolean;
[key: string]: unknown;
}
export interface ColumnPermission {
id?: number;
table_name?: string;
column_name?: string;
active?: boolean;
[key: string]: unknown;
}
export interface SensitiveField {
id?: number;
table_name?: string;
column_name?: string;
mask_type?: string;
active?: boolean;
[key: string]: unknown;
}
export interface MaintenanceJobResult {
name?: string;
status?: string;
attempts?: number;
detail?: unknown;
error_type?: string | null;
}
export type MaintenanceTask =
| "metadata_sync"
| "vector_cleanup"
| "consistency_check"
| "history_cleanup";
function qs(params: Record<string, string | number | undefined | null>) {
const search = new URLSearchParams();
for (const [key, value] of Object.entries(params)) {
if (value !== undefined && value !== null && value !== "") search.set(key, String(value));
}
const text = search.toString();
return text ? `?${text}` : "";
}
export const nl2sqlApi = {
/* ---------------------------------------------------------- 查询域(11) */
query: (body: {
question: string;
session_id?: string;
caller_agent?: string;
max_rows?: number;
include_sql?: boolean;
page?: number;
page_size?: number;
sort_by?: string;
sort_order?: "asc" | "desc";
}) => apiFetch<Nl2SqlQueryResult>("/nl2sql/query", { method: "POST", body: JSON.stringify(body) }),
health: () => apiFetch<Nl2SqlHealth>("/nl2sql/health"),
explain: (sql: string) =>
apiFetch<Record<string, unknown>[]>("/nl2sql/query/explain", {
method: "POST",
body: JSON.stringify({ sql }),
}),
history: (params: {
page?: number;
page_size?: number;
status?: string;
start_time?: string;
end_time?: string;
} = {}) =>
apiFetch<{ page?: number; page_size?: number; items?: QueryHistoryItem[] }>(
`/nl2sql/query-history${qs(params)}`
),
historyDetail: (queryId: string) =>
apiFetch<QueryHistoryItem>(`/nl2sql/query-history/${encodeURIComponent(queryId)}`),
exportHistory: async (queryId: string) => {
const blob = await apiFetchBlob(`/nl2sql/query-history/${encodeURIComponent(queryId)}/export`);
downloadBlob(blob, `nl2sql-${queryId}.csv`);
},
running: () => apiFetch<Record<string, unknown>[]>("/nl2sql/query/running"),
kill: (queryId: string) =>
apiFetch<{ query_id?: string; verified?: boolean }>("/nl2sql/query/kill", {
method: "POST",
body: JSON.stringify({ query_id: queryId }),
}),
diagnostics: () =>
apiFetch<{
health?: Nl2SqlHealth;
running?: Record<string, unknown>[];
metrics?: Record<string, unknown>;
recent?: unknown[];
}>("/nl2sql/query/diagnostics"),
invalidateCache: (tableNames: string[]) =>
apiFetch<Record<string, unknown>>("/nl2sql/cache/invalidate", {
method: "POST",
body: JSON.stringify({ table_names: tableNames }),
}),
/* ------------------------------------------------------ 管理域(20) */
roles: () => apiFetch<QueryRole[]>("/nl2sql/admin/roles"),
roleTables: (roleId: number) =>
apiFetch<TablePermission[]>(`/nl2sql/admin/roles/${roleId}/tables`),
roleColumns: (roleId: number) =>
apiFetch<ColumnPermission[]>(`/nl2sql/admin/roles/${roleId}/columns`),
sensitiveFields: () => apiFetch<SensitiveField[]>("/nl2sql/admin/sensitive-fields"),
metrics: () => apiFetch<Record<string, unknown>>("/nl2sql/admin/metrics"),
metricsPrometheus: () =>
apiFetch<unknown>("/nl2sql/admin/metrics/prometheus"),
runtimeConfig: () => apiFetch<Record<string, unknown>>("/nl2sql/admin/runtime-config"),
runJob: (task: MaintenanceTask, beforeDays = 180) =>
apiFetch<MaintenanceJobResult>("/nl2sql/admin/jobs", {
method: "POST",
body: JSON.stringify({ task, before_days: beforeDays }),
}),
jobHistory: (params: { page?: number; page_size?: number; status?: string } = {}) =>
apiFetch<{ items?: Record<string, unknown>[]; page?: number; page_size?: number }>(
`/nl2sql/admin/jobs/history${qs(params)}`
),
semantics: () => apiFetch<Record<string, unknown>>("/nl2sql/admin/semantics"),
refreshSemantics: () =>
apiFetch<Record<string, unknown>>("/nl2sql/admin/semantics/refresh", { method: "POST" }),
};