修复 lint warnings
This commit is contained in:
@@ -1,6 +1,14 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
|
images: {
|
||||||
|
remotePatterns: [
|
||||||
|
{
|
||||||
|
protocol: "https",
|
||||||
|
hostname: "refine.ams3.cdn.digitaloceanspaces.com",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
turbopack: {
|
turbopack: {
|
||||||
rules: {
|
rules: {
|
||||||
"*.svg": {
|
"*.svg": {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import Image from "next/image";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Container from "@mui/material/Container";
|
import Container from "@mui/material/Container";
|
||||||
@@ -38,10 +39,12 @@ export default function Login() {
|
|||||||
</Button>
|
</Button>
|
||||||
<Typography align="center" color={"text.secondary"} fontSize="12px">
|
<Typography align="center" color={"text.secondary"} fontSize="12px">
|
||||||
Powered by
|
Powered by
|
||||||
<img
|
<Image
|
||||||
style={{ padding: "0 5px" }}
|
style={{ padding: "0 5px" }}
|
||||||
alt="Keycloak"
|
alt="Keycloak"
|
||||||
src="https://refine.ams3.cdn.digitaloceanspaces.com/superplate-auth-icons%2Fkeycloak.svg"
|
src="https://refine.ams3.cdn.digitaloceanspaces.com/superplate-auth-icons%2Fkeycloak.svg"
|
||||||
|
width={18}
|
||||||
|
height={18}
|
||||||
/>
|
/>
|
||||||
Keycloak
|
Keycloak
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -61,6 +61,39 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
duration > 0 &&
|
duration > 0 &&
|
||||||
schemeName.trim() !== "";
|
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(() => {
|
useEffect(() => {
|
||||||
if (!map) return;
|
if (!map) return;
|
||||||
@@ -137,7 +170,7 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
map.removeLayer(highlightLayer);
|
map.removeLayer(highlightLayer);
|
||||||
map.un("click", handleMapClickSelectFeatures);
|
map.un("click", handleMapClickSelectFeatures);
|
||||||
};
|
};
|
||||||
}, [map]);
|
}, [map, handleMapClickSelectFeatures]);
|
||||||
// 高亮要素的函数
|
// 高亮要素的函数
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!highlightLayer) {
|
if (!highlightLayer) {
|
||||||
@@ -155,7 +188,7 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
source.addFeature(feature);
|
source.addFeature(feature);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [highlightFeatures]);
|
}, [highlightFeatures, highlightLayer]);
|
||||||
|
|
||||||
// 同步高亮要素和爆管点信息
|
// 同步高亮要素和爆管点信息
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -185,42 +218,6 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
});
|
});
|
||||||
}, [highlightFeatures]);
|
}, [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 = () => {
|
const handleStartSelection = () => {
|
||||||
if (!map) return;
|
if (!map) return;
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
|
|||||||
source.addFeature(feature);
|
source.addFeature(feature);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [highlightFeatures]);
|
}, [highlightFeatures, highlightLayer]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -59,6 +59,32 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
);
|
);
|
||||||
}, [network, startTime, sourceNode, concentration, duration, schemeName]);
|
}, [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(() => {
|
useEffect(() => {
|
||||||
if (!map) return;
|
if (!map) return;
|
||||||
|
|
||||||
@@ -106,7 +132,7 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
map.removeLayer(layer);
|
map.removeLayer(layer);
|
||||||
map.un("click", handleMapClickSelectFeatures);
|
map.un("click", handleMapClickSelectFeatures);
|
||||||
};
|
};
|
||||||
}, [map]);
|
}, [map, handleMapClickSelectFeatures]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!highlightLayer) return;
|
if (!highlightLayer) return;
|
||||||
@@ -118,32 +144,6 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [highlightFeature, highlightLayer]);
|
}, [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 = () => {
|
const handleStartSelection = () => {
|
||||||
if (!map) return;
|
if (!map) return;
|
||||||
setIsSelecting(true);
|
setIsSelecting(true);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ const DMALeakDetectionPanel: React.FC = () => {
|
|||||||
|
|
||||||
const drawerWidth = 450;
|
const drawerWidth = 450;
|
||||||
const panelTitle = "DMA 漏损识别";
|
const panelTitle = "DMA 漏损识别";
|
||||||
const activeAreas = loadedResult?.areas ?? [];
|
const activeAreas = useMemo(() => loadedResult?.areas ?? [], [loadedResult]);
|
||||||
const legendColors = useMemo(
|
const legendColors = useMemo(
|
||||||
() => activeAreas.map((area) => getAreaColor(area.area_id)),
|
() => activeAreas.map((area) => getAreaColor(area.area_id)),
|
||||||
[activeAreas],
|
[activeAreas],
|
||||||
|
|||||||
@@ -55,6 +55,54 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
|
|
||||||
const [highlightLayer, setHighlightLayer] = useState<VectorLayer<VectorSource> | null>(null);
|
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
|
// Initialize highlight layer
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!map) return;
|
if (!map) return;
|
||||||
@@ -103,7 +151,7 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
map.removeLayer(layer);
|
map.removeLayer(layer);
|
||||||
map.un("click", handleMapClickSelectFeatures);
|
map.un("click", handleMapClickSelectFeatures);
|
||||||
};
|
};
|
||||||
}, [map]);
|
}, [map, handleMapClickSelectFeatures]);
|
||||||
|
|
||||||
// Update highlight layer features
|
// Update highlight layer features
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -134,54 +182,6 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
|
|
||||||
}, [highlightLayer, valves, drainageFeature]);
|
}, [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
|
// Bind click event based on selection mode
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!map || selectionMode === "none") return;
|
if (!map || selectionMode === "none") return;
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
setCurrentYear(value);
|
setCurrentYear(value);
|
||||||
}, 500); // 500ms 防抖延迟
|
}, 500); // 500ms 防抖延迟
|
||||||
},
|
},
|
||||||
[minTime, maxTime],
|
[minTime, maxTime, setCurrentYear],
|
||||||
);
|
);
|
||||||
|
|
||||||
// 播放控制
|
// 播放控制
|
||||||
@@ -133,7 +133,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
});
|
});
|
||||||
}, playInterval);
|
}, playInterval);
|
||||||
}
|
}
|
||||||
}, [isPlaying, playInterval]);
|
}, [isPlaying, playInterval, maxTime, minTime, setCurrentYear]);
|
||||||
|
|
||||||
const handlePause = useCallback(() => {
|
const handlePause = useCallback(() => {
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
@@ -172,7 +172,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
if (next < minTime) next += maxTime - minTime + 1;
|
if (next < minTime) next += maxTime - minTime + 1;
|
||||||
return next;
|
return next;
|
||||||
});
|
});
|
||||||
}, [minTime, maxTime]);
|
}, [minTime, maxTime, setCurrentYear]);
|
||||||
|
|
||||||
const handleStepForward = useCallback(() => {
|
const handleStepForward = useCallback(() => {
|
||||||
setCurrentYear((prev: number) => {
|
setCurrentYear((prev: number) => {
|
||||||
@@ -180,7 +180,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
if (next > maxTime) next = minTime;
|
if (next > maxTime) next = minTime;
|
||||||
return next;
|
return next;
|
||||||
});
|
});
|
||||||
}, [minTime, maxTime]);
|
}, [minTime, maxTime, setCurrentYear]);
|
||||||
|
|
||||||
// 日期时间选择处理
|
// 日期时间选择处理
|
||||||
const handleDateTimeChange = useCallback((newDate: Date | null) => {
|
const handleDateTimeChange = useCallback((newDate: Date | null) => {
|
||||||
@@ -207,7 +207,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
}, newInterval);
|
}, newInterval);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[isPlaying],
|
[isPlaying, maxTime, minTime, setCurrentYear],
|
||||||
);
|
);
|
||||||
|
|
||||||
// 组件加载时设置初始时间为当前时间的最近15分钟
|
// 组件加载时设置初始时间为当前时间的最近15分钟
|
||||||
@@ -372,7 +372,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
if (predictionResults.length > 0 && pipeLayer) {
|
if (predictionResults.length > 0 && pipeLayer) {
|
||||||
applyPipeHealthStyle();
|
applyPipeHealthStyle();
|
||||||
}
|
}
|
||||||
}, [applyPipeHealthStyle]);
|
}, [applyPipeHealthStyle, pipeLayer, predictionResults.length]);
|
||||||
|
|
||||||
// 这里防止地图缩放时,瓦片重新加载引起的属性更新出错
|
// 这里防止地图缩放时,瓦片重新加载引起的属性更新出错
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
|
|||||||
source.addFeature(feature);
|
source.addFeature(feature);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [highlightFeatures]);
|
}, [highlightFeatures, highlightLayer]);
|
||||||
|
|
||||||
// 查询方案
|
// 查询方案
|
||||||
const handleQuery = async () => {
|
const handleQuery = async () => {
|
||||||
|
|||||||
@@ -416,6 +416,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
|
|||||||
|
|
||||||
const hasDevices = deviceIds.length > 0;
|
const hasDevices = deviceIds.length > 0;
|
||||||
const hasData = timeSeries.length > 0;
|
const hasData = timeSeries.length > 0;
|
||||||
|
const deviceIdsKey = useMemo(() => deviceIds.join(","), [deviceIds]);
|
||||||
|
|
||||||
const dataset = useMemo(
|
const dataset = useMemo(
|
||||||
() => buildDataset(timeSeries, deviceIds, fractionDigits, showCleaning),
|
() => buildDataset(timeSeries, deviceIds, fractionDigits, showCleaning),
|
||||||
@@ -528,7 +529,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
|
|||||||
} else {
|
} else {
|
||||||
setTimeSeries([]);
|
setTimeSeries([]);
|
||||||
}
|
}
|
||||||
}, [deviceIds.join(",")]);
|
}, [deviceIdsKey, handleFetch, hasDevices]);
|
||||||
|
|
||||||
// 当设备数量变化时,调整数据源选择
|
// 当设备数量变化时,调整数据源选择
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -741,7 +741,7 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
|
|||||||
source.addFeature(feature);
|
source.addFeature(feature);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [selectedDeviceIds, highlightFeatures]);
|
}, [selectedDeviceIds, highlightFeatures, highlightLayer]);
|
||||||
// 清理定时器
|
// 清理定时器
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
import Image from "next/image";
|
||||||
import { useMap } from "../MapComponent";
|
import { useMap } from "../MapComponent";
|
||||||
import TileLayer from "ol/layer/Tile.js";
|
import TileLayer from "ol/layer/Tile.js";
|
||||||
import XYZ from "ol/source/XYZ.js";
|
import XYZ from "ol/source/XYZ.js";
|
||||||
@@ -136,7 +137,7 @@ const BaseLayers: React.FC = () => {
|
|||||||
}
|
}
|
||||||
layerInfo.layer.setVisible(layerInfo.id === activeId);
|
layerInfo.layer.setVisible(layerInfo.id === activeId);
|
||||||
});
|
});
|
||||||
}, [map]);
|
}, [map, activeId]);
|
||||||
|
|
||||||
const changeMapLayers = (id: string) => {
|
const changeMapLayers = (id: string) => {
|
||||||
if (map) {
|
if (map) {
|
||||||
@@ -187,7 +188,7 @@ const BaseLayers: React.FC = () => {
|
|||||||
>
|
>
|
||||||
<div className="w-20 h-20 p-1">
|
<div className="w-20 h-20 p-1">
|
||||||
<button onClick={() => handleQuickSwitch()}>
|
<button onClick={() => handleQuickSwitch()}>
|
||||||
<img
|
<Image
|
||||||
width={240}
|
width={240}
|
||||||
height={100}
|
height={100}
|
||||||
src={
|
src={
|
||||||
@@ -200,6 +201,7 @@ const BaseLayers: React.FC = () => {
|
|||||||
? baseLayers[1].name
|
? baseLayers[1].name
|
||||||
: baseLayers[0].name
|
: baseLayers[0].name
|
||||||
}
|
}
|
||||||
|
sizes="72px"
|
||||||
className="object-cover object-left w-18 h-18 rounded-xl"
|
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">
|
<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"
|
className="flex flex-auto flex-col justify-center items-center text-gray-500 text-xs"
|
||||||
onClick={() => handleMapLayers(item.id)}
|
onClick={() => handleMapLayers(item.id)}
|
||||||
>
|
>
|
||||||
<img
|
<Image
|
||||||
width={240}
|
width={240}
|
||||||
height={100}
|
height={100}
|
||||||
src={item.img}
|
src={item.img}
|
||||||
alt={item.name}
|
alt={item.name}
|
||||||
|
sizes="64px"
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"object-cover object-left w-16 h-16 rounded-md border-2 border-white hover:ring-2 ring-blue-300",
|
"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 hasDevices = deviceIds.length > 0;
|
||||||
const hasData = timeSeries.length > 0;
|
const hasData = timeSeries.length > 0;
|
||||||
|
const featureInfosKey = useMemo(
|
||||||
|
() => JSON.stringify(featureInfos),
|
||||||
|
[featureInfos]
|
||||||
|
);
|
||||||
|
|
||||||
const dataset = useMemo(
|
const dataset = useMemo(
|
||||||
() => buildDataset(timeSeries, deviceIds, fractionDigits),
|
() => buildDataset(timeSeries, deviceIds, fractionDigits),
|
||||||
@@ -468,7 +472,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
|
|||||||
} else {
|
} else {
|
||||||
setTimeSeries([]);
|
setTimeSeries([]);
|
||||||
}
|
}
|
||||||
}, [JSON.stringify(featureInfos)]);
|
}, [featureInfosKey, handleFetch, hasDevices]);
|
||||||
|
|
||||||
// 当设备数量变化时,调整数据源选择
|
// 当设备数量变化时,调整数据源选择
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -15,6 +15,18 @@ interface LayerItem {
|
|||||||
layerRef: any; // OpenLayers Layer 实例或 deck.gl layer 对象
|
layerRef: any; // OpenLayers Layer 实例或 deck.gl layer 对象
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LAYER_ORDER = [
|
||||||
|
"junctions",
|
||||||
|
"reservoirs",
|
||||||
|
"tanks",
|
||||||
|
"pipes",
|
||||||
|
"pumps",
|
||||||
|
"valves",
|
||||||
|
"scada",
|
||||||
|
"waterflowLayer",
|
||||||
|
"junctionContourLayer",
|
||||||
|
];
|
||||||
|
|
||||||
const LayerControl: React.FC = () => {
|
const LayerControl: React.FC = () => {
|
||||||
const map = useMap();
|
const map = useMap();
|
||||||
const data = useData();
|
const data = useData();
|
||||||
@@ -25,19 +37,9 @@ const LayerControl: React.FC = () => {
|
|||||||
const setShowWaterflowLayer = data?.setShowWaterflowLayer;
|
const setShowWaterflowLayer = data?.setShowWaterflowLayer;
|
||||||
const setShowContourLayer = data?.setShowContourLayer;
|
const setShowContourLayer = data?.setShowContourLayer;
|
||||||
|
|
||||||
const layerOrder = [
|
|
||||||
"junctions",
|
|
||||||
"reservoirs",
|
|
||||||
"tanks",
|
|
||||||
"pipes",
|
|
||||||
"pumps",
|
|
||||||
"valves",
|
|
||||||
"scada",
|
|
||||||
"waterflowLayer",
|
|
||||||
"junctionContourLayer",
|
|
||||||
];
|
|
||||||
|
|
||||||
const layerItems = useMemo(() => {
|
const layerItems = useMemo(() => {
|
||||||
|
void refreshKey;
|
||||||
|
|
||||||
if (!map || !data) return [];
|
if (!map || !data) return [];
|
||||||
|
|
||||||
const items: LayerItem[] = [];
|
const items: LayerItem[] = [];
|
||||||
@@ -87,8 +89,8 @@ const LayerControl: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return items
|
return items
|
||||||
.filter((item) => layerOrder.includes(item.id))
|
.filter((item) => LAYER_ORDER.includes(item.id))
|
||||||
.sort((a, b) => layerOrder.indexOf(a.id) - layerOrder.indexOf(b.id));
|
.sort((a, b) => LAYER_ORDER.indexOf(a.id) - LAYER_ORDER.indexOf(b.id));
|
||||||
}, [
|
}, [
|
||||||
map,
|
map,
|
||||||
data,
|
data,
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
|||||||
}
|
}
|
||||||
return colors;
|
return colors;
|
||||||
},
|
},
|
||||||
[styleConfig.gradientPaletteIndex, parseColor]
|
[styleConfig.gradientPaletteIndex]
|
||||||
);
|
);
|
||||||
|
|
||||||
// 根据分段数生成彩虹色
|
// 根据分段数生成彩虹色
|
||||||
@@ -1065,6 +1065,8 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
|||||||
if (!applyPipeStyle) {
|
if (!applyPipeStyle) {
|
||||||
removeVectorTileSourceLoadedEvent("pipes");
|
removeVectorTileSourceLoadedEvent("pipes");
|
||||||
}
|
}
|
||||||
|
// This effect is intentionally driven by explicit style triggers and data snapshots.
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [
|
}, [
|
||||||
styleUpdateTrigger,
|
styleUpdateTrigger,
|
||||||
applyJunctionStyle,
|
applyJunctionStyle,
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ interface TimelineProps {
|
|||||||
schemeType?: string;
|
schemeType?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NOOP_SET_CURRENT_TIME = (_: any) => undefined;
|
||||||
|
const NOOP_SET_SELECTED_DATE = (_: any) => undefined;
|
||||||
|
|
||||||
const Timeline: React.FC<TimelineProps> = ({
|
const Timeline: React.FC<TimelineProps> = ({
|
||||||
schemeDate,
|
schemeDate,
|
||||||
timeRange,
|
timeRange,
|
||||||
@@ -47,6 +50,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
schemeType = "burst_Analysis",
|
schemeType = "burst_Analysis",
|
||||||
}) => {
|
}) => {
|
||||||
const data = useData();
|
const data = useData();
|
||||||
|
const fallbackSelectedDateRef = useRef(new Date());
|
||||||
const hasTimelineState =
|
const hasTimelineState =
|
||||||
data &&
|
data &&
|
||||||
data.setCurrentTime !== undefined &&
|
data.setCurrentTime !== undefined &&
|
||||||
@@ -54,9 +58,9 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
data.selectedDate !== undefined &&
|
data.selectedDate !== undefined &&
|
||||||
data.setSelectedDate !== undefined;
|
data.setSelectedDate !== undefined;
|
||||||
const currentTime = data?.currentTime ?? -1;
|
const currentTime = data?.currentTime ?? -1;
|
||||||
const setCurrentTime = data?.setCurrentTime ?? ((_: any) => undefined);
|
const setCurrentTime = data?.setCurrentTime ?? NOOP_SET_CURRENT_TIME;
|
||||||
const selectedDate = data?.selectedDate ?? new Date();
|
const selectedDate = data?.selectedDate ?? fallbackSelectedDateRef.current;
|
||||||
const setSelectedDate = data?.setSelectedDate ?? ((_: any) => undefined);
|
const setSelectedDate = data?.setSelectedDate ?? NOOP_SET_SELECTED_DATE;
|
||||||
const setCurrentJunctionCalData = data?.setCurrentJunctionCalData;
|
const setCurrentJunctionCalData = data?.setCurrentJunctionCalData;
|
||||||
const setCurrentPipeCalData = data?.setCurrentPipeCalData;
|
const setCurrentPipeCalData = data?.setCurrentPipeCalData;
|
||||||
const junctionText = data?.junctionText ?? "";
|
const junctionText = data?.junctionText ?? "";
|
||||||
@@ -78,7 +82,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
if (schemeDate) {
|
if (schemeDate) {
|
||||||
setSelectedDate(schemeDate);
|
setSelectedDate(schemeDate);
|
||||||
}
|
}
|
||||||
}, [schemeDate]);
|
}, [schemeDate, setSelectedDate]);
|
||||||
// 新增:用于 Draggable 的 nodeRef
|
// 新增:用于 Draggable 的 nodeRef
|
||||||
const draggableRef = useRef<HTMLDivElement>(null);
|
const draggableRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
@@ -90,7 +94,20 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
// 添加防抖引用
|
// 添加防抖引用
|
||||||
const debounceRef = useRef<NodeJS.Timeout | null>(null);
|
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,
|
queryTime: Date,
|
||||||
junctionProperties: string,
|
junctionProperties: string,
|
||||||
pipeProperties: string,
|
pipeProperties: string,
|
||||||
@@ -170,21 +187,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
}
|
}
|
||||||
// 更新状态
|
// 更新状态
|
||||||
updateDataStates(nodeRecords.results || [], linkRecords.results || []);
|
updateDataStates(nodeRecords.results || [], linkRecords.results || []);
|
||||||
};
|
}, [disableDateSelection, updateDataStates]);
|
||||||
|
|
||||||
// 提取更新状态的逻辑
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 时间刻度数组 (每5分钟一个刻度)
|
// 时间刻度数组 (每5分钟一个刻度)
|
||||||
const timeMarks = Array.from({ length: 288 }, (_, i) => ({
|
const timeMarks = Array.from({ length: 288 }, (_, i) => ({
|
||||||
@@ -241,7 +244,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
setCurrentTime(value);
|
setCurrentTime(value);
|
||||||
}, 500); // 500ms 防抖延迟
|
}, 500); // 500ms 防抖延迟
|
||||||
},
|
},
|
||||||
[timeRange, minTime, maxTime],
|
[timeRange, minTime, maxTime, setCurrentTime],
|
||||||
);
|
);
|
||||||
|
|
||||||
// 播放控制
|
// 播放控制
|
||||||
@@ -268,7 +271,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
});
|
});
|
||||||
}, playInterval);
|
}, playInterval);
|
||||||
}
|
}
|
||||||
}, [isPlaying, playInterval]);
|
}, [isPlaying, playInterval, timeRange, maxTime, minTime, setCurrentTime]);
|
||||||
|
|
||||||
const handlePause = useCallback(() => {
|
const handlePause = useCallback(() => {
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
@@ -288,7 +291,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
clearInterval(intervalRef.current);
|
clearInterval(intervalRef.current);
|
||||||
intervalRef.current = null;
|
intervalRef.current = null;
|
||||||
}
|
}
|
||||||
}, []);
|
}, [setCurrentTime]);
|
||||||
|
|
||||||
// 步进控制
|
// 步进控制
|
||||||
const handleDayStepBackward = useCallback(() => {
|
const handleDayStepBackward = useCallback(() => {
|
||||||
@@ -297,14 +300,14 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
newDate.setDate(newDate.getDate() - 1);
|
newDate.setDate(newDate.getDate() - 1);
|
||||||
return newDate;
|
return newDate;
|
||||||
});
|
});
|
||||||
}, []);
|
}, [setSelectedDate]);
|
||||||
const handleDayStepForward = useCallback(() => {
|
const handleDayStepForward = useCallback(() => {
|
||||||
setSelectedDate((prev) => {
|
setSelectedDate((prev) => {
|
||||||
const newDate = new Date(prev);
|
const newDate = new Date(prev);
|
||||||
newDate.setDate(newDate.getDate() + 1);
|
newDate.setDate(newDate.getDate() + 1);
|
||||||
return newDate;
|
return newDate;
|
||||||
});
|
});
|
||||||
}, []);
|
}, [setSelectedDate]);
|
||||||
const handleStepBackward = useCallback(() => {
|
const handleStepBackward = useCallback(() => {
|
||||||
setCurrentTime((prev) => {
|
setCurrentTime((prev) => {
|
||||||
let next = prev - 15;
|
let next = prev - 15;
|
||||||
@@ -315,7 +318,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
}
|
}
|
||||||
return next;
|
return next;
|
||||||
});
|
});
|
||||||
}, [timeRange, minTime, maxTime]);
|
}, [timeRange, minTime, maxTime, setCurrentTime]);
|
||||||
|
|
||||||
const handleStepForward = useCallback(() => {
|
const handleStepForward = useCallback(() => {
|
||||||
setCurrentTime((prev) => {
|
setCurrentTime((prev) => {
|
||||||
@@ -327,14 +330,14 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
}
|
}
|
||||||
return next;
|
return next;
|
||||||
});
|
});
|
||||||
}, [timeRange, minTime, maxTime]);
|
}, [timeRange, minTime, maxTime, setCurrentTime]);
|
||||||
|
|
||||||
// 日期选择处理
|
// 日期选择处理
|
||||||
const handleDateChange = useCallback((newDate: Date | null) => {
|
const handleDateChange = useCallback((newDate: Date | null) => {
|
||||||
if (newDate) {
|
if (newDate) {
|
||||||
setSelectedDate(newDate);
|
setSelectedDate(newDate);
|
||||||
}
|
}
|
||||||
}, []);
|
}, [setSelectedDate]);
|
||||||
|
|
||||||
// 播放间隔改变处理
|
// 播放间隔改变处理
|
||||||
const handleIntervalChange = useCallback(
|
const handleIntervalChange = useCallback(
|
||||||
@@ -358,7 +361,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
}, newInterval);
|
}, newInterval);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[isPlaying],
|
[isPlaying, timeRange, maxTime, minTime, setCurrentTime],
|
||||||
);
|
);
|
||||||
// 计算时间段改变处理
|
// 计算时间段改变处理
|
||||||
const handleCalculatedIntervalChange = useCallback((event: any) => {
|
const handleCalculatedIntervalChange = useCallback((event: any) => {
|
||||||
@@ -389,6 +392,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
|
fetchFrameData,
|
||||||
junctionText,
|
junctionText,
|
||||||
pipeText,
|
pipeText,
|
||||||
currentTime,
|
currentTime,
|
||||||
@@ -414,14 +418,14 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
clearTimeout(debounceRef.current);
|
clearTimeout(debounceRef.current);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, []);
|
}, [setCurrentTime]);
|
||||||
|
|
||||||
// 当 timeRange 改变时,设置 currentTime 到 minTime
|
// 当 timeRange 改变时,设置 currentTime 到 minTime
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (timeRange) {
|
if (timeRange) {
|
||||||
setCurrentTime(minTime);
|
setCurrentTime(minTime);
|
||||||
}
|
}
|
||||||
}, [timeRange, minTime]);
|
}, [timeRange, minTime, setCurrentTime]);
|
||||||
// 获取地图实例
|
// 获取地图实例
|
||||||
const map = useMap();
|
const map = useMap();
|
||||||
// 这里防止地图缩放时,瓦片重新加载引起的属性更新出错
|
// 这里防止地图缩放时,瓦片重新加载引起的属性更新出错
|
||||||
|
|||||||
@@ -409,8 +409,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
|
|||||||
setComputedProperties({});
|
setComputedProperties({});
|
||||||
} else {
|
} else {
|
||||||
setComputedProperties(data.result[0] || {});
|
setComputedProperties(data.result[0] || {});
|
||||||
console.log("查询到的计算属性:", data.result[0]);
|
// console.log("查询到的计算属性:", data.result[0]);
|
||||||
console.log(computedProperties);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error querying computed properties:", error);
|
console.error("Error querying computed properties:", error);
|
||||||
@@ -419,7 +418,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
|
|||||||
};
|
};
|
||||||
// 仅当 currentTime 有效时查询
|
// 仅当 currentTime 有效时查询
|
||||||
if (currentTime !== -1 && queryType) queryComputedProperties();
|
if (currentTime !== -1 && queryType) queryComputedProperties();
|
||||||
}, [highlightFeatures, currentTime, selectedDate, queryType, schemeName, schemeType]);
|
}, [highlightFeatures, currentTime, selectedDate, queryType, schemeName, schemeType, showPropertyPanel]);
|
||||||
|
|
||||||
// 从要素属性中提取属性面板需要的数据
|
// 从要素属性中提取属性面板需要的数据
|
||||||
const getFeatureProperties = useCallback(() => {
|
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(() => {
|
useEffect(() => {
|
||||||
if (!mapRef.current) return;
|
if (!mapRef.current) return;
|
||||||
// 缓存 junction、pipe 数据,提供给 deck.gl 提供坐标供标签显示
|
// 缓存 junction、pipe 数据,提供给 deck.gl 提供坐标供标签显示
|
||||||
@@ -807,6 +808,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
map.dispose();
|
map.dispose();
|
||||||
deck.finalize();
|
deck.finalize();
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [MAP_WORKSPACE, MAP_EXTENT]);
|
}, [MAP_WORKSPACE, MAP_EXTENT]);
|
||||||
|
|
||||||
// 当数据变化时,更新 deck.gl 图层
|
// 当数据变化时,更新 deck.gl 图层
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import React, { createContext, useContext, useEffect, useState } from "react";
|
import React, { createContext, useCallback, useContext, useEffect, useState } from "react";
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import { config, NETWORK_NAME, setMapWorkspace, setNetworkName, setMapExtent } from "@/config/config";
|
import { config, NETWORK_NAME, setMapWorkspace, setNetworkName, setMapExtent } from "@/config/config";
|
||||||
import { ProjectSelector } from "@/components/project/ProjectSelector";
|
import { ProjectSelector } from "@/components/project/ProjectSelector";
|
||||||
@@ -28,25 +28,7 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
extent: config.MAP_EXTENT,
|
extent: config.MAP_EXTENT,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
const applyConfig = useCallback(async (
|
||||||
// Check localStorage
|
|
||||||
const savedWorkspace = localStorage.getItem("NEXT_PUBLIC_MAP_WORKSPACE");
|
|
||||||
const savedNetwork = localStorage.getItem("NEXT_PUBLIC_NETWORK_NAME");
|
|
||||||
const savedExtent = localStorage.getItem("NEXT_PUBLIC_MAP_EXTENT");
|
|
||||||
const savedProjectId = localStorage.getItem("active_project");
|
|
||||||
|
|
||||||
// If we have saved config, use it.
|
|
||||||
if (savedWorkspace && savedNetwork) {
|
|
||||||
applyConfig(
|
|
||||||
savedProjectId || savedNetwork || savedWorkspace,
|
|
||||||
savedWorkspace,
|
|
||||||
savedNetwork,
|
|
||||||
savedExtent ? savedExtent.split(",").map(Number) : config.MAP_EXTENT,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const applyConfig = async (
|
|
||||||
projectId: string,
|
projectId: string,
|
||||||
ws: string,
|
ws: string,
|
||||||
net: string,
|
net: string,
|
||||||
@@ -91,7 +73,25 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to open project:", error);
|
console.error("Failed to open project:", error);
|
||||||
}
|
}
|
||||||
};
|
}, [setCurrentProjectId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Check localStorage
|
||||||
|
const savedWorkspace = localStorage.getItem("NEXT_PUBLIC_MAP_WORKSPACE");
|
||||||
|
const savedNetwork = localStorage.getItem("NEXT_PUBLIC_NETWORK_NAME");
|
||||||
|
const savedExtent = localStorage.getItem("NEXT_PUBLIC_MAP_EXTENT");
|
||||||
|
const savedProjectId = localStorage.getItem("active_project");
|
||||||
|
|
||||||
|
// If we have saved config, use it.
|
||||||
|
if (savedWorkspace && savedNetwork) {
|
||||||
|
applyConfig(
|
||||||
|
savedProjectId || savedNetwork || savedWorkspace,
|
||||||
|
savedWorkspace,
|
||||||
|
savedNetwork,
|
||||||
|
savedExtent ? savedExtent.split(",").map(Number) : config.MAP_EXTENT,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [applyConfig]);
|
||||||
|
|
||||||
// Only show selector if authenticated and not configured
|
// Only show selector if authenticated and not configured
|
||||||
if (status === "authenticated" && !isConfigured) {
|
if (status === "authenticated" && !isConfigured) {
|
||||||
|
|||||||
Reference in New Issue
Block a user