diff --git a/src/components/olmap/BurstLocation/AnalysisParameters.tsx b/src/components/olmap/BurstLocation/AnalysisParameters.tsx index bc2befd..ac5f105 100644 --- a/src/components/olmap/BurstLocation/AnalysisParameters.tsx +++ b/src/components/olmap/BurstLocation/AnalysisParameters.tsx @@ -28,6 +28,7 @@ import { NETWORK_NAME, config } from "@config/config"; import { useControllableObjectState } from "@components/olmap/core/useControllableState"; import { FLOW_DISPLAY_UNIT, toM3s } from "@utils/units"; import { BurstLocationResult } from "./types"; +import { getBurstLocationErrorNotice } from "./burstLocationError"; interface Props { onResult: (result: BurstLocationResult) => void; @@ -262,11 +263,12 @@ const AnalysisParameters: React.FC = ({ description: `定位到管段: ${(response.data as BurstLocationResult).located_pipe}`, }); } catch (error: any) { + const notice = getBurstLocationErrorNotice(error); open?.({ key: "burst-location-analysis-error", type: "error", - message: "提交分析失败", - description: error?.response?.data?.detail ?? error?.message ?? "请求失败", + message: notice.message, + description: notice.description, }); } finally { setRunning(false); @@ -303,22 +305,30 @@ const AnalysisParameters: React.FC = ({ - - 数据选择规则 + + {isSimulationMode ? "模拟方案分析前置条件" : "数据选择规则"} - + {isSimulationMode - ? "当前为模拟方案:爆管数据取所选方案模拟结果,正常数据取实时模拟结果,两者使用同一爆管时间窗。" + ? "爆管数据取所选方案,正常数据取同一时间窗的实时模拟结果。所选时间窗必须已有实时模拟正常基线,否则无法分析;系统不会自动补数据。" : "当前为监测数据:爆管数据取所选监测时间窗,正常数据默认取前一天同一时段的监测数据。"} diff --git a/src/components/olmap/BurstLocation/burstLocationError.test.ts b/src/components/olmap/BurstLocation/burstLocationError.test.ts new file mode 100644 index 0000000..ae7b620 --- /dev/null +++ b/src/components/olmap/BurstLocation/burstLocationError.test.ts @@ -0,0 +1,45 @@ +import { getBurstLocationErrorNotice } from "./burstLocationError"; + +describe("getBurstLocationErrorNotice", () => { + it("explains a missing realtime normal-pressure baseline", () => { + const notice = getBurstLocationErrorNotice({ + response: { + data: { + detail: "正常压力数据 在时间窗内无有效模拟数据: 10186", + }, + }, + }); + + expect(notice.message).toBe("缺少正常模拟基线"); + expect(notice.description).toContain("实时模拟正常压力数据"); + expect(notice.description).toContain("10186"); + expect(notice.description).toContain("系统不会自动补数据"); + }); + + it("distinguishes incomplete burst-scheme data", () => { + const notice = getBurstLocationErrorNotice({ + response: { + data: { + detail: "爆管压力数据 在时间窗内无有效模拟数据: 10186", + }, + }, + }); + + expect(notice).toEqual({ + message: "所选方案数据不完整", + description: + "所选方案时间窗内没有可用的爆管压力数据,缺失点位:10186。请选择数据完整的模拟方案。", + }); + }); + + it("preserves unrelated backend details", () => { + expect( + getBurstLocationErrorNotice({ + response: { data: { detail: "分析参数不合法" } }, + }), + ).toEqual({ + message: "提交分析失败", + description: "分析参数不合法", + }); + }); +}); diff --git a/src/components/olmap/BurstLocation/burstLocationError.ts b/src/components/olmap/BurstLocation/burstLocationError.ts new file mode 100644 index 0000000..cb8be8e --- /dev/null +++ b/src/components/olmap/BurstLocation/burstLocationError.ts @@ -0,0 +1,50 @@ +export interface BurstLocationErrorNotice { + message: string; + description: string; +} + +const DATA_GAP_PATTERN = + /^(爆管压力数据|正常压力数据|爆管流量数据|正常流量数据) 在时间窗内无有效模拟数据: (.+)$/; + +const extractErrorDetail = (error: unknown): string => { + const candidate = error as { + message?: string; + response?: { data?: { detail?: unknown } }; + }; + const detail = candidate?.response?.data?.detail; + + if (typeof detail === "string" && detail.trim()) { + return detail.trim(); + } + if (typeof candidate?.message === "string" && candidate.message.trim()) { + return candidate.message.trim(); + } + return "请求失败"; +}; + +export const getBurstLocationErrorNotice = ( + error: unknown, +): BurstLocationErrorNotice => { + const detail = extractErrorDetail(error); + const match = detail.match(DATA_GAP_PATTERN); + + if (!match) { + return { + message: "提交分析失败", + description: detail, + }; + } + + const [, dataLabel, missingIds] = match; + if (dataLabel.startsWith("正常")) { + return { + message: "缺少正常模拟基线", + description: `所选方案时间窗内没有可用的实时模拟${dataLabel},缺失点位:${missingIds}。请选择已有正常基线覆盖的方案或时间窗,系统不会自动补数据。`, + }; + } + + return { + message: "所选方案数据不完整", + description: `所选方案时间窗内没有可用的${dataLabel},缺失点位:${missingIds}。请选择数据完整的模拟方案。`, + }; +};