重新设计弹出组件的层次布局,非常驻窗口将置于顶部;新增变量控制水流图层的显示;完善历史数据面板的设计

This commit is contained in:
JIANG
2025-12-16 16:08:29 +08:00
parent 715ec9ead0
commit 3aa68d796b
10 changed files with 53 additions and 78 deletions

View File

@@ -179,7 +179,7 @@ const BaseLayers: React.FC = () => {
}; };
return ( return (
<div className="absolute right-17 bottom-8 z-99"> <div className="absolute right-17 bottom-8 z-1300">
<div <div
className="w-20 h-20 bg-white rounded-xl drop-shadow-xl shadow-black" className="w-20 h-20 bg-white rounded-xl drop-shadow-xl shadow-black"
onMouseEnter={handleEnter} onMouseEnter={handleEnter}

View File

@@ -306,7 +306,7 @@ const DrawPanel: React.FC = () => {
const isSaveDisabled = drawnFeatures.length === 0; const isSaveDisabled = drawnFeatures.length === 0;
return ( return (
<div className="absolute top-20 left-4 bg-white p-1 rounded-xl shadow-lg flex flex-col opacity-85 hover:opacity-100 transition-opacity z-10"> <div className="absolute top-20 left-4 bg-white p-1 rounded-xl shadow-lg flex flex-col opacity-85 hover:opacity-100 transition-opacity z-1300">
<div className="flex"> <div className="flex">
<ToolbarButton <ToolbarButton
icon={<BackHandOutlinedIcon />} icon={<BackHandOutlinedIcon />}

View File

@@ -12,7 +12,6 @@ import {
Tabs, Tabs,
Tooltip, Tooltip,
Typography, Typography,
Drawer,
} from "@mui/material"; } from "@mui/material";
import { Refresh, ShowChart, TableChart } from "@mui/icons-material"; import { Refresh, ShowChart, TableChart } from "@mui/icons-material";
import { DataGrid, GridColDef } from "@mui/x-data-grid"; import { DataGrid, GridColDef } from "@mui/x-data-grid";
@@ -649,34 +648,38 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
return ( return (
<> <>
{/* 主面板 */} {/* 主面板 */}
<Drawer <Box
anchor="right"
variant="persistent"
hideBackdrop
sx={{ sx={{
width: 0, position: "fixed",
flexShrink: 0, left: "50%",
"& .MuiDrawer-paper": { top: "50%",
width: "min(920px, calc(100vw - 2rem))", transform: "translate(-50%, -50%)",
boxSizing: "border-box", width: "min(920px, calc(100vw - 2rem))",
position: "absolute", maxWidth: "100vw",
top: 80, height: "860px",
right: 16, maxHeight: "calc(100vh - 2rem)",
height: "860px", boxSizing: "border-box",
borderRadius: "12px", borderRadius: "12px",
boxShadow: boxShadow:
"0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)", "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
backdropFilter: "blur(8px)", backdropFilter: "blur(8px)",
opacity: 0.95, opacity: 0.95,
transition: "transform 0.3s ease-in-out, opacity 0.3s ease-in-out", transition: "opacity 0.3s ease-in-out",
border: "none", border: "none",
"&:hover": { display: "flex",
opacity: 1, flexDirection: "column",
}, zIndex: 1300,
backgroundColor: "white",
overflow: "hidden",
"&:hover": {
opacity: 1,
}, },
}} }}
> >
<Box className="flex flex-col h-full bg-white rounded-xl overflow-hidden"> <Box
className="flex flex-col h-full rounded-xl"
sx={{ height: "100%", width: "100%" }}
>
{/* Header */} {/* Header */}
<Box <Box
sx={{ sx={{
@@ -852,7 +855,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
{activeTab === "chart" ? renderChart() : renderTable()} {activeTab === "chart" ? renderChart() : renderTable()}
</Box> </Box>
</Box> </Box>
</Drawer> </Box>
</> </>
); );
}; };

View File

@@ -24,8 +24,8 @@ const LayerControl: React.FC = () => {
deckLayer, deckLayer,
isContourLayerAvailable, isContourLayerAvailable,
isWaterflowLayerAvailable, isWaterflowLayerAvailable,
setShowWaterflowLayer,
setShowContourLayer, setShowContourLayer,
flowAnimation,
} = data; } = data;
const [layerItems, setLayerItems] = useState<LayerItem[]>([]); const [layerItems, setLayerItems] = useState<LayerItem[]>([]);
@@ -142,7 +142,7 @@ const LayerControl: React.FC = () => {
setShowContourLayer && setShowContourLayer(checked); setShowContourLayer && setShowContourLayer(checked);
} }
if (item.id === "waterflowLayer") { if (item.id === "waterflowLayer") {
if (flowAnimation) flowAnimation.current = checked; setShowWaterflowLayer && setShowWaterflowLayer(checked);
} }
} }
@@ -156,7 +156,7 @@ const LayerControl: React.FC = () => {
} }
return ( return (
<div className="absolute left-4 bottom-4 bg-white rounded-md drop-shadow-lg z-10 opacity-85 hover:opacity-100 transition-opacity max-w-xs"> <div className="absolute left-4 bottom-4 bg-white rounded-md drop-shadow-lg z-1300 opacity-85 hover:opacity-100 transition-opacity max-w-xs">
<div className="ml-3 grid grid-cols-3"> <div className="ml-3 grid grid-cols-3">
{layerItems.map((item) => ( {layerItems.map((item) => (
<FormControlLabel <FormControlLabel

View File

@@ -50,7 +50,7 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
: 0; : 0;
return ( return (
<div className="absolute top-4 right-4 bg-white shadow-2xl rounded-xl overflow-hidden w-96 max-h-[850px] flex flex-col backdrop-blur-sm z-50 opacity-95 hover:opacity-100 transition-all duration-300 "> <div className="absolute top-4 right-4 bg-white shadow-2xl rounded-xl overflow-hidden w-96 max-h-[850px] flex flex-col backdrop-blur-sm z-1300 opacity-95 hover:opacity-100 transition-all duration-300 ">
{/* 头部 */} {/* 头部 */}
<div className="flex justify-between items-center px-5 py-4 bg-[#257DD4] text-white"> <div className="flex justify-between items-center px-5 py-4 bg-[#257DD4] text-white">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">

View File

@@ -35,7 +35,7 @@ const Scale: React.FC = () => {
}, [map]); }, [map]);
return ( return (
<div className="absolute bottom-0 right-0 flex col-auto px-2 bg-white bg-opacity-70 text-black rounded-tl shadow-md text-sm"> <div className="absolute bottom-0 right-0 flex col-auto px-2 bg-white bg-opacity-70 text-black rounded-tl shadow-md text-sm z-1300">
<div className="px-1">: {zoomLevel.toFixed(1)}</div> <div className="px-1">: {zoomLevel.toFixed(1)}</div>
<div className="px-1"> <div className="px-1">
: {coordinates[0]}, {coordinates[1]} : {coordinates[0]}, {coordinates[1]}

View File

@@ -1436,7 +1436,7 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
return ( return (
<> <>
<div className="absolute top-20 left-4 bg-white p-4 rounded-xl shadow-lg opacity-95 hover:opacity-100 transition-opacity w-80 z-10"> <div className="absolute top-20 left-4 bg-white p-4 rounded-xl shadow-lg opacity-95 hover:opacity-100 transition-opacity w-80 z-1300">
{/* 图层选择 */} {/* 图层选择 */}
<FormControl variant="standard" fullWidth margin="dense"> <FormControl variant="standard" fullWidth margin="dense">
<InputLabel></InputLabel> <InputLabel></InputLabel>

View File

@@ -7,6 +7,7 @@ import PaletteOutlinedIcon from "@mui/icons-material/PaletteOutlined";
import QueryStatsOutlinedIcon from "@mui/icons-material/QueryStatsOutlined"; import QueryStatsOutlinedIcon from "@mui/icons-material/QueryStatsOutlined";
import PropertyPanel from "./PropertyPanel"; // 引入属性面板组件 import PropertyPanel from "./PropertyPanel"; // 引入属性面板组件
import DrawPanel from "./DrawPanel"; // 引入绘图面板组件 import DrawPanel from "./DrawPanel"; // 引入绘图面板组件
import HistoryDataPanel from "./HistoryDataPanel"; // 引入绘图面板组件
import VectorSource from "ol/source/Vector"; import VectorSource from "ol/source/Vector";
import VectorLayer from "ol/layer/Vector"; import VectorLayer from "ol/layer/Vector";
@@ -39,6 +40,7 @@ const Toolbar: React.FC<ToolbarProps> = ({ hiddenButtons, queryType }) => {
const [showPropertyPanel, setShowPropertyPanel] = useState<boolean>(false); const [showPropertyPanel, setShowPropertyPanel] = useState<boolean>(false);
const [showDrawPanel, setShowDrawPanel] = useState<boolean>(false); const [showDrawPanel, setShowDrawPanel] = useState<boolean>(false);
const [showStyleEditor, setShowStyleEditor] = useState<boolean>(false); const [showStyleEditor, setShowStyleEditor] = useState<boolean>(false);
const [showHistoryPanel, setShowHistoryPanel] = useState<boolean>(false);
const [highlightLayer, setHighlightLayer] = const [highlightLayer, setHighlightLayer] =
useState<VectorLayer<VectorSource> | null>(null); useState<VectorLayer<VectorSource> | null>(null);
@@ -240,7 +242,7 @@ const Toolbar: React.FC<ToolbarProps> = ({ hiddenButtons, queryType }) => {
setShowDrawPanel(false); setShowDrawPanel(false);
break; break;
case "history": case "history":
// 取消历史查询激活时的清理(目前不保留额外状态) setShowHistoryPanel(false);
break; break;
} }
}; };
@@ -255,54 +257,18 @@ const Toolbar: React.FC<ToolbarProps> = ({ hiddenButtons, queryType }) => {
setShowDrawPanel(true); setShowDrawPanel(true);
break; break;
case "history": case "history":
// 激活历史查询后立即触发一次网络历史数据查询(结果暂时打印到控制台) setShowHistoryPanel(true);
queryNetworkHistory(); // 激活历史查询后HistoryDataPanel 自行负责根据传入的 props 拉取数据。
break; break;
} }
}; };
// 查询管网历史数据的函数(激活时调用)
const queryNetworkHistory = async () => {
try {
// 由当前选中日期和 currentTime 构造查询时间UTC ISO
let dateObj: Date;
if (selectedDate instanceof Date) {
dateObj = new Date(selectedDate);
} else {
dateObj = new Date(selectedDate as any);
}
const minutes = Number(currentTime) || 0;
dateObj.setHours(Math.floor(minutes / 60), minutes % 60, 0, 0);
const querytime = dateObj.toISOString();
let url: string;
if (queryType === "scheme") {
url = `${backendUrl}/queryschemesimulationrecordsbytime/?scheme_name=${schemeName}&querytime=${querytime}`;
} else {
url = `${backendUrl}/querysimulationrecordsbytime/?querytime=${querytime}`;
}
const response = await fetch(url);
if (!response.ok) {
console.error("查询管网历史数据失败:", response.statusText);
return;
}
const result = await response.json();
// TODO: 根据需要把结果展示到面板或状态中,目前先打印
console.log("管网历史数据:", result);
// 简单提示用户已查询(可改为更友好的 UI
// eslint-disable-next-line no-alert
alert("已查询管网历史数据(请查看控制台或后续面板展示)。");
} catch (error) {
console.error("查询管网历史数据出错:", error);
}
};
// 关闭所有面板(除了样式编辑器) // 关闭所有面板(除了样式编辑器)
const closeAllPanelsExceptStyle = () => { const closeAllPanelsExceptStyle = () => {
setShowPropertyPanel(false); setShowPropertyPanel(false);
setHighlightFeature(null); setHighlightFeature(null);
setShowDrawPanel(false); setShowDrawPanel(false);
setShowHistoryPanel(false);
// 样式编辑器保持其当前状态,不自动关闭 // 样式编辑器保持其当前状态,不自动关闭
}; };
const [computedProperties, setComputedProperties] = useState< const [computedProperties, setComputedProperties] = useState<
@@ -686,6 +652,7 @@ const Toolbar: React.FC<ToolbarProps> = ({ hiddenButtons, queryType }) => {
setLayerStyleStates={setLayerStyleStates} setLayerStyleStates={setLayerStyleStates}
/> />
)} )}
{showHistoryPanel && <HistoryDataPanel deviceIds={[]} />}
{/* 图例显示 */} {/* 图例显示 */}
{activeLegendConfigs.length > 0 && ( {activeLegendConfigs.length > 0 && (

View File

@@ -30,7 +30,7 @@ const Zoom: React.FC = () => {
}; };
return ( return (
<div className="absolute right-4 bottom-8 z-10"> <div className="absolute right-4 bottom-8 z-1300">
<div className="w-8 h-26 flex flex-col gap-2 items-center"> <div className="w-8 h-26 flex flex-col gap-2 items-center">
<div className="w-8 h-8 bg-gray-50 flex items-center justify-center rounded-xl drop-shadow-xl shadow-black"> <div className="w-8 h-8 bg-gray-50 flex items-center justify-center rounded-xl drop-shadow-xl shadow-black">
<button <button

View File

@@ -52,8 +52,9 @@ interface DataContextType {
setShowJunctionTextLayer?: React.Dispatch<React.SetStateAction<boolean>>; setShowJunctionTextLayer?: React.Dispatch<React.SetStateAction<boolean>>;
setShowPipeTextLayer?: React.Dispatch<React.SetStateAction<boolean>>; setShowPipeTextLayer?: React.Dispatch<React.SetStateAction<boolean>>;
setShowContourLayer?: React.Dispatch<React.SetStateAction<boolean>>; setShowContourLayer?: React.Dispatch<React.SetStateAction<boolean>>;
flowAnimation?: React.RefObject<boolean>; // flowAnimation?: React.RefObject<boolean>;
isContourLayerAvailable?: boolean; isContourLayerAvailable?: boolean;
setShowWaterflowLayer?: React.Dispatch<React.SetStateAction<boolean>>;
setContourLayerAvailable?: React.Dispatch<React.SetStateAction<boolean>>; setContourLayerAvailable?: React.Dispatch<React.SetStateAction<boolean>>;
isWaterflowLayerAvailable?: boolean; isWaterflowLayerAvailable?: boolean;
setWaterflowLayerAvailable?: React.Dispatch<React.SetStateAction<boolean>>; setWaterflowLayerAvailable?: React.Dispatch<React.SetStateAction<boolean>>;
@@ -124,7 +125,8 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
const flowAnimation = useRef(false); // 添加动画控制标志 const flowAnimation = useRef(false); // 添加动画控制标志
const [isContourLayerAvailable, setContourLayerAvailable] = useState(false); // 控制等高线图层显示 const [isContourLayerAvailable, setContourLayerAvailable] = useState(false); // 控制等高线图层显示
const [isWaterflowLayerAvailable, setWaterflowLayerAvailable] = const [isWaterflowLayerAvailable, setWaterflowLayerAvailable] =
useState(false); // 控制等高线图层显示 useState(true); // 控制等高线图层显示
const [showWaterflowLayer, setShowWaterflowLayer] = useState(false); // 控制等高线图层显示
const [currentZoom, setCurrentZoom] = useState(11); // 当前缩放级别 const [currentZoom, setCurrentZoom] = useState(11); // 当前缩放级别
// 防抖更新函数 // 防抖更新函数
@@ -867,6 +869,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
opacity: 0.8, opacity: 0.8,
visible: visible:
isWaterflowLayerAvailable && isWaterflowLayerAvailable &&
showWaterflowLayer &&
flowAnimation.current && flowAnimation.current &&
currentZoom >= 12 && currentZoom >= 12 &&
currentZoom <= 24, currentZoom <= 24,
@@ -898,6 +901,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
pipeText, pipeText,
pipeData.length, pipeData.length,
isWaterflowLayerAvailable, isWaterflowLayerAvailable,
showWaterflowLayer,
]); ]);
// 计算值更新时,更新 junctionData 和 pipeData // 计算值更新时,更新 junctionData 和 pipeData
@@ -967,11 +971,12 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
setShowJunctionTextLayer, setShowJunctionTextLayer,
setShowPipeTextLayer, setShowPipeTextLayer,
setShowContourLayer, setShowContourLayer,
flowAnimation, // flowAnimation,
isContourLayerAvailable, isContourLayerAvailable,
setContourLayerAvailable, setContourLayerAvailable,
isWaterflowLayerAvailable, isWaterflowLayerAvailable,
setWaterflowLayerAvailable, setWaterflowLayerAvailable,
setShowWaterflowLayer,
setJunctionText, setJunctionText,
setPipeText, setPipeText,
junctionText, junctionText,