From f07405d8787e8bbd43453c81ec4f599dc34153b9 Mon Sep 17 00:00:00 2001
From: wujingjing <gersonwu@qq.com>
Date: 星期三, 02 四月 2025 16:44:34 +0800
Subject: [PATCH] Merge branch 'master' into huishui_iframe

---
 src/model/map/OLMap.ts |  348 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 335 insertions(+), 13 deletions(-)

diff --git a/src/model/map/OLMap.ts b/src/model/map/OLMap.ts
index d1d9a90..1666f55 100644
--- a/src/model/map/OLMap.ts
+++ b/src/model/map/OLMap.ts
@@ -3,7 +3,7 @@
 import type { Overlay } from 'ol';
 import { Feature, Map as OpenLayerMap, View } from 'ol';
 import type { Extent } from 'ol/extent';
-import { extend, getTopLeft, getWidth } from 'ol/extent';
+import { extend, getCenter, getTopLeft, getWidth } from 'ol/extent';
 import type { FeatureLike } from 'ol/Feature';
 import MVT from 'ol/format/MVT.js';
 import WKT from 'ol/format/WKT';
@@ -30,17 +30,21 @@
 import { Logger } from '../logger/Logger';
 import { MarkerOverlay } from './overlay/marker';
 import { getCurrentPosition } from '/@/utils/brower';
+import { travelTree } from '/@/utils/util';
+import { ElLoadingService } from 'element-plus';
+import { switchMapTheme } from '/@/api/map';
+import { formatDate } from '/@/utils/formatTime';
 
 export type LangType = 'zh_cn' | 'en';
 export const enum GaoDeSourceType {
 	/** @description 榛樿鍦板浘 */
-	Default = 0,
+	Default = 'default',
 	/** @description 褰卞儚鍦板浘 */
-	Satellite = 1,
+	Satellite = 'satellite',
 	/** @description 鐭㈤噺鍦板浘 */
-	Vector = 2,
+	Vector = 'standard',
 	/** @description 褰卞儚璺綉 */
-	SatelliteRoad = 3,
+	SatelliteRoad = 'road_network',
 }
 export const enum OverlayType {
 	Marker = 'marker',
@@ -88,6 +92,9 @@
 
 	/** @description 鍥惧眰鎺у埗淇℃伅 */
 	layerInfo = ref([] as any[]);
+
+	/** @description 鍥惧眰鎺у埗淇℃伅 */
+	legendList = ref([] as any[]);
 
 	drawStyles = ref([] as any[]);
 
@@ -400,6 +407,7 @@
 			const zoom = that.map.getView().getZoom(); //鑾峰彇褰撳墠鍦板浘鐨勭缉鏀剧骇鍒�
 			Logger.info('褰撳墠鍦板浘缂╂斁绾у埆涓猴細' + zoom);
 		});
+		this.pointermove();
 	}
 
 	hightLightColor: '0000FFFF';
@@ -762,8 +770,11 @@
 				layers.push(layer);
 			});
 			const feature = features[0];
+			feature?.get('click')?.(event);
+
 			const layer = layers[0];
 			if (layer === this.drawLayer) return;
+			this.labelOverlay?.setVisible(false);
 
 			if (feature !== this.activeFeature.value) {
 				this.emit('featureChange', feature, layer);
@@ -813,7 +824,6 @@
 				// 鍚堝苟鑼冨洿
 				return extend(extent, layerExtent);
 			}, extent);
-
 		}
 
 		// 鑱氱劍鍒板悎骞跺悗鐨勮寖鍥�
@@ -831,6 +841,189 @@
 				return preVal;
 			}
 		}, []);
+	}
+
+	setLayerVisible(layerId: string, visible: boolean) {
+		const layer = this.getAllLayers().find((item) => item.id === layerId);
+		if (layer) {
+			layer.isVisible = visible;
+		}
+	}
+
+	setThemeById(themeId: string) {
+		let group;
+		let theme;
+		travelTree(this.themeInfo.value, (item, index, array, parent) => {
+			if (item.type === 'theme' && item.id === themeId) {
+				group = parent;
+				theme = item;
+				return true;
+			}
+		});
+		if (group) {
+			group.activeTheme = themeId;
+			this.handleThemeChange(themeId, group);
+		}
+	}
+
+	async changeTheme(ids: string) {
+		const loadingInstance = ElLoadingService({
+			text: '鍔犺浇涓婚涓�...',
+			target: '.layout-parent',
+		});
+		const res = await switchMapTheme({
+			theme_id: ids,
+			time: formatDate(new Date()),
+		}).finally(() => {
+			loadingInstance.close();
+		});
+
+		// 鍔犲叆涓婚涔嬪悗鐨勬牱寮忓嚱鏁�
+		const themeLayerStyleFunc = (feature, resolution) => {
+			const otype = feature.get('otype');
+			const oname = feature.get('oname');
+			// oname 鏄犲皠鏍峰紡
+			const onameStyleMap = res?.[`O_${otype}`] ?? {};
+			const themeStyles = res?.styles ?? [];
+			const styleIndex = onameStyleMap[oname]?.style_id;
+			const themeStyle = styleIndex == null ? null : themeStyles[styleIndex];
+			// if(themeStyle){
+			// }
+			const shape = feature.getGeometry().getType();
+			const styles = [];
+			switch (shape) {
+				case 'Point':
+					const pSize = themeStyle?.PSIZE ?? feature.get('psize');
+
+					const pcolor = themeStyle?.PCOLOR ?? feature.get('pcolor');
+
+					const pStyle = themeStyle?.PSTYLE ?? feature.get('pstyle');
+
+					const pointStyle = this.getPointStyles({
+						size: pSize,
+						color: pcolor,
+						style: pStyle,
+					});
+					pointStyle && styles.push(pointStyle);
+					break;
+				case 'LineString':
+					const lSize = themeStyle?.LSIZE ?? feature.get('lsize');
+					const lColor = themeStyle?.LCOLOR ?? feature.get('lcolor');
+					const lStyle = themeStyle?.LSTYLE ?? feature.get('lstyle');
+
+					const pSize1 = themeStyle?.PSIZE ?? feature.get('psize');
+					const pcolor1 = themeStyle?.PCOLOR ?? feature.get('pcolor');
+					const pStyle1 = themeStyle?.PSTYLE ?? feature.get('pstyle');
+
+					const lineStyle = this.getLineStyles({
+						lsize: lSize,
+						lcolor: lColor,
+						lstyle: lStyle,
+						psize: pSize1,
+						pcolor: pcolor1,
+						pstyle: pStyle1,
+					});
+					lineStyle && styles.push(...lineStyle);
+
+					break;
+				case 'Polygon':
+					const pColor = themeStyle?.PCOLOR ?? feature.get('pcolor');
+					const lSize1 = themeStyle?.LSIZE ?? feature.get('lsize');
+					const lColor1 = themeStyle?.LCOLOR ?? feature.get('lcolor');
+					const lstyle1 = themeStyle?.LSTYLE ?? feature.get('lstyle');
+					const polygonStyle = this.getPolygonStyles({
+						pcolor: pColor,
+						lsize: lSize1,
+						lcolor: lColor1,
+						lstyle: lstyle1,
+					});
+					polygonStyle && styles.push(...polygonStyle);
+
+					break;
+				default:
+					break;
+			}
+
+			// switch (otype) {
+			// 	case 'WDM_JUNCTIONS':
+			// 		const textStyle = createTextStyle(feature, resolution);
+			// 		styles.push(textStyle);
+
+			// 	case 'WDM_PIPES':
+			// 		break;
+			// }
+			//#region ====================== 娣诲姞鏍囨敞 ======================
+			const tString = themeStyle?.TSTRING ?? feature.get('tstring');
+			const tStringStyle = this.getLabelStyles({
+				textContent: tString,
+				resolution,
+			});
+			tStringStyle && styles.push(tStringStyle);
+			//#endregion
+
+			return styles;
+		};
+		const allLayers = this.getAllLayers();
+		for (const item of allLayers) {
+			if (this.unsupportedLayers.includes(item.id)) {
+				continue;
+			}
+			item.model.setStyle(themeLayerStyleFunc);
+		}
+		return res?.legends ?? [];
+	}
+
+	async handleThemeChange(val?, themeGroup?) {
+		const allIds = [];
+		for (const item of this.themeInfo.value) {
+			if (item.activeTheme) {
+				allIds.push(item.activeTheme);
+			}
+		}
+		const ids = allIds.join(',');
+
+		if (!ids) {
+			const allLayers = this.getAllLayerModels();
+			for (const item of allLayers) {
+				const originStyle = item.get('originStyle');
+				originStyle && item.setStyle(originStyle);
+			}
+			return;
+		}
+		const legends = await this.changeTheme(ids);
+		this.legendList.value = this.parseLegends(legends);
+	}
+
+	parseLegends(legends) {
+		const result = legends.map((item) => {
+			const isEqual = item.operate === '=';
+			const result = {
+				...item,
+				legend: item.legend.map((legendItem, index, array) => {
+					const preItem = array[index - 1];
+					let label = '';
+					if (isEqual) {
+						label = legendItem.value;
+					} else if (preItem) {
+						label = `>${preItem.value}涓�${item.operate}${legendItem.value}`;
+					} else {
+						label = `${item.operate}${legendItem.value}`;
+					}
+					return {
+						...legendItem,
+						label: label,
+					};
+				}),
+			};
+
+			result.legend.push({
+				style: item.default,
+				value: '',
+				label: result.legend.length == 0 ? '榛樿' : `>${item.legend[item.legend.length - 1].value}`,
+			});
+			return result;
+		});
+		return result;
 	}
 
 	/** @description 璁板綍鎵�鏈夊浘灞� */
@@ -948,19 +1141,59 @@
 	/**
 	 * 鏀惧ぇ鍦板浘
 	 */
-	zoomIn() {
+	zoomIn(offsetLevel = 1) {
 		const view = this.map.getView();
 		const zoom = view.getZoom();
-		view.setZoom(zoom + 1);
+		view.setZoom(zoom + offsetLevel);
 	}
 
 	/**
 	 * 缂╁皬鍦板浘
 	 */
-	zoomOut() {
+	zoomOut(offsetLevel = 1) {
 		const view = this.map.getView();
 		const zoom = view.getZoom();
-		view.setZoom(zoom - 1);
+		view.setZoom(zoom - offsetLevel);
+	}
+
+	/**
+	 * 鍦板浘宸︾Щ
+	 */
+	panLeft(offset = 1000) {
+		const view = this.map.getView();
+		const center = view.getCenter();
+		if (!center) return;
+		view.setCenter([center[0] - offset, center[1]]);
+	}
+
+	/**
+	 * 鍦板浘鍙崇Щ
+	 */
+	panRight(offset = 1000) {
+		const view = this.map.getView();
+		const center = view.getCenter();
+		if (!center) return;
+		view.setCenter([center[0] + offset, center[1]]);
+	}
+
+	/**
+	 * 鍦板浘涓婄Щ
+	 */
+	panUp(offset = 1000) {
+		const view = this.map.getView();
+		const center = view.getCenter();
+		if (!center) return;
+		view.setCenter([center[0], center[1] + offset]);
+	}
+
+	/**
+	 * 鍦板浘涓嬬Щ
+	 */
+	panDown(offset = 1000) {
+		const view = this.map.getView();
+		const center = view.getCenter();
+		if (!center) return;
+		view.setCenter([center[0], center[1] - offset]);
 	}
 
 	private tileUrlFunction(url) {
@@ -1163,11 +1396,85 @@
 		}
 	}
 
+	private labelOverlay: MarkerOverlay = null;
+	private initLabelOverlay() {
+		if (this.labelOverlay) return;
+		// 鍒涘缓涓�涓� div 鍏冪礌鐢ㄤ簬鏄剧ず鏍囩
+		const labelElement = document.createElement('div');
+		labelElement.className = 'ol-label-overlay';
+		labelElement.style.position = 'relative';
+		labelElement.style.background = 'rgba(0,0,0,0.6)';
+		labelElement.style.borderRadius = '4px';
+		labelElement.style.color = '#fff';
+		labelElement.style.padding = '4px 8px';
+		labelElement.style.whiteSpace = 'nowrap';
+		labelElement.style.fontSize = '12px';
+		labelElement.style.transform = 'translate(-50%, -100%)';
+		labelElement.style.marginBottom = '8px';
+
+		// 鍒涘缓 overlay
+		this.labelOverlay = new MarkerOverlay({
+			element: labelElement,
+			offset: [0, 0],
+			positioning: 'bottom-center',
+		});
+
+		// 娣诲姞鍒板湴鍥�
+		this.map.addOverlay(this.labelOverlay);
+	}
 	private preSearchHighlightFeatures: Feature[] = [];
 	highlightSearch(features) {
 		if (!Array.isArray(features)) {
 			features = [features];
 		}
+
+		const positionFeatures = features.map((feature, index, array) => {
+			const geometry = feature.getGeometry();
+			const center = geometry.getExtent ? getCenter(geometry.getExtent()) : geometry.getCoordinates();
+
+			// 鍒涘缓涓�涓柊鐨凢eature鐢ㄤ簬鏄剧ず瀛椾綋鍥炬爣
+			const iconFeature = new Feature({
+				geometry: new Point(center),
+			});
+
+			// 璁剧疆瀛椾綋鍥炬爣鏍峰紡
+			// 娣诲姞鐐瑰嚮浜嬩欢鐩戝惉
+			// iconFeature.set('click', (event) => {
+			// 	// 鍒濆鍖� labelOverlay
+			// 	this.initLabelOverlay();
+			// 	// 鑾峰彇鐐瑰嚮浣嶇疆鐨勫潗鏍�
+			// 	const coordinate = event.coordinate;
+			// 	// 璁剧疆 labelOverlay 鐨勫唴瀹瑰拰浣嶇疆
+			// 	const element = this.labelOverlay.getElement();
+			// 	element.innerHTML = `绗�${index + 1}涓綅缃甡;
+			// 	this.labelOverlay.setPosition(coordinate);
+			// });
+
+			iconFeature.setStyle([
+				new Style({
+					text: new Text({
+						text: '\ue642', // 浣跨敤瀛椾綋鍥炬爣鐨剈nicode缂栫爜
+						font: '24px "ywifont"', // 璁剧疆瀛椾綋澶у皬鍜屽瓧浣撳悕绉�
+						fill: new Fill({
+							color: '#1677ff',
+						}),
+						offsetY: -20, // 璋冩暣鍥炬爣浣嶇疆
+					}),
+				}),
+				new Style({
+					text: new Text({
+						text: array.length === 1 ? '' : index + 1, // 娣诲姞鏁板瓧
+						font: '14px Arial', // 璁剧疆鏁板瓧瀛椾綋
+						fill: new Fill({
+							color: '#ffffff', // 鏁板瓧棰滆壊璁句负鐧借壊
+						}),
+						offsetY: -20, // 涓庡浘鏍囦繚鎸佺浉鍚岀殑鍋忕Щ
+					}),
+				}),
+			]);
+
+			return iconFeature;
+		});
 		// 鍒涘缓楂樹寒鍥惧眰
 		if (!this.searchHighlightLayer) {
 			this.searchHighlightLayer = new VectorLayer({
@@ -1184,11 +1491,26 @@
 		}
 
 		// 璁剧疆楂樹寒瑕佺礌
-		if (features && features.length > 0) {
-			this.searchHighlightLayer.getSource().addFeatures(features);
+		if (positionFeatures && positionFeatures.length > 0) {
+			this.searchHighlightLayer.getSource().addFeatures(positionFeatures);
 		}
-		this.preSearchHighlightFeatures = features;
+		this.preSearchHighlightFeatures = positionFeatures;
 	}
+
+	pointermove() {
+		this.map.on('pointermove', (e) => {
+			if (this.map.hasFeatureAtPixel(e.pixel)) {
+				this.map.getViewport().style.cursor = 'pointer';
+			} else {
+				this.map.getViewport().style.cursor = 'inherit';
+			}
+		});
+	}
+
+	clearMarker() {
+		this.clearObjectSearch();
+	}
+
 	getWMTS = () => {
 		const projection = getProjection('EPSG:3857');
 		const projectionExtent = projection.getExtent();

--
Gitblit v1.9.3