fix(burst): show actual pipe diameters

This commit is contained in:
2026-07-17 10:01:06 +08:00
parent fddb0ceb34
commit d8ee2e1f0c
3 changed files with 136 additions and 1 deletions
@@ -51,6 +51,10 @@ import { Point } from "ol/geom";
import { toLonLat } from "ol/proj";
import Timeline from "@components/olmap/core/Controls/Timeline";
import { SchemaItem, SchemeRecord } from "./types";
import {
getPipeDiameterDisplay,
type PipeDiameterMap,
} from "./schemePipeDiameters";
interface SchemeQueryProps {
schemes?: SchemeRecord[];
@@ -109,6 +113,12 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
const [internalSchemes, setInternalSchemes] = useState<SchemeRecord[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const [mapContainer, setMapContainer] = useState<HTMLElement | null>(null); // 地图容器元素
const [pipeDiametersByScheme, setPipeDiametersByScheme] = useState<
Record<number, PipeDiameterMap>
>({});
const [loadingDiameterByScheme, setLoadingDiameterByScheme] = useState<
Record<number, boolean>
>({});
const { open } = useNotification();
@@ -209,6 +219,80 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
}
};
useEffect(() => {
if (expandedId === null || pipeDiametersByScheme[expandedId]) {
return;
}
const scheme = filteredSchemes.find((scheme) => scheme.id === expandedId);
const pipeIds = scheme?.schemeDetail?.burst_ID ?? [];
if (pipeIds.length === 0) {
return;
}
let cancelled = false;
setLoadingDiameterByScheme((previous) => ({
...previous,
[expandedId]: true,
}));
const loadPipeDiameters = async () => {
let features = await queryFeaturesByIds(pipeIds, "geo_pipes_mat");
const foundPipeIds = new Set(
features.map((feature) => String(feature.getProperties().id)),
);
const missingPipeIds = pipeIds.filter(
(pipeId) => !foundPipeIds.has(pipeId),
);
if (missingPipeIds.length > 0) {
const fallbackFeatures = await queryFeaturesByIds(
missingPipeIds,
"geo_pipes",
);
features = [...features, ...fallbackFeatures];
}
const nextDiameters: PipeDiameterMap = Object.fromEntries(
pipeIds.map((pipeId) => [pipeId, null]),
);
features.forEach((feature) => {
const properties = feature.getProperties();
const pipeId = String(properties.id);
const diameter = Number(properties.diameter);
nextDiameters[pipeId] = Number.isFinite(diameter) ? diameter : null;
});
if (cancelled) {
return;
}
setPipeDiametersByScheme((previous) => ({
...previous,
[expandedId]: nextDiameters,
}));
setLoadingDiameterByScheme((previous) => ({
...previous,
[expandedId]: false,
}));
};
loadPipeDiameters().catch((error) => {
console.error("查询管径失败:", error);
if (!cancelled) {
setLoadingDiameterByScheme((previous) => ({
...previous,
[expandedId]: false,
}));
}
});
return () => {
cancelled = true;
};
}, [expandedId, filteredSchemes, pipeDiametersByScheme]);
// 内部的方案查询函数
const handleViewDetails = (id: number) => {
const scheme = filteredSchemes.find((s) => s.id === id);
@@ -568,7 +652,11 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
variant="caption"
className="font-medium text-gray-900"
>
560 mm
{getPipeDiameterDisplay(
scheme.schemeDetail?.burst_ID,
pipeDiametersByScheme[scheme.id],
!!loadingDiameterByScheme[scheme.id],
)}
</Typography>
</Box>
<Box className="flex items-center gap-2">
@@ -0,0 +1,20 @@
import { getPipeDiameterDisplay } from "./schemePipeDiameters";
describe("getPipeDiameterDisplay", () => {
it("shows the actual diameter for one burst pipe", () => {
expect(getPipeDiameterDisplay(["P-1"], { "P-1": 315 })).toBe("315 mm");
});
it("shows pipe IDs with diameters for multiple burst pipes", () => {
expect(
getPipeDiameterDisplay(["P-1", "P-2"], {
"P-1": 315,
"P-2": 800,
}),
).toBe("P-1: 315 mmP-2: 800 mm");
});
it("does not fall back to a fixed diameter when a diameter is missing", () => {
expect(getPipeDiameterDisplay(["P-1"], {})).toBe("N/A");
});
});
@@ -0,0 +1,27 @@
export type PipeDiameterMap = Record<string, number | null | undefined>;
export const getPipeDiameterDisplay = (
pipeIds: string[] | undefined,
diameters: PipeDiameterMap | undefined,
loading = false,
): string => {
if (loading) {
return "查询中...";
}
if (!pipeIds?.length) {
return "N/A";
}
const values = pipeIds.map((pipeId) => {
const diameter = diameters?.[pipeId];
const displayValue =
typeof diameter === "number" && Number.isFinite(diameter)
? `${diameter} mm`
: "N/A";
return pipeIds.length === 1 ? displayValue : `${pipeId}: ${displayValue}`;
});
return values.join("");
};