feat(flushing): 添加阀门状态与设置值控制
This commit is contained in:
@@ -25,6 +25,12 @@ import {
|
||||
} from "./toolbarFeatureHelpers";
|
||||
import { useToolbarChatActions } from "./useToolbarChatActions";
|
||||
import { useStyleEditor } from "./useStyleEditor";
|
||||
import {
|
||||
type LinkStatus,
|
||||
isLinkStatus,
|
||||
normalizeValveSetting,
|
||||
validateValveSetting,
|
||||
} from "./valveControl";
|
||||
|
||||
import { config, NETWORK_NAME } from "@/config/config";
|
||||
import { useProject } from "@/contexts/ProjectContext";
|
||||
@@ -41,7 +47,6 @@ interface ToolbarProps {
|
||||
enableCompare?: boolean;
|
||||
}
|
||||
|
||||
type LinkStatus = "OPEN" | "CLOSED" | "ACTIVE";
|
||||
type ValveProperties = {
|
||||
vType: string | null;
|
||||
setting: string | null;
|
||||
@@ -50,42 +55,6 @@ type ValveProperties = {
|
||||
const isValveLayer = (layerId: string | undefined) =>
|
||||
layerId === "geo_valves_mat" || layerId === "geo_valves";
|
||||
|
||||
const isLinkStatus = (value: unknown): value is LinkStatus =>
|
||||
value === "OPEN" || value === "CLOSED" || value === "ACTIVE";
|
||||
|
||||
const normalizeValveSetting = (value: unknown): string | null => {
|
||||
if (value === undefined || value === null) return null;
|
||||
return String(value);
|
||||
};
|
||||
|
||||
const validateValveSetting = (
|
||||
valveType: string | null,
|
||||
value: string,
|
||||
): string | null => {
|
||||
const normalizedType = valveType?.toUpperCase();
|
||||
const trimmedValue = value.trim();
|
||||
const numericTypes = new Set(["PRV", "PSV", "PBV", "FCV", "TCV"]);
|
||||
|
||||
if (normalizedType === "GPV") {
|
||||
return trimmedValue ? null : "GPV 阀门设置值必须是非空曲线 ID。";
|
||||
}
|
||||
|
||||
if (numericTypes.has(normalizedType ?? "")) {
|
||||
if (!trimmedValue) {
|
||||
return "阀门设置值必须是 0 或正数。";
|
||||
}
|
||||
|
||||
const numericValue = Number(trimmedValue);
|
||||
if (!Number.isFinite(numericValue) || numericValue < 0) {
|
||||
return "阀门设置值必须是有限数字,且大于或等于 0。";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return trimmedValue ? null : "阀门设置值不能为空。";
|
||||
};
|
||||
|
||||
const Toolbar: React.FC<ToolbarProps> = ({
|
||||
hiddenButtons,
|
||||
queryType,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import Feature from "ol/Feature";
|
||||
|
||||
import { FLOW_DISPLAY_UNIT, toM3h } from "@utils/units";
|
||||
import {
|
||||
getValveSettingHelperText,
|
||||
VALVE_STATUS_OPTIONS,
|
||||
} from "./valveControl";
|
||||
|
||||
type ToolbarBaseProperty = {
|
||||
label: string;
|
||||
@@ -66,30 +70,6 @@ export type ValveSettingPropertyOptions = {
|
||||
onSave: (value: string) => Promise<void>;
|
||||
};
|
||||
|
||||
const getValveSettingHelperText = (
|
||||
vType: string | null,
|
||||
status?: string | null,
|
||||
) => {
|
||||
if (status === "OPEN" || status === "CLOSED") {
|
||||
return "开启/关闭状态下 EPANET 会忽略阀门设置值";
|
||||
}
|
||||
|
||||
switch (vType?.toUpperCase()) {
|
||||
case "PRV":
|
||||
case "PSV":
|
||||
case "PBV":
|
||||
return "压力设置值,需为 0 或正数";
|
||||
case "FCV":
|
||||
return "流量设置值,需为 0 或正数";
|
||||
case "TCV":
|
||||
return "损失系数,需为 0 或正数";
|
||||
case "GPV":
|
||||
return "水头损失曲线 ID";
|
||||
default:
|
||||
return "阀门类型相关设置值";
|
||||
}
|
||||
};
|
||||
|
||||
const getFeatureHistoryType = (feature: Feature): string | null => {
|
||||
const layerId = feature.getId()?.toString().split(".")[0] || "";
|
||||
if (layerId.includes("pipe")) return "pipe";
|
||||
@@ -366,11 +346,7 @@ export const buildFeatureProperties = (
|
||||
type: "select" as const,
|
||||
label: "开关状态",
|
||||
value: valveStatus.value ?? "",
|
||||
options: [
|
||||
{ label: "开启", value: "OPEN" },
|
||||
{ label: "关闭", value: "CLOSED" },
|
||||
{ label: "激活", value: "ACTIVE" },
|
||||
],
|
||||
options: VALVE_STATUS_OPTIONS,
|
||||
placeholder: valveStatus.loading ? "加载中" : "未设置",
|
||||
disabled: valveStatus.loading,
|
||||
saving: valveStatus.saving,
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import {
|
||||
getValveSettingHelperText,
|
||||
isLinkStatus,
|
||||
normalizeValveSetting,
|
||||
VALVE_STATUS_OPTIONS,
|
||||
validateValveSetting,
|
||||
} from "./valveControl";
|
||||
|
||||
describe("valveControl", () => {
|
||||
it("provides the status translations shared by valve editors", () => {
|
||||
expect(VALVE_STATUS_OPTIONS).toEqual([
|
||||
{ label: "开启", value: "OPEN" },
|
||||
{ label: "关闭", value: "CLOSED" },
|
||||
{ label: "激活", value: "ACTIVE" },
|
||||
]);
|
||||
expect(isLinkStatus("ACTIVE")).toBe(true);
|
||||
expect(isLinkStatus("UNKNOWN")).toBe(false);
|
||||
});
|
||||
|
||||
it("normalizes setting values without dropping zero", () => {
|
||||
expect(normalizeValveSetting(0)).toBe("0");
|
||||
expect(normalizeValveSetting(null)).toBeNull();
|
||||
});
|
||||
|
||||
it("validates numeric and curve settings by valve type", () => {
|
||||
expect(validateValveSetting("PRV", "2.5")).toBeNull();
|
||||
expect(validateValveSetting("PRV", "-1")).toContain("大于或等于 0");
|
||||
expect(validateValveSetting("GPV", "curve-1")).toBeNull();
|
||||
expect(validateValveSetting("GPV", " ")).toContain("曲线 ID");
|
||||
});
|
||||
|
||||
it("explains that OPEN and CLOSED ignore the setting", () => {
|
||||
expect(getValveSettingHelperText("PRV", "OPEN")).toContain("忽略");
|
||||
expect(getValveSettingHelperText("FCV", "ACTIVE")).toContain("流量");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
export type LinkStatus = "OPEN" | "CLOSED" | "ACTIVE";
|
||||
|
||||
export const VALVE_STATUS_OPTIONS: Array<{
|
||||
label: string;
|
||||
value: LinkStatus;
|
||||
}> = [
|
||||
{ label: "开启", value: "OPEN" },
|
||||
{ label: "关闭", value: "CLOSED" },
|
||||
{ label: "激活", value: "ACTIVE" },
|
||||
];
|
||||
|
||||
export const isLinkStatus = (value: unknown): value is LinkStatus =>
|
||||
value === "OPEN" || value === "CLOSED" || value === "ACTIVE";
|
||||
|
||||
export const normalizeValveSetting = (value: unknown): string | null => {
|
||||
if (value === undefined || value === null) return null;
|
||||
return String(value);
|
||||
};
|
||||
|
||||
export const validateValveSetting = (
|
||||
valveType: string | null | undefined,
|
||||
value: string,
|
||||
): string | null => {
|
||||
const normalizedType = valveType?.toUpperCase();
|
||||
const trimmedValue = value.trim();
|
||||
const numericTypes = new Set(["PRV", "PSV", "PBV", "FCV", "TCV"]);
|
||||
|
||||
if (normalizedType === "GPV") {
|
||||
return trimmedValue ? null : "GPV 阀门设置值必须是非空曲线 ID。";
|
||||
}
|
||||
|
||||
if (numericTypes.has(normalizedType ?? "")) {
|
||||
if (!trimmedValue) {
|
||||
return "阀门设置值必须是 0 或正数。";
|
||||
}
|
||||
|
||||
const numericValue = Number(trimmedValue);
|
||||
if (!Number.isFinite(numericValue) || numericValue < 0) {
|
||||
return "阀门设置值必须是有限数字,且大于或等于 0。";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return trimmedValue ? null : "阀门设置值不能为空。";
|
||||
};
|
||||
|
||||
export const getValveSettingHelperText = (
|
||||
valveType: string | null | undefined,
|
||||
status?: LinkStatus | string | null,
|
||||
) => {
|
||||
if (status === "OPEN" || status === "CLOSED") {
|
||||
return "开启/关闭状态下 EPANET 会忽略阀门设置值";
|
||||
}
|
||||
|
||||
switch (valveType?.toUpperCase()) {
|
||||
case "PRV":
|
||||
case "PSV":
|
||||
case "PBV":
|
||||
return "压力设置值,需为 0 或正数";
|
||||
case "FCV":
|
||||
return "流量设置值,需为 0 或正数";
|
||||
case "TCV":
|
||||
return "损失系数,需为 0 或正数";
|
||||
case "GPV":
|
||||
return "水头损失曲线 ID";
|
||||
default:
|
||||
return "阀门类型相关设置值";
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user