diff --git a/src/components/olmap/SCADADeviceList.tsx b/src/components/olmap/SCADADeviceList.tsx index 7baa6d4..bcba84c 100644 --- a/src/components/olmap/SCADADeviceList.tsx +++ b/src/components/olmap/SCADADeviceList.tsx @@ -37,11 +37,14 @@ import { FilterList, Clear, DeviceHub, + TouchApp, } from "@mui/icons-material"; import { FixedSizeList } from "react-window"; +import { useNotification } from "@refinedev/core"; import { useMap } from "@app/OlMap/MapComponent"; import { GeoJSON } from "ol/format"; +import { handleMapClickSelectFeatures as mapClickSelectFeatures } from "@/utils/mapQueryService"; import VectorLayer from "ol/layer/Vector"; import VectorSource from "ol/source/Vector"; import { Stroke, Style, Circle, Fill } from "ol/style"; @@ -95,6 +98,7 @@ const SCADADeviceList: React.FC = ({ const [selectedStatus, setSelectedStatus] = useState("all"); const [selectedReliability, setSelectedReliability] = useState("all"); const [isExpanded, setIsExpanded] = useState(true); + const [isSelecting, setIsSelecting] = useState(false); const [internalSelection, setInternalSelection] = useState([]); const [pendingSelection, setPendingSelection] = useState( null @@ -106,7 +110,6 @@ const SCADADeviceList: React.FC = ({ const [highlightLayer, setHighlightLayer] = useState | null>(null); const [highlightFeatures, setHighlightFeatures] = useState([]); - const [blinkingFeature, setBlinkingFeature] = useState(null); const blinkListenerKeyRef = useRef(null); const debounceTimerRef = useRef(null); @@ -125,7 +128,8 @@ const SCADADeviceList: React.FC = ({ const activeSelection = selectedDeviceIds ?? internalSelection; - const map = useMap(); // 移到此处,确保在条件检查前调用 + const map = useMap(); // 移到此处,确保在条件检查前调用 + const { open } = useNotification(); useEffect(() => { if (selectedDeviceIds) { @@ -323,7 +327,6 @@ const SCADADeviceList: React.FC = ({ const blinkFeature = new Feature({ geometry: new Point(coordinates), }); - setBlinkingFeature(blinkFeature); const duration = 2000; // 闪烁持续时间 const start = Date.now(); @@ -334,7 +337,6 @@ const SCADADeviceList: React.FC = ({ if (elapsed > duration) { // 动画结束 unByKey(listenerKey); - setBlinkingFeature(null); blinkListenerKeyRef.current = null; map.render(); // 最后渲染一次以清除效果 return; @@ -435,6 +437,91 @@ const SCADADeviceList: React.FC = ({ setPendingSelection([]); }, []); + // 地图点击选择 SCADA 设备事件处理函数 + const handleMapClickSelectFeatures = useCallback( + async (event: { coordinate: number[] }) => { + if (!map) return; + const feature = await mapClickSelectFeatures(event, map); + const layer = feature?.getId()?.toString().split(".")[0]; + + if (!feature) return; + if (layer !== "geo_scada_mat" && layer !== "geo_scada") { + open?.({ + type: "error", + message: "请选择 SCADA 设备。", + }); + return; + } + + const featureId = feature.getProperties().id; + + // 在设备列表中查找对应的设备 + const device = effectiveDevices.find((d) => d.id === featureId); + if (!device) { + open?.({ + type: "error", + message: "未找到对应的 SCADA 设备。", + }); + return; + } + + // 更新选择状态 + setInternalSelection((prev) => { + const exists = prev.includes(featureId); + const nextSelection = multiSelect + ? exists + ? prev.filter((id) => id !== featureId) + : [...prev, featureId] + : exists + ? [] + : [featureId]; + + setPendingSelection(nextSelection); + return nextSelection; + }); + + // 更新高亮要素 + setHighlightFeatures((prev) => { + const existingIndex = prev.findIndex( + (f) => f.getProperties().id === featureId + ); + if (existingIndex !== -1) { + // 如果已存在,移除 + return prev.filter((_, i) => i !== existingIndex); + } else { + // 如果不存在,添加 + return [...prev, feature]; + } + }); + }, + [map, effectiveDevices, multiSelect, open] + ); + + // 开始选择 SCADA 设备 + const handleStartSelection = useCallback(() => { + if (!map) return; + setIsSelecting(true); + // 注册点击事件 + map.on("click", handleMapClickSelectFeatures); + }, [map, handleMapClickSelectFeatures]); + + // 结束选择 SCADA 设备 + const handleEndSelection = useCallback(() => { + if (!map) return; + setIsSelecting(false); + // 移除点击事件 + map.un("click", handleMapClickSelectFeatures); + }, [map, handleMapClickSelectFeatures]); + + // 组件卸载时清理地图事件 + useEffect(() => { + return () => { + if (map && isSelecting) { + map.un("click", handleMapClickSelectFeatures); + } + }; + }, [map, isSelecting, handleMapClickSelectFeatures]); + // 初始化管道图层和高亮图层 useEffect(() => { if (!map) return; @@ -635,11 +722,34 @@ const SCADADeviceList: React.FC = ({ {/* 筛选结果统计 */} - - 共找到 {filteredDevices.length} 个设备 - {devices.length !== filteredDevices.length && - ` (共 ${effectiveDevices.length} 个设备)`} - + + + 共找到 {filteredDevices.length} 个设备 + {devices.length !== filteredDevices.length && + ` (共 ${effectiveDevices.length} 个设备)`} + + + {/* 地图选择按钮 */} + + + + + + {/* 清除选择按钮 */} {activeSelection.length > 0 && (