Newer
Older
smartcity_map_front / src / views / overview / compEdit.vue
StephanieGitHub on 9 Mar 2021 11 KB MOD:新增部件编辑功能
<!--
 * @Description: 部件编辑
 * @Author: 王晓颖
 * @Date: 2021-03-08 09:46:39
 -->
<template>
  <app-container>
    <div id="map" class="leaflet_container"/>
    <!--查询显示组件-->
    <search-list ref="searchList"/>
    <div class="points-add-div">
      <el-button icon="el-icon-plus" @click="openAddMode">
        添加部件
      </el-button>
    </div>
    <!--图层选择组件-->
    <layer-choose :layers="layers" :select-layers="selectLayers" @choose="layerChange"/>
    <!--编辑部件弹窗-->
    <edit-parts-dialog ref="editPartsDialog" @update="onUpdateFeature"/>
  </app-container>
</template>
<script>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import AppContainer from '@/components/layout/AppContainer'
import LayerChoose from './components/layerChoose'
import SearchList from './components/searchList'
import { mapGetters } from 'vuex'
import EditPartsDialog from './components/editPartsDialog'
var esri = require('esri-leaflet')
export default {
  name: 'ComponentEdit',
  components: { EditPartsDialog, LayerChoose, AppContainer, SearchList },
  data() {
    return {
      loading: false, // 加载动画
      addMode: false, // 添加元素状态
      map: null, // 地图对象
      drawLayer: null, // 绘制图层(框选)
      layers: [
        { id: 0, name: '底图', type: 'map', domain: [] },
        { id: 1, name: '网格', type: 'layer', domain: [] },
        { id: 2, name: '商户', type: 'layer', domain: [] },
        { id: 3, name: '视频监控点', type: 'layer', domain: [35] },
        { id: 4, name: '路灯杆和灯箱', type: 'layer', domain: [1, 3, 4, 22, 25, 34] },
        { id: 5, name: '雨水井盖', type: 'layer', domain: [14] },
        { id: 6, name: '污水井盖', type: 'layer', domain: [37] },
        { id: 7, name: '公共厕所', type: 'layer', domain: [12, 13] },
        { id: 8, name: '垃圾箱', type: 'layer', domain: [24] },
        { id: 9, name: '其他部件', type: 'layer', domain: [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] }
      ],
      selectLayers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
      maps: [], // 地图图层
      parts: [], // 部件图层
      curretLayer: null, // 当前选中featureLayer
      currentItem: null // 当前选中部件
    }
  },
  computed: {
    ...mapGetters([
      'baseUrl',
      'partsUrl',
      'partsAllUrl',
      'mapUrl',
      'partsEditUrl'
    ])
  },
  // 销毁时移除监听
  destroyed() {
    window.removeEventListener('click', this.handleKeyup, true)
    this.socket.close()
  },
  // 加载完添加点击事件的监听
  mounted() {
    this.init()
    window.addEventListener('click', this.handleKeyup, true)
  },
  methods: {
    // 地图上点击之后,搜索列表隐藏
    handleKeyup(val) {
      if (this.$refs.searchList && val.target.id === 'map') {
        this.$refs.searchList.hideSearch()
      }
    },
    // 移除绘制图层
    drawDelete() {
      if (this.drawLayer) {
        this.drawLayer.layer.remove()
      }
    },
    // 绘制矩形
    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])
        }
      }
    },
    // 部件图层切换
    layerChange(node, checked) {
      const selectItem = this.layers.filter(item => item.name === node.name)[0]
      // 如果选中底图,选中添加,没选中移除
      if (selectItem.type === 'map') {
        if (!checked) {
          for (const item of this.maps) {
            this.map.removeLayer(item)
          }
        } else {
          for (const item of this.maps) {
            this.map.addLayer(item)
          }
        }
      } else if (node.type === 'layer') { // 其他图层
        if (!checked) {
          for (let i = 0; i < selectItem.domain.length; i++) {
            this.map.removeLayer(this.parts[selectItem.domain[i] - 1])
          }
        } else {
          for (let i = 0; i < selectItem.domain.length; i++) {
            this.map.addLayer(this.parts[selectItem.domain[i] - 1])
          }
        }
      }
    },
    // 移除点
    removemarkers() {
      for (var i = 0; i < this.iconlist.length; i++) {
        this.map.removeLayer(this.iconlist[i])
      }
      var base = this.baselayer
      this.map.eachLayer(function(layer) {
        if (layer !== base[0] && layer !== base[1]) {
          layer.remove()
        }
      })
    },
    // 初始化地图
    init() {
      this.loading = false
      const map = L.map('map', {
        minZoom: 13,
        // maxZoom: 21,
        center: this.baseConfig.center,
        zoom: this.baseConfig.zoom,
        zoomControl: false,
        attributionControl: false,
        crs: L.CRS.EPSG3857
      })
      map.doubleClickZoom.disable() // 禁止双击
      this.map = map // data挂载map
      window.map = map
      const that = this
      this.map.on('pm:create', e => {
        if (that.drawLayer) {
          that.drawLayer.layer.remove()
        }
        that.drawLayer = e
      })
      this.map.on('popupopen', e => {
        // 给按钮添加点击事件
        document.getElementById('btnEdit').onclick = that.editInfo
        document.getElementById('btnDelete').onclick = that.delete
      })
      // 添加底图
      for (let i = 0; i <= 21; i++) {
        // const layer = { url: `${this.baseUrl}${this.mapUrl}/${i}` }
        var item = { url: this.baseUrl + this.mapUrl + '/' + i.toString() }
        this.maps.push(esri.featureLayer(item).addTo(map))
      }
      // 添加部件
      for (let i = 1; i <= 40; i++) {
        let item = { url: `${this.baseUrl}${this.partsEditUrl}/${i}`, minZoom: 18 }
        console.log(item)
        if (i === 15) {
          item = {
            url: `${this.baseUrl}${this.partsEditUrl}/${i}`,
            minZoom: 18,
            style: function(feature) {
              return { color: '#ff0000', opacity: 0.75, weight: 5 }
            }
          }
        }
        var layer = esri.featureLayer(item).addTo(map)
        // 点击部件事件
        layer.on('click', function(e) {
          // 获取要素的属性
          const properties = e.layer.feature.properties
          that.currentItem = e.layer.feature
          that.searchLayerByUrl(e.layer.options.url)
          // 弹窗样式
          var str = `<div class="pop-window">
                        <div class="pop-title">
                          ${properties['小类名称']}
                        </div>
                        <div class="pop-line"><col>大类:</col>${properties['大类名称']}</div>
                        <div class="pop-line"><col>小类:</col>${properties['小类名称']}</div>
                        <div class="pop-line"><col>部件编码:</col>${properties['编码']}</div>
                        <div class="pop-line"><col>权属单位:</col>${properties['权属单位'] ? properties.权属单位 : '未知'}</div>
                        <div class="pop-line"><col>详细地址:</col>${properties['详细地址'] ? properties.详细地址 : '未知'}</div>
                        <div class="pop-btns">
                          <button id="btnEdit" class="mini-btn">编辑</button>
                          <button id="btnDelete" class="mini-btn">删除</button>
                        </div>
                      <div>`
          var popup = L.popup().setContent(str)
          e.layer.dragging._marker.bindPopup(popup, { minWidth: 200 }).openPopup()
        })
        this.parts.push(layer)
      }
      // this.map.setZoom(this.baseConfig.zoom)
    },
    // 点击新增部件
    openAddMode() {
      this.addMode = true
      var icon = L.icon({
        iconUrl: require('../../assets/icons/icon-position.png'),
        iconSize: [35, 35],
        iconAnchor: [17.5, 35]
      })
      this.map.on('click', e => {
        // convert to GeoJSON
        const feat = L.marker(e.latlng, { icon: icon })
        feat.addTo(this.map)
        console.log(feat)
        this.$refs.editPartsDialog.initDialog(feat, 'create')
      })
    },
    // 点击编辑
    editInfo(ev) {
      // 打开弹窗
      console.log(this.currentItem)
      this.$refs.editPartsDialog.initDialog(this.currentItem, 'update')
    },
    // 点击删除
    delete(code) {
      if (this.currentLayer) {
        debugger
        this.currentLayer.deleteFeature(this.currentItem)
        this.$messsage.success('删除成功')
      }
    },
    onCreateFeature(feature) {

    },
    // 放弃操作,dialogStatus弹窗类型
    onAbort(dialogStatus) {
      if (dialogStatus === 'create') {
        // 清除地图上的锚点
        this.map.removeLayer(this.currentItem)
      }
    },
    // 编辑保存操作
    onUpdateFeature(feature) {
      if (this.currentLayer) {
        debugger
        this.currentLayer.updateFeature(feature, () => {
          this.$messsage.success('编辑成功')
        })
      }
    },
    // 根据url找到layer
    searchLayerByUrl(url) {
      const layer = this.parts.filter(item => item.options.url === url)[0]
      if (layer) {
        this.currentLayer = layer
      }
    }
  }
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
  $tableTitleHeight:35px;
  .leaflet_container{
    width: 100%;
    height: 85vh;
    background-color: white;
  }
  .draw-icon{
    background-color: white;
    width: 100px;height: 40px;
    border: 1px solid #DCDFE6;
    border-radius:4px;
  }
  .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;
  }
  .points-add-div{
    position: absolute;
    right:250px;
    top:20px;
    background-color: white;
    border-radius: 3px;
  }
</style>
<style rel="stylesheet/scss" lang="scss">
  .pop-window{
    font-size: 14px;width:200px;
    padding-right:5px;
    .pop-title{
      font-size: 16px;
      margin-bottom: 8px;
    }
    .pop-line{
      line-height:20px;
    }
    .pop-btns{
      margin:10px 0px;
      .mini-btn{
        display: inline-block;
        line-height: 1;
        white-space: nowrap;
        cursor: pointer;
        background: #fff;
        border: 1px solid #dcdfe6;
        color: #606266;
        -webkit-appearance: none;
        text-align: center;
        box-sizing: border-box;
        outline: none;
        margin: 0;
        transition: .1s;
        font-weight: 500;
        padding: 7px 15px;
        font-size: 12px;
        border-radius: 3px;
      }
      .mini-btn+.mini-btn{
        margin-left:10px;
      }
      #btnEdit{
        color: #409eff;
        background: #ecf5ff;
        border-color: #b3d8ff;
      }
      #btnEdit:hover{
        background: #409eff;
        border-color: #409eff;
        color: #fff;
      }
      #btnDelete{
        color: #f56c6c;
        background: #fef0f0;
        border-color: #fbc4c4;
      }
      #btnDelete:hover{
        background: #f56c6c;
        border-color: #f56c6c;
        color: #fff;
      }
    }
  }
</style>