<!-- * @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>