|  | @@ -0,0 +1,819 @@
 | 
	
		
			
				|  |  | +<script lang="ts" setup>
 | 
	
		
			
				|  |  | +import {points} from "@turf/helpers";
 | 
	
		
			
				|  |  | +import {bbox} from "@turf/bbox";
 | 
	
		
			
				|  |  | +import {LayerPopup, LineLayer, PointLayer, PolygonLayer, Popup, RasterLayer, Scene} from '@antv/l7';
 | 
	
		
			
				|  |  | +import {Map} from '@antv/l7-maps';
 | 
	
		
			
				|  |  | +// import {getLegendData, loadMapData, setCenter} from "@/utils/mapConfig";
 | 
	
		
			
				|  |  | +import {formatStringByTemplate} from "@/utils/string";
 | 
	
		
			
				|  |  | +import {copyObj} from "@/utils/ruoyi";
 | 
	
		
			
				|  |  | +import {onMounted, reactive} from "vue";
 | 
	
		
			
				|  |  | +import {getImageSrc} from "@/utils/image";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +let scene;
 | 
	
		
			
				|  |  | +let pointLayer;
 | 
	
		
			
				|  |  | +let pointLayerText;
 | 
	
		
			
				|  |  | +let lineLayer;
 | 
	
		
			
				|  |  | +let lineTextLayer;
 | 
	
		
			
				|  |  | +let polygonLayer;
 | 
	
		
			
				|  |  | +let polygonTextLayer;
 | 
	
		
			
				|  |  | +const token = 'a4eab5a1b0d94268669e192b8799f626';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 初始化地图
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function init() {
 | 
	
		
			
				|  |  | +  const scene = new Scene({
 | 
	
		
			
				|  |  | +    id: 'mapDiv',
 | 
	
		
			
				|  |  | +    map: new Map({
 | 
	
		
			
				|  |  | +      center: [120.543139, 31.243133],
 | 
	
		
			
				|  |  | +      zoom: 9,
 | 
	
		
			
				|  |  | +    }),
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const url1 = 'https://t0.tianditu.gov.cn/img_w/wmts?tk=b72aa81ac2b3cae941d1eb213499e15e&';
 | 
	
		
			
				|  |  | +  const layer1 = new RasterLayer().source(url1, {
 | 
	
		
			
				|  |  | +    parser: {
 | 
	
		
			
				|  |  | +      type: 'rasterTile',
 | 
	
		
			
				|  |  | +      tileSize: 256,
 | 
	
		
			
				|  |  | +      wmtsOptions: {
 | 
	
		
			
				|  |  | +        layer: 'img',
 | 
	
		
			
				|  |  | +        tileMatrixset: 'w',
 | 
	
		
			
				|  |  | +        format: 'tiles',
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  scene.on('loaded', () => {
 | 
	
		
			
				|  |  | +    scene.addLayer(layer1);
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // scene = new Scene({
 | 
	
		
			
				|  |  | +  //   id: 'mapDiv',
 | 
	
		
			
				|  |  | +  //   map: new Map({}),
 | 
	
		
			
				|  |  | +  // });
 | 
	
		
			
				|  |  | +  // scene.on('mapmove', () => {
 | 
	
		
			
				|  |  | +  //   console.log('中心点:', scene.getCenter().lng, scene.getCenter().lat, scene.getZoom(), scene.getPitch())
 | 
	
		
			
				|  |  | +  // }); // 地图平移时触发事件
 | 
	
		
			
				|  |  | +  //
 | 
	
		
			
				|  |  | +  // // 天地图卫片地图
 | 
	
		
			
				|  |  | +  // scene.on('loaded', () => {
 | 
	
		
			
				|  |  | +  //   // 底图服务
 | 
	
		
			
				|  |  | +  //   const baseLayer = new RasterLayer({zIndex: 1})
 | 
	
		
			
				|  |  | +  //     .source(
 | 
	
		
			
				|  |  | +  //       `https://t1.tianditu.gov.cn/DataServer?T=vec_w&X={x}&Y={y}&L={z}&tk=${this.token}`,
 | 
	
		
			
				|  |  | +  //       {
 | 
	
		
			
				|  |  | +  //         parser: {
 | 
	
		
			
				|  |  | +  //           type: 'rasterTile',
 | 
	
		
			
				|  |  | +  //           tileSize: 256,
 | 
	
		
			
				|  |  | +  //         }
 | 
	
		
			
				|  |  | +  //       }
 | 
	
		
			
				|  |  | +  //     );
 | 
	
		
			
				|  |  | +  //   // 注记服务
 | 
	
		
			
				|  |  | +  //   const annotionLayer = new RasterLayer({zIndex: 2})
 | 
	
		
			
				|  |  | +  //     .source(
 | 
	
		
			
				|  |  | +  //       `https://t1.tianditu.gov.cn/DataServer?T=cva_w&X={x}&Y={y}&L={z}&tk=${this.token}`,
 | 
	
		
			
				|  |  | +  //       {
 | 
	
		
			
				|  |  | +  //         parser: {
 | 
	
		
			
				|  |  | +  //           type: 'rasterTile',
 | 
	
		
			
				|  |  | +  //           tileSize: 256,
 | 
	
		
			
				|  |  | +  //         }
 | 
	
		
			
				|  |  | +  //       }
 | 
	
		
			
				|  |  | +  //     );
 | 
	
		
			
				|  |  | +  //   scene.addLayer(baseLayer);
 | 
	
		
			
				|  |  | +  //   scene.addLayer(annotionLayer);
 | 
	
		
			
				|  |  | +  //
 | 
	
		
			
				|  |  | +  //   setCenter(scene, [120.543139, 31.243133], 8.03)
 | 
	
		
			
				|  |  | +  // });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function getWaterQualityTextByLevel(val, hasUnit = false) {
 | 
	
		
			
				|  |  | +  let waterQualityText = ''
 | 
	
		
			
				|  |  | +  switch (val) {
 | 
	
		
			
				|  |  | +    case '1':
 | 
	
		
			
				|  |  | +      waterQualityText = 'Ⅰ'
 | 
	
		
			
				|  |  | +      break
 | 
	
		
			
				|  |  | +    case '2':
 | 
	
		
			
				|  |  | +      waterQualityText = 'Ⅱ'
 | 
	
		
			
				|  |  | +      break
 | 
	
		
			
				|  |  | +    case '3':
 | 
	
		
			
				|  |  | +      waterQualityText = 'Ⅲ'
 | 
	
		
			
				|  |  | +      break
 | 
	
		
			
				|  |  | +    case '4':
 | 
	
		
			
				|  |  | +      waterQualityText = 'Ⅳ'
 | 
	
		
			
				|  |  | +      break
 | 
	
		
			
				|  |  | +    case '5':
 | 
	
		
			
				|  |  | +      waterQualityText = 'Ⅴ'
 | 
	
		
			
				|  |  | +      break
 | 
	
		
			
				|  |  | +    case '6':
 | 
	
		
			
				|  |  | +      waterQualityText = 'Ⅵ'
 | 
	
		
			
				|  |  | +      break
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (hasUnit && waterQualityText) {
 | 
	
		
			
				|  |  | +    waterQualityText = waterQualityText + '类'
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  return waterQualityText
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 图例
 | 
	
		
			
				|  |  | +const legendList = reactive([{}])
 | 
	
		
			
				|  |  | +const legendStyle = reactive({})
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** 添加点(多个) */
 | 
	
		
			
				|  |  | +function addPoint(data, dataOptions = {}, nameField) {
 | 
	
		
			
				|  |  | +  // 1. 删除之前的图层
 | 
	
		
			
				|  |  | +  scene.removeAllLayer();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 2. 添加点
 | 
	
		
			
				|  |  | +  // 点位标注
 | 
	
		
			
				|  |  | +  pointLayer = new PointLayer({})
 | 
	
		
			
				|  |  | +    .source(data, dataOptions)
 | 
	
		
			
				|  |  | +    .shape('circle')
 | 
	
		
			
				|  |  | +    .size(16)
 | 
	
		
			
				|  |  | +    .color('#004ef8')
 | 
	
		
			
				|  |  | +    .active(true)
 | 
	
		
			
				|  |  | +  scene.addLayer(pointLayer);
 | 
	
		
			
				|  |  | +  // 名称标注
 | 
	
		
			
				|  |  | +  pointLayerText = new PointLayer()
 | 
	
		
			
				|  |  | +    .source(data, dataOptions)
 | 
	
		
			
				|  |  | +    .shape(nameField, 'text')
 | 
	
		
			
				|  |  | +    .size(14)
 | 
	
		
			
				|  |  | +    .color('#000')
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      textOffset: [0, -50],
 | 
	
		
			
				|  |  | +      spacing: 2, // 字符间距
 | 
	
		
			
				|  |  | +      stroke: '#ffffff', // 描边颜色
 | 
	
		
			
				|  |  | +      strokeWidth: 2, // 描边宽度
 | 
	
		
			
				|  |  | +      strokeOpacity: 1.0,
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  scene.addLayer(pointLayerText);
 | 
	
		
			
				|  |  | +  // 3. 添加悬浮窗口
 | 
	
		
			
				|  |  | +  let keys = Object.keys(data[0]);
 | 
	
		
			
				|  |  | +  keys = keys.filter(k => !['经度', '纬度'].includes(k));
 | 
	
		
			
				|  |  | +  const fields = keys.map(k => {
 | 
	
		
			
				|  |  | +    return {
 | 
	
		
			
				|  |  | +      field: k,
 | 
	
		
			
				|  |  | +      formatField: () => k,
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +  const layerPopup = new LayerPopup({
 | 
	
		
			
				|  |  | +    items: [
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        layer: pointLayer,
 | 
	
		
			
				|  |  | +        fields: fields,
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    ],
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +  scene.addPopup(layerPopup);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** 添加线(多个) */
 | 
	
		
			
				|  |  | +function addLine(data, nameField) {
 | 
	
		
			
				|  |  | +  // 1. 删除之前的图层
 | 
	
		
			
				|  |  | +  scene.removeAllLayer();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  lineLayer = new LineLayer()
 | 
	
		
			
				|  |  | +    .source(data)
 | 
	
		
			
				|  |  | +    .size(5)
 | 
	
		
			
				|  |  | +    .shape('line')
 | 
	
		
			
				|  |  | +    .active(true)
 | 
	
		
			
				|  |  | +    .color('ICON', (ICON) => {
 | 
	
		
			
				|  |  | +      switch (ICON) {
 | 
	
		
			
				|  |  | +        case '1':
 | 
	
		
			
				|  |  | +          return '#1d8add'
 | 
	
		
			
				|  |  | +        case '2':
 | 
	
		
			
				|  |  | +          return '#4af905'
 | 
	
		
			
				|  |  | +        case '3':
 | 
	
		
			
				|  |  | +          return '#fed202'
 | 
	
		
			
				|  |  | +        case '4':
 | 
	
		
			
				|  |  | +          return '#f91005'
 | 
	
		
			
				|  |  | +        case '5':
 | 
	
		
			
				|  |  | +          return '#fb0891'
 | 
	
		
			
				|  |  | +        case '6':
 | 
	
		
			
				|  |  | +          return '#252627'
 | 
	
		
			
				|  |  | +        default:
 | 
	
		
			
				|  |  | +          return '#909399'
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      borderWidth: 0.4,
 | 
	
		
			
				|  |  | +      borderColor: '#fff',
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  scene.addLayer(lineLayer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 名称标注
 | 
	
		
			
				|  |  | +  const texts = []
 | 
	
		
			
				|  |  | +  data.features.forEach(d => {
 | 
	
		
			
				|  |  | +    let index = Math.ceil(d.geometry.coordinates[0].length / 2)
 | 
	
		
			
				|  |  | +    let array = d.geometry.coordinates[0][index]
 | 
	
		
			
				|  |  | +    texts.push({name: d.properties[nameField], x: array[0], y: array[1]})
 | 
	
		
			
				|  |  | +  })
 | 
	
		
			
				|  |  | +  lineTextLayer = new PointLayer()
 | 
	
		
			
				|  |  | +    .source(texts, {
 | 
	
		
			
				|  |  | +      parser: {
 | 
	
		
			
				|  |  | +        type: 'json',
 | 
	
		
			
				|  |  | +        x: 'x',
 | 
	
		
			
				|  |  | +        y: 'y',
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +    .shape('name', 'text')
 | 
	
		
			
				|  |  | +    .color('#fff')
 | 
	
		
			
				|  |  | +    .size(14)
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      textOffset: [0, -50],
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  scene.addLayer(lineTextLayer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 悬浮窗
 | 
	
		
			
				|  |  | +  const fields = [
 | 
	
		
			
				|  |  | +    {field: 'HLNM', formatField: () => '河流名称'},
 | 
	
		
			
				|  |  | +    {field: 'ICON', formatField: () => '水质', formatValue: (val) => getWaterQualityTextByLevel(val, true)},
 | 
	
		
			
				|  |  | +  ];
 | 
	
		
			
				|  |  | +  const layerPopup = new LayerPopup({items: [{layer: lineLayer, fields: fields,},],});
 | 
	
		
			
				|  |  | +  scene.addPopup(layerPopup);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function addPolygon(data, nameField) {
 | 
	
		
			
				|  |  | +  // 1. 删除之前的图层
 | 
	
		
			
				|  |  | +  scene.removeAllLayer();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const color = [
 | 
	
		
			
				|  |  | +    'rgb(255,255,217)',
 | 
	
		
			
				|  |  | +    'rgb(237,248,177)',
 | 
	
		
			
				|  |  | +    'rgb(199,233,180)',
 | 
	
		
			
				|  |  | +    'rgb(127,205,187)',
 | 
	
		
			
				|  |  | +    'rgb(65,182,196)',
 | 
	
		
			
				|  |  | +    'rgb(29,145,192)',
 | 
	
		
			
				|  |  | +    'rgb(34,94,168)',
 | 
	
		
			
				|  |  | +    'rgb(12,44,132)',
 | 
	
		
			
				|  |  | +  ];
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   *         .scale('用水量', {
 | 
	
		
			
				|  |  | +   *           type: 'quantile',
 | 
	
		
			
				|  |  | +   *         })
 | 
	
		
			
				|  |  | +   *         .color('用水量', color)
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  const layer = new PolygonLayer({})
 | 
	
		
			
				|  |  | +    .source(data)
 | 
	
		
			
				|  |  | +    .color('rgba(65,182,196,0.4)')
 | 
	
		
			
				|  |  | +    .shape('fill')
 | 
	
		
			
				|  |  | +    .active(true);
 | 
	
		
			
				|  |  | +  const layer2 = new LineLayer({zIndex: 2})
 | 
	
		
			
				|  |  | +    .source(data)
 | 
	
		
			
				|  |  | +    .color('#fff')
 | 
	
		
			
				|  |  | +    .active(true)
 | 
	
		
			
				|  |  | +    .size(1)
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      lineType: 'dash',
 | 
	
		
			
				|  |  | +      dashArray: [2, 2],
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  scene.addLayer(layer);
 | 
	
		
			
				|  |  | +  scene.addLayer(layer2);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const polygonTextLayer = new PointLayer({})
 | 
	
		
			
				|  |  | +    .source(data)
 | 
	
		
			
				|  |  | +    .shape(nameField, 'text')
 | 
	
		
			
				|  |  | +    .size(12)
 | 
	
		
			
				|  |  | +    .color('#000')
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
 | 
	
		
			
				|  |  | +      textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直]
 | 
	
		
			
				|  |  | +      spacing: 2, // 字符间距
 | 
	
		
			
				|  |  | +      padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
 | 
	
		
			
				|  |  | +      stroke: '#ffffff', // 描边颜色
 | 
	
		
			
				|  |  | +      strokeWidth: 2, // 描边宽度
 | 
	
		
			
				|  |  | +      strokeOpacity: 1.0,
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  scene.addLayer(polygonTextLayer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // layer.on('mousemove', (e) => {
 | 
	
		
			
				|  |  | +  //   const popup = new Popup({
 | 
	
		
			
				|  |  | +  //     offsets: [0, 0],
 | 
	
		
			
				|  |  | +  //     closeButton: false,
 | 
	
		
			
				|  |  | +  //   })
 | 
	
		
			
				|  |  | +  //     .setLnglat(e.lngLat)
 | 
	
		
			
				|  |  | +  //     .setHTML(
 | 
	
		
			
				|  |  | +  //       `
 | 
	
		
			
				|  |  | +  //       <span>${e.feature.properties['市']}: ${e.feature.properties['用水量']}</span>
 | 
	
		
			
				|  |  | +  //       <br/>
 | 
	
		
			
				|  |  | +  //       <span>许可水量: ${e.feature.properties['许可水量']}</span>
 | 
	
		
			
				|  |  | +  //       `
 | 
	
		
			
				|  |  | +  //     );
 | 
	
		
			
				|  |  | +  //   scene.addPopup(popup);
 | 
	
		
			
				|  |  | +  // });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function add3DPoint(list) {
 | 
	
		
			
				|  |  | +  const pointLayer = new PointLayer({})
 | 
	
		
			
				|  |  | +    .source(list, {
 | 
	
		
			
				|  |  | +      parser: {
 | 
	
		
			
				|  |  | +        type: 'json',
 | 
	
		
			
				|  |  | +        x: 'j',
 | 
	
		
			
				|  |  | +        y: 'w',
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +    .shape('cylinder')
 | 
	
		
			
				|  |  | +    .size('t', function (level) {
 | 
	
		
			
				|  |  | +      return [2, 2, level * 2 + 20];
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +    .animate(true)
 | 
	
		
			
				|  |  | +    .active(true)
 | 
	
		
			
				|  |  | +    .color('t', [
 | 
	
		
			
				|  |  | +      '#094D4A',
 | 
	
		
			
				|  |  | +      '#146968',
 | 
	
		
			
				|  |  | +      '#1D7F7E',
 | 
	
		
			
				|  |  | +      '#289899',
 | 
	
		
			
				|  |  | +      '#34B6B7',
 | 
	
		
			
				|  |  | +      '#4AC5AF',
 | 
	
		
			
				|  |  | +      '#5FD3A6',
 | 
	
		
			
				|  |  | +      '#7BE39E',
 | 
	
		
			
				|  |  | +      '#A1EDB8',
 | 
	
		
			
				|  |  | +      '#CEF8D6',
 | 
	
		
			
				|  |  | +    ]);
 | 
	
		
			
				|  |  | +  scene.addLayer(pointLayer);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function getScene() {
 | 
	
		
			
				|  |  | +  return scene;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function loadMapData(mapConfig) {
 | 
	
		
			
				|  |  | +  if (['left', 'center', 'right'].includes(mapConfig.legend.left)) {
 | 
	
		
			
				|  |  | +    switch (mapConfig.legend.left) {
 | 
	
		
			
				|  |  | +      case "left":
 | 
	
		
			
				|  |  | +        this.legendStyle.left = '10px';
 | 
	
		
			
				|  |  | +        break
 | 
	
		
			
				|  |  | +      case "center":
 | 
	
		
			
				|  |  | +        this.legendStyle.left = `calc(50% - (${this.$refs.mapLegend.offsetWidth} / 2))`;
 | 
	
		
			
				|  |  | +        break
 | 
	
		
			
				|  |  | +      case "right":
 | 
	
		
			
				|  |  | +        this.legendStyle.right = '10px';
 | 
	
		
			
				|  |  | +        break
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  } else if (mapConfig.legend.left.startsWith('-')) {
 | 
	
		
			
				|  |  | +    this.legendStyle.right = mapConfig.legend.left.replace('-', '')
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    this.legendStyle.left = mapConfig.legend.left
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (['top', 'center', 'bottom'].includes(mapConfig.legend.top)) {
 | 
	
		
			
				|  |  | +    switch (mapConfig.legend.top) {
 | 
	
		
			
				|  |  | +      case "top":
 | 
	
		
			
				|  |  | +        this.legendStyle.top = '10px';
 | 
	
		
			
				|  |  | +        break
 | 
	
		
			
				|  |  | +      case "center":
 | 
	
		
			
				|  |  | +        this.legendStyle.top = `calc(50% - (${this.$refs.mapLegend.offsetHeight} / 2))`;
 | 
	
		
			
				|  |  | +        break
 | 
	
		
			
				|  |  | +      case "bottom":
 | 
	
		
			
				|  |  | +        this.legendStyle.bottom = '10px';
 | 
	
		
			
				|  |  | +        break
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  } else if (mapConfig.legend.top.startsWith('-')) {
 | 
	
		
			
				|  |  | +    this.legendStyle.bottom = mapConfig.legend.top.replace('-', '')
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    this.legendStyle.top = mapConfig.legend.top
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // this.legendList = getLegendData(mapConfig)
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function fitBounds(data) {
 | 
	
		
			
				|  |  | +  const features = points(data);
 | 
	
		
			
				|  |  | +  const bboxs = bbox(features);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  let lttddd = (bboxs[3] - bboxs[1]) / 8 // 计算缩放级别
 | 
	
		
			
				|  |  | +  let lgtddd = (bboxs[2] - bboxs[0]) / 8 // 计算缩放级别
 | 
	
		
			
				|  |  | +  scene.fitBounds([[bboxs[0] - lgtddd, bboxs[1] - lttddd], [bboxs[2] + lgtddd, bboxs[3] + lttddd]]);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** 设置事件节点 */
 | 
	
		
			
				|  |  | +function setEventData(events) {
 | 
	
		
			
				|  |  | +  const _self = this
 | 
	
		
			
				|  |  | +  // 1. 删除之前的图层
 | 
	
		
			
				|  |  | +  scene.removeAllLayer();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const sourceOptions = {
 | 
	
		
			
				|  |  | +    parser: {
 | 
	
		
			
				|  |  | +      type: 'json',
 | 
	
		
			
				|  |  | +      x: 'x',
 | 
	
		
			
				|  |  | +      y: 'y',
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const imageSet = new Set()
 | 
	
		
			
				|  |  | +  events.forEach(event => {
 | 
	
		
			
				|  |  | +    if (event.image) {
 | 
	
		
			
				|  |  | +      imageSet.add(event.image)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  })
 | 
	
		
			
				|  |  | +  imageSet.forEach(image => {
 | 
	
		
			
				|  |  | +    scene.addImage(
 | 
	
		
			
				|  |  | +      image,
 | 
	
		
			
				|  |  | +      getImageSrc(image)
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +  })
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const imageEvents = events.filter(event => !!event.image)
 | 
	
		
			
				|  |  | +  const imagePointLayer = new PointLayer()
 | 
	
		
			
				|  |  | +    .source(imageEvents, sourceOptions)
 | 
	
		
			
				|  |  | +    .size(16)
 | 
	
		
			
				|  |  | +    .shape('image', Array.of(imageSet))
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      opacity: 0.8,
 | 
	
		
			
				|  |  | +      strokeWidth: 4
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +    .active(true);
 | 
	
		
			
				|  |  | +  scene.addLayer(imagePointLayer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const shapeEvents = events.filter(event => !event.image)
 | 
	
		
			
				|  |  | +  const shapePointLayer = new PointLayer()
 | 
	
		
			
				|  |  | +    .source(shapeEvents, sourceOptions)
 | 
	
		
			
				|  |  | +    .size(16)
 | 
	
		
			
				|  |  | +    .shape('shape')
 | 
	
		
			
				|  |  | +    .color('color')
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      opacity: 0.8,
 | 
	
		
			
				|  |  | +      strokeWidth: 4
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +    .active(true);
 | 
	
		
			
				|  |  | +  scene.addLayer(shapePointLayer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 设置标签
 | 
	
		
			
				|  |  | +  pointLayerText = new PointLayer()
 | 
	
		
			
				|  |  | +    .source(events, sourceOptions)
 | 
	
		
			
				|  |  | +    .shape('name', 'text')
 | 
	
		
			
				|  |  | +    .size(12)
 | 
	
		
			
				|  |  | +    .color('#000')
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
 | 
	
		
			
				|  |  | +      textOffset: [0, -60], // 文本相对锚点的偏移量 [水平, 垂直]
 | 
	
		
			
				|  |  | +      spacing: 2, // 字符间距
 | 
	
		
			
				|  |  | +      padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
 | 
	
		
			
				|  |  | +      stroke: '#fff', // 描边颜色
 | 
	
		
			
				|  |  | +      strokeWidth: 2, // 描边宽度
 | 
	
		
			
				|  |  | +      strokeOpacity: 1.0,
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  scene.addLayer(pointLayerText);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 显示弹窗
 | 
	
		
			
				|  |  | +  const showPopup = (e) => {
 | 
	
		
			
				|  |  | +    let data = e.feature.data
 | 
	
		
			
				|  |  | +    const template =
 | 
	
		
			
				|  |  | +      '<div class="entry-card-component"><section class="entry-base-info">' +
 | 
	
		
			
				|  |  | +      '<section class="base-info"><div class="entry-avatar"><img alt="" src="{{imgUrl}}"></div><div class="entry-text-info"><div class="entry-name">{{name}}</div><div class="entry-desc">{{summary}}</div></div></section></section>' +
 | 
	
		
			
				|  |  | +      '<section class="entry-nodes"><div class="nodes-list"><div class="node-item" data-id="{{id}}">' +
 | 
	
		
			
				|  |  | +      '<div class="title">{{source.title}}</div>' +
 | 
	
		
			
				|  |  | +      '<div class="sub-title"><div class="time">{{source.dateString}}</div>' +
 | 
	
		
			
				|  |  | +      '<div class="address">{{source.locationDesc}}</div></div>' +
 | 
	
		
			
				|  |  | +      '<div class="desc">{{source.description}}</div></div></div></section></div>'
 | 
	
		
			
				|  |  | +    const content = formatStringByTemplate(data, template)
 | 
	
		
			
				|  |  | +    const popup = new Popup({maxWidth: '36vw', autoClose: true})
 | 
	
		
			
				|  |  | +      .setLnglat(e.lngLat)
 | 
	
		
			
				|  |  | +      .setHTML(content);
 | 
	
		
			
				|  |  | +    scene.addPopup(popup);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 确保在 DOM 完全更新后执行
 | 
	
		
			
				|  |  | +    setTimeout(() => {
 | 
	
		
			
				|  |  | +      const eventItems = document.getElementsByClassName('node-item');
 | 
	
		
			
				|  |  | +      // 遍历所有 node-item 元素
 | 
	
		
			
				|  |  | +      Array.from(eventItems).forEach(item => {
 | 
	
		
			
				|  |  | +        item.addEventListener('click', (event) => {
 | 
	
		
			
				|  |  | +          // const id = event.currentTarget?.dataset?.id;
 | 
	
		
			
				|  |  | +          // _self.$router.push({path: `/geoTemporalSearch/detail/${id}`});
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +    }, 0); // 使用 setTimeout 来确保 DOM 已经更新
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  imagePointLayer.on('click', showPopup);
 | 
	
		
			
				|  |  | +  shapePointLayer.on('click', showPopup);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function setEventPoint(events) {
 | 
	
		
			
				|  |  | +  const _self = this
 | 
	
		
			
				|  |  | +  // 1. 删除之前的图层
 | 
	
		
			
				|  |  | +  scene.removeAllLayer();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const sourceOptions = {
 | 
	
		
			
				|  |  | +    parser: {
 | 
	
		
			
				|  |  | +      type: 'json',
 | 
	
		
			
				|  |  | +      x: 'x',
 | 
	
		
			
				|  |  | +      y: 'y',
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  const pointLayer = new PointLayer()
 | 
	
		
			
				|  |  | +    .source(events, sourceOptions)
 | 
	
		
			
				|  |  | +    .size(12)
 | 
	
		
			
				|  |  | +    .shape('simple')
 | 
	
		
			
				|  |  | +    .color('#fe7331')
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      strokeWidth: 4
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +    .active(false);
 | 
	
		
			
				|  |  | +  scene.addLayer(pointLayer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 设置标签
 | 
	
		
			
				|  |  | +  pointLayerText = new PointLayer()
 | 
	
		
			
				|  |  | +    .source(events, sourceOptions)
 | 
	
		
			
				|  |  | +    .shape('title', 'text')
 | 
	
		
			
				|  |  | +    .size(12)
 | 
	
		
			
				|  |  | +    .color('#000')
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
 | 
	
		
			
				|  |  | +      textOffset: [0, -60], // 文本相对锚点的偏移量 [水平, 垂直]
 | 
	
		
			
				|  |  | +      spacing: 2, // 字符间距
 | 
	
		
			
				|  |  | +      padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
 | 
	
		
			
				|  |  | +      stroke: '#fff', // 描边颜色
 | 
	
		
			
				|  |  | +      strokeWidth: 2, // 描边宽度
 | 
	
		
			
				|  |  | +      strokeOpacity: 1.0,
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  scene.addLayer(pointLayerText);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function setEventPointDetail(events) {
 | 
	
		
			
				|  |  | +  const allPoints = copyObj(events)
 | 
	
		
			
				|  |  | +  // 1. 删除之前的图层
 | 
	
		
			
				|  |  | +  scene.removeAllLayer();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  let mainEvent;
 | 
	
		
			
				|  |  | +  let index = events.findIndex(item => item.pointType === 'main');
 | 
	
		
			
				|  |  | +  if (index > -1) {
 | 
	
		
			
				|  |  | +    mainEvent = events.splice(index, 1); // 移除找到的第一个元素  l
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    return
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const sourceOptions = {
 | 
	
		
			
				|  |  | +    parser: {
 | 
	
		
			
				|  |  | +      type: 'json',
 | 
	
		
			
				|  |  | +      x: 'x',
 | 
	
		
			
				|  |  | +      y: 'y',
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  const pointLayer = new PointLayer()
 | 
	
		
			
				|  |  | +    .source(events, sourceOptions)
 | 
	
		
			
				|  |  | +    .size(12)
 | 
	
		
			
				|  |  | +    .shape('simple')
 | 
	
		
			
				|  |  | +    .color('#fe7331')
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      strokeWidth: 4
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +    .active(false);
 | 
	
		
			
				|  |  | +  scene.addLayer(pointLayer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const mainPointLayer = new PointLayer()
 | 
	
		
			
				|  |  | +    .source(mainEvent, sourceOptions)
 | 
	
		
			
				|  |  | +    .size(20)
 | 
	
		
			
				|  |  | +    .shape('simple')
 | 
	
		
			
				|  |  | +    .color('#fe7331')
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      strokeWidth: 4
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +    .active(false);
 | 
	
		
			
				|  |  | +  scene.addLayer(mainPointLayer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 设置标签
 | 
	
		
			
				|  |  | +  pointLayerText = new PointLayer()
 | 
	
		
			
				|  |  | +    .source(allPoints, sourceOptions)
 | 
	
		
			
				|  |  | +    .shape('title', 'text')
 | 
	
		
			
				|  |  | +    .size(12)
 | 
	
		
			
				|  |  | +    .color('#000')
 | 
	
		
			
				|  |  | +    .style({
 | 
	
		
			
				|  |  | +      textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
 | 
	
		
			
				|  |  | +      textOffset: [0, -60], // 文本相对锚点的偏移量 [水平, 垂直]
 | 
	
		
			
				|  |  | +      spacing: 2, // 字符间距
 | 
	
		
			
				|  |  | +      padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
 | 
	
		
			
				|  |  | +      stroke: '#fff', // 描边颜色
 | 
	
		
			
				|  |  | +      strokeWidth: 2, // 描边宽度
 | 
	
		
			
				|  |  | +      strokeOpacity: 1.0,
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  scene.addLayer(pointLayerText);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  for (let e of events) {
 | 
	
		
			
				|  |  | +    let data = []
 | 
	
		
			
				|  |  | +    if (e.pointType === 'previous') {
 | 
	
		
			
				|  |  | +      data.push({lng: e.x, lat: e.y, lng1: mainEvent[0].x, lat1: mainEvent[0].y})
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      data.push({lng: mainEvent[0].x, lat: mainEvent[0].y, lng1: e.x, lat1: e.y})
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    const lineLayer = new LineLayer()
 | 
	
		
			
				|  |  | +      .source(data, {
 | 
	
		
			
				|  |  | +        parser: {
 | 
	
		
			
				|  |  | +          type: 'json',
 | 
	
		
			
				|  |  | +          x: 'lng',
 | 
	
		
			
				|  |  | +          y: 'lat',
 | 
	
		
			
				|  |  | +          x1: 'lng1',
 | 
	
		
			
				|  |  | +          y1: 'lat1',
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  | +      .shape('line')
 | 
	
		
			
				|  |  | +      .size(2)
 | 
	
		
			
				|  |  | +      .color('#f00')
 | 
	
		
			
				|  |  | +      .animate({
 | 
	
		
			
				|  |  | +        duration: 2,
 | 
	
		
			
				|  |  | +        interval: 1,
 | 
	
		
			
				|  |  | +        trailLength: 1,
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  | +      .style({
 | 
	
		
			
				|  |  | +        lineType: 'dash', // 设置虚线类型
 | 
	
		
			
				|  |  | +        // dashArray: [5, 5], // 设置虚线的间隔和长度
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +    scene.addLayer(lineLayer);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  pointLayer.on('click', e => {
 | 
	
		
			
				|  |  | +    if (e.feature?.id) {
 | 
	
		
			
				|  |  | +      this.$emit('updateEventId', e.feature?.id)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +onMounted(() => {
 | 
	
		
			
				|  |  | +  init()
 | 
	
		
			
				|  |  | +})
 | 
	
		
			
				|  |  | +</script>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<template>
 | 
	
		
			
				|  |  | +  <div class="gw-map">
 | 
	
		
			
				|  |  | +    <!-- 2D地图 -->
 | 
	
		
			
				|  |  | +    <div id="mapDiv"></div>
 | 
	
		
			
				|  |  | +    <!--    <div v-if="legendList && legendList.length > 0" ref="mapLegend" :style="legendStyle" class="map-legend">-->
 | 
	
		
			
				|  |  | +    <!--      <ul>-->
 | 
	
		
			
				|  |  | +    <!--        <li v-for="(item, index) in legendList" :key="index">-->
 | 
	
		
			
				|  |  | +    <!--          <span :title="item.label">{{ item.label }}</span>-->
 | 
	
		
			
				|  |  | +    <!--          <template v-if="item.imgType === 'svg'">-->
 | 
	
		
			
				|  |  | +    <!--            <svg-icon :icon-class="item.src" :style="item.imgStyle" class="image"></svg-icon>-->
 | 
	
		
			
				|  |  | +    <!--          </template>-->
 | 
	
		
			
				|  |  | +    <!--          <template v-if="item.imgType === 'img'">-->
 | 
	
		
			
				|  |  | +    <!--            <el-image :src="item.src" :style="item.imgStyle" class="image"></el-image>-->
 | 
	
		
			
				|  |  | +    <!--          </template>-->
 | 
	
		
			
				|  |  | +    <!--        </li>-->
 | 
	
		
			
				|  |  | +    <!--      </ul>-->
 | 
	
		
			
				|  |  | +    <!--    </div>-->
 | 
	
		
			
				|  |  | +  </div>
 | 
	
		
			
				|  |  | +</template>
 | 
	
		
			
				|  |  | +<style lang="scss" scoped>
 | 
	
		
			
				|  |  | +.gw-map {
 | 
	
		
			
				|  |  | +  width: 100%;
 | 
	
		
			
				|  |  | +  height: 100%;
 | 
	
		
			
				|  |  | +  position: relative;
 | 
	
		
			
				|  |  | +  pointer-events: auto;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#mapDiv {
 | 
	
		
			
				|  |  | +  width: 100%;
 | 
	
		
			
				|  |  | +  height: 100%;
 | 
	
		
			
				|  |  | +  z-index: 1;
 | 
	
		
			
				|  |  | +  opacity: 1;
 | 
	
		
			
				|  |  | +  overflow: hidden;
 | 
	
		
			
				|  |  | +  filter: saturate(1) contrast(1) hue-rotate(0deg) brightness(1);
 | 
	
		
			
				|  |  | +  transform: rotateZ(0deg) rotateX(0deg) rotateY(0deg) skewX(0deg) skewY(0deg);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +.map-legend {
 | 
	
		
			
				|  |  | +  position: absolute;
 | 
	
		
			
				|  |  | +  bottom: 0;
 | 
	
		
			
				|  |  | +  right: 0;
 | 
	
		
			
				|  |  | +  z-index: 100;
 | 
	
		
			
				|  |  | +  background-color: #f2f2f2;
 | 
	
		
			
				|  |  | +  border-radius: 8px;
 | 
	
		
			
				|  |  | +  padding: 5px 10px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  ul {
 | 
	
		
			
				|  |  | +    margin: 0;
 | 
	
		
			
				|  |  | +    padding: 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    li {
 | 
	
		
			
				|  |  | +      margin: 5px 0;
 | 
	
		
			
				|  |  | +      list-style: none;
 | 
	
		
			
				|  |  | +      display: flex;
 | 
	
		
			
				|  |  | +      justify-content: flex-end;
 | 
	
		
			
				|  |  | +      align-items: center;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      span {
 | 
	
		
			
				|  |  | +        text-align: right;
 | 
	
		
			
				|  |  | +        width: 7vw;
 | 
	
		
			
				|  |  | +        white-space: nowrap;
 | 
	
		
			
				|  |  | +        overflow: hidden;
 | 
	
		
			
				|  |  | +        text-overflow: ellipsis;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      .image {
 | 
	
		
			
				|  |  | +        margin-left: 5px;
 | 
	
		
			
				|  |  | +        width: 1rem;
 | 
	
		
			
				|  |  | +        height: 1rem;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +:deep(.l7-control-logo) {
 | 
	
		
			
				|  |  | +  display: none;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +:deep(.esri-view-surface) {
 | 
	
		
			
				|  |  | +  &:after {
 | 
	
		
			
				|  |  | +    display: none;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +</style>
 | 
	
		
			
				|  |  | +<style lang="scss">
 | 
	
		
			
				|  |  | +.entry-card-component {
 | 
	
		
			
				|  |  | +  .entry-base-info {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .base-info {
 | 
	
		
			
				|  |  | +      display: flex;
 | 
	
		
			
				|  |  | +      margin-bottom: 14px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      .entry-avatar {
 | 
	
		
			
				|  |  | +        width: 90px;
 | 
	
		
			
				|  |  | +        margin-right: 8px;
 | 
	
		
			
				|  |  | +        height: 108px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        img {
 | 
	
		
			
				|  |  | +          width: 100%;
 | 
	
		
			
				|  |  | +          height: 100%;
 | 
	
		
			
				|  |  | +          object-fit: cover;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      .entry-text-info {
 | 
	
		
			
				|  |  | +        flex: 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .entry-name {
 | 
	
		
			
				|  |  | +          font-size: 16px;
 | 
	
		
			
				|  |  | +          line-height: 22px;
 | 
	
		
			
				|  |  | +          font-weight: 600;
 | 
	
		
			
				|  |  | +          margin-bottom: 10px;
 | 
	
		
			
				|  |  | +          margin-right: 24px;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .entry-desc {
 | 
	
		
			
				|  |  | +          line-height: 20px;
 | 
	
		
			
				|  |  | +          font-size: 12px;
 | 
	
		
			
				|  |  | +          word-break: break-word;
 | 
	
		
			
				|  |  | +          display: -webkit-box;
 | 
	
		
			
				|  |  | +          height: 80px;
 | 
	
		
			
				|  |  | +          overflow: hidden;
 | 
	
		
			
				|  |  | +          text-overflow: ellipsis;
 | 
	
		
			
				|  |  | +          -webkit-line-clamp: 4;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  .entry-nodes {
 | 
	
		
			
				|  |  | +    .nodes-list {
 | 
	
		
			
				|  |  | +      border-top: 1px solid #ebebeb;
 | 
	
		
			
				|  |  | +      padding-top: 7px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      .node-item {
 | 
	
		
			
				|  |  | +        cursor: pointer;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .title {
 | 
	
		
			
				|  |  | +          word-break: break-word;
 | 
	
		
			
				|  |  | +          display: -webkit-box;
 | 
	
		
			
				|  |  | +          -webkit-box-orient: vertical;
 | 
	
		
			
				|  |  | +          overflow: hidden;
 | 
	
		
			
				|  |  | +          text-overflow: ellipsis;
 | 
	
		
			
				|  |  | +          -webkit-line-clamp: 2;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .sub-title {
 | 
	
		
			
				|  |  | +          display: flex;
 | 
	
		
			
				|  |  | +          margin-bottom: 8px;
 | 
	
		
			
				|  |  | +          color: #999;
 | 
	
		
			
				|  |  | +          line-height: 14px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          .time {
 | 
	
		
			
				|  |  | +            margin-right: 4px;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          .address {
 | 
	
		
			
				|  |  | +            overflow: hidden;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .desc {
 | 
	
		
			
				|  |  | +          font-size: 12px;
 | 
	
		
			
				|  |  | +          color: #666;
 | 
	
		
			
				|  |  | +          line-height: 20px;
 | 
	
		
			
				|  |  | +          max-height: 40px;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +</style>
 |