新增features多选模式

This commit is contained in:
JIANG
2025-12-19 16:27:59 +08:00
parent eb15100f4f
commit 3b4f7fd694

View File

@@ -12,12 +12,12 @@ import HistoryDataPanel from "./HistoryDataPanel"; // 引入绘图面板组件
import VectorSource from "ol/source/Vector";
import VectorLayer from "ol/layer/Vector";
import { Style, Stroke, Fill, Circle } from "ol/style";
import { FeatureLike } from "ol/Feature";
import Feature from "ol/Feature";
import StyleEditorPanel from "./StyleEditorPanel";
import { LayerStyleState } from "./StyleEditorPanel";
import StyleLegend from "./StyleLegend"; // 引入图例组件
import { handleMapClickSelectFeatures as mapClickSelectFeatures } from "@/utils/mapQueryService";
import { useNotification } from "@refinedev/core";
import { config } from "@/config/config";
const backendUrl = config.BACKEND_URL;
@@ -35,12 +35,11 @@ const Toolbar: React.FC<ToolbarProps> = ({
}) => {
const map = useMap();
const data = useData();
const { open } = useNotification();
if (!data) return null;
const { currentTime, selectedDate, schemeName } = data;
const [activeTools, setActiveTools] = useState<string[]>([]);
const [highlightFeature, setHighlightFeature] = useState<FeatureLike | null>(
null
);
const [highlightFeatures, setHighlightFeatures] = useState<Feature[]>([]);
const [showPropertyPanel, setShowPropertyPanel] = useState<boolean>(false);
const [showDrawPanel, setShowDrawPanel] = useState<boolean>(false);
const [showStyleEditor, setShowStyleEditor] = useState<boolean>(false);
@@ -56,7 +55,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
layerName: "节点图层",
styleConfig: {
property: "pressure",
classificationMethod: "pretty_breaks",
classificationMethod: "custom_breaks",
segments: 6,
minSize: 4,
maxSize: 12,
@@ -175,18 +174,74 @@ const Toolbar: React.FC<ToolbarProps> = ({
// 清除之前的高亮
source.clear();
// 添加新的高亮要素
if (highlightFeature instanceof Feature) {
source.addFeature(highlightFeature);
highlightFeatures.forEach((feature) => {
if (feature instanceof Feature) {
source.addFeature(feature);
}
}, [highlightFeature]);
});
}, [highlightFeatures, highlightLayer]);
// 地图点击选择要素事件处理函数
const handleMapClickSelectFeatures = useCallback(
async (event: { coordinate: number[] }) => {
if (!map) return;
const feature = await mapClickSelectFeatures(event, map); // 调用导入的函数
setHighlightFeature(feature);
if (!feature || !(feature instanceof Feature)) return;
if (activeTools.includes("history")) {
// 历史查询模式:支持同类型多选
const featureId = feature.getProperties().id;
const layerId = feature.getId()?.toString().split(".")[0] || "";
// 简单的类型检查函数
const getBaseType = (lid: string) => {
if (lid.includes("pipe")) return "pipe";
if (lid.includes("junction")) return "junction";
if (lid.includes("tank")) return "tank";
if (lid.includes("reservoir")) return "reservoir";
if (lid.includes("pump")) return "pump";
if (lid.includes("valve")) return "valve";
return lid;
};
// 检查是否与已选要素类型一致
if (highlightFeatures.length > 0) {
const firstLayerId =
highlightFeatures[0].getId()?.toString().split(".")[0] || "";
if (getBaseType(layerId) !== getBaseType(firstLayerId)) {
// 如果点击的是已选中的要素(为了取消选中),则不报错
const isAlreadySelected = highlightFeatures.some(
(f) => f.getProperties().id === featureId
);
if (!isAlreadySelected) {
open?.({
type: "error",
message: "请选择相同类型的要素进行多选查询。",
});
return;
}
}
}
setHighlightFeatures((prev) => {
const existingIndex = prev.findIndex(
(f) => f.getProperties().id === featureId
);
if (existingIndex !== -1) {
// 如果已存在,移除
return prev.filter((_, i) => i !== existingIndex);
} else {
// 如果不存在,添加
return [...prev, feature];
}
});
} else {
// 其他模式(如 info单选
setHighlightFeatures([feature]);
}
},
[map, setHighlightFeature]
[map, activeTools, highlightFeatures, open]
);
// 添加矢量属性查询事件监听器
useEffect(() => {
@@ -243,13 +298,14 @@ const Toolbar: React.FC<ToolbarProps> = ({
switch (tool) {
case "info":
setShowPropertyPanel(false);
setHighlightFeature(null);
setHighlightFeatures([]);
break;
case "draw":
setShowDrawPanel(false);
break;
case "history":
setShowHistoryPanel(false);
setHighlightFeatures([]);
break;
}
};
@@ -273,7 +329,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
// 关闭所有面板(除了样式编辑器)
const closeAllPanelsExceptStyle = () => {
setShowPropertyPanel(false);
setHighlightFeature(null);
setHighlightFeatures([]);
setShowDrawPanel(false);
setShowHistoryPanel(false);
// 样式编辑器保持其当前状态,不自动关闭
@@ -283,11 +339,12 @@ const Toolbar: React.FC<ToolbarProps> = ({
>({});
// 添加 useEffect 来查询计算属性
useEffect(() => {
if (!highlightFeature || !selectedDate || !showPropertyPanel) {
if (highlightFeatures.length === 0 || !selectedDate || !showPropertyPanel) {
setComputedProperties({});
return;
}
const highlightFeature = highlightFeatures[0];
const id = highlightFeature.getProperties().id;
if (!id) {
setComputedProperties({});
@@ -334,11 +391,12 @@ const Toolbar: React.FC<ToolbarProps> = ({
};
// 仅当 currentTime 有效时查询
if (currentTime !== -1 && queryType) queryComputedProperties();
}, [highlightFeature, currentTime, selectedDate]);
}, [highlightFeatures, currentTime, selectedDate]);
// 从要素属性中提取属性面板需要的数据
const getFeatureProperties = useCallback(() => {
if (!highlightFeature) return {};
if (highlightFeatures.length === 0) return {};
const highlightFeature = highlightFeatures[0];
const layer = highlightFeature?.getId()?.toString().split(".")[0];
const properties = highlightFeature.getProperties();
// 计算属性字段,增加 key 字段
@@ -613,7 +671,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
return result;
}
return {};
}, [highlightFeature, computedProperties]);
}, [highlightFeatures, computedProperties]);
return (
<>
@@ -663,14 +721,18 @@ const Toolbar: React.FC<ToolbarProps> = ({
(HistoryPanel ? (
<HistoryPanel
featureInfos={(() => {
if (!highlightFeature || !showHistoryPanel) return [];
const properties = highlightFeature.getProperties();
if (highlightFeatures.length === 0 || !showHistoryPanel)
return [];
return highlightFeatures
.map((feature) => {
const properties = feature.getProperties();
const id = properties.id;
if (!id) return [];
if (!id) return null;
// 从图层名称推断类型
const layerId =
highlightFeature.getId()?.toString().split(".")[0] || "";
feature.getId()?.toString().split(".")[0] || "";
let type = "unknown";
if (layerId.includes("pipe")) {
@@ -688,9 +750,11 @@ const Toolbar: React.FC<ToolbarProps> = ({
}
// 仅处理 type 为 pipe 或 junction 的情况
if (type !== "pipe" && type !== "junction") {
return [];
return null;
}
return [[id, type]];
return [id, type];
})
.filter(Boolean) as [string, string][];
})()}
scheme_type="burst_Analysis"
scheme_name={schemeName}
@@ -699,14 +763,18 @@ const Toolbar: React.FC<ToolbarProps> = ({
) : (
<HistoryDataPanel
featureInfos={(() => {
if (!highlightFeature || !showHistoryPanel) return [];
const properties = highlightFeature.getProperties();
if (highlightFeatures.length === 0 || !showHistoryPanel)
return [];
return highlightFeatures
.map((feature) => {
const properties = feature.getProperties();
const id = properties.id;
if (!id) return [];
if (!id) return null;
// 从图层名称推断类型
const layerId =
highlightFeature.getId()?.toString().split(".")[0] || "";
feature.getId()?.toString().split(".")[0] || "";
let type = "unknown";
if (layerId.includes("pipe")) {
@@ -724,9 +792,11 @@ const Toolbar: React.FC<ToolbarProps> = ({
}
// 仅处理 type 为 pipe 或 junction 的情况
if (type !== "pipe" && type !== "junction") {
return [];
return null;
}
return [[id, type]];
return [id, type];
})
.filter(Boolean) as [string, string][];
})()}
scheme_type="burst_Analysis"
scheme_name={schemeName}