Newer
Older
smartwell_front_yizhuang / src / components / leaftletMap / leafletMap.vue
dutingting on 24 Mar 2023 10 KB 联调-自测-bug修复
<template>
  <div ref="map" :id="id" class="base-map">
    <slot/>
  </div>
</template>

<script>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import { crsDict } from './base/crsUtils'
// import 'leaflet-canvas-marker'
import 'leaflet-canvas-marker-xrr2021'
import { getWellInfo, getWellAlarms, getWellList } from '@/api/overview'
// import { getLatLng } from './base/commonTools'

export default {
  name: 'LeafletMap',
  props: {
    id: {
      type: String,
      required: true
    }, // id
    basemaps: {
      type: Array,
      required: true
    }, // 图层地址列表
    zoom: { // 缩放层级
      type: Number,
      default: 21
    },
    zooms: {
      type: Array,
      default: () => {
        return [15, 21]
      }
    }, // 缩放范围
    autoResize: { // 自动重绘
      type: Boolean,
      default: true
    },
    size: { // marker大小
      type: Array,
      default: function() {
        return [30, 30]
      }
    },
    center: {
      type: Array,
      default: () => {
        return [116.4, 39.9]
      }
    }, // 地图中心
    crs: {
      type: String,
      default: '3857'
    }, // 支持坐标系
    alarmMarkers: { // 报警Marker,原数据
      type: Array,
      default: function() {
        return []
      }
    },
    normalMarkers: { // 正常Marker,原数据
      type: Array,
      default: function() {
        return []
      }
    },
    anchor: { // 位移
      type: Array,
      default: () => [15, 30]
    },
    popupTemplate: { // 弹窗html内容
      type: String,
      default: '<div>hello</div>'
    },
    popupAnchor: { // 弹窗位移
      type: Array,
      default: function() {
        return [0, -24]
      }
    },
    // 是否显示全部井
    showAll: {
      type: Boolean,
      default: false
    },
    // 是否显示报警
    showAlarm: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      map: null, // 底图
      basebasemaps: [], // 地图图层的地址
      overlays: [], // 地图上的标注,报警的
      ciLayer: null, // 告警图层
      queryString: '', // 地图筛选条件
      normalCoverage: null // 正常井图层
    }
  },
  watch: {
    basemaps: {
      handler(val) {
        console.log(val)
        this.clearBaseMaps()
        this.addBaseMaps()
      },
      deep: true
    },
    zoom(val) {
      this.map.setZoom(val)
    },
    center(val, oldVal) {
      console.log('中点', val)
    },
    // 报警的井列表
    alarmMarkers(val) {
      console.log('报警的井列表')
      if (this.showAll) {
        this.renderNormalMarkers() // 画正常井
      } else {
        this.renderMarkers()
      }
    },
    // 正常井列表
    normalMarkers() {
      console.log('正常的井列表')
      if (this.showAll) {
        this.renderNormalMarkers()
      }
    },
    // 是否展示全部井
    showAll(val) {
      if (!val) { // 不显示全部井
        if (this.ciLayer) {
          this.map.removeLayer(this.ciLayer)
          this.renderMarkers()
        }
      }
    }
  },
  mounted() {
    this.initMap()
  },
  methods: {
    // 初始化地图
    initMap() {
      const { zooms, zoom, center, crs } = this
      const map = L.map(this.$refs.map, {
        minZoom: zooms[0],
        maxZoom: zooms[1],
        center: center,
        zoom: zoom,
        zoomControl: false,
        doubleClickZoom: false, // 禁用双击放大
        attributionControl: true, // 默认情况下,是否将 attribution 版权控件添加到地图中。
        crs: crsDict[crs]
      })
      map.doubleClickZoom.disable()
      this.map = map // data上需要挂载
      this.$emit('onload', map)
      this.clearBaseMaps() // 清除所有图层
      // 加载图层
      this.addBaseMaps()
    },
    // 添加图层
    addBaseMaps() {
      console.log('添加底图')
      const { map, basemaps } = this
      basemaps.forEach(layerInfo => {
        if (layerInfo.show) {
          const options = {}
          if (layerInfo.zooms) {
            options.minZoom = layerInfo.zooms[0]
            options.maxZoom = layerInfo.zooms[1]
          }// 缩放情况
          const layer = L.tileLayer(layerInfo.url, options)
          this.basebasemaps.push({ name: layerInfo.name, layer: layer.addTo(map) })
        }
      })
    },
    // 清除所有图层
    clearBaseMaps() {
      const { map } = this
      this.basebasemaps.forEach(layer => {
        map.removeLayer(layer)
      })
      this.basebasemaps = []
    },
    // 加载报警markers
    renderMarkers() {
      console.log('render.markers')
      const { map, alarmMarkers, size, anchor, popupAnchor } = this
      if (!map) {
        return
      }
      if (this.ciLayer) {
        console.log('清理图层')
        map.removeLayer(this.ciLayer)
      }
      // 告警图层
      this.ciLayer = L.canvasIconLayer({}).addTo(map)
      this.overlays = []
      // 遍历所有报警井信息
      for (const item of alarmMarkers) {
        console.log('画图层')
        const icon = L.icon({
          iconUrl: './static/images/map_images/alarm-well1.png',
          iconSize: size,
          iconAnchor: [18, 15],
          popupAnchor: popupAnchor
        })
        const opts = {
          icon: icon,
          title: item.wellCode,
          wellId: item.wellId
        }
        // console.log(item)
        // console.log('坐标', [item.position.lat, item.position.lng])
        const marker = L.marker([item.position.lat, item.position.lng], opts)
        this.ciLayer.addLayer(marker)
        this.overlays.push(marker)
      }
      map.setView(map.getCenter())
      const that = this
      // 监听点击marker
      this.ciLayer.addOnClickListener(function(e, data) {
        // console.log('监听到点击告警信息')
        // console.log(e)
        // console.log(data[0].data.options)
        // 某井报警信息
        getWellAlarms(data[0].data.options.wellId).then(response => {
          if (response.code === 200) {
            const wellInfo = response.data
            const alarmInfo = {
              wellCode: wellInfo.wellCode,
              position: wellInfo.position,
              deptName: wellInfo.deptName,
              wellTypeName: wellInfo.wellTypeName,
              alarms: wellInfo.alarmList,
              deep: wellInfo.deep
            }
            let dom = "<div class='alarm-window'>" +
              "<div style='line-height: 20px;color: red;font-weight: bold;'>" + alarmInfo.wellCode + '</div>' +
              "<div style='line-height: 23px;font-size: 14px;'>"
            for (const alarm of alarmInfo.alarms) {
              dom += "<div>告警原因:<span style='color:red'>" + alarm.alarmContent + '</span></div>' +
                '<div>设备编号:<span style="font-weight: bold;">' + alarm.devcode + '</span></div>'
            }
            dom += "<div class='divider'></div>" +
              '<div>井类型: ' + alarmInfo.wellTypeName + '</div>' +
              '<div>权属单位:' + alarmInfo.deptName + '</div>' +
              '<div>详细地址:' + alarmInfo.position + '</div>' +
              '</div>' +
              '</div>'
            console.log('setPopupContent_inrender')
            that.$emit('popupCenter', [e.latlng.lat, e.latlng.lng])
            // 显示popup
            L.popup()
              .setLatLng([e.latlng.lat, e.latlng.lng])
              .setContent(dom)
              .openOn(map)
          }
        })
      })
    },
    // 加载正常井markers
    renderNormalMarkers() {
      // console.log('渲染正常井图层')
      const { map, normalMarkers, size, anchor, popupAnchor } = this
      if (!map) {
        return
      }
      this.renderMarkers()
      // 正常图层
      // 遍历所有报警井信息
      for (const item of normalMarkers) {
        console.log('画正常井图层')
        const icon = L.icon({
          iconUrl: './static/images/map_images/1.png',
          iconSize: [12, 16],
          iconAnchor: [6, 8],
          popupAnchor: popupAnchor
        })
        const opts = {
          icon: icon,
          title: item.wellCode,
          wellId: item.id // 井id
        }
        const marker = L.marker([item.coordinateY, item.coordinateX], opts)
        this.ciLayer.addLayer(marker)
      }
      // map.setView(map.getCenter())
    },
    // 打开弹窗
    openAlarmInfoWindow(wellId) {
      const { map } = this
      for (const overlay of this.overlays) {
        if (overlay.options.wellId === wellId) {
          getWellAlarms(wellId).then(response => {
            if (response.code === 200) {
              const wellInfo = response.data
              const alarmInfo = {
                wellCode: wellInfo.wellCode,
                position: wellInfo.position,
                deptName: wellInfo.deptName,
                wellTypeName: wellInfo.wellTypeName,
                alarms: wellInfo.alarmList,
                deep: wellInfo.deep
              }
              let dom = "<div class='alarm-window'>" +
              "<div style='line-height: 20px;color: red;font-weight: bold;'>" + alarmInfo.wellCode + '</div>' +
              "<div style='line-height: 23px;font-size: 14px;'>"
              for (const alarm of alarmInfo.alarms) {
                dom += "<div>告警原因:<span style='color:red'>" + alarm.alarmContent + '</span></div>' +
                '<div>设备编号:<span style="font-weight: bold;">' + alarm.devcode + '</span></div>'
              }
              dom += "<div class='divider'></div>" +
              '<div>井类型: ' + alarmInfo.wellTypeName + '</div>' +
              '<div>权属单位:' + alarmInfo.deptName + '</div>' +
              '<div>详细地址:' + alarmInfo.position + '</div>' +
              '</div>' +
              '</div>'
              // map.setZoom(17)
              map.setZoom(37)
              console.log('ppp')
              console.log([overlay.getLatLng().lat, overlay.getLatLng().lng])
              this.$emit('popupCenter', [overlay.getLatLng().lat, overlay.getLatLng().lng])
              setTimeout(() => {
                map.flyTo([overlay.getLatLng().lat, overlay.getLatLng().lng])
                // map.panTo([overlay.getLatLng().lat, overlay.getLatLng().lng])
                // 显示popup
                L.popup()
                  .setLatLng([overlay.getLatLng().lat, overlay.getLatLng().lng])
                  .setContent(dom)
                  .openOn(map)
              })
            }
          })
        }
      }
    },
    // 关闭弹窗
    closePopup() {
      this.map.closePopup()
    }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
  .base-map {
    width:100%;
    // height: calc(100vh - 84px);
    height: calc(100vh - 115px);
  }
  .alarm-window{
    max-width: 250px;
    background-color: #ffeaf1;
    .alarm-header {
      padding: 10px 10px 5px 10px;
      line-height: 30px;
      color: red;
      font-weight: bold;
      background-color: #ffecec;
    }
    .alarm-body{
      padding: 5px 10px 10px 10px;
      line-height: 23px;
      font-size: 14px;
      .alarm-red{
        color: #ff0000;
      }
    }
  }
</style>