diff --git a/src/app/(main)/risk-analysis-location/loading.tsx b/src/app/(main)/hydraulic-simulation/pipe-burst-analysis/loading.tsx
similarity index 100%
rename from src/app/(main)/risk-analysis-location/loading.tsx
rename to src/app/(main)/hydraulic-simulation/pipe-burst-analysis/loading.tsx
diff --git a/src/app/(main)/risk-analysis-location/page.tsx b/src/app/(main)/hydraulic-simulation/pipe-burst-analysis/page.tsx
similarity index 100%
rename from src/app/(main)/risk-analysis-location/page.tsx
rename to src/app/(main)/hydraulic-simulation/pipe-burst-analysis/page.tsx
diff --git a/src/app/(main)/hydraulic-simulation/pipe-flushing/loading.tsx b/src/app/(main)/hydraulic-simulation/pipe-flushing/loading.tsx
new file mode 100644
index 0000000..2c57921
--- /dev/null
+++ b/src/app/(main)/hydraulic-simulation/pipe-flushing/loading.tsx
@@ -0,0 +1,5 @@
+import { MapSkeleton } from "@components/loading/MapSkeleton";
+
+export default function Loading() {
+ return ;
+}
diff --git a/src/app/(main)/hydraulic-simulation/water-quality-simulation/page.tsx b/src/app/(main)/hydraulic-simulation/water-quality-simulation/page.tsx
new file mode 100644
index 0000000..a3133fb
--- /dev/null
+++ b/src/app/(main)/hydraulic-simulation/water-quality-simulation/page.tsx
@@ -0,0 +1,16 @@
+"use client";
+
+import MapComponent from "@app/OlMap/MapComponent";
+import MapToolbar from "@app/OlMap/Controls/Toolbar";
+import WaterQualityPanel from "@/components/olmap/ContaminantSimulation/WaterQualityPanel";
+
+export default function Home() {
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/_refine_context.tsx b/src/app/_refine_context.tsx
index 1ac8bf6..d5366d1 100644
--- a/src/app/_refine_context.tsx
+++ b/src/app/_refine_context.tsx
@@ -21,6 +21,7 @@ import { LuReplace } from "react-icons/lu";
import { AiOutlineSecurityScan } from "react-icons/ai";
import { TbLocationPin } from "react-icons/tb";
import { AiOutlinePartition } from "react-icons/ai";
+import { MdWater, MdOutlineWaterDrop, MdCleaningServices } from "react-icons/md";
type RefineContextProps = {
defaultMode?: string;
@@ -154,11 +155,37 @@ const App = (props: React.PropsWithChildren) => {
},
},
{
- name: "风险分析定位",
- list: "/risk-analysis-location",
+ name: "Hydraulic Simulation",
meta: {
+ icon: ,
+ label: "水力仿真",
+ },
+ },
+ {
+ name: "爆管分析定位",
+ list: "/hydraulic-simulation/pipe-burst-analysis",
+ meta: {
+ parent: "Hydraulic Simulation",
icon: ,
- label: "风险分析定位",
+ label: "爆管分析定位",
+ },
+ },
+ {
+ name: "水质模拟",
+ list: "/hydraulic-simulation/water-quality-simulation",
+ meta: {
+ parent: "Hydraulic Simulation",
+ icon: ,
+ label: "水质模拟",
+ },
+ },
+ {
+ name: "管道冲洗",
+ list: "/hydraulic-simulation/pipe-flushing",
+ meta: {
+ parent: "Hydraulic Simulation",
+ icon: ,
+ label: "管道冲洗",
},
},
{
diff --git a/src/components/loading/MapSkeleton.tsx b/src/components/loading/MapSkeleton.tsx
index 6cb2bb8..755d1ca 100644
--- a/src/components/loading/MapSkeleton.tsx
+++ b/src/components/loading/MapSkeleton.tsx
@@ -1,4 +1,4 @@
-import { Box, Skeleton } from "@mui/material";
+import { Box, Skeleton, CircularProgress } from "@mui/material";
/**
* 地图页面骨架屏组件
@@ -26,7 +26,24 @@ export function MapSkeleton() {
}}
/>
- {/* 左侧工具栏骨架 */}
+ {/* 中央加载指示器 */}
+
+
+
+
+ {/* 左侧工具栏骨架 (垂直) */}
- {[1, 2, 3, 4, 5].map((i) => (
+ {[1, 2, 3, 4].map((i) => (
))}
- {/* 右侧控制面板骨架 */}
+ {/* 右侧控制面板骨架 (抽屉式) */}
-
-
-
-
-
+
+
+ {/* 面板内容区块 */}
+
+
+
+
+
+
+ {[1, 2, 3].map((i) => (
+
+
+
+
+
+
+
+ ))}
+
+
- {/* 底部时间轴骨架 */}
+ {/* 底部时间轴/控制条骨架 */}
-
+
+
+
- {/* 缩放控制骨架 */}
+ {/* 缩放控制骨架 (右下) */}
-
-
-
-
- {/* 比例尺骨架 */}
-
-
+
+
);
diff --git a/src/components/olmap/BurstPipeAnalysis/BurstPipeAnalysisPanel.tsx b/src/components/olmap/BurstPipeAnalysis/BurstPipeAnalysisPanel.tsx
index 4b00334..6d204cc 100644
--- a/src/components/olmap/BurstPipeAnalysis/BurstPipeAnalysisPanel.tsx
+++ b/src/components/olmap/BurstPipeAnalysis/BurstPipeAnalysisPanel.tsx
@@ -22,13 +22,9 @@ import AnalysisParameters from "./AnalysisParameters";
import SchemeQuery from "./SchemeQuery";
import LocationResults from "./LocationResults";
import ValveIsolation from "./ValveIsolation";
-import ContaminantAnalysisParameters from "../ContaminantSimulation/AnalysisParameters";
-import ContaminantSchemeQuery from "../ContaminantSimulation/SchemeQuery";
-import ContaminantResultsPanel from "../ContaminantSimulation/ResultsPanel";
import axios from "axios";
import { config } from "@config/config";
import { useNotification } from "@refinedev/core";
-import { useData } from "@app/OlMap/MapComponent";
import { LocationResult, SchemeRecord, ValveIsolationResult } from "./types";
interface TabPanelProps {
@@ -56,17 +52,12 @@ interface BurstPipeAnalysisPanelProps {
onToggle?: () => void;
}
-type PanelMode = "burst" | "contaminant";
-
const BurstPipeAnalysisPanel: React.FC = ({
open: controlledOpen,
onToggle,
}) => {
const [internalOpen, setInternalOpen] = useState(true);
const [currentTab, setCurrentTab] = useState(0);
- const [panelMode, setPanelMode] = useState("burst");
-
- const data = useData();
// 持久化方案查询结果
const [schemes, setSchemes] = useState([]);
@@ -92,16 +83,6 @@ const BurstPipeAnalysisPanel: React.FC = ({
setCurrentTab(newValue);
};
- const handleModeChange = (_event: React.SyntheticEvent, newMode: PanelMode) => {
- setPanelMode(newMode);
- // 切换模式时,如果当前标签索引超出新模式的标签数量,重置为第一个标签
- // 爆管分析有4个标签(0-3),水质模拟有3个标签(0-2)
- const maxTabIndex = newMode === "burst" ? 3 : 2;
- if (currentTab > maxTabIndex) {
- setCurrentTab(0);
- }
- };
-
const handleLocateScheme = async (scheme: SchemeRecord) => {
try {
const response = await axios.get(
@@ -120,8 +101,7 @@ const BurstPipeAnalysisPanel: React.FC = ({
};
const drawerWidth = 520;
- const isBurstMode = panelMode === "burst";
- const panelTitle = isBurstMode ? "爆管分析" : "水质模拟";
+ const panelTitle = "爆管分析";
return (
<>
@@ -197,32 +177,6 @@ const BurstPipeAnalysisPanel: React.FC = ({
- {/* Tabs 导航 */}
-
-
-
-
-
-
= ({
}
iconPosition="start"
- label={isBurstMode ? "定位结果" : "模拟结果"}
+ label="定位结果"
+ />
+ }
+ iconPosition="start"
+ label="关阀分析"
/>
- {isBurstMode && (
- }
- iconPosition="start"
- label="关阀分析"
- />
- )}
{/* Tab 内容 */}
- {isBurstMode ? (
-
- ) : (
-
- )}
+
- {isBurstMode ? (
-
- ) : (
- setCurrentTab(2)} />
- )}
+
- {isBurstMode ? (
-
- ) : (
-
- )}
+
- {isBurstMode && (
-
-
-
- )}
+
+
+
>
diff --git a/src/components/olmap/ContaminantSimulation/WaterQualityPanel.tsx b/src/components/olmap/ContaminantSimulation/WaterQualityPanel.tsx
new file mode 100644
index 0000000..9450e9f
--- /dev/null
+++ b/src/components/olmap/ContaminantSimulation/WaterQualityPanel.tsx
@@ -0,0 +1,208 @@
+"use client";
+
+import React, { useState } from "react";
+import {
+ Box,
+ Drawer,
+ Tabs,
+ Tab,
+ Typography,
+ IconButton,
+ Tooltip,
+} from "@mui/material";
+import {
+ ChevronRight,
+ ChevronLeft,
+ Analytics as AnalyticsIcon,
+ Search as SearchIcon,
+ MyLocation as MyLocationIcon,
+} from "@mui/icons-material";
+import ContaminantAnalysisParameters from "./AnalysisParameters";
+import ContaminantSchemeQuery from "./SchemeQuery";
+import ContaminantResultsPanel from "./ResultsPanel";
+import { useData } from "@app/OlMap/MapComponent";
+
+interface WaterQualityPanelProps {
+ open?: boolean;
+ onToggle?: () => void;
+}
+
+const WaterQualityPanel: React.FC = ({
+ open: controlledOpen,
+ onToggle,
+}) => {
+ const [internalOpen, setInternalOpen] = useState(true);
+ const [currentTab, setCurrentTab] = useState(0);
+
+ const data = useData();
+
+ // 使用受控或非受控状态
+ const isOpen = controlledOpen !== undefined ? controlledOpen : internalOpen;
+ const handleToggle = () => {
+ if (onToggle) {
+ onToggle();
+ } else {
+ setInternalOpen(!internalOpen);
+ }
+ };
+
+ const handleTabChange = (_event: React.SyntheticEvent, newValue: number) => {
+ setCurrentTab(newValue);
+ };
+
+ const drawerWidth = 520;
+ const panelTitle = "水质模拟";
+
+ return (
+ <>
+ {/* 收起时的触发按钮 */}
+ {!isOpen && (
+
+
+
+
+ {panelTitle}
+
+
+
+
+ )}
+
+ {/* 主面板 */}
+
+
+ {/* 头部 */}
+
+
+
+
+ {panelTitle}
+
+
+
+
+
+
+
+
+
+
+
+ }
+ iconPosition="start"
+ label="分析要件"
+ />
+ }
+ iconPosition="start"
+ label="方案查询"
+ />
+ {/* }
+ iconPosition="start"
+ label="模拟结果"
+ /> */}
+
+
+
+ {/* Tab 内容 */}
+
+
+
+
+
+ setCurrentTab(2)} />
+
+
+
+
+
+
+
+ >
+ );
+};
+
+interface TabPanelProps {
+ children?: React.ReactNode;
+ index: number;
+ value: number;
+}
+
+const TabPanel: React.FC = ({ children, value, index }) => {
+ return (
+
+ {value === index && (
+ {children}
+ )}
+
+ );
+};
+
+export default WaterQualityPanel;