Newer
Older
smartcity_map_front / src / views / overview / mapSearch.vue
wangxitong on 9 Mar 2021 21 KB 地图加载
<template>
  <div>
    <div id="map" class="leaflet_container" style="background-color: white">
      <div class="right-card" style="right: 150px;width: 200px">
        <el-button style="height: 40px;width: 40px;padding: 0px" @click="drawSquare">
          <img src="@/assets/global_images/square.png" style="height: 18px;width: 18px;">
        </el-button>
        <el-button style="height: 40px;width: 40px;padding: 0px" @click="drawPolygon">
          <img src="@/assets/global_images/polygon.png" style="height: 18px;width: 18px;">
        </el-button>
        <el-button style="height: 40px;width: 40px;padding: 0px" @click="drawDelete">
          <img src="@/assets/global_images/delete.png" style="height: 18px;width: 18px;">
        </el-button>
      </div>
      <div class="right-card">
        <el-row>
          <el-button icon="el-icon-copy-document" style="width: 100px;" @click="btnList=!btnList">
            图层<i class="el-icon-arrow-down el-icon--right"/></el-button>
        </el-row>
        <el-checkbox-group v-show="btnList" v-model="selectParts" style=" width: 130px;margin-top: 10px;position: absolute;right: 10px">
          <el-checkbox key="底图" :disabled="checkboxloading" label="底图" border style="margin-left: 10px;width: 130px;background-color: white" @change="mapChange"/>
          <el-checkbox v-for="parts in partsOptions" :disabled="checkboxloading" :label="parts" :key="parts" border style="width: 130px;background-color: white" @change="partsChange">{{ parts }}</el-checkbox>
        </el-checkbox-group>
      </div>
      <div style="margin-top: 20px;position: absolute;left:50px;z-index: 100000">
        <el-input v-model="keyword" placeholder="请输入查询条件" class="input-with-select" style="width: 300px;">
          <el-button slot="append" :disabled="!cansearch" icon="el-icon-search" style="background-color: #409eff;color: white" @click="search"/>
        </el-input>
        <div v-show="isShow" class="search-total">
          共找到 {{ searchlist.length }} 条个查询结果
        </div>
        <div v-show="isShow && searchlist.length!==0" class="table">
          <el-table :data="showlist" :show-header="false" style="border-color: white">
            <el-table-column key="编码" label="编码" width="298" align="left" show-overflow-tooltip>
              <template slot-scope="scope">
                <el-row class="table-item">
                  <el-col :span="2">
                    <div class="item-icon"> {{ scope.$index + 1 }}</div>
                  </el-col>
                  <el-col :offset="2" :span="8" style="font-size: 12px;">
                    <el-row style="height: 18px">名称:{{ scope.row.properties.小类名称 }}</el-row>
                    <el-row style="height: 18px">编码:{{ scope.row.properties.编码 }}</el-row>
                    <el-row style="height: 18px;margin-bottom: 3px">地址:{{ scope.row.properties.OBJECTID }}</el-row>
                  </el-col>
                </el-row>
              </template>
            </el-table-column>
          </el-table>
          <el-pagination
            :current-page="offset"
            :page-size="5"
            :total="searchlist.length"
            small
            style="background-color: white"
            align="center"
            layout="prev, pager, next"
            @current-change="handleCurrentChange"/>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import { getServerList } from '@/api/server'
var esri = require('esri-leaflet')
const rainHole = [14]
const sewageHole = [37]
const video = [35]
const lamp = [1, 3, 4, 22, 25, 34]
const toilet = [12, 13, 41]
const garbage = [24]
const othersParts = [2, 5, 6, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21, 23, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 38, 39, 40, 42, 43, 44, 45]
export default {
  name: 'MapSearch',
  data() {
    return {
      drawLayer: null,
      keyword: '',
      offset: 1,
      btnList: false,
      listLoading: false, // 加载动画
      showlist: [], // 列表展示项
      checkboxloading: false,
      list: [], // url列表
      searchlist: [],
      cansearch: true,
      layerlist: [],
      map: null,
      bounds: null,
      showtable: true,
      isShow: false,
      partsOptions: ['网格', '商户', '视频监控点', '路灯杆和灯箱', '雨水井盖', '污水井盖', '公共厕所', '垃圾箱', '其他部件'],
      selectParts: ['底图', '网格', '商户', '视频监控点', '路灯杆和灯箱', '雨水井盖', '污水井盖', '公共厕所', '垃圾箱', '其他部件'],
      listQuery: {
        offset: 1,
        limit: 15
      }, // 筛选条件
      maps: [],
      parts: [],
      baseUrl: '',
      partsUrl: '',
      mapUrl: '',
      multipleSelection: [], // 多选选中项
      baselayer: [],
      markerlist: []
    }
  },
  destroyed() {
    window.removeEventListener('click', this.handleKeyup, true)
    this.socket.close()
  },
  mounted() {
    var southWest = L.latLng(27.74, 116.06)
    var northEast = L.latLng(27.77, 116.1)
    this.bounds = L.latLngBounds(southWest, northEast)
    window.addEventListener('click', this.handleKeyup, true)
    this.init()
  },
  methods: {
    handleKeyup(val) {
      if (this.btnList && val.target.id === 'map') {
        this.btnList = false
      }
    },
    addPointsToMap(results) {
      if (!results.hasOwnProperty('features') ||
        results.features.length === 0) {
        return // no features, something went wrong
      }
      var features = results.features
      console.log(features)
      var feature
      var items = []
      for (var i = 0; i < features.length; i++) {
        var symbol11 = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([0, 0, 255, 0.35]), 1), new dojo.Color([125, 125, 125, 0.35]))
        feature = features[i]
        feature.setSymbol(symbol11)
        this.map.graphics.add(feature)
        items.push(feature.attributes)
      }
      this.searchlist = items
    },
    search() {
      this.cansearch = false
      var that = this
      this.searchlist = []
      for (let i = 0; i < this.layerlist.length; i++) {
        var str = ['编码', '小类名称', '大类名称']
        var query = esri.query({
          url: this.baseUrl + this.partsUrl + '/' + this.layerlist[i].toString()
        })
        if (this.keyword === '') {
          query.where('1=1')
          query.within(this.bounds)
          query.run(function(error, featureCollection, response) {
            if (error) {
              console.log(error)
              return
            }
            for (let j = featureCollection.features.length - 1; j >= 0; j--) {
              that.searchlist.push(featureCollection.features[j])
            }
            if (i === that.layerlist.length - 1) {
              that.offset = 1
              that.showlist = that.searchlist.slice(0, 5)
              that.isShow = true
              that.drawIcon()
            }
            console.log(featureCollection.features)
          })
        } else {
          for (let j = 0; j < str.length; j++) {
            query.where(str[j] + " like '%" + this.keyword + "%'")
            query.within(this.bounds)
            query.run(function(error, featureCollection, response) {
              if (error) {
                console.log(error)
                return
              }
              for (let k = featureCollection.features.length - 1; k >= 0; k--) {
                that.searchlist.push(featureCollection.features[k])
              }
              console.log(featureCollection.features)
              if (i === that.layerlist.length - 1) {
                that.offset = 1
                that.showlist = that.searchlist.slice(0, 5)
                that.isShow = true
                that.drawIcon()
              }
            })
          }
        }
      }
    },
    drawIcon() {
      var that = this
      for (var i = 0; i < that.markerlist.length; i++) {
        that.map.removeLayer(that.markerlist[i])
      }
      that.markerlist = []
      for (let num = 0; num < that.showlist.length; num++) {
        var Icon
        switch (num) {
          case 0:
            Icon = L.icon({
              iconUrl: require('../../assets/global_images/point1.png'),
              iconSize: [25, 25]
            })
            break
          case 1:
            Icon = L.icon({
              iconUrl: require('../../assets/global_images/point2.png'),
              iconSize: [25, 25]
            })
            break
          case 2:
            Icon = L.icon({
              iconUrl: require('../../assets/global_images/point3.png'),
              iconSize: [25, 25]
            })
            break
          case 3:
            Icon = L.icon({
              iconUrl: require('../../assets/global_images/point4.png'),
              iconSize: [25, 25]
            })
            break
          case 4:
            Icon = L.icon({
              iconUrl: require('../../assets/global_images/point5.png'),
              iconSize: [25, 25]
            })
            break
          default:
            break
        }
        var item = L.marker([that.showlist[num].geometry.coordinates[1], that.showlist[num].geometry.coordinates[0]], {
          icon: Icon,
          id: that.showlist[num].properties
        }).addTo(that.map)
        that.markerlist.push(item)
        item.on('click', function(e) {
          console.log(e)
          if (e.target.dragging._marker._popup) {
            e.target.dragging._marker.unbindPopup()
          }
          var str = '<div style="font-size: 14px;width:200px;">' +
            '<div style="font-size: 14px;margin-bottom: 8px;">' +
            '<div>' + e.target.options.id.小类名称 + '</div></div>' +
            '<div style="padding-bottom: 4px"><col style="padding-right: 5px">大类:</col>' + e.target.options.id.大类名称	 + '</div>' +
            '<div style="padding-bottom: 4px"><col style="padding-right: 5px">小类:</col>' + e.target.options.id.小类名称	 + '</div>' +
            '<div style="padding-bottom: 4px"><col style="padding-right: 5px">部件编码:</col>' + e.target.options.id.编码 	 + '</div>' +
            '<div style="padding-bottom: 4px"><col style="padding-right: 5px">权属单位:</col>' + e.target.options.id.权属单位 + '</div>' +
            '<div style="padding-bottom: 4px"><col style="padding-right: 5px">详细地址:</col>' + e.target.options.id.详细地址 + '</div>' +
            '<div>'
          var popup = L.popup().setContent(str)
          e.target.dragging._marker.bindPopup(popup).openPopup()
          e.target.dragging._marker.openPopup()
        })
      }
      this.cansearch = true
    },
    drawDelete() {
      if (this.drawLayer) {
        this.drawLayer.layer.remove()
      }
      var southWest = L.latLng(27.74, 116.06)
      var northEast = L.latLng(27.77, 116.1)
      this.bounds = L.latLngBounds(southWest, northEast)
      this.search()
    },
    drawSquare() {
      if (this.drawLayer) {
        this.drawLayer.layer.remove()
      }
      this.$nextTick(() => {
        this.map.pm.enableDraw('Rectangle', {
          snappable: false
        })
      })
    },
    drawPolygon() {
      if (this.drawLayer) {
        this.drawLayer.layer.remove()
      }
      this.$nextTick(() => {
        this.map.pm.enableDraw('Polygon', {
          snappable: false
        })
      })
    },
    mapChange(val) {
      if (!val) { // 隐藏底图
        for (let i = 0; i < this.maps.length; i++) {
          this.map.removeLayer(this.maps[i])
        }
      } else {
        for (let i = 0; i < this.maps.length; i++) {
          this.map.addLayer(this.maps[i])
        }
      }
    },
    partsChange(val, item) {
      this.checkboxloading = true
      var selectItem
      switch (item.target.defaultValue) {
        case '视频监控点':
          selectItem = video
          break
        case '路灯杆和灯箱':
          selectItem = lamp
          break
        case '公共厕所':
          selectItem = toilet
          break
        case '垃圾箱':
          selectItem = garbage
          break
        case '雨水井盖':
          selectItem = rainHole
          break
        case '污水井盖':
          selectItem = sewageHole
          break
        case '其他部件':
          selectItem = othersParts
          break
        default:
          selectItem = []
          break
      }
      if (!val) { // 隐藏底图
        for (let i = 0; i < selectItem.length; i++) {
          this.map.removeLayer(this.parts[selectItem[i] - 1])
          for (let j = 0; j < this.layerlist.length; j++) {
            if (this.layerlist[j] === selectItem[i]) {
              this.layerlist.splice(j, 1)
            }
          }
        }
      } else if (val) {
        for (let i = 0; i < selectItem.length; i++) {
          this.map.addLayer(this.parts[selectItem[i] - 1])
          var res = -1
          for (let j = 0; j < this.layerlist.length; j++) {
            if (this.layerlist[j] === selectItem[i]) {
              res = j
            }
          }
          if (res === -1) {
            this.layerlist.push(selectItem[i])
          }
        }
      }
      this.checkboxloading = false
    },
    tableclick() {
      this.showtable = !this.showtable
    },
    setZoom(points) {
      if (points.length > 0) {
        var maxLng = points[0][1]
        var minLng = points[0][1]
        var maxLat = points[0][0]
        var minLat = points[0][0]
        var res
        for (var i = points.length - 1; i >= 0; i--) {
          res = points[i]
          if (res[1] > maxLng) maxLng = res[1]
          if (res[1] < minLng) minLng = res[1]
          if (res[0] > maxLat) maxLat = res[0]
          if (res[0] < minLat) minLat = res[0]
        }
        var cenLng = (parseFloat(maxLng) + parseFloat(minLng)) / 2
        var cenLat = (parseFloat(maxLat) + parseFloat(minLat)) / 2
        var zoom = this.getZoom(maxLng, minLng, maxLat, minLat)
        this.map.setView({ lat: cenLat, lng: cenLng }, zoom)
      } else {
        // 没有坐标,显示全中国
        this.map.setView({ lat: 103.388611, lng: 35.563611 }, 5)
      }
    },
    getZoom(maxLng, minLng, maxLat, minLat) {
      var zoom = ['50', '100', '200', '500', '1000', '2000', '5000', '10000', '20000', '25000', '50000', '100000', '200000', '500000', '1000000', '2000000', '5000000']// 级别18到3。
      var latlng = L.latLng(maxLat, maxLng)
      var distance = latlng.distanceTo(L.latLng(minLat, minLng))
      // var distance = pointA.distanceTo(pointB)// 获取两点距离,保留小数点后两位
      for (var i = 0, zoomLen = zoom.length; i < zoomLen; i++) {
        if (zoom[i] - distance > 0) {
          return 18 - i + 2 // 之所以会多2,是因为地图范围常常是比例尺距离的10倍以上。所以级别会增加3。
        }
      }
      return 5
    },
    async init() {
      const map = L.map('map', {
        minZoom: 2,
        // maxZoom: 18,
        center: [27.755, 116.08],
        zoom: 18,
        zoomControl: false,
        attributionControl: false,
        crs: L.CRS.EPSG3857
      })
      map.doubleClickZoom.disable()
      this.map = map // data上需要挂载
      window.map = map
      var that = this
      this.map.on('pm:create', e => {
        if (that.drawLayer) {
          that.drawLayer.layer.remove()
        }
        that.drawLayer = e
      })
      const res = await getServerList(this.listQuery)
      this.list = res.data.rows
      for (var i = 0; i < this.list.length; i++) {
        if (this.list[i].name === 'GIS地图') {
          this.baseUrl = this.list[i].url
        } else if (this.list[i].name === '部件分层URL') {
          this.partsUrl = this.list[i].url
        } else if (this.list[i].name === '二维地图URL') {
          this.mapUrl = this.list[i].url
        }
      }
      // 底图
      this.maps.push(esri.dynamicMapLayer({
        url: this.baseUrl + this.mapUrl,
        minZoom: 4, // 最小缩放等级
        maxZoom: 21// 最大缩放等级
      }).addTo(map))
      // 部件
      for (let i = 1; i <= 45; i++) {
        this.layerlist.push(i)
        let item = { url: this.baseUrl + this.partsUrl + '/' + i.toString(), minZoom: 10 }
        if (i === 15) {
          item = { url: this.baseUrl + this.partsUrl + '/' + i.toString(), minZoom: 10,
            style: function(feature) {
              return { color: '#ff0000', opacity: 0.75, weight: 5 }
            } }
        }
        var layer = esri.featureLayer(item).addTo(map)
        layer.on('click', function(e) {
          // console.log(e)
          var str = '<div style="font-size: 14px;width:200px;">' +
              '<div style="font-size: 14px;margin-bottom: 8px;">' +
              '<div>' + e.layer.feature.properties.小类名称 + '</div></div>' +
              '<div style="padding-bottom: 4px"><col style="padding-right: 5px">大类:</col>' + e.layer.feature.properties.大类名称	 + '</div>' +
              '<div style="padding-bottom: 4px"><col style="padding-right: 5px">小类:</col>' + e.layer.feature.properties.小类名称	 + '</div>' +
              '<div style="padding-bottom: 4px"><col style="padding-right: 5px">部件编码:</col>' + e.layer.feature.properties.编码 	 + '</div>' +
              '<div style="padding-bottom: 4px"><col style="padding-right: 5px">权属单位:</col>' + e.layer.feature.properties.权属单位 + '</div>' +
              '<div style="padding-bottom: 4px"><col style="padding-right: 5px">详细地址:</col>' + e.layer.feature.properties.详细地址 + '</div>' +
              '<div>'
          var popup = L.popup().setContent(str)
          e.layer.dragging._marker.bindPopup(popup, { minWidth: 200 }).openPopup()
          // var id = e.layer.feature.properties.FID
        })
        this.parts.push(layer)
      }
      this.map.on('pm:create', e => {
        // console.log(e)
        this.bounds = e.layer._bounds
        this.search()
      })
      this.map.setZoom(15)
    },
    handleCurrentChange(val) {
      this.offset = val
      var num = 5 * val >= this.searchlist.length ? this.searchlist.length : 5 * val
      this.showlist = this.searchlist.slice(5 * (val - 1), num)
      this.drawIcon()
    }
  }
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
  /deep/ .el-input-group__append, .el-input-group__prepend {
    background-color: #409eff !important;
    border: 1px solid #409eff !important;
  }
  /*/deep/ .leaflet-touch .leaflet-control-layers, /deep/ .leaflet-touch .leaflet-bar {*/
    /*!*border: 2px solid rgba(0,0,0,0.2);*!*/
    /*!*background-clip: padding-box;*!*/
    /*position: absolute !important;*/
    /*right: 300px !important;*/
    /*top: 10px;*/
  /*}*/
  $tableTitleHeight:35px;
  .leaflet_container{
    width: 100%;
    height: 84vh;
  }
  .search-total{
    background-color: white; width: 300px;height: 35px;
    margin-top: 6px;border: 1px solid #DCDFE6;
    padding-left: 15px;color: #409eff;
    padding-top: 8px;
    font-size: 13px;
    border-radius:3px;
  }
  .draw-icon{
    background-color: white;
    width: 100px;height: 40px;
    border: 1px solid #DCDFE6;
    border-radius:4px;
  }
  .table{
    width: 300px;margin-top: 3px;
    border: 1px solid #DCDFE6;
    border-radius:3px;
    /deep/ .el-table th.is-leaf, /deep/ .el-table td {
      border-bottom: 1px solid white !important;
    }
    /deep/ .el-table--group::after, .el-table--border::after, .el-table::before {
      background-color: white !important;
    }
    .table-item{
      padding: 5px;
      margin-top: 2px;
      margin-bottom: 1px;
      -moz-box-shadow: 0px 1px 3px #d9d9d9; /* 老的 Firefox */
      box-shadow: 0px 1px 3px #d9d9d9;
      .item-icon{
        width: 30px;
        height: 30px;
        background-size: contain;
        background-image: url("../../assets/global_images/point.png");
        color: white;
        text-align: center;
        margin-top: 10px;
        margin-left: 5px;
        padding-top: 2px;
      }
    }
  }
  .top_title{
    height: 40px;
    font-size: 18px;
    border: 1px solid #b5b5b5;
    padding-top: 10px;
  }
  .title{
    height: 40px;
    width: 320px;
    padding-top: 10px;
    padding-left: 5px;
    z-index: 100000;
    background-color: rgba(255, 255, 255, 0.91);
  }
  .titletext{
    text-align: center;
    font-size: 15px;
  }
  .titlenumtext{
    text-align: center;
    font-size: 19px;
  }
  .list{
    text-align:center;
    width: 500px;
    height: 40px;
    z-index: 10000;
    position: absolute;
    right:20px;
    top:20px;
  }
  .btn_bottom{
    text-align:center;
    width: 100%;
    height:70px;
    z-index: 1000;
    position: fixed; bottom: 0; left: 0;right:0;
  }
  .table-name{
    position:relative;
    width: 100px;
    top:20px;
    margin:-10px auto; //外面的div高度的一半
    z-index: 100001;
  }
  .right-card{
    margin-top: 20px;position: absolute;right:50px;z-index: 100000;width: 130px;
  }
  .table-title{
    background-color:rgba(243, 243, 243, 1);
    height: $tableTitleHeight;
    .title-header{
      line-height:$tableTitleHeight;
      color: #606266;
      font-size: 15px;
      i{
        margin-left: 5px;
        margin-right: 5px;
      }
    }
  }
</style>