Newer
Older
smartwell_front_yizhuang / src / components / CMap / components / cmap.vue
<template>
  <div>
    <div id="map" ref="map" class="mapDiv"/>
    <slot/>
  </div>
</template>

<script>
import bindEvents from './../base/bindEvents'
import { createIcon, getGlobalBounds, intersectBox } from '../base/factory.js'
import { getWellInfo, getWellAlarms } from '@/api/overview'

export default {
  name: 'Cmap',
  props: {
    center: { // 地图中心
      type: Object,
      default: function() {
        return { lat: 39.9, lng: 116.4 }
      }
    },
    zoom: { // 缩放层级
      type: Number,
      default: 12
    },
    minZoom: { // 最小缩放层级
      type: Number,
      default: 9
    },
    maxZoom: { // 最大缩放层级
      type: Number,
      default: 21
    },
    autoResize: { // 自动重绘
      type: Boolean,
      default: true
    },
    alarmMarkers: { // 报警Marker,原数据
      type: Array,
      default: function() {
        return []
      }
    },
    size: { // marker大小
      type: Array,
      default: function() {
        return [30, 30]
      }
    },
    anchor: { // 位移
      type: Array,
      default: function() {
        return [15, 30]
      }
    },
    popupTemplate: { // 弹窗html内容
      type: String,
      default: '<div>hello</div>'
    },
    popupAnchor: { // 弹窗位移
      type: Array,
      default: function() {
        return [0, -15]
      }
    }
  },
  data() {
    return {
      mapLayers: null, // 地图图层s
      overlays: [], // 地图上的标注,报警的
      // 海量点显示相关
      iconManager: {
        '': { size: [10, 10], anchor: [10, 10] }
      }, // 图标管理器
      layerId: 'yizhuang_poi', // 需要加载的图层id
      queryString: '', // 地图筛选条件
      layerInfoManager: {
        yizhuang_poi: { pm: 'yizhuang', table: 'poi', spanzoom: 18, latfd: 'COORDINATE_Y', lngfd: 'COORDINATE_X', style: '', morecon: '', namefd: 'WELL_NAME', keyfd: 'ID', attrfds: 'POSITION', cache: true, showtype: 'auto' }
      }, // 图层信息管理器
      style: 'resource/images/sys/markers/未分类/dot',
      stylepos: 1,
      overlay: null,
      overlayManager: {},
      featureLayerManager: {},
      lastMinBounds: null,
      clickEvent: null
    }
  },
  watch: {
    center(val, oldVal) {
      const { mapLayers } = this
      if (mapLayers != null && val !== oldVal) {
        mapLayers.setCenter(new CLatLng(val.lat, val.lng))
      }
    },
    'center.lng'(val, oldVal) {
      const { mapLayers, center } = this
      if (mapLayers != null && val !== oldVal) {
        mapLayers.setCenter(new CLatLng(center.lat, val))
      }
    },
    'center.lat'(val, oldVal) {
      const { mapLayers, center } = this
      if (mapLayers != null && val !== oldVal) {
        mapLayers.setCenter(new CLatLng(val, center.lng))
      }
    },
    zoom(val, oldVal) {
      const { mapLayers } = this
      mapLayers.setZoom(val)
    },
    minZoom(val, oldVal) {
      const { mapLayers } = this
      mapLayers.setMinZoom(val)
    },
    maxZoom(val, oldVal) {
      const { mapLayers } = this
      mapLayers.setMaxZoom(val)
    },
    alarmMarkers(val) {
      this.renderMarkers()
    }
  },
  mounted() {
    this.reset()
  },
  activated() {
    console.log('map activated')
    this.init()
  },
  methods: {
    // 初始化地图
    init() {
      if (this.mapLayers) {
        return
      }
      const $el = this.$refs.map
      /*      默认影像和矢量地图,此处无用
      const sateLayer = new CTileLayer(2, 18, 'sate', null, null)// 影像
      const sateLabelLayer = new CTileLayer(2, 18, 'satelabel', null, null)// 影像注记
      const mapLayer = new CTileLayer(2, 18, 'map', null, null)// 矢量
      const mapLabelLayer = new CTileLayer(2, 18, 'maplabel', null, null)// 矢量注记
      const VECTORMAP = new CMapType([mapLayer, mapLabelLayer], '矢量')
      const SATEMAP = new CMapType([sateLayer, sateLabelLayer], '影像')*/

      /**
       * 天地图影像和资源
       */
      // 天地图卫星影像资源,此处无用
      // const tianditusateLayer = new CTileLayer({
      //   zbound: [2, 18],
      //   tileName: 'sate',
      //   subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
      //   url: 'http://t{s}.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=80310778300778a15b36e70a6da5af00'
      // })
      // 天地图卫星影像资源备注资源,此处无用
      // const tianditusateLabelLayer = new CTileLayer({
      //   zbound: [2, 18],
      //   tileName: 'satelabel',
      //   subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
      //   url: 'http://t{s}.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=80310778300778a15b36e70a6da5af00'
      // })
      // 天地图矢量地图
      const tianditumapLayer = new CTileLayer({
        zbound: [2, 18],
        tileName: 'map',
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: 'http://t{s}.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=80310778300778a15b36e70a6da5af00'
      })
      // 天地图矢量地图标注
      const tianditumapLabelLayer = new CTileLayer({
        zbound: [2, 18],
        tileName: 'maplabel',
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: 'http://t{s}.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=80310778300778a15b36e70a6da5af00'
      })
      var mapLayer = new CTileLayer({
        zbound: [1, 18],
        tileName: 'map',
        zIndex: null,
        subdomains: CGeowin.BaseMapServer
      })

      var mapLabelLayer = new CTileLayer({
        zbound: [1, 18],
        tileName: 'maplabel',
        zIndex: null,
        subdomains: CGeowin.BaseMapServer
      })

      // const VECTORMAP = new CMapType([tianditumapLayer, tianditumapLabelLayer], '矢量')
      const VECTORMAP = new CMapType([mapLayer, mapLabelLayer], '矢量')

      const { getCenterPoint, zoom } = this
      // 初始化配置
      const opts = {
        mapTypes: [VECTORMAP],
        center: getCenterPoint(),
        zoom: zoom
      }
      // 加载图层
      this.mapLayers = new CMapLayers($el, opts)
      this.mapLayers.addMapTypeControl()

      bindEvents.call(this, this.mapLayers)

      // 此处强行初始化一次地图 回避一个由于错误的 center 字符串导致初始化失败抛出的错误
      // this.mapLayers.reset()
      this.reset()
      this.mapLayers.setCenter(getCenterPoint(), zoom)
      this.$emit('ready', { mapLayers: this.mapLayers })
      // this.renderMarkers()
    },
    // 加载报警markers
    renderMarkers() {
      console.log('render.markers')
      const { mapLayers, size, anchor, popupAnchor, alarmMarkers } = this
      if (!mapLayers) {
        return
      }
      // 清除报警标注图层
      for (const overlay of this.overlays) {
        mapLayers.removeOverlay(overlay) // 清除地图上所有的overlay
      }
      this.overlays = []
      // 遍历所有报警井信息
      for (const marker of alarmMarkers) {
        const options = {
          // url: markers.icon,
          url: './static/images/map_images/alarm-well1.png',
          size: size,
          anchor: anchor,
          popupAnchor: popupAnchor
        }
        const cmapIcon = createIcon(options)
        const opts = {
          icon: cmapIcon,
          title: marker.wellCode,
          draggable: false,
          wellId: marker.wellId
        }
        const overlay = new CMarker(new CLatLng(marker.position.lat, marker.position.lng), opts)
        mapLayers.addOverlay(overlay)
        // const overlay = mapLayers.drawMarker(new CLatLng(marker.position.lat, marker.position.lng), opts)
        overlay.bindPopup('')
        // overlay.openPopup()
        // 添加点击事件
        console.log('添加点击事件')
        CEvent.addListener(overlay, 'click', function(e) {
          console.log('click overlay')
          getWellAlarms(e.target.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 class='alarm-header'>" + alarmInfo.wellCode + '</div>' +
                "<div class='alarm-body'>"
              for (const alarm of alarmInfo.alarms) {
                dom += "<div>告警原因:<span class='alarm-red'>" + alarm.alarmContent + '</span></div>' +
                  '<div>设备编号:<span>' + 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')
              overlay.setPopupContent(dom)
            }
          })
        })
        this.overlays.push(overlay)
      }
    },
    // 清除报警图层
    clearAlarmMarkers() {
      const { mapLayers } = this
      // 清除报警标注图层
      for (const overlay of this.overlays) {
        mapLayers.clearOverlay(overlay) // 清除地图上所有的overlay
      }
      this.overlays = []
    },
    // 获取数据权限
    getDataScope() {
      const dataScope = this.$store.getters.dataScope
      return dataScope
    },
    // 加载海量点
    renderPoi(needClear = true) {
      // 需要清除原有查询条件
      if (needClear) {
        this.queryString = 'DEPTID IN (' + this.getDataScope() + ')'
      }
      console.log(this.queryString)
      const { mapLayers, layerInfoManager, layerId, overlayManager } = this
      // 没有图层信息提示错误
      if (layerInfoManager[layerId] == null) {
        this.$message.warning('没有' + layerId + '图层')
        return
      }
      const layerInfo = layerInfoManager[layerId]
      // 获取图标样式
      if (this.style instanceof Object) { // 如果style是对象,对象转string
        this.style = CJsonToStringify(this.style)
      }
      // stylepos
      if (layerInfoManager[layerId].stylepos) {
        this.stylepos = layerInfo.stylepos
      }
      // ?
      const opts = {
        params: {
          serviceproviderid: 'map.tablepointlayerserviceprovider',
          serviceid: 'gettile'
        },
        zbound: [4, layerInfo.spanzoom]
      }
      // 有layerid
      if (layerInfoManager[layerId].layerid) {
        opts.params.layerid = CEncode(layerInfoManager[layerId].layerid)
      } else {
        const tableinfo = {
          pm: layerInfoManager[layerId].pm,
          table: layerInfoManager[layerId].table,
          latfd: layerInfoManager[layerId].latfd,
          lngfd: layerInfoManager[layerId].lngfd,
          style: this.style,
          stylepos: this.stylepos,
          stylefd: layerInfoManager[layerId].stylefd,
          morecon: this.queryString,
          namefd: layerInfoManager[layerId].namefd,
          keyfd: '',
          attrfds: layerInfoManager[layerId].attrfds }
        const tableinfostr = CEncodeSpecialChar(CJsonToStringify(tableinfo))
        opts.params.tableinfo = tableinfostr
      }
      opts.params.morecon = this.queryString
      this.overlay = new CCustomOverlay(opts)
      this.overlay.lid = layerId
      this.overlay.zPriority = 1000
      mapLayers.addOverlay(this.overlay)
      overlayManager[layerId] = this.overlay
      const that = this
      // 点击事件监听回调
      this.registerDotQuery('yizhuang_poi', function(e, _data) {
        if (_data.length > 0) {
          that.openInfoWindow(_data[0].id, e)
        }
      })
      // this.loadBigViewFeature(layerId, this.drawFeature)
    },
    // 清除海量点
    cleanPoi() {
      const { mapLayers, layerId, overlayManager } = this
      // 有图层,先移除
      if (overlayManager[layerId]) {
        mapLayers.removeLayer(overlayManager[layerId])
        delete overlayManager[layerId]
      }
      mapLayers.closePopup()
    },
    // 过滤海量点
    filterPoi(listQuery) {
      console.log('过滤Poi')
      const queryList = []
      this.queryString = ''
      const keywords = listQuery.keywords
      const deptid = listQuery.deptid
      const wellType = listQuery.wellType
      if (keywords !== '') {
        queryList.push('(WELL_CODE like \'%' + keywords + '%\' ' + 'or POSITION like \'%' + keywords + '%\')')
      }
      if (wellType !== '') {
        queryList.push('WELL_TYPE=' + wellType)
      }
      if (deptid !== '') {
        queryList.push('DEPTID=' + deptid)
      } else {
        queryList.push('DEPTID IN (' + this.getDataScope() + ')')
      }
      this.queryString = queryList.join(' and ')
      this.cleanPoi()
      this.renderPoi(false)
    },
    // loadBigViewFeature
    loadBigViewFeature(id, callback) {
      const { mapLayers, layerInfoManager } = this
      if (layerInfoManager[id].spanzoom > mapLayers.getZoom() && layerInfoManager[id].showtype !== 'client') { return }
      var bounds = getGlobalBounds()
      if (layerInfoManager[id].showtype !== 'client') {
        bounds = mapLayers.getBounds().pad(1)
      }
      if (this.lastMinBounds == null) {
        this.lastMinBounds = bounds
      }
      this.lastMinBounds = intersectBox(this.lastMinBounds, bounds)
      // 取范围的相交部分,没有则为空
      const boundstr = bounds.toBBoxString()

      const transObj = {}
      transObj.serviceProviderId = 'map.tablepointlayerserviceprovider'
      transObj.serviceId = 'rectquery'

      if (layerInfoManager[id].layerid) {
        transObj.params = { layerid: CEncode(layerInfoManager[id].layerid), bounds: boundstr }
      } else {
        var tableinfo = { pm: layerInfoManager[id].pm, table: layerInfoManager[id].table, id: id, latfd: layerInfoManager[id].latfd, lngfd: layerInfoManager[id].lngfd, stylefd: layerInfoManager[id].stylefd, morecon: this.queryString, namefd: layerInfoManager[id].namefd, keyfd: layerInfoManager[id].keyfd, attrfds: layerInfoManager[id].attrfds }

        transObj.params = { tableinfo: CEncodeSpecialChar(CJsonToStringify(tableinfo)), bounds: boundstr }
      }
      CGetData(transObj, function(data) {
        data = CParseObj(data)
        if (callback) callback(id, data, bounds)
      })
    },
    drawFeature(id, list, bounds) {
      console.log('drawFeature')
      const { mapLayers, featureLayerManager, layerId } = this
      if (list == null) return
      if (featureLayerManager[layerId] == null) {
        const featuresLayer = new CFeatureGroup()
        mapLayers.addOverlay(featuresLayer)
        featureLayerManager[layerId] = featuresLayer
        CEvent.addListener(featuresLayer, 'click', function(event) {
          var data = {}
          data[layerId] = event.layer.data
          // if (clickCallBack) clickCallBack(data)
        })
      }
      featureLayerManager[layerId].clearLayers()
      featureLayerManager[layerId].lastBounds = bounds
      const icons = {}
      const icon = {
        // url: markers.icon,
        url: './static/images/map_images/alarm-well1.png',
        size: this.size,
        anchor: this.anchor,
        popupAnchor: this.popupAnchor
      }
      if (!(icon instanceof Object)) {
        icons[''] = createIcon(this.icon)
      }
      for (var i = 0; i < list.length; i++) {
        this.addMarker(layerId, list[i], icons)
      }
    },
    registerDotQuery(id, callback) {
      console.log('registerDotQuery')
      const { mapLayers } = this
      const that = this
      if (this.clickEvent) CEvent.removeListener(this.clickEvent)
      this.clickEvent = CEvent.addListener(mapLayers, 'click', function(event) {
        that.clickQuery(id, event.latlng, callback)
      })
    },
    clickQuery(id, point, callback) {
      console.log('clickQuery')
      const { mapLayers, layerInfoManager } = this
      const transObj = {}
      transObj.serviceProviderId = 'map.tablepointlayerserviceprovider'
      transObj.serviceId = 'dotquery'
      transObj.params = { point: point.lng + ',' + point.lat, zoom: mapLayers.getZoom() }
      if (layerInfoManager[id].layerid) {
        transObj.params.layerid = CEncode(layerInfoManager[id].layerid)
      } else {
        const tableinfo = { pm: layerInfoManager[id].pm, table: layerInfoManager[id].table, id: id, latfd: layerInfoManager[id].latfd, lngfd: layerInfoManager[id].lngfd, stylefd: layerInfoManager[id].stylefd, morecon: this.queryString, namefd: layerInfoManager[id].namefd, keyfd: layerInfoManager[id].keyfd, attrfds: layerInfoManager[id].attrfds }
        transObj.params.tableinfo = CEncodeSpecialChar(CJsonToStringify(tableinfo))
      }

      CGetData(transObj, function(data) {
        data = CParseObj(data)
        if (callback) callback(id, data)
      })
    },
    addMarker(id, data, icons) {
      const { layerInfoManager, featureLayerManager } = this
      var style = ''
      if (data.style != null) {
        style = data.style

        if (icons[style] == null && layerInfoManager[id].style[style] != null) {
          icons[style] = createIcon(layerInfoManager[id].style[style])
        }
      }
      var icon = icons[style]

      var opts = { icon: icon, title: data.name }
      var marker = new CMarker(new CLatLng(data.point[1], data.point[0]), opts)
      marker.data = data
      featureLayerManager[id].addLayer(marker)
      var _html = ''
      _html += "<div class='mapTips'>"
      _html += "<div class='mapTitle'>"
      _html += '<span>' + '名称' + ': ' + '</td>'
      _html += "<span class='docName'>" + data.name + '</span>'
      _html += '</div>'
      _html += "<div class='mapTitle' style='margin-bottom:4px;'>"
      _html += '<span>' + '地址' + ': ' + '</span>'
      _html += "<span class='docNun'>" + data.attbr[0] + '</span>'
      _html += '</div>'
      _html += "<div class='mapTitle' style='margin-bottom:4px;'>"
      _html += '<span>' + '经纬度' + ': ' + '</span>'
      _html += "<span class='docNun'>" + data.point[1] + ',' + data.point[0] + '</span>'
      _html += '</div>'
      _html += '</div>'
      marker.bindPopup(_html)
      return marker
    },
    // 获取图层id
    getLayerID(name) {
      const { layerInfoManager } = this
      for (const key in layerInfoManager) {
        if (layerInfoManager[key].name === name) { return key }
      }
      return ''
    },
    // 打开弹窗
    openAlarmInfoWindow(wellId) {
      const { mapLayers } = 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 class='alarm-header'>" + alarmInfo.wellCode + '</div>' +
                "<div class='alarm-body'>"
              for (const alarm of alarmInfo.alarms) {
                dom += "<div>告警原因:<span class='alarm-red'>" + alarm.alarmContent + '</span></div>' +
                  '<div>设备编号:<span>' + alarm.devcode + '</span></div>'
              }
              dom += "<div class='divider'></div>" +
                '<div>井类型: ' + alarmInfo.wellTypeName + '</div>' +
                '<div>权属单位:' + alarmInfo.deptName + '</div>' +
                '<div>详细地址:' + alarmInfo.position + '</div>' +
                '</div>' +
                '</div>'
              mapLayers.setZoom(17)
              mapLayers.setCenter(overlay.getLatLng())
              // this.center = alarmInfo.position
              overlay.setPopupContent(dom)
              // debugger
              overlay.openPopup()
            }
          })
        }
      }
    },
    // 打开井信息弹窗
    openInfoWindow(wellId, e) {
      const { mapLayers } = this
      getWellInfo(wellId).then(response => {
        if (response.code === 200) {
          const wellInfo = response.data
          let dom = "<div class='info-window'>" +
            "<div class='info-header'>" + wellInfo.wellCode + '</div>' +
            "<div class='info-body'>"
          dom += '<div>井类型: ' + wellInfo.wellTypeName + '</div>' +
            '<div>权属单位:' + wellInfo.deptName + '</div>' +
            '<div>详细地址:' + wellInfo.position + '</div>' +
            '</div>' +
            '</div>'
          const position = new CLatLng(wellInfo.coordinateY, wellInfo.coordinateX)
          // mapLayers.setZoom(17)
          mapLayers.openInfoWindow(position, dom)
        }
      })
    },
    // 获取中点
    getCenterPoint() {
      const { center } = this
      console.log('getCenterPoint:' + center.lat + ',' + center.lng)
      return new CLatLng(center.lat, center.lng)
    },
    initMap(CMapLayers) {
      this.CMapLayers = CMapLayers
      this.init(CMapLayers)
    },
    getMapScript() {
      // 动态获取cmap的脚本
      // const TMapURL = 'http://119.3.228.125:8080/geowinmap/api?version=tapi&map=map&utils=mapcase,mapv'
      const TMapURL = 'http://10.10.5.42:8080/geowinmap/api?version=tapi&map=map&utils=mapcase,mapv'
      return new Promise((resolve, reject) => {
        console.log(window.CMapLayers)
        // 如果已加载直接返回
        if (typeof window.CMapLayers !== 'undefined') {
          console.log('地图脚本初始化成功1111...')
          resolve(window.CMapLayers)
          // return true
        } else {
          // 插入script脚本
          const scriptNode = document.createElement('script')
          scriptNode.setAttribute('type', 'text/javascript')
          scriptNode.setAttribute('src', TMapURL)

          if (scriptNode.readyState) { // IE
            scriptNode.onreadystatechange = function() {
              if (scriptNode.readyState === 'loaded' || scriptNode.readyState === 'complete') {
                scriptNode.onreadystatechange = null
                console.log('地图脚本初始化成功2...')
                // eslint-disable-next-line
                resolve(window.CMapLayers)
              }
            }
          } else { // 其他浏览器
            scriptNode.onload = function() {
              console.log('地图脚本初始化成功3...')
              resolve(window.CMapLayers)
            }
          }
          document.body.appendChild(scriptNode)
          console.log(scriptNode)
        }
      })
    },
    reset() {
      console.log('map reset')
      const { initMap, getMapScript } = this
      getMapScript()
        .then(initMap)
    }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss">
  .mapDiv{
    width:100%;
    height: calc(100vh - 84px);
  }
  .selectedmaptypecontrol{
    display: none;
  }
  /*.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>