599 lines
19 KiB
TypeScript
599 lines
19 KiB
TypeScript
import type { Map as MapLibreMap } from "maplibre-gl";
|
|
import type {
|
|
BaseLayerOption,
|
|
MapLayerControlItem,
|
|
MapLayerControlVisual,
|
|
MapLegendItem
|
|
} from "@/features/map/core";
|
|
import { MAP_STYLE_TOKENS } from "./map-colors";
|
|
import { SOURCE_GIS_MIN_ZOOM, SUPPLY_LAYER_VISUALS } from "./map-layer-visuals";
|
|
import {
|
|
AVAILABLE_WATER_NETWORK_SOURCE_IDS,
|
|
SUPPLY_LAYER_CATALOG,
|
|
type WaterNetworkSourceId
|
|
} from "./sources";
|
|
import { SCADA_ICON_PATHS, SCADA_LAYER_CONTROL_ITEMS, SCADA_LAYER_GROUPS } from "./scada";
|
|
import { SUPPLY_ASSET_ICON_PATHS } from "./supply-icons";
|
|
|
|
export const INITIAL_LAYER_VISIBILITY: Record<string, boolean> = {
|
|
...Object.fromEntries(
|
|
SUPPLY_LAYER_CATALOG.filter((layer) => layer.id !== "scada").map((layer) => [
|
|
layer.id,
|
|
layer.initialVisible
|
|
])
|
|
),
|
|
...Object.fromEntries(SCADA_LAYER_CONTROL_ITEMS.map((item) => [item.id, true]))
|
|
};
|
|
|
|
export type AnalysisOverlayLayer = {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
visible: boolean;
|
|
disabled?: boolean;
|
|
featureCount: number;
|
|
color?: string;
|
|
};
|
|
|
|
const SOURCE_CONTROL_LABELS = Object.fromEntries(
|
|
SUPPLY_LAYER_CATALOG.filter((layer) => layer.available).map((layer) => [layer.id, layer.label])
|
|
) as Record<WaterNetworkSourceId, string>;
|
|
|
|
type LayerControlPresentation = {
|
|
description: string;
|
|
minZoom?: number;
|
|
collection?: string;
|
|
collectionLabel?: string;
|
|
visual: MapLayerControlVisual;
|
|
};
|
|
|
|
const LAYER_CONTROL_PRESENTATION: Record<
|
|
Exclude<WaterNetworkSourceId, "scada">,
|
|
LayerControlPresentation
|
|
> = {
|
|
pipes: {
|
|
description: "按管径分级",
|
|
minZoom: 8.5,
|
|
visual: {
|
|
kind: "line-stack",
|
|
colors: [
|
|
MAP_STYLE_TOKENS.supply.pipeMinor,
|
|
MAP_STYLE_TOKENS.supply.pipeMedium,
|
|
MAP_STYLE_TOKENS.supply.pipeMajor
|
|
]
|
|
}
|
|
},
|
|
junctions: {
|
|
description: "拓扑连接点 · 随缩放细化",
|
|
minZoom: SUPPLY_LAYER_VISUALS.junctions.minzoom,
|
|
visual: { kind: "point", color: MAP_STYLE_TOKENS.supply.junction }
|
|
},
|
|
valves: {
|
|
description: "控制设施 · 符号自动避让",
|
|
minZoom: SUPPLY_LAYER_VISUALS.valves.minzoom,
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.valve }
|
|
},
|
|
reservoirs: {
|
|
description: "供水设施",
|
|
minZoom: 8.5,
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.reservoir }
|
|
},
|
|
pumps: {
|
|
description: "加压设施",
|
|
minZoom: SUPPLY_LAYER_VISUALS.pumps.minzoom,
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.pump }
|
|
},
|
|
tanks: {
|
|
description: "调蓄设施",
|
|
minZoom: SUPPLY_LAYER_VISUALS.tanks.minzoom,
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.tank }
|
|
},
|
|
water_quality_monitoring_points: {
|
|
description: "灵敏度分析选点",
|
|
minZoom: SUPPLY_LAYER_VISUALS.waterQuality.minzoom,
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.waterQuality }
|
|
},
|
|
fx_20200423_pipes: {
|
|
description: "全口径管线",
|
|
minZoom: SOURCE_GIS_MIN_ZOOM.fx_20200423_pipes,
|
|
collection: "fx-water-assets-20200423",
|
|
collectionLabel: "2020-04-23 · 全网除头桥快照",
|
|
visual: {
|
|
kind: "line-stack",
|
|
colors: [
|
|
MAP_STYLE_TOKENS.supply.sourcePipe,
|
|
MAP_STYLE_TOKENS.supply.sourcePipeMedium,
|
|
MAP_STYLE_TOKENS.supply.sourcePipeMajor
|
|
]
|
|
}
|
|
},
|
|
fx_20200811_dn100_pipes: {
|
|
description: "DN100 及以上",
|
|
minZoom: SOURCE_GIS_MIN_ZOOM.fx_20200811_dn100_pipes,
|
|
collection: "fx-pipe-inventory-20200811",
|
|
collectionLabel: "2020-08-11 · 专项管线台账",
|
|
visual: {
|
|
kind: "line",
|
|
color: MAP_STYLE_TOKENS.supply.sourcePipeInventory,
|
|
dashed: true
|
|
}
|
|
},
|
|
fx_20200423_valves: {
|
|
description: "源设施台账",
|
|
minZoom: SOURCE_GIS_MIN_ZOOM.fx_20200423_valves,
|
|
collection: "fx-water-assets-20200423",
|
|
collectionLabel: "2020-04-23 · 全网除头桥快照",
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceValve }
|
|
},
|
|
fx_20200423_drain_valves: {
|
|
description: "源设施台账",
|
|
minZoom: SOURCE_GIS_MIN_ZOOM.fx_20200423_drain_valves,
|
|
collection: "fx-water-assets-20200423",
|
|
collectionLabel: "2020-04-23 · 全网除头桥快照",
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceDrainValve }
|
|
},
|
|
fx_20200423_flow_meters: {
|
|
description: "源仪表台账",
|
|
minZoom: SOURCE_GIS_MIN_ZOOM.fx_20200423_flow_meters,
|
|
collection: "fx-water-assets-20200423",
|
|
collectionLabel: "2020-04-23 · 全网除头桥快照",
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceFlowMeter }
|
|
},
|
|
fx_20200423_hydrants: {
|
|
description: "源设施台账",
|
|
minZoom: SOURCE_GIS_MIN_ZOOM.fx_20200423_hydrants,
|
|
collection: "fx-water-assets-20200423",
|
|
collectionLabel: "2020-04-23 · 全网除头桥快照",
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceHydrant }
|
|
},
|
|
fx_20200423_service_connections: {
|
|
description: "源设施台账",
|
|
minZoom: SOURCE_GIS_MIN_ZOOM.fx_20200423_service_connections,
|
|
collection: "fx-water-assets-20200423",
|
|
collectionLabel: "2020-04-23 · 全网除头桥快照",
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceConnection }
|
|
},
|
|
fx_20200423_customer_meters: {
|
|
description: "源水表台账",
|
|
minZoom: SOURCE_GIS_MIN_ZOOM.fx_20200423_customer_meters,
|
|
collection: "fx-water-assets-20200423",
|
|
collectionLabel: "2020-04-23 · 全网除头桥快照",
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceCustomerMeter }
|
|
},
|
|
fx_20200423_non_residential_meters: {
|
|
description: "源水表台账",
|
|
minZoom: SOURCE_GIS_MIN_ZOOM.fx_20200423_non_residential_meters,
|
|
collection: "fx-water-assets-20200423",
|
|
collectionLabel: "2020-04-23 · 全网除头桥快照",
|
|
visual: { kind: "image", imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceNonResidentialMeter }
|
|
}
|
|
};
|
|
|
|
const MODEL_PIPE_LEGEND_GROUP = {
|
|
group: "model-pipe",
|
|
groupLabel: "模型管线",
|
|
groupDescription: "颜色与线宽共同表示口径",
|
|
groupLayout: "list"
|
|
} as const;
|
|
const MODEL_FACILITY_LEGEND_GROUP = {
|
|
group: "model-facility",
|
|
groupLabel: "供水设施",
|
|
groupDescription: "拓扑节点与关键设施",
|
|
groupLayout: "grid"
|
|
} as const;
|
|
const MONITORING_LEGEND_GROUP = {
|
|
group: "monitoring",
|
|
groupLabel: "监测点",
|
|
groupDescription: "在线监测与水质选点",
|
|
groupLayout: "grid"
|
|
} as const;
|
|
const SOURCE_APRIL_PIPE_LEGEND_GROUP = {
|
|
group: "source-pipe-april",
|
|
groupLabel: "原始 GIS 管线 · 2020-04-23",
|
|
groupDescription: "全网快照,实线按已知口径分级",
|
|
groupLayout: "list"
|
|
} as const;
|
|
const SOURCE_AUGUST_PIPE_LEGEND_GROUP = {
|
|
group: "source-pipe-august",
|
|
groupLabel: "原始 GIS 管线 · 2020-08-11",
|
|
groupDescription: "DN100+ 专项台账,蓝色虚线",
|
|
groupLayout: "list"
|
|
} as const;
|
|
const SOURCE_FACILITY_LEGEND_GROUP = {
|
|
group: "source-facility",
|
|
groupLabel: "原始 GIS 设施",
|
|
groupDescription: "源设施与水表台账",
|
|
groupLayout: "grid"
|
|
} as const;
|
|
const ANALYSIS_LEGEND_GROUP = {
|
|
group: "analysis",
|
|
groupLabel: "分析覆盖",
|
|
groupDescription: "仅随空间分析成果显示",
|
|
groupLayout: "list"
|
|
} as const;
|
|
|
|
export const MAP_LEGEND_ITEMS: MapLegendItem[] = [
|
|
{
|
|
id: "major-pipe",
|
|
label: "DN600 及以上",
|
|
description: "主干管",
|
|
color: MAP_STYLE_TOKENS.supply.pipeMajor,
|
|
lineWidth: 5,
|
|
shape: "line",
|
|
layerControlId: "pipes",
|
|
...MODEL_PIPE_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "medium-pipe",
|
|
label: "DN300-DN599",
|
|
description: "次干管",
|
|
color: MAP_STYLE_TOKENS.supply.pipeMedium,
|
|
lineWidth: 3.5,
|
|
shape: "line",
|
|
layerControlId: "pipes",
|
|
...MODEL_PIPE_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "minor-pipe",
|
|
label: "DN300 以下",
|
|
description: "配水支管",
|
|
color: MAP_STYLE_TOKENS.supply.pipeMinor,
|
|
lineWidth: 2,
|
|
shape: "line",
|
|
layerControlId: "pipes",
|
|
...MODEL_PIPE_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "inactive-pipe",
|
|
label: "停运管线",
|
|
description: "虚线",
|
|
color: MAP_STYLE_TOKENS.state.inactive,
|
|
lineWidth: 2.5,
|
|
shape: "dashed-line",
|
|
layerControlId: "pipes",
|
|
...MODEL_PIPE_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "junction",
|
|
label: "节点",
|
|
color: MAP_STYLE_TOKENS.supply.junction,
|
|
shape: "dot",
|
|
layerControlId: "junctions",
|
|
...MODEL_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "valve",
|
|
label: "阀门",
|
|
color: MAP_STYLE_TOKENS.supply.valve,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.valve,
|
|
layerControlId: "valves",
|
|
...MODEL_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "reservoir",
|
|
label: "水库",
|
|
color: MAP_STYLE_TOKENS.supply.reservoir,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.reservoir,
|
|
layerControlId: "reservoirs",
|
|
...MODEL_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "pump",
|
|
label: "水泵",
|
|
color: MAP_STYLE_TOKENS.supply.pump,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.pump,
|
|
layerControlId: "pumps",
|
|
...MODEL_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "tank",
|
|
label: "水箱",
|
|
color: MAP_STYLE_TOKENS.supply.tank,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.tank,
|
|
layerControlId: "tanks",
|
|
...MODEL_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "scada-flow",
|
|
label: "流量监测",
|
|
color: MAP_STYLE_TOKENS.supply.scadaFlow,
|
|
imageSrc: SCADA_ICON_PATHS.flow,
|
|
layerControlId: "scada-flow",
|
|
...MONITORING_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "scada-pressure",
|
|
label: "压力监测",
|
|
color: MAP_STYLE_TOKENS.supply.scadaPressure,
|
|
imageSrc: SCADA_ICON_PATHS.pressure,
|
|
layerControlId: "scada-pressure",
|
|
...MONITORING_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "water-quality-monitoring",
|
|
label: "水质监测",
|
|
color: MAP_STYLE_TOKENS.supply.waterQuality,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.waterQuality,
|
|
layerControlId: "water_quality_monitoring_points",
|
|
...MONITORING_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-major-pipe",
|
|
label: "DN600 及以上",
|
|
color: MAP_STYLE_TOKENS.supply.sourcePipeMajor,
|
|
lineWidth: 5,
|
|
shape: "line",
|
|
layerControlId: "fx_20200423_pipes",
|
|
...SOURCE_APRIL_PIPE_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-medium-pipe",
|
|
label: "DN300-DN599",
|
|
color: MAP_STYLE_TOKENS.supply.sourcePipeMedium,
|
|
lineWidth: 3.5,
|
|
shape: "line",
|
|
layerControlId: "fx_20200423_pipes",
|
|
...SOURCE_APRIL_PIPE_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-minor-pipe",
|
|
label: "DN300 以下",
|
|
color: MAP_STYLE_TOKENS.supply.sourcePipe,
|
|
lineWidth: 2,
|
|
shape: "line",
|
|
layerControlId: "fx_20200423_pipes",
|
|
...SOURCE_APRIL_PIPE_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-unknown-pipe",
|
|
label: "未标注口径",
|
|
color: MAP_STYLE_TOKENS.state.inactive,
|
|
lineWidth: 2,
|
|
shape: "line",
|
|
layerControlId: "fx_20200423_pipes",
|
|
...SOURCE_APRIL_PIPE_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-inventory-pipe",
|
|
label: "DN100 及以上",
|
|
color: MAP_STYLE_TOKENS.supply.sourcePipeInventory,
|
|
lineWidth: 3,
|
|
shape: "dashed-line",
|
|
layerControlId: "fx_20200811_dn100_pipes",
|
|
...SOURCE_AUGUST_PIPE_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-valve",
|
|
label: "GIS 阀门",
|
|
color: MAP_STYLE_TOKENS.supply.sourceValve,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceValve,
|
|
layerControlId: "fx_20200423_valves",
|
|
...SOURCE_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-drain-valve",
|
|
label: "排水阀",
|
|
color: MAP_STYLE_TOKENS.supply.sourceDrainValve,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceDrainValve,
|
|
layerControlId: "fx_20200423_drain_valves",
|
|
...SOURCE_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-flow-meter",
|
|
label: "流量仪",
|
|
color: MAP_STYLE_TOKENS.supply.sourceFlowMeter,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceFlowMeter,
|
|
layerControlId: "fx_20200423_flow_meters",
|
|
...SOURCE_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-hydrant",
|
|
label: "消火栓",
|
|
color: MAP_STYLE_TOKENS.supply.sourceHydrant,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceHydrant,
|
|
layerControlId: "fx_20200423_hydrants",
|
|
...SOURCE_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-connection",
|
|
label: "接水点",
|
|
color: MAP_STYLE_TOKENS.supply.sourceConnection,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceConnection,
|
|
layerControlId: "fx_20200423_service_connections",
|
|
...SOURCE_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-customer-meter",
|
|
label: "用户水表",
|
|
color: MAP_STYLE_TOKENS.supply.sourceCustomerMeter,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceCustomerMeter,
|
|
layerControlId: "fx_20200423_customer_meters",
|
|
...SOURCE_FACILITY_LEGEND_GROUP
|
|
},
|
|
{
|
|
id: "source-non-residential-meter",
|
|
label: "非居民水表",
|
|
color: MAP_STYLE_TOKENS.supply.sourceNonResidentialMeter,
|
|
imageSrc: SUPPLY_ASSET_ICON_PATHS.sourceNonResidentialMeter,
|
|
layerControlId: "fx_20200423_non_residential_meters",
|
|
...SOURCE_FACILITY_LEGEND_GROUP
|
|
}
|
|
];
|
|
|
|
export function createVisibleMapLegendItems(
|
|
layerItems: readonly MapLayerControlItem[]
|
|
) {
|
|
const visibleLayerIds = new Set(layerItems.filter((item) => item.visible).map((item) => item.id));
|
|
return [
|
|
...MAP_LEGEND_ITEMS.filter((item) =>
|
|
item.layerControlId ? visibleLayerIds.has(item.layerControlId) : true
|
|
),
|
|
...layerItems.filter((item) => item.group === "analysis" && item.visible).map((item) => ({
|
|
id: item.id,
|
|
label: item.label,
|
|
description: item.description,
|
|
color: item.visual?.color ?? MAP_STYLE_TOKENS.state.risk,
|
|
shape: "area" as const,
|
|
layerControlId: item.id,
|
|
...ANALYSIS_LEGEND_GROUP
|
|
}))
|
|
];
|
|
}
|
|
|
|
export const BASE_LAYER_GROUPS = {
|
|
"mapbox-light": ["mapbox-light"],
|
|
"mapbox-satellite": ["mapbox-satellite"],
|
|
"tianditu-vector": ["tianditu-vector", "tianditu-vector-annotation"],
|
|
"tianditu-image": ["tianditu-image", "tianditu-image-annotation"]
|
|
} as const;
|
|
|
|
export const BASE_LAYER_IDS = Object.values(BASE_LAYER_GROUPS).flat();
|
|
|
|
export function applyBaseLayerVisibility(map: MapLibreMap, activeBaseLayerId: string) {
|
|
const activeLayerIds = new Set<string>(
|
|
BASE_LAYER_GROUPS[activeBaseLayerId as keyof typeof BASE_LAYER_GROUPS] ?? []
|
|
);
|
|
BASE_LAYER_IDS.forEach((layerId) => {
|
|
if (map.getLayer(layerId)) {
|
|
map.setLayoutProperty(
|
|
layerId,
|
|
"visibility",
|
|
activeLayerIds.has(layerId) ? "visible" : "none"
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
export const BASE_LAYER_OPTIONS: BaseLayerOption[] = [
|
|
{
|
|
id: "mapbox-light",
|
|
label: "浅色",
|
|
description: "道路底图",
|
|
swatchClassName: "bg-gradient-to-br from-slate-50 via-slate-100 to-blue-100"
|
|
},
|
|
{
|
|
id: "mapbox-satellite",
|
|
label: "影像",
|
|
description: "卫星街道",
|
|
swatchClassName: "bg-gradient-to-br from-emerald-950 via-emerald-700 to-yellow-200"
|
|
},
|
|
{
|
|
id: "tianditu-vector",
|
|
label: "天地图矢量",
|
|
description: "矢量与中文注记",
|
|
swatchClassName: "bg-gradient-to-br from-sky-50 via-stone-100 to-emerald-100"
|
|
},
|
|
{
|
|
id: "tianditu-image",
|
|
label: "天地图影像",
|
|
description: "影像与中文注记",
|
|
swatchClassName: "bg-gradient-to-br from-slate-950 via-emerald-800 to-stone-300"
|
|
},
|
|
{
|
|
id: "none",
|
|
label: "无底图",
|
|
description: "仅业务图层",
|
|
swatchClassName: "bg-slate-100"
|
|
}
|
|
];
|
|
|
|
export function createLayerControlItems(
|
|
layerVisibility: Record<string, boolean>,
|
|
availableSourceIds: readonly WaterNetworkSourceId[] = AVAILABLE_WATER_NETWORK_SOURCE_IDS,
|
|
featureCounts: Partial<Record<WaterNetworkSourceId, number>> = {},
|
|
analysisOverlays: readonly AnalysisOverlayLayer[] = []
|
|
): MapLayerControlItem[] {
|
|
const available = new Set<WaterNetworkSourceId>(availableSourceIds);
|
|
const catalogItems = SUPPLY_LAYER_CATALOG.filter(
|
|
(layer) => layer.available && layer.id !== "scada" && available.has(layer.id)
|
|
);
|
|
const modelItems = catalogItems.filter((layer) => layer.group === "model");
|
|
const monitoringItems = catalogItems.filter((layer) => layer.group === "monitoring");
|
|
const sourceGisItems = catalogItems.filter((layer) => layer.group === "source-gis");
|
|
return [
|
|
...modelItems.map((layer) => ({
|
|
id: layer.id,
|
|
label: SOURCE_CONTROL_LABELS[layer.id],
|
|
...LAYER_CONTROL_PRESENTATION[layer.id as Exclude<WaterNetworkSourceId, "scada">],
|
|
featureCount: featureCounts[layer.id],
|
|
visible: layerVisibility[layer.id],
|
|
group: "model",
|
|
groupLabel: "管网模型",
|
|
groupDescription: "计算模型与基础设施"
|
|
})),
|
|
...(available.has("scada")
|
|
? SCADA_LAYER_CONTROL_ITEMS.map((item) => ({
|
|
id: item.id,
|
|
label: item.label,
|
|
description: item.description,
|
|
minZoom: item.minZoom,
|
|
visual: {
|
|
kind: "image" as const,
|
|
imageSrc:
|
|
item.id === "scada-pressure" ? SCADA_ICON_PATHS.pressure : SCADA_ICON_PATHS.flow
|
|
},
|
|
visible: layerVisibility[item.id],
|
|
group: "monitoring",
|
|
groupLabel: "监测点",
|
|
groupDescription: "在线监测与分析选点"
|
|
}))
|
|
: []),
|
|
...monitoringItems.map((layer) => ({
|
|
id: layer.id,
|
|
label: SOURCE_CONTROL_LABELS[layer.id],
|
|
...LAYER_CONTROL_PRESENTATION[layer.id as Exclude<WaterNetworkSourceId, "scada">],
|
|
featureCount: featureCounts[layer.id],
|
|
visible: layerVisibility[layer.id],
|
|
group: "monitoring",
|
|
groupLabel: "监测点",
|
|
groupDescription: "在线监测与分析选点"
|
|
})),
|
|
...sourceGisItems.map((layer) => ({
|
|
id: layer.id,
|
|
label: SOURCE_CONTROL_LABELS[layer.id],
|
|
...LAYER_CONTROL_PRESENTATION[layer.id as Exclude<WaterNetworkSourceId, "scada">],
|
|
featureCount: featureCounts[layer.id],
|
|
visible: layerVisibility[layer.id],
|
|
group: "source-gis",
|
|
groupLabel: "GIS 原始数据",
|
|
groupDescription: "源数据快照与专项台账",
|
|
groupDefaultOpen: false
|
|
})),
|
|
...analysisOverlays.map((overlay) => ({
|
|
id: overlay.id,
|
|
label: overlay.title,
|
|
description: overlay.description,
|
|
featureCount: overlay.featureCount,
|
|
visual: { kind: "area" as const, color: overlay.color ?? MAP_STYLE_TOKENS.state.risk },
|
|
visible: overlay.visible,
|
|
disabled: overlay.disabled,
|
|
group: "analysis",
|
|
groupLabel: "分析覆盖",
|
|
groupDescription: "Agent 生成的范围与分析成果"
|
|
}))
|
|
];
|
|
}
|
|
|
|
export function getWorkbenchLayerIds(
|
|
map: Pick<MapLibreMap, "getLayer" | "getStyle">,
|
|
groupId: string
|
|
) {
|
|
if (groupId in SCADA_LAYER_GROUPS) {
|
|
return SCADA_LAYER_GROUPS[groupId as keyof typeof SCADA_LAYER_GROUPS].filter((layerId) =>
|
|
map.getLayer(layerId)
|
|
);
|
|
}
|
|
if (isWaterNetworkSourceId(groupId)) {
|
|
return map
|
|
.getStyle()
|
|
.layers.filter((layer) => "source" in layer && layer.source === groupId)
|
|
.map((layer) => layer.id);
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
function isWaterNetworkSourceId(value: string): value is WaterNetworkSourceId {
|
|
return (AVAILABLE_WATER_NETWORK_SOURCE_IDS as readonly string[]).includes(value);
|
|
}
|