<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>