From 08c6ecf506bfc7003894775fe57d98d9b11f3d9e Mon Sep 17 00:00:00 2001
From: wujingjing <gersonwu@qq.com>
Date: 星期三, 26 二月 2025 11:43:18 +0800
Subject: [PATCH] 地图对话

---
 src/components/chat/chatComponents/summaryCom/components/recordSetTable/map/BasicMap.vue |  395 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 373 insertions(+), 22 deletions(-)

diff --git a/src/components/chat/chatComponents/summaryCom/components/recordSetTable/map/BasicMap.vue b/src/components/chat/chatComponents/summaryCom/components/recordSetTable/map/BasicMap.vue
index 2431907..5d42cb7 100644
--- a/src/components/chat/chatComponents/summaryCom/components/recordSetTable/map/BasicMap.vue
+++ b/src/components/chat/chatComponents/summaryCom/components/recordSetTable/map/BasicMap.vue
@@ -1,5 +1,5 @@
 <template>
-	<div class="relative">
+	<div class="relative bg-white">
 		<div ref="containerRef" class="h-full"></div>
 		<div ref="infoWindowRef" v-show="infoWindowIsShow">
 			<div
@@ -34,30 +34,95 @@
 				</div>
 			</div>
 		</div>
+		<!-- <LayerControl v-if="olMap" :olMap="olMap" class="absolute top-3 left-3 z-10" /> -->
+
+		<!-- <PropertyPanel class="absolute top-14 left-10 z-14"></PropertyPanel> -->
+		<PanelTool
+			v-if="olMap"
+			ref="panelToolRef"
+			:propertyMap="propertyMap"
+			:propertyConfigMap="propertyConfigMap"
+			class="absolute top-0 right-2 z-14 h-full"
+			:olMap="olMap"
+			:isFullscreen="isFullscreen"
+			@toggleFullScreen="toggleFullScreen"
+		></PanelTool>
+
+		<Search class="absolute top-0 left-2 z-14 w-fit" :olMap="olMap" :propertyMap="propertyMap"  :propertyConfigMap="propertyConfigMap"/>
 	</div>
 </template>
 
 <script setup lang="ts" name="BasicMap">
-import type { Overlay } from 'ol';
+import { reverse } from 'lodash-es';
+import type { Feature, Overlay } from 'ol';
+import type { FeatureLike } from 'ol/Feature';
+import type Layer from 'ol/layer/Layer';
+import type VectorTileLayer from 'ol/layer/VectorTile';
 import 'ol/ol.css';
-import { computed, onMounted, ref } from 'vue';
+import type LayerRenderer from 'ol/renderer/Layer';
+import type Source from 'ol/source/Source';
+import { Text } from 'ol/style';
+import Circle from 'ol/style/Circle';
+import Fill from 'ol/style/Fill';
+import Stroke from 'ol/style/Stroke';
+import Style from 'ol/style/Style';
+import { computed, onMounted, ref, shallowRef } from 'vue';
 import equipSelectPic from './img/equip-select.svg';
 import equipPic from './img/equip.svg';
-import { OLMap } from '/@/model/map/OLMap';
+import LayerControl from './LayerControl.vue';
+import PanelTool from './panelTool/index.vue';
+import Search from './Search.vue';
+import {
+	getMapDrawStyles,
+	getMapLayerGroupList,
+	getMapLayersByPost,
+	getMapThemeList,
+	getMapVpropsByPost,
+	getMapVpropsConfigByPost,
+	switchMapTheme,
+} from '/@/api/map';
+import { MAIN_URL } from '/@/constants';
+import { GaoDeSourceType, OLMap } from '/@/model/map/OLMap';
+import { MarkerOverlay } from '/@/model/map/overlay/marker';
+import { useCompRef } from '/@/utils/types';
+import { formatDate } from '/@/utils/formatTime';
+import { MapPanelTool } from './types';
 
-const props = defineProps<{
-	data: any;
-}>();
+const panelToolRef = useCompRef(PanelTool);
+
+const props = withDefaults(
+	defineProps<{
+		data: any;
+		config?: {
+			sourceType: GaoDeSourceType;
+		};
+		isFullscreen: boolean;
+	}>(),
+	{
+		config: () => ({
+			sourceType: GaoDeSourceType.Vector,
+		}),
+	}
+);
+
+const locationCurrent = () => {
+	olMap.value.locationCurrent();
+};
+
 const colsArray = computed(() => {
 	return props.data.cols ?? [];
 });
-const emit = defineEmits(['markerClick', 'closeInfoWindow']);
+const emit = defineEmits(['markerClick', 'closeInfoWindow', 'toggleFullScreen']);
+
+const toggleFullScreen = () => {
+	emit('toggleFullScreen');
+};
 
 const containerRef = ref<HTMLDivElement>(null);
 const infoWindowRef = ref<HTMLDivElement>(null);
 const infoWindowIsShow = ref(false);
 const infoWindowMapRow = ref(null);
-let olMap: OLMap;
+const olMap = shallowRef<OLMap>();
 let infoWindowOverlay: Overlay;
 let lastOverlay: Overlay;
 const setMarkerIcon = (overlay: Overlay, icon: string) => {
@@ -68,7 +133,8 @@
 };
 const showInfoWindow = (overlay: Overlay) => {
 	const position = overlay.getPosition();
-	const row = overlay.get('extData');
+	const row = overlay.get('extData')?.value;
+	if (!row) return;
 	lastOverlay && setMarkerIcon(lastOverlay, equipPic);
 	infoWindowIsShow.value = true;
 	infoWindowOverlay.setPosition(position);
@@ -87,7 +153,6 @@
 const addMarkerLayer = () => {
 	const map = props.data.map;
 	if (map.pos_x == null && map.pos_y == null) return;
-
 	const dataList = (props.data?.values ?? []).map((item) => {
 		const x = item[map.pos_x];
 		const y = item[map.pos_y];
@@ -95,18 +160,20 @@
 		return {
 			position: [x, y],
 			// textColor: item.color,
-			extData: item,
-			title: item.title,
+			extData: {
+				value: item,
+				recordSetTable: props.data,
+			},
 		};
 	});
-	olMap.addMarkerLayer(dataList, {
+	olMap.value.addMarkerLayer(dataList, {
 		markerOpt: {
 			icon: {
 				url: equipPic,
 				size: 30,
 				selectUrl: equipSelectPic,
 			},
-			click(e, label, item, position) {
+			click(e, label, extData, position) {
 				showInfoWindow(label);
 			},
 		},
@@ -115,17 +182,301 @@
 		},
 	});
 };
-const initMap = () => {
-	olMap = new OLMap({
-		container: containerRef.value,
-	});
-	addMarkerLayer();
-	infoWindowOverlay = olMap.createEleOverlay(infoWindowRef.value);
-	olMap.map.addOverlay(infoWindowOverlay);
+
+const hoverStyleMap = {};
+
+const resetLastActiveStyle = () => {
+	if (!olMap.value.activeFeature.value) return;
+	const originStyle = olMap.value.activeFeature.value?.get('originStyle');
+
+	(olMap.value.activeFeature.value as Feature).setStyle(originStyle);
 };
+
+const setActiveStyle = (feature: FeatureLike, layer: Layer<Source, LayerRenderer<any>>) => {
+	resetLastActiveStyle();
+
+	const geometryType = feature.getGeometry().getType();
+	const otype = feature.get('otype');
+	const key = `${geometryType}_${otype}`;
+	const style = hoverStyleMap[key];
+	const source = layer.getSource();
+
+	// const isFeatureLike = feature instanceof FeatureLike;
+	const curStyle = feature?.getStyle();
+	if (curStyle) {
+		feature.set('originStyle', curStyle);
+	}
+	if (style) {
+		feature?.setStyle(style);
+	} else {
+		let style = null;
+		if (geometryType === 'Point') {
+			style = new Style({
+				image: new Circle({
+					radius: 5,
+					fill: new Fill({ color: 'yellow' }),
+				}),
+			});
+		} else if (geometryType === 'LineString') {
+			style = new Style({
+				stroke: new Stroke({
+					color: 'yellow',
+					width: 2,
+				}),
+			});
+		}
+		if (style) {
+			feature?.setStyle(style);
+			hoverStyleMap[key] = style;
+		}
+	}
+};
+
+const overlayLabelMap = {};
+
+const renderFeatureLabel = new Set();
+
+const setOverlayLabel = (feature: FeatureLike, resolution: any) => {
+	const oname = feature.get('oname');
+	const otype = feature.get('otype');
+	const key = `${oname}_${otype}`;
+	if (resolution > 30) {
+		const overlay = overlayLabelMap[key];
+		if (overlay) {
+			(overlay as MarkerOverlay).setVisible(false);
+		}
+		return;
+	}
+
+	if (overlayLabelMap.hasOwnProperty(key)) {
+		return;
+	}
+
+	const position = (feature as any).getFlatCoordinates();
+	const div = document.createElement('div');
+
+	div.innerHTML = `first-${oname[0]}`;
+	const overlay = new MarkerOverlay({
+		position,
+		element: div,
+		stopEvent: false,
+	});
+	// overlayLabelMap[key] = overlay;
+	// renderFeatureLabel.add(olUid);
+	renderFeatureLabel.add(key);
+	overlayLabelMap[key] = overlay;
+
+	olMap.value.map.addOverlay(overlay);
+};
+
+const handleVectorTileClick = (feature, layer) => {
+	panelToolRef.value.featureClick(feature);
+	feature && panelToolRef.value.setActivePanel(MapPanelTool.Property);
+	// setActiveStyle(feature,layer);
+};
+const propertyMap = ref({});
+const propertyConfigMap = ref({});
+const getPropertyList = async () => {
+	const res = await getMapVpropsByPost();
+	const otypes = res?.otypes ?? {};
+	propertyMap.value = otypes;
+
+	const res1 = await getMapVpropsConfigByPost();
+	propertyConfigMap.value = res1?.values ?? {};
+};
+
+const maxResolution = 1;
+
+const getText = function (textContent, resolution) {
+	let text = `${textContent}`;
+	if (resolution > maxResolution) {
+		text = '';
+	}
+
+	// else if (type == 'hide') {
+	// 	text = '';
+	// } else if (type == 'shorten') {
+	// 	text = text.trunc(12);
+	// } else if (type == 'wrap' && (!dom.placement || dom.placement.value != 'line')) {
+	// 	text = stringDivider(text, 16, '\n');
+	// }
+
+	return text;
+};
+const createTextStyle = (textContent, resolution) => {
+	return new Style({
+		text: new Text({
+			text: getText(textContent, resolution),
+			font: '14px Arial',
+			fill: new Fill({ color: '#000' }),
+			stroke: new Stroke({ color: '#fff', width: 2 }),
+			offsetX: 10, // 鏂囧瓧鐩稿浜庡嚑浣曚腑蹇冪殑姘村钩鍋忕Щ
+			offsetY: 20, // 鏂囧瓧鐩稿浜庡嚑浣曚腑蹇冪殑鍨傜洿鍋忕Щ
+		}),
+	});
+};
+
+const styleMap: Record<string, Record<string, Style>> = {
+	point: {},
+	line: {},
+	polygon: {},
+};
+
+const unsupportedLayers = ['dma1', 'dma2', 'dma3'];
+const layerStyleFunc = function (feature, resolution) {
+	const shape = feature.getGeometry().getType();
+	const styles = [];
+	switch (shape) {
+		case 'Point':
+			const pSize = feature.get('psize');
+
+			const pcolor = feature.get('pcolor');
+			const pstyle = feature.get('pstyle');
+			const pointStyle = olMap.value.getPointStyles({
+				size: pSize,
+				color: pcolor,
+				style: pstyle,
+			});
+
+			styles.push(pointStyle);
+			break;
+		case 'LineString':
+			const lSize = feature.get('lsize');
+			const lColor = feature.get('lcolor');
+			const lstyle = feature.get('lstyle');
+			const pSize1 = feature.get('psize');
+			const pcolor1 = feature.get('pcolor');
+			const pStyle1 = feature.get('pstyle');
+			const lineStyle = olMap.value.getLineStyles({
+				lsize: lSize,
+				lcolor: lColor,
+				lstyle: lstyle,
+				psize: pSize1,
+				pcolor: pcolor1,
+				pstyle: pStyle1,
+			});
+			styles.push(...lineStyle);
+			break;
+		case 'Polygon':
+			const pColor = feature.get('pcolor');
+			const lSize1 = feature.get('lsize');
+			const lColor1 = feature.get('lcolor');
+			const lstyle1 = feature.get('lstyle');
+			const polygonStyle = olMap.value.getPolygonStyles({
+				pcolor: pColor,
+				lsize: lSize1,
+				lcolor: lColor1,
+				lstyle: lstyle1,
+			});
+			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 = feature.get('tstring');
+
+	const tStringStyle = olMap.value.getLabelStyles({
+		textContent: tString,
+		resolution,
+	});
+	if (tStringStyle) {
+		styles.push(tStringStyle);
+	}
+	//#endregion
+
+	return styles;
+};
+
+const getGroupList = async () => {
+	const res = await getMapLayerGroupList();
+	const groupList = res?.values ?? [];
+	return groupList;
+};
+
+const getDrawStyles = async () => {
+	const res = await getMapDrawStyles();
+	const styleList = res?.values ?? [];
+	olMap.value.setDrawStyles(styleList);
+};
+
+const getThemeList = async () => {
+	const res = await getMapThemeList();
+	const themeList = res?.values ?? [];
+	const themeTreeData = themeList.reduce((preVal, curVal) => {
+		const group = curVal.group;
+		const groupId = `group-${group}`;
+		let mapGroupItem = preVal.find((item) => item.id === groupId);
+		if (!mapGroupItem) {
+			mapGroupItem = { id: groupId, title: group, type: 'theme-group' };
+			preVal.push(mapGroupItem);
+		}
+		if (!mapGroupItem.children) {
+			mapGroupItem.children = [];
+		}
+		const id = curVal.id;
+		const data = {
+			id,
+			title: curVal.title,
+			type: 'theme',
+			activeTheme: null,
+			legends: null,
+		};
+		mapGroupItem.children.push(data);
+		return preVal;
+	}, []);
+	olMap.value.setAllThemes(themeTreeData);
+};
+const initVectorTileLayer = async () => {
+	await getDrawStyles();
+	const res = await getMapLayersByPost();
+	const layers = reverse(res?.layers ?? []);
+	const layerModels = [];
+	for (const item of layers) {
+		const styleFunc = olMap.value.unsupportedLayers.includes(item.id) ? undefined : layerStyleFunc;
+		const layer = olMap.value.addCustomLayer(`${MAIN_URL}map/get_vector_tile?x={x}&y={y}&z={z}&layer_id=${item.id}`, styleFunc);
+
+		layer.set('originStyle', styleFunc);
+		layerModels.push(layer);
+	}
+	getGroupList().then((groupList) => {
+		olMap.value.setAllLayers(layerModels, layers, groupList);
+	});
+	if (layers.length === 0) return;
+
+	getThemeList();
+	getPropertyList();
+	olMap.value.on('featureChange', handleVectorTileClick);
+};
+const initMap = () => {
+	olMap.value = new OLMap({
+		container: containerRef.value,
+		sourceType: props.config?.sourceType,
+	});
+
+	addMarkerLayer();
+	infoWindowOverlay = olMap.value.createEleOverlay(infoWindowRef.value);
+	olMap.value.map.addOverlay(infoWindowOverlay);
+	initVectorTileLayer();
+};
+
+defineExpose({
+	olMap: olMap,
+});
 
 onMounted(() => {
 	initMap();
+	// window.olMap = olMap.value;
+	// window.map = olMap.value.map;
 });
 </script>
 <style scoped lang="scss"></style>

--
Gitblit v1.9.3