refactor(frontend): align TJWater Next integrations

This commit is contained in:
2026-08-26 12:26:29 +08:00
parent 6623f4f7fb
commit fee4fc6ce1
51 changed files with 3074 additions and 22280 deletions
+96
View File
@@ -0,0 +1,96 @@
import { api } from "@/lib/api";
import {
getAnalysisResults,
getAnalysisScheme,
listAnalysisSchemes,
} from "./analysisRuns";
jest.mock("@/lib/api", () => ({
api: { get: jest.fn() },
}));
const get = api.get as jest.Mock;
describe("analysis runs API adapter", () => {
beforeEach(() => get.mockReset());
it("filters runs and exposes the new run identity to scheme screens", async () => {
get.mockResolvedValue({
data: {
success: true,
count: 2,
data: [
{
run_id: "run-1",
name: "burst-a",
run_type: "burst_analysis",
created_by: "alice",
created_at: "2026-08-25T02:00:00Z",
started_at: "2026-08-25T01:00:00Z",
status: "completed",
parameters: { burst_ID: ["P-1"] },
},
{
run_id: "run-2",
name: "flush-a",
run_type: "flushing_analysis",
created_by: "bob",
created_at: "2026-08-24T02:00:00Z",
started_at: "2026-08-24T01:00:00Z",
status: "completed",
parameters: {},
},
],
},
});
const result = await listAnalysisSchemes({
runType: "burst_analysis",
queryDate: "2026-08-25",
});
expect(get).toHaveBeenCalledWith("/api/v1/analysis/runs");
expect(result).toEqual([
expect.objectContaining({
id: "run-1",
scheme_id: "run-1",
scheme_name: "burst-a",
schemeDetail: { burst_ID: ["P-1"] },
}),
]);
});
it("loads a run and its structured results by run id", async () => {
get
.mockResolvedValueOnce({
data: {
run_id: "run-1",
name: "burst-a",
run_type: "burst_analysis",
created_by: "alice",
created_at: "2026-08-25T02:00:00Z",
started_at: "2026-08-25T01:00:00Z",
status: "completed",
parameters: {},
},
})
.mockResolvedValueOnce({
data: [
{
result_id: "result-1",
run_id: "run-1",
result_type: "summary",
payload: { ok: true },
created_at: "2026-08-25T03:00:00Z",
},
],
});
expect((await getAnalysisScheme("run-1")).scheme_id).toBe("run-1");
expect(await getAnalysisResults("run-1", "summary")).toHaveLength(1);
expect(get).toHaveBeenLastCalledWith(
"/api/v1/analysis/runs/run-1/results",
{ params: { result_type: "summary" } },
);
});
});
+105
View File
@@ -0,0 +1,105 @@
import { api } from "@/lib/api";
export type AnalysisRun = {
run_id: string;
name: string;
run_type: string;
created_by: string;
created_at: string;
started_at: string;
status: string;
parameters: Record<string, unknown>;
};
export type AnalysisResult = {
result_id: string;
run_id: string;
result_type: string;
node_id?: string | null;
link_id?: string | null;
payload: Record<string, unknown>;
created_at: string;
};
type AnalysisRunListResponse = {
success: boolean;
data: AnalysisRun[];
count: number;
};
export type AnalysisSchemeRecord = AnalysisRun & {
id: string;
scheme_id: string;
scheme_name: string;
scheme_type: string;
username: string;
create_time: string;
scheme_start_time: string;
scheme_detail: Record<string, unknown>;
schemeName: string;
type: string;
startTime: string;
schemeDetail: Record<string, unknown>;
};
const normalizeParameters = (value: unknown): Record<string, unknown> =>
value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: {};
export const toAnalysisSchemeRecord = (run: AnalysisRun): AnalysisSchemeRecord => {
const parameters = normalizeParameters(run.parameters);
return {
...run,
parameters,
id: run.run_id,
scheme_id: run.run_id,
scheme_name: run.name,
scheme_type: run.run_type,
username: run.created_by,
create_time: run.created_at,
scheme_start_time: run.started_at,
scheme_detail: parameters,
schemeName: run.name,
type: run.run_type,
startTime: run.started_at,
schemeDetail: parameters,
};
};
export const listAnalysisSchemes = async ({
runType,
queryDate,
}: {
runType?: string;
queryDate?: string;
} = {}): Promise<AnalysisSchemeRecord[]> => {
const response = await api.get<AnalysisRunListResponse>(
"/api/v1/analysis/runs",
);
const runs = Array.isArray(response.data.data) ? response.data.data : [];
return runs
.filter((run) => !runType || run.run_type === runType)
.filter((run) => !queryDate || run.created_at.slice(0, 10) === queryDate)
.map(toAnalysisSchemeRecord);
};
export const getAnalysisScheme = async (
runId: string,
): Promise<AnalysisSchemeRecord> => {
const response = await api.get<AnalysisRun>(
`/api/v1/analysis/runs/${encodeURIComponent(runId)}`,
);
return toAnalysisSchemeRecord(response.data);
};
export const getAnalysisResults = async (
runId: string,
resultType?: string,
): Promise<AnalysisResult[]> => {
const response = await api.get<AnalysisResult[]>(
`/api/v1/analysis/runs/${encodeURIComponent(runId)}/results`,
{ params: resultType ? { result_type: resultType } : undefined },
);
return Array.isArray(response.data) ? response.data : [];
};
+1 -2
View File
@@ -29,8 +29,7 @@ const FIELD_LABELS: Record<string, string> = {
scada_burst_start: "爆管开始时间",
scada_burst_end: "爆管结束时间",
use_scada_flow: "使用流量监测数据",
simulation_scheme_name: "模拟方案名称",
simulation_scheme_type: "模拟方案类型",
simulation_run_id: "模拟运行 ID",
source: "污染源节点",
concentration: "污染物浓度",
pattern: "污染物注入模式",