diff --git a/public/icons/valve.svg b/public/icons/valve.svg
index 84c3055..2e5bf85 100644
--- a/public/icons/valve.svg
+++ b/public/icons/valve.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/app/OlMap/Controls/HistoryDataPanel.tsx b/src/app/OlMap/Controls/HistoryDataPanel.tsx
index c923edd..2949962 100644
--- a/src/app/OlMap/Controls/HistoryDataPanel.tsx
+++ b/src/app/OlMap/Controls/HistoryDataPanel.tsx
@@ -70,7 +70,6 @@ export interface HistoryDataPanelProps {
defaultTab?: "chart" | "table";
/** Y 轴数值的小数位数 */
fractionDigits?: number;
- // 清洗功能已移除,相关参数请通过外部面板/服务清洗后再传入
}
type PanelTab = "chart" | "table";
@@ -235,7 +234,7 @@ const HistoryDataPanel: React.FC = ({
fetchTimeSeriesData = defaultFetcher,
visible = true,
defaultTab = "chart",
- fractionDigits = 2,
+ fractionDigits = 3,
}) => {
// 从 devices 中提取 id 列表用于渲染与查询
const deviceIds = devices?.map((d) => d.id) ?? [];
diff --git a/src/app/OlMap/Controls/StyleEditorPanel.tsx b/src/app/OlMap/Controls/StyleEditorPanel.tsx
index d3fdf19..4fdf6c1 100644
--- a/src/app/OlMap/Controls/StyleEditorPanel.tsx
+++ b/src/app/OlMap/Controls/StyleEditorPanel.tsx
@@ -301,7 +301,7 @@ const StyleEditorPanel: React.FC = ({
if (layerId !== undefined && property !== undefined) {
// 验证自定义断点设置
if (styleConfig.classificationMethod === "custom_breaks") {
- const expected = styleConfig.segments + 1;
+ const expected = styleConfig.segments;
const custom = styleConfig.customBreaks || [];
if (
custom.length !== expected ||
@@ -609,7 +609,6 @@ const StyleEditorPanel: React.FC = ({
// 更新当前 VectorTileSource 中的所有缓冲要素属性
const updateVectorTileSource = (property: string, data: any[]) => {
if (!map) return;
-
const vectorTileSources = map
.getAllLayers()
.filter((layer) => layer instanceof WebGLVectorTileLayer)
@@ -636,7 +635,12 @@ const StyleEditorPanel: React.FC = ({
const featureId = renderFeature.get("id");
const value = dataMap.get(featureId);
if (value !== undefined) {
- (renderFeature as any).properties_[property] = value;
+ if (property === "flow") {
+ // 特殊处理流量属性,取绝对值
+ (renderFeature as any).properties_[property] = Math.abs(value);
+ } else {
+ (renderFeature as any).properties_[property] = value;
+ }
}
});
});
@@ -677,7 +681,12 @@ const StyleEditorPanel: React.FC = ({
const featureId = renderFeature.get("id");
const value = dataMap.get(featureId);
if (value !== undefined) {
- (renderFeature as any).properties_[property] = value;
+ if (property === "flow") {
+ // 特殊处理流量属性,取绝对值
+ (renderFeature as any).properties_[property] = Math.abs(value);
+ } else {
+ (renderFeature as any).properties_[property] = value;
+ }
}
});
}
@@ -845,7 +854,7 @@ const StyleEditorPanel: React.FC = ({
useEffect(() => {
if (styleConfig.classificationMethod !== "custom_breaks") return;
- const numBreaks = styleConfig.segments + 1;
+ const numBreaks = styleConfig.segments;
setStyleConfig((prev) => {
const prevBreaks = prev.customBreaks || [];
if (prevBreaks.length === numBreaks) return prev;
@@ -1372,46 +1381,44 @@ const StyleEditorPanel: React.FC = ({
className="flex flex-col gap-2"
sx={{ maxHeight: "240px", overflowY: "auto", paddingTop: "12px" }}
>
- {Array.from({ length: styleConfig.segments + 1 }).map(
- (_, idx) => (
- {
- const v = parseFloat(e.target.value);
- setStyleConfig((prev) => {
- const prevBreaks = prev.customBreaks
- ? [...prev.customBreaks]
- : [];
- // 保证长度
- while (prevBreaks.length < styleConfig.segments + 1)
- prevBreaks.push(0);
- prevBreaks[idx] = isNaN(v) ? 0 : Math.max(0, v);
- return { ...prev, customBreaks: prevBreaks };
- });
- }}
- onBlur={() => {
- // on blur 保证升序
- setStyleConfig((prev) => {
- const prevBreaks = (prev.customBreaks || []).slice(
- 0,
- styleConfig.segments + 1
- );
- prevBreaks.sort((a, b) => a - b);
- return { ...prev, customBreaks: prevBreaks };
- });
- }}
- />
- )
- )}
+ {Array.from({ length: styleConfig.segments }).map((_, idx) => (
+ {
+ const v = parseFloat(e.target.value);
+ setStyleConfig((prev) => {
+ const prevBreaks = prev.customBreaks
+ ? [...prev.customBreaks]
+ : [];
+ // 保证长度
+ while (prevBreaks.length < styleConfig.segments + 1)
+ prevBreaks.push(0);
+ prevBreaks[idx] = isNaN(v) ? 0 : Math.max(0, v);
+ return { ...prev, customBreaks: prevBreaks };
+ });
+ }}
+ onBlur={() => {
+ // on blur 保证升序
+ setStyleConfig((prev) => {
+ const prevBreaks = (prev.customBreaks || []).slice(
+ 0,
+ styleConfig.segments + 1
+ );
+ prevBreaks.sort((a, b) => a - b);
+ return { ...prev, customBreaks: prevBreaks };
+ });
+ }}
+ />
+ ))}
)}
@@ -1473,7 +1480,7 @@ const StyleEditorPanel: React.FC = ({
}
/>
}
- label="显示属性(放大后显示)"
+ label="显示属性(缩放 >=15 级时显示)"
/>
{/* 操作按钮 */}
diff --git a/src/app/OlMap/Controls/Toolbar.tsx b/src/app/OlMap/Controls/Toolbar.tsx
index a4860dd..e2572f1 100644
--- a/src/app/OlMap/Controls/Toolbar.tsx
+++ b/src/app/OlMap/Controls/Toolbar.tsx
@@ -403,7 +403,7 @@ const Toolbar: React.FC = ({ hiddenButtons, queryType }) => {
result.properties.push({
label,
value:
- computedProperties[key].toFixed?.(2) || computedProperties[key],
+ computedProperties[key].toFixed?.(3) || computedProperties[key],
unit,
});
}
@@ -446,7 +446,7 @@ const Toolbar: React.FC = ({ hiddenButtons, queryType }) => {
result.properties.push({
label,
value:
- computedProperties[key].toFixed?.(2) || computedProperties[key],
+ computedProperties[key].toFixed?.(3) || computedProperties[key],
unit,
});
}
diff --git a/src/app/OlMap/MapComponent.tsx b/src/app/OlMap/MapComponent.tsx
index 6804d06..448a972 100644
--- a/src/app/OlMap/MapComponent.tsx
+++ b/src/app/OlMap/MapComponent.tsx
@@ -400,7 +400,7 @@ const MapComponent: React.FC = ({ children }) => {
useEffect(() => {
if (!mapRef.current) return;
- // 缓存 junction、pipe 数据,提供给 deck.gl 显示标签使用
+ // 缓存 junction、pipe 数据,提供给 deck.gl 提供坐标供标签显示
junctionSource.on("tileloadend", (event) => {
try {
if (event.tile instanceof VectorTile) {
@@ -555,14 +555,14 @@ const MapComponent: React.FC = ({ children }) => {
});
// 重新排列图层顺序,确保顺序 点>线>面
availableLayers.sort((a, b) => {
- // 明确顺序(点类优先)
+ // 明确顺序(点类优先),这里 valves 特殊处理
const order = [
+ "valves",
"junctions",
"scada",
"reservoirs",
"pumps",
"tanks",
- "valves",
"pipes",
].reverse();
// 取值时做安全检查,兼容不同写法(properties.value 或 直接 value)
@@ -850,7 +850,9 @@ const MapComponent: React.FC = ({ children }) => {
pipeProperties === "flow" && record.value < 0 && p.flowFlag > 0
? [...p.path].reverse()
: p.path,
- [pipeProperties]: record.value,
+ // 流量数值
+ [pipeProperties]:
+ pipeProperties === "flow" ? Math.abs(record.value) : record.value,
};
}
return p;
diff --git a/src/components/olmap/BurstPipeAnalysis/LocationResults.tsx b/src/components/olmap/BurstPipeAnalysis/LocationResults.tsx
index 44e142a..ce564eb 100644
--- a/src/components/olmap/BurstPipeAnalysis/LocationResults.tsx
+++ b/src/components/olmap/BurstPipeAnalysis/LocationResults.tsx
@@ -1,6 +1,6 @@
-'use client';
+"use client";
-import React, { useState } from 'react';
+import React, { useState } from "react";
import {
Box,
Typography,
@@ -14,8 +14,11 @@ import {
Chip,
IconButton,
Tooltip,
-} from '@mui/material';
-import { LocationOn as LocationIcon, Visibility as VisibilityIcon } from '@mui/icons-material';
+} from "@mui/material";
+import {
+ LocationOn as LocationIcon,
+ Visibility as VisibilityIcon,
+} from "@mui/icons-material";
interface LocationResult {
id: number;
@@ -24,7 +27,7 @@ interface LocationResult {
pressure: number;
waterLevel: number;
flow: number;
- status: 'normal' | 'warning' | 'danger';
+ status: "normal" | "warning" | "danger";
coordinates: [number, number];
}
@@ -33,7 +36,10 @@ interface LocationResultsProps {
onViewDetail?: (id: number) => void;
}
-const LocationResults: React.FC = ({ onLocate, onViewDetail }) => {
+const LocationResults: React.FC = ({
+ onLocate,
+ onViewDetail,
+}) => {
const [results, setResults] = useState([
// 示例数据
// {
@@ -50,27 +56,27 @@ const LocationResults: React.FC = ({ onLocate, onViewDetai
const getStatusColor = (status: string) => {
switch (status) {
- case 'normal':
- return 'success';
- case 'warning':
- return 'warning';
- case 'danger':
- return 'error';
+ case "normal":
+ return "success";
+ case "warning":
+ return "warning";
+ case "danger":
+ return "error";
default:
- return 'default';
+ return "default";
}
};
const getStatusText = (status: string) => {
switch (status) {
- case 'normal':
- return '正常';
- case 'warning':
- return '预警';
- case 'danger':
- return '危险';
+ case "normal":
+ return "正常";
+ case "warning":
+ return "预警";
+ case "danger":
+ return "危险";
default:
- return '未知';
+ return "未知";
}
};
@@ -95,7 +101,7 @@ const LocationResults: React.FC = ({ onLocate, onViewDetai
正常
- {results.filter((r) => r.status === 'normal').length}
+ {results.filter((r) => r.status === "normal").length}
@@ -103,7 +109,7 @@ const LocationResults: React.FC = ({ onLocate, onViewDetai
预警
- {results.filter((r) => r.status === 'warning').length}
+ {results.filter((r) => r.status === "warning").length}
@@ -111,7 +117,7 @@ const LocationResults: React.FC = ({ onLocate, onViewDetai
危险
- {results.filter((r) => r.status === 'danger').length}
+ {results.filter((r) => r.status === "danger").length}
@@ -129,12 +135,46 @@ const LocationResults: React.FC = ({ onLocate, onViewDetai
fill="none"
className="opacity-40"
>
-
+
-
-
-
-
+
+
+
+
暂无定位结果
@@ -161,9 +201,15 @@ const LocationResults: React.FC = ({ onLocate, onViewDetai
{result.nodeName}
{result.nodeId}
- {result.pressure.toFixed(2)}
- {result.waterLevel.toFixed(2)}
- {result.flow.toFixed(1)}
+
+ {result.pressure.toFixed(3)}
+
+
+ {result.waterLevel.toFixed(3)}
+
+
+ {result.flow.toFixed(1)}
+