fix(burst-location): clarify simulation baseline requirement
This commit is contained in:
@@ -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<Props> = ({
|
||||
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<Props> = ({
|
||||
</Select>
|
||||
</FormControl>
|
||||
<Alert
|
||||
severity="info"
|
||||
severity={isSimulationMode ? "warning" : "info"}
|
||||
variant="outlined"
|
||||
sx={{
|
||||
mt: 1,
|
||||
alignItems: "flex-start",
|
||||
borderColor: "info.light",
|
||||
backgroundColor: "#eff6ff",
|
||||
borderColor: isSimulationMode ? "warning.light" : "info.light",
|
||||
backgroundColor: isSimulationMode ? "#fff8e1" : "#eff6ff",
|
||||
"& .MuiAlert-message": { width: "100%" },
|
||||
}}
|
||||
>
|
||||
<Typography variant="caption" className="block font-semibold text-blue-900">
|
||||
数据选择规则
|
||||
<Typography
|
||||
variant="caption"
|
||||
className="block font-semibold"
|
||||
sx={{ color: isSimulationMode ? "warning.dark" : "info.dark" }}
|
||||
>
|
||||
{isSimulationMode ? "模拟方案分析前置条件" : "数据选择规则"}
|
||||
</Typography>
|
||||
<Typography variant="caption" className="block leading-5 text-blue-800">
|
||||
<Typography
|
||||
variant="caption"
|
||||
className="block leading-5"
|
||||
sx={{ color: isSimulationMode ? "warning.dark" : "info.dark" }}
|
||||
>
|
||||
{isSimulationMode
|
||||
? "当前为模拟方案:爆管数据取所选方案模拟结果,正常数据取实时模拟结果,两者使用同一爆管时间窗。"
|
||||
? "爆管数据取所选方案,正常数据取同一时间窗的实时模拟结果。所选时间窗必须已有实时模拟正常基线,否则无法分析;系统不会自动补数据。"
|
||||
: "当前为监测数据:爆管数据取所选监测时间窗,正常数据默认取前一天同一时段的监测数据。"}
|
||||
</Typography>
|
||||
</Alert>
|
||||
|
||||
@@ -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: "分析参数不合法",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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}。请选择数据完整的模拟方案。`,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user