gerson
2025-02-09 6e2557b3ae3e1b43bc01a5122f5fd4aa9b83d755
src/components/chat/chatComponents/summaryCom/components/recordSetTable/map/BasicMap.vue
@@ -34,20 +34,56 @@
            </div>
         </div>
      </div>
      <LayerControl v-if="olMap" :olMap="olMap" class="absolute top-3 left-10 z-10" />
      <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-12 right-2 z-14"
         :olMap="olMap"
      ></PanelTool>
      <!-- <el-button class="absolute top-3 right-4" @click="changeTheme" type="primary">切换主题</el-button> -->
   </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 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 LayerControl from './LayerControl.vue';
import PanelTool from './panelTool/index.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';
const panelToolRef = useCompRef(PanelTool);
const props = withDefaults(
   defineProps<{
      data: any;
@@ -63,6 +99,7 @@
      }),
   }
);
const colsArray = computed(() => {
   return props.data.cols ?? [];
});
@@ -132,15 +169,274 @@
      },
   });
};
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);
   // 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: {},
};
/** @description 已经做的layer,后续全部做好,可以不做判断 */
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 lineStyle = olMap.value.getLineStyles({
            lsize: lSize,
            lcolor: lColor,
            lstyle: lstyle,
         });
         styles.push(...lineStyle);
         break;
      case 'Polygon':
         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 ?? []);
   if (layers.length === 0) return;
   const layerModels = [];
   for (const item of layers) {
      const styleFunc = 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);
   });
   getThemeList();
   getPropertyList();
   olMap.value.on('featureChange', handleVectorTileClick);
};
const initMap = () => {
   olMap.value = new OLMap({
      container: containerRef.value,
      sourceType: props.config?.sourceType,
      markerIsVisible: props.config?.markerIsVisible,
   });
   addMarkerLayer();
   infoWindowOverlay = olMap.value.createEleOverlay(infoWindowRef.value);
   olMap.value.map.addOverlay(infoWindowOverlay);
   initVectorTileLayer();
};
defineExpose({
@@ -149,6 +445,8 @@
onMounted(() => {
   initMap();
   // window.olMap = olMap.value;
   // window.map = olMap.value.map;
});
</script>
<style scoped lang="scss"></style>