修复 lint warnings
This commit is contained in:
@@ -61,6 +61,39 @@ const AnalysisParameters: React.FC = () => {
|
||||
duration > 0 &&
|
||||
schemeName.trim() !== "";
|
||||
|
||||
// 地图点击选择要素事件处理函数
|
||||
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 (
|
||||
feature.getGeometry()?.getType() === "Point" ||
|
||||
(layer !== "geo_pipes_mat" && layer !== "geo_pipes")
|
||||
) {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "请选择线类型管道要素。",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const featureId = feature.getProperties().id;
|
||||
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, open],
|
||||
);
|
||||
|
||||
// 初始化管道图层和高亮图层
|
||||
useEffect(() => {
|
||||
if (!map) return;
|
||||
@@ -137,7 +170,7 @@ const AnalysisParameters: React.FC = () => {
|
||||
map.removeLayer(highlightLayer);
|
||||
map.un("click", handleMapClickSelectFeatures);
|
||||
};
|
||||
}, [map]);
|
||||
}, [map, handleMapClickSelectFeatures]);
|
||||
// 高亮要素的函数
|
||||
useEffect(() => {
|
||||
if (!highlightLayer) {
|
||||
@@ -155,7 +188,7 @@ const AnalysisParameters: React.FC = () => {
|
||||
source.addFeature(feature);
|
||||
}
|
||||
});
|
||||
}, [highlightFeatures]);
|
||||
}, [highlightFeatures, highlightLayer]);
|
||||
|
||||
// 同步高亮要素和爆管点信息
|
||||
useEffect(() => {
|
||||
@@ -185,42 +218,6 @@ const AnalysisParameters: React.FC = () => {
|
||||
});
|
||||
}, [highlightFeatures]);
|
||||
|
||||
// 地图点击选择要素事件处理函数
|
||||
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 (
|
||||
feature.getGeometry()?.getType() === "Point" ||
|
||||
(layer !== "geo_pipes_mat" && layer !== "geo_pipes")
|
||||
) {
|
||||
// 点类型几何不处理
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "请选择线类型管道要素。",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const featureId = feature.getProperties().id;
|
||||
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],
|
||||
);
|
||||
|
||||
// 开始选择管道
|
||||
const handleStartSelection = () => {
|
||||
if (!map) return;
|
||||
|
||||
@@ -299,7 +299,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
|
||||
source.addFeature(feature);
|
||||
}
|
||||
});
|
||||
}, [highlightFeatures]);
|
||||
}, [highlightFeatures, highlightLayer]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -59,6 +59,32 @@ const AnalysisParameters: React.FC = () => {
|
||||
);
|
||||
}, [network, startTime, sourceNode, concentration, duration, schemeName]);
|
||||
|
||||
const handleMapClickSelectFeatures = useCallback(
|
||||
async (event: { coordinate: number[] }) => {
|
||||
if (!map) return;
|
||||
const feature = await mapClickSelectFeatures(event, map);
|
||||
if (!feature) return;
|
||||
|
||||
const layerId = feature.getId()?.toString().split(".")[0] || "";
|
||||
const isJunction = layerId.includes("junction");
|
||||
if (!isJunction) {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "请选择节点类型要素作为污染源。",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const id = feature.getProperties().id;
|
||||
if (!id) return;
|
||||
setSourceNode(id);
|
||||
setHighlightFeature(feature);
|
||||
setIsSelecting(false);
|
||||
map.un("click", handleMapClickSelectFeatures);
|
||||
},
|
||||
[map, open],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!map) return;
|
||||
|
||||
@@ -106,7 +132,7 @@ const AnalysisParameters: React.FC = () => {
|
||||
map.removeLayer(layer);
|
||||
map.un("click", handleMapClickSelectFeatures);
|
||||
};
|
||||
}, [map]);
|
||||
}, [map, handleMapClickSelectFeatures]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!highlightLayer) return;
|
||||
@@ -118,32 +144,6 @@ const AnalysisParameters: React.FC = () => {
|
||||
}
|
||||
}, [highlightFeature, highlightLayer]);
|
||||
|
||||
const handleMapClickSelectFeatures = useCallback(
|
||||
async (event: { coordinate: number[] }) => {
|
||||
if (!map) return;
|
||||
const feature = await mapClickSelectFeatures(event, map);
|
||||
if (!feature) return;
|
||||
|
||||
const layerId = feature.getId()?.toString().split(".")[0] || "";
|
||||
const isJunction = layerId.includes("junction");
|
||||
if (!isJunction) {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "请选择节点类型要素作为污染源。",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const id = feature.getProperties().id;
|
||||
if (!id) return;
|
||||
setSourceNode(id);
|
||||
setHighlightFeature(feature);
|
||||
setIsSelecting(false);
|
||||
map.un("click", handleMapClickSelectFeatures);
|
||||
},
|
||||
[map, open],
|
||||
);
|
||||
|
||||
const handleStartSelection = () => {
|
||||
if (!map) return;
|
||||
setIsSelecting(true);
|
||||
|
||||
@@ -55,7 +55,7 @@ const DMALeakDetectionPanel: React.FC = () => {
|
||||
|
||||
const drawerWidth = 450;
|
||||
const panelTitle = "DMA 漏损识别";
|
||||
const activeAreas = loadedResult?.areas ?? [];
|
||||
const activeAreas = useMemo(() => loadedResult?.areas ?? [], [loadedResult]);
|
||||
const legendColors = useMemo(
|
||||
() => activeAreas.map((area) => getAreaColor(area.area_id)),
|
||||
[activeAreas],
|
||||
|
||||
@@ -55,6 +55,54 @@ const AnalysisParameters: React.FC = () => {
|
||||
|
||||
const [highlightLayer, setHighlightLayer] = useState<VectorLayer<VectorSource> | null>(null);
|
||||
|
||||
// Map click handler
|
||||
const handleMapClickSelectFeatures = useCallback(
|
||||
async (event: { coordinate: number[] }) => {
|
||||
if (!map || selectionMode === 'none') return;
|
||||
|
||||
const feature = await mapClickSelectFeatures(event, map);
|
||||
if (!feature) return;
|
||||
|
||||
const layer = feature.getId()?.toString().split(".")[0];
|
||||
const featureId = feature.getProperties().id;
|
||||
|
||||
if (selectionMode === 'valve') {
|
||||
if (layer !== 'geo_valves') {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "请选择阀门要素",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setValves((prev) => {
|
||||
if (prev.some((v) => v.id === featureId)) {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "该阀门已添加",
|
||||
});
|
||||
return prev;
|
||||
}
|
||||
return [...prev, { id: featureId, k: 1.0, feature }];
|
||||
});
|
||||
|
||||
} else if (selectionMode === 'drainage') {
|
||||
if (layer !== 'geo_junctions') {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "请选择节点要素作为排水点",
|
||||
});
|
||||
return;
|
||||
}
|
||||
setDrainageNode(featureId);
|
||||
setDrainageFeature(feature);
|
||||
setSelectionMode('none');
|
||||
map.un("click", handleMapClickSelectFeatures);
|
||||
}
|
||||
},
|
||||
[map, selectionMode, open]
|
||||
);
|
||||
|
||||
// Initialize highlight layer
|
||||
useEffect(() => {
|
||||
if (!map) return;
|
||||
@@ -103,7 +151,7 @@ const AnalysisParameters: React.FC = () => {
|
||||
map.removeLayer(layer);
|
||||
map.un("click", handleMapClickSelectFeatures);
|
||||
};
|
||||
}, [map]);
|
||||
}, [map, handleMapClickSelectFeatures]);
|
||||
|
||||
// Update highlight layer features
|
||||
useEffect(() => {
|
||||
@@ -134,54 +182,6 @@ const AnalysisParameters: React.FC = () => {
|
||||
|
||||
}, [highlightLayer, valves, drainageFeature]);
|
||||
|
||||
// Map click handler
|
||||
const handleMapClickSelectFeatures = useCallback(
|
||||
async (event: { coordinate: number[] }) => {
|
||||
if (!map || selectionMode === 'none') return;
|
||||
|
||||
const feature = await mapClickSelectFeatures(event, map);
|
||||
if (!feature) return;
|
||||
|
||||
const layer = feature.getId()?.toString().split(".")[0];
|
||||
const featureId = feature.getProperties().id;
|
||||
|
||||
if (selectionMode === 'valve') {
|
||||
if (layer !== 'geo_valves') {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "请选择阀门要素",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setValves((prev) => {
|
||||
if (prev.some((v) => v.id === featureId)) {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "该阀门已添加",
|
||||
});
|
||||
return prev;
|
||||
}
|
||||
return [...prev, { id: featureId, k: 1.0, feature }]; // Default k=1.0? User can change.
|
||||
});
|
||||
|
||||
} else if (selectionMode === 'drainage') {
|
||||
if (layer !== 'geo_junctions') {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "请选择节点要素作为排水点",
|
||||
});
|
||||
return;
|
||||
}
|
||||
setDrainageNode(featureId);
|
||||
setDrainageFeature(feature);
|
||||
setSelectionMode('none'); // Auto exit selection after picking one
|
||||
map.un("click", handleMapClickSelectFeatures);
|
||||
}
|
||||
},
|
||||
[map, selectionMode, open]
|
||||
);
|
||||
|
||||
// Bind click event based on selection mode
|
||||
useEffect(() => {
|
||||
if (!map || selectionMode === "none") return;
|
||||
|
||||
@@ -117,7 +117,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
setCurrentYear(value);
|
||||
}, 500); // 500ms 防抖延迟
|
||||
},
|
||||
[minTime, maxTime],
|
||||
[minTime, maxTime, setCurrentYear],
|
||||
);
|
||||
|
||||
// 播放控制
|
||||
@@ -133,7 +133,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
});
|
||||
}, playInterval);
|
||||
}
|
||||
}, [isPlaying, playInterval]);
|
||||
}, [isPlaying, playInterval, maxTime, minTime, setCurrentYear]);
|
||||
|
||||
const handlePause = useCallback(() => {
|
||||
setIsPlaying(false);
|
||||
@@ -172,7 +172,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
if (next < minTime) next += maxTime - minTime + 1;
|
||||
return next;
|
||||
});
|
||||
}, [minTime, maxTime]);
|
||||
}, [minTime, maxTime, setCurrentYear]);
|
||||
|
||||
const handleStepForward = useCallback(() => {
|
||||
setCurrentYear((prev: number) => {
|
||||
@@ -180,7 +180,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
if (next > maxTime) next = minTime;
|
||||
return next;
|
||||
});
|
||||
}, [minTime, maxTime]);
|
||||
}, [minTime, maxTime, setCurrentYear]);
|
||||
|
||||
// 日期时间选择处理
|
||||
const handleDateTimeChange = useCallback((newDate: Date | null) => {
|
||||
@@ -207,7 +207,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
}, newInterval);
|
||||
}
|
||||
},
|
||||
[isPlaying],
|
||||
[isPlaying, maxTime, minTime, setCurrentYear],
|
||||
);
|
||||
|
||||
// 组件加载时设置初始时间为当前时间的最近15分钟
|
||||
@@ -372,7 +372,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
if (predictionResults.length > 0 && pipeLayer) {
|
||||
applyPipeHealthStyle();
|
||||
}
|
||||
}, [applyPipeHealthStyle]);
|
||||
}, [applyPipeHealthStyle, pipeLayer, predictionResults.length]);
|
||||
|
||||
// 这里防止地图缩放时,瓦片重新加载引起的属性更新出错
|
||||
useEffect(() => {
|
||||
|
||||
@@ -140,7 +140,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
|
||||
source.addFeature(feature);
|
||||
}
|
||||
});
|
||||
}, [highlightFeatures]);
|
||||
}, [highlightFeatures, highlightLayer]);
|
||||
|
||||
// 查询方案
|
||||
const handleQuery = async () => {
|
||||
|
||||
@@ -416,6 +416,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
|
||||
|
||||
const hasDevices = deviceIds.length > 0;
|
||||
const hasData = timeSeries.length > 0;
|
||||
const deviceIdsKey = useMemo(() => deviceIds.join(","), [deviceIds]);
|
||||
|
||||
const dataset = useMemo(
|
||||
() => buildDataset(timeSeries, deviceIds, fractionDigits, showCleaning),
|
||||
@@ -528,7 +529,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
|
||||
} else {
|
||||
setTimeSeries([]);
|
||||
}
|
||||
}, [deviceIds.join(",")]);
|
||||
}, [deviceIdsKey, handleFetch, hasDevices]);
|
||||
|
||||
// 当设备数量变化时,调整数据源选择
|
||||
useEffect(() => {
|
||||
|
||||
@@ -741,7 +741,7 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
|
||||
source.addFeature(feature);
|
||||
}
|
||||
});
|
||||
}, [selectedDeviceIds, highlightFeatures]);
|
||||
}, [selectedDeviceIds, highlightFeatures, highlightLayer]);
|
||||
// 清理定时器
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import Image from "next/image";
|
||||
import { useMap } from "../MapComponent";
|
||||
import TileLayer from "ol/layer/Tile.js";
|
||||
import XYZ from "ol/source/XYZ.js";
|
||||
@@ -136,7 +137,7 @@ const BaseLayers: React.FC = () => {
|
||||
}
|
||||
layerInfo.layer.setVisible(layerInfo.id === activeId);
|
||||
});
|
||||
}, [map]);
|
||||
}, [map, activeId]);
|
||||
|
||||
const changeMapLayers = (id: string) => {
|
||||
if (map) {
|
||||
@@ -187,7 +188,7 @@ const BaseLayers: React.FC = () => {
|
||||
>
|
||||
<div className="w-20 h-20 p-1">
|
||||
<button onClick={() => handleQuickSwitch()}>
|
||||
<img
|
||||
<Image
|
||||
width={240}
|
||||
height={100}
|
||||
src={
|
||||
@@ -200,6 +201,7 @@ const BaseLayers: React.FC = () => {
|
||||
? baseLayers[1].name
|
||||
: baseLayers[0].name
|
||||
}
|
||||
sizes="72px"
|
||||
className="object-cover object-left w-18 h-18 rounded-xl"
|
||||
/>
|
||||
<div className=" absolute left-1 bottom-1 flex w-18 h-auto items-center justify-center rounded-b-xl text-xs text-white bg-black opacity-80">
|
||||
@@ -227,11 +229,12 @@ const BaseLayers: React.FC = () => {
|
||||
className="flex flex-auto flex-col justify-center items-center text-gray-500 text-xs"
|
||||
onClick={() => handleMapLayers(item.id)}
|
||||
>
|
||||
<img
|
||||
<Image
|
||||
width={240}
|
||||
height={100}
|
||||
src={item.img}
|
||||
alt={item.name}
|
||||
sizes="64px"
|
||||
className={clsx(
|
||||
"object-cover object-left w-16 h-16 rounded-md border-2 border-white hover:ring-2 ring-blue-300",
|
||||
{
|
||||
|
||||
@@ -422,6 +422,10 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
|
||||
|
||||
const hasDevices = deviceIds.length > 0;
|
||||
const hasData = timeSeries.length > 0;
|
||||
const featureInfosKey = useMemo(
|
||||
() => JSON.stringify(featureInfos),
|
||||
[featureInfos]
|
||||
);
|
||||
|
||||
const dataset = useMemo(
|
||||
() => buildDataset(timeSeries, deviceIds, fractionDigits),
|
||||
@@ -468,7 +472,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
|
||||
} else {
|
||||
setTimeSeries([]);
|
||||
}
|
||||
}, [JSON.stringify(featureInfos)]);
|
||||
}, [featureInfosKey, handleFetch, hasDevices]);
|
||||
|
||||
// 当设备数量变化时,调整数据源选择
|
||||
useEffect(() => {
|
||||
|
||||
@@ -15,6 +15,18 @@ interface LayerItem {
|
||||
layerRef: any; // OpenLayers Layer 实例或 deck.gl layer 对象
|
||||
}
|
||||
|
||||
const LAYER_ORDER = [
|
||||
"junctions",
|
||||
"reservoirs",
|
||||
"tanks",
|
||||
"pipes",
|
||||
"pumps",
|
||||
"valves",
|
||||
"scada",
|
||||
"waterflowLayer",
|
||||
"junctionContourLayer",
|
||||
];
|
||||
|
||||
const LayerControl: React.FC = () => {
|
||||
const map = useMap();
|
||||
const data = useData();
|
||||
@@ -25,19 +37,9 @@ const LayerControl: React.FC = () => {
|
||||
const setShowWaterflowLayer = data?.setShowWaterflowLayer;
|
||||
const setShowContourLayer = data?.setShowContourLayer;
|
||||
|
||||
const layerOrder = [
|
||||
"junctions",
|
||||
"reservoirs",
|
||||
"tanks",
|
||||
"pipes",
|
||||
"pumps",
|
||||
"valves",
|
||||
"scada",
|
||||
"waterflowLayer",
|
||||
"junctionContourLayer",
|
||||
];
|
||||
|
||||
const layerItems = useMemo(() => {
|
||||
void refreshKey;
|
||||
|
||||
if (!map || !data) return [];
|
||||
|
||||
const items: LayerItem[] = [];
|
||||
@@ -87,8 +89,8 @@ const LayerControl: React.FC = () => {
|
||||
}
|
||||
|
||||
return items
|
||||
.filter((item) => layerOrder.includes(item.id))
|
||||
.sort((a, b) => layerOrder.indexOf(a.id) - layerOrder.indexOf(b.id));
|
||||
.filter((item) => LAYER_ORDER.includes(item.id))
|
||||
.sort((a, b) => LAYER_ORDER.indexOf(a.id) - LAYER_ORDER.indexOf(b.id));
|
||||
}, [
|
||||
map,
|
||||
data,
|
||||
|
||||
@@ -321,7 +321,7 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
}
|
||||
return colors;
|
||||
},
|
||||
[styleConfig.gradientPaletteIndex, parseColor]
|
||||
[styleConfig.gradientPaletteIndex]
|
||||
);
|
||||
|
||||
// 根据分段数生成彩虹色
|
||||
@@ -1065,6 +1065,8 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
if (!applyPipeStyle) {
|
||||
removeVectorTileSourceLoadedEvent("pipes");
|
||||
}
|
||||
// This effect is intentionally driven by explicit style triggers and data snapshots.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
styleUpdateTrigger,
|
||||
applyJunctionStyle,
|
||||
|
||||
@@ -39,6 +39,9 @@ interface TimelineProps {
|
||||
schemeType?: string;
|
||||
}
|
||||
|
||||
const NOOP_SET_CURRENT_TIME = (_: any) => undefined;
|
||||
const NOOP_SET_SELECTED_DATE = (_: any) => undefined;
|
||||
|
||||
const Timeline: React.FC<TimelineProps> = ({
|
||||
schemeDate,
|
||||
timeRange,
|
||||
@@ -47,6 +50,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
schemeType = "burst_Analysis",
|
||||
}) => {
|
||||
const data = useData();
|
||||
const fallbackSelectedDateRef = useRef(new Date());
|
||||
const hasTimelineState =
|
||||
data &&
|
||||
data.setCurrentTime !== undefined &&
|
||||
@@ -54,9 +58,9 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
data.selectedDate !== undefined &&
|
||||
data.setSelectedDate !== undefined;
|
||||
const currentTime = data?.currentTime ?? -1;
|
||||
const setCurrentTime = data?.setCurrentTime ?? ((_: any) => undefined);
|
||||
const selectedDate = data?.selectedDate ?? new Date();
|
||||
const setSelectedDate = data?.setSelectedDate ?? ((_: any) => undefined);
|
||||
const setCurrentTime = data?.setCurrentTime ?? NOOP_SET_CURRENT_TIME;
|
||||
const selectedDate = data?.selectedDate ?? fallbackSelectedDateRef.current;
|
||||
const setSelectedDate = data?.setSelectedDate ?? NOOP_SET_SELECTED_DATE;
|
||||
const setCurrentJunctionCalData = data?.setCurrentJunctionCalData;
|
||||
const setCurrentPipeCalData = data?.setCurrentPipeCalData;
|
||||
const junctionText = data?.junctionText ?? "";
|
||||
@@ -78,7 +82,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
if (schemeDate) {
|
||||
setSelectedDate(schemeDate);
|
||||
}
|
||||
}, [schemeDate]);
|
||||
}, [schemeDate, setSelectedDate]);
|
||||
// 新增:用于 Draggable 的 nodeRef
|
||||
const draggableRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -90,7 +94,20 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
// 添加防抖引用
|
||||
const debounceRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const fetchFrameData = async (
|
||||
const updateDataStates = useCallback((nodeResults: any[], linkResults: any[]) => {
|
||||
if (setCurrentJunctionCalData) {
|
||||
setCurrentJunctionCalData(nodeResults);
|
||||
} else {
|
||||
console.log("setCurrentJunctionCalData is undefined");
|
||||
}
|
||||
if (setCurrentPipeCalData) {
|
||||
setCurrentPipeCalData(linkResults);
|
||||
} else {
|
||||
console.log("setCurrentPipeCalData is undefined");
|
||||
}
|
||||
}, [setCurrentJunctionCalData, setCurrentPipeCalData]);
|
||||
|
||||
const fetchFrameData = useCallback(async (
|
||||
queryTime: Date,
|
||||
junctionProperties: string,
|
||||
pipeProperties: string,
|
||||
@@ -170,21 +187,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
}
|
||||
// 更新状态
|
||||
updateDataStates(nodeRecords.results || [], linkRecords.results || []);
|
||||
};
|
||||
|
||||
// 提取更新状态的逻辑
|
||||
const updateDataStates = (nodeResults: any[], linkResults: any[]) => {
|
||||
if (setCurrentJunctionCalData) {
|
||||
setCurrentJunctionCalData(nodeResults);
|
||||
} else {
|
||||
console.log("setCurrentJunctionCalData is undefined");
|
||||
}
|
||||
if (setCurrentPipeCalData) {
|
||||
setCurrentPipeCalData(linkResults);
|
||||
} else {
|
||||
console.log("setCurrentPipeCalData is undefined");
|
||||
}
|
||||
};
|
||||
}, [disableDateSelection, updateDataStates]);
|
||||
|
||||
// 时间刻度数组 (每5分钟一个刻度)
|
||||
const timeMarks = Array.from({ length: 288 }, (_, i) => ({
|
||||
@@ -241,7 +244,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
setCurrentTime(value);
|
||||
}, 500); // 500ms 防抖延迟
|
||||
},
|
||||
[timeRange, minTime, maxTime],
|
||||
[timeRange, minTime, maxTime, setCurrentTime],
|
||||
);
|
||||
|
||||
// 播放控制
|
||||
@@ -268,7 +271,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
});
|
||||
}, playInterval);
|
||||
}
|
||||
}, [isPlaying, playInterval]);
|
||||
}, [isPlaying, playInterval, timeRange, maxTime, minTime, setCurrentTime]);
|
||||
|
||||
const handlePause = useCallback(() => {
|
||||
setIsPlaying(false);
|
||||
@@ -288,7 +291,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
clearInterval(intervalRef.current);
|
||||
intervalRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
}, [setCurrentTime]);
|
||||
|
||||
// 步进控制
|
||||
const handleDayStepBackward = useCallback(() => {
|
||||
@@ -297,14 +300,14 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
newDate.setDate(newDate.getDate() - 1);
|
||||
return newDate;
|
||||
});
|
||||
}, []);
|
||||
}, [setSelectedDate]);
|
||||
const handleDayStepForward = useCallback(() => {
|
||||
setSelectedDate((prev) => {
|
||||
const newDate = new Date(prev);
|
||||
newDate.setDate(newDate.getDate() + 1);
|
||||
return newDate;
|
||||
});
|
||||
}, []);
|
||||
}, [setSelectedDate]);
|
||||
const handleStepBackward = useCallback(() => {
|
||||
setCurrentTime((prev) => {
|
||||
let next = prev - 15;
|
||||
@@ -315,7 +318,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
}
|
||||
return next;
|
||||
});
|
||||
}, [timeRange, minTime, maxTime]);
|
||||
}, [timeRange, minTime, maxTime, setCurrentTime]);
|
||||
|
||||
const handleStepForward = useCallback(() => {
|
||||
setCurrentTime((prev) => {
|
||||
@@ -327,14 +330,14 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
}
|
||||
return next;
|
||||
});
|
||||
}, [timeRange, minTime, maxTime]);
|
||||
}, [timeRange, minTime, maxTime, setCurrentTime]);
|
||||
|
||||
// 日期选择处理
|
||||
const handleDateChange = useCallback((newDate: Date | null) => {
|
||||
if (newDate) {
|
||||
setSelectedDate(newDate);
|
||||
}
|
||||
}, []);
|
||||
}, [setSelectedDate]);
|
||||
|
||||
// 播放间隔改变处理
|
||||
const handleIntervalChange = useCallback(
|
||||
@@ -358,7 +361,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
}, newInterval);
|
||||
}
|
||||
},
|
||||
[isPlaying],
|
||||
[isPlaying, timeRange, maxTime, minTime, setCurrentTime],
|
||||
);
|
||||
// 计算时间段改变处理
|
||||
const handleCalculatedIntervalChange = useCallback((event: any) => {
|
||||
@@ -389,6 +392,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
);
|
||||
}
|
||||
}, [
|
||||
fetchFrameData,
|
||||
junctionText,
|
||||
pipeText,
|
||||
currentTime,
|
||||
@@ -414,14 +418,14 @@ const Timeline: React.FC<TimelineProps> = ({
|
||||
clearTimeout(debounceRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
}, [setCurrentTime]);
|
||||
|
||||
// 当 timeRange 改变时,设置 currentTime 到 minTime
|
||||
useEffect(() => {
|
||||
if (timeRange) {
|
||||
setCurrentTime(minTime);
|
||||
}
|
||||
}, [timeRange, minTime]);
|
||||
}, [timeRange, minTime, setCurrentTime]);
|
||||
// 获取地图实例
|
||||
const map = useMap();
|
||||
// 这里防止地图缩放时,瓦片重新加载引起的属性更新出错
|
||||
|
||||
@@ -409,8 +409,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
|
||||
setComputedProperties({});
|
||||
} else {
|
||||
setComputedProperties(data.result[0] || {});
|
||||
console.log("查询到的计算属性:", data.result[0]);
|
||||
console.log(computedProperties);
|
||||
// console.log("查询到的计算属性:", data.result[0]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error querying computed properties:", error);
|
||||
@@ -419,7 +418,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
|
||||
};
|
||||
// 仅当 currentTime 有效时查询
|
||||
if (currentTime !== -1 && queryType) queryComputedProperties();
|
||||
}, [highlightFeatures, currentTime, selectedDate, queryType, schemeName, schemeType]);
|
||||
}, [highlightFeatures, currentTime, selectedDate, queryType, schemeName, schemeType, showPropertyPanel]);
|
||||
|
||||
// 从要素属性中提取属性面板需要的数据
|
||||
const getFeatureProperties = useCallback(() => {
|
||||
|
||||
@@ -515,6 +515,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
},
|
||||
});
|
||||
|
||||
// The map and layer instances are intentionally rebuilt only when workspace or extent changes.
|
||||
useEffect(() => {
|
||||
if (!mapRef.current) return;
|
||||
// 缓存 junction、pipe 数据,提供给 deck.gl 提供坐标供标签显示
|
||||
@@ -807,6 +808,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
map.dispose();
|
||||
deck.finalize();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [MAP_WORKSPACE, MAP_EXTENT]);
|
||||
|
||||
// 当数据变化时,更新 deck.gl 图层
|
||||
|
||||
Reference in New Issue
Block a user