import type { MapGeoJSONFeature } from "maplibre-gl"; import type { DetailFeature } from "../types"; import { formatValue } from "../utils/format-value"; import { SOURCE_LAYERS, type WaterNetworkSourceId } from "./sources"; const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; export function getFeatureId(feature: MapGeoJSONFeature) { const layer = getWaterNetworkSourceId(feature); const raw = layer === "scada" ? feature.properties?.scada_id ?? (typeof feature.id === "string" && UUID_PATTERN.test(feature.id) ? feature.id : undefined) : feature.id ?? feature.properties?.id; return raw === undefined || raw === null ? "" : String(raw); } export function getWaterNetworkSourceId(feature: MapGeoJSONFeature): WaterNetworkSourceId | null { const entry = Object.entries(SOURCE_LAYERS).find(([, sourceLayer]) => sourceLayer === feature.sourceLayer); return (entry?.[0] as WaterNetworkSourceId | undefined) ?? null; } export function toDetailFeature(feature: MapGeoJSONFeature): DetailFeature { const layer = getWaterNetworkSourceId(feature); if (!layer) { throw new Error(`Unsupported water network source layer: ${feature.sourceLayer ?? "unknown"}`); } const id = getFeatureId(feature); const properties = feature.properties ?? {}; const presentation = getFeaturePresentation(layer, id, properties); return { id, layer, ...presentation, properties }; } function getFeaturePresentation( layer: WaterNetworkSourceId, id: string, properties: Record ) { const displayId = id || "未命名"; switch (layer) { case "conduits": return { title: `管渠 ${displayId}`, subtitle: `DN${formatValue(properties.diameter)} · ${formatValue(properties.length)} m` }; case "junctions": return { title: `检查井 ${displayId}`, subtitle: `最大深度 ${formatValue(properties.max_depth)} m · 井底高程 ${formatValue(properties.invert_elevation)} m` }; case "orifices": return { title: `孔口 ${displayId}`, subtitle: `类型 ${formatValue(properties.orifice_type)} · 断面 ${formatValue(properties.shape)}` }; case "pumps": return { title: `泵 ${displayId}`, subtitle: `状态 ${formatValue(properties.status)} · 曲线 ${formatValue(properties.pump_curve)}` }; case "outfalls": return { title: `排放口 ${displayId}`, subtitle: `类型 ${formatValue(properties.outfall_type)} · 井底高程 ${formatValue(properties.invert_elevation)} m` }; case "scada": return { title: String(properties.name || `SCADA 测点 ${displayId}`), subtitle: `${formatValue(properties.kind)} · 设备 ${formatValue(properties.external_id)}` }; } }