index.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <template>
  2. <div class="map-container">
  3. <nav>
  4. <map-selector :default-val="formData.mapId" @setMapInfo="handleSelectMap" />
  5. </nav>
  6. <div class="layout-map">
  7. <div id="vmap" />
  8. <div id="marker-tip" :style="marker_tip_style">
  9. <div class="head">基本信息</div>
  10. <div class="item">
  11. <p class="title">巡检任务统计(20)</p>
  12. <p><span>未完成:8</span><span>已完成:8</span></p>
  13. </div>
  14. <div class="item">
  15. <p class="title">传感器统计(21)</p>
  16. <p><span>在线:8</span><span>离线:8</span></p>
  17. <p><span class="warn">预警:8</span></p>
  18. </div>
  19. </div>
  20. </div>
  21. <MapLayerDetail ref="layer-detail" />
  22. </div>
  23. </template>
  24. <script>
  25. import * as L from 'leaflet'
  26. import '@geoman-io/leaflet-geoman-free'
  27. import MapSelector from '@/components/MapSelector'
  28. import MapLayerDetail from './components/table'
  29. import { getMapLayerById } from '@/api/goaf/layer'
  30. import { getMapLayer, getNewSensorData } from '@/api/iiot/map'
  31. const iconSize = [50, 50]
  32. export default {
  33. name: 'GoafVisualEditor',
  34. components: {
  35. MapSelector,
  36. MapLayerDetail
  37. },
  38. data() {
  39. return {
  40. viewData: {},
  41. formData: {
  42. mapId: undefined,
  43. layerId: undefined,
  44. layerVector: ''
  45. },
  46. map: undefined,
  47. geoLayer: undefined,
  48. conditions: {
  49. layerId: undefined
  50. },
  51. layer: {
  52. containerPoint: {
  53. x: '',
  54. y: ''
  55. }
  56. },
  57. marker_tip_style: '',
  58. layers: [],
  59. layerGroup: [],
  60. mapList: [],
  61. imageOverlay: undefined
  62. }
  63. },
  64. mounted() {
  65. this.init()
  66. },
  67. methods: {
  68. init() {
  69. this.initMap()
  70. },
  71. // 初始化
  72. getData() {
  73. getMapLayerById(this.conditions.layerId).then((resp) => {
  74. const { data } = resp
  75. this.viewData = data
  76. this.setRasterLayer()
  77. })
  78. },
  79. // 初始化地图
  80. initMap() {
  81. var yx = L.latLng
  82. var xy = function xy(x, y) {
  83. if (L.Util.isArray(x)) {
  84. return yx(x[1], x[0])
  85. }
  86. return yx(y, x)
  87. }
  88. var bounds = [xy(-800, -600), xy(500, 300)]
  89. this.map = L.map('vmap', {
  90. crs: L.CRS.Simple, // 一个简单的CRS,可将经度和纬度直接映射到x其中y。可用于平面地图(例如游戏地图)
  91. minZoom: -0.65,
  92. maxZoom: 2,
  93. zoom: 1,
  94. maxBounds: bounds, // 地图拖动到边界后自动弹回
  95. maxBoundsViscosity: 0.2,
  96. attributionControl: true,
  97. zoomControl: true // zoomControl(缩放控制):确定缩放控制是否默认加载在地图上。
  98. })
  99. this.map._onResize()
  100. this.layerGroup = L.layerGroup().addTo(this.map)
  101. this.geoLayer = L.geoJson(null, { pmIgnore: false })
  102. this.geoLayer.addTo(this.map)
  103. if (!this.viewData.layerVector) return
  104. this.geoLayer.addData(this.viewData.layerVector)
  105. },
  106. // 设置地图背景图
  107. setRasterLayer() {
  108. var yx = L.latLng
  109. var xy = function xy(x, y) {
  110. if (L.Util.isArray(x)) {
  111. return yx(x[1], x[0])
  112. }
  113. return yx(y, x)
  114. }
  115. var bounds = [xy(-800, -600), xy(500, 300)]
  116. if (this.imageOverlay) {
  117. this.imageOverlay.setUrl(this.viewData.mapRasterLayer)
  118. } else {
  119. this.imageOverlay = L.imageOverlay(this.viewData.mapRasterLayer, bounds).addTo(this.map)
  120. }
  121. this.map.fitBounds(bounds)
  122. this.getMapLayers()
  123. },
  124. // 选择地图
  125. handleSelectMap(obj, mapList) {
  126. this.viewData.mapRasterLayer = obj.mapRasterLayer
  127. this.viewData.mapId = obj.mapId
  128. this.formData.mapId = obj.mapId
  129. if (mapList) {
  130. this.mapList = mapList
  131. }
  132. this.setRasterLayer()
  133. this.clearLayers()
  134. },
  135. formSuccess() {
  136. this.$emit('formSuccess')
  137. },
  138. // 获取地图图层数据
  139. getMapLayers() {
  140. getMapLayer({
  141. map: this.formData.mapId
  142. }).then((resp) => {
  143. const { code, data, msg } = resp
  144. if (code === 0) {
  145. this.mapLayerList = data
  146. this.initMapLayers()
  147. } else {
  148. this.$message.error(msg)
  149. }
  150. })
  151. },
  152. updateMapLayers(mapId, type = 1) {
  153. if (type === 1) {
  154. this.setRasterLayer()
  155. this.clearLayers()
  156. } else {
  157. /** 其他图层改变需要跳转 */
  158. if (this.formData.mapId === mapId) {
  159. this.setRasterLayer()
  160. this.clearLayers()
  161. } else {
  162. const obj = this.mapList.filter(item => item.mapId === mapId)[0]
  163. this.viewData.mapRasterLayer = obj.mapRasterLayer
  164. this.viewData.mapId = obj.mapId
  165. this.formData.mapId = obj.mapId
  166. this.setRasterLayer()
  167. this.clearLayers()
  168. }
  169. }
  170. },
  171. // 初始化地图图层
  172. initMapLayers() {
  173. const layerList = this.mapLayerList
  174. const feature = []
  175. const self = this
  176. if (layerList != null && layerList.length > 0) {
  177. layerList.forEach((item) => {
  178. feature.push({
  179. 'type': 'Feature',
  180. 'properties': item,
  181. 'geometry': {
  182. 'type': 'Point',
  183. 'coordinates': [item.sensorQywzjd, item.sensorQywzwd]
  184. }
  185. })
  186. })
  187. L.geoJSON(feature, {
  188. pointToLayer: function(_feature, latlng) {
  189. const sensorLocationId = _feature.properties.sensorLocationId
  190. const goafSensorName = _feature.properties.goafSensorName
  191. const html = `<div data-layer="${sensorLocationId}-${goafSensorName}" title="${goafSensorName}" class="goaf-icon-box" style="width:100%;height:100%;position: relative;"></div>`
  192. var icon = L.divIcon({
  193. html,
  194. iconSize
  195. })
  196. return L.marker(latlng, { icon })
  197. },
  198. onEachFeature: (_feature, layer) => {
  199. this.layerGroup.addLayer(layer)
  200. layer.on('click', (ev) => {
  201. self.showLayerDetail(ev.target.feature.properties)
  202. })
  203. }
  204. }).addTo(this.layerGroup)
  205. }
  206. },
  207. clearLayers() {
  208. if (this.layerGroup && this.layerGroup.clearLayers) {
  209. this.layerGroup.clearLayers()
  210. }
  211. },
  212. createGeoJson() {
  213. var layerArray = []
  214. this.map.eachLayer(function(layer) {
  215. if (layer.pm !== 'undefined' && layer.pm != null && layer.pm !== '') {
  216. if (layer.pm._enabled === false && layer.pm.options.draggable === true) {
  217. layerArray.push(layer)
  218. }
  219. }
  220. })
  221. var geojson = L.layerGroup(layerArray).toGeoJSON()
  222. for (var n = 0; n < geojson.features.length; n++) {
  223. var nowJson = JSON.stringify(geojson.features[n])
  224. for (var m = n + 1; m < geojson.features.length; m++) {
  225. var nextJson = JSON.stringify(geojson.features[m])
  226. if (nowJson === nextJson) {
  227. geojson.features.splice(n, 1)
  228. }
  229. }
  230. }
  231. return geojson
  232. },
  233. showLayerDetail(item) {
  234. debugger
  235. getNewSensorData({
  236. map: item.mapId,
  237. goafSensorId: item.goafSensorId
  238. }).then((resp) => {
  239. const { data } = resp
  240. this.$refs['layer-detail'].loadData(data)
  241. })
  242. },
  243. updateLayerState(layerId = 0, type = 1) {
  244. // eslint-disable-next-line no-undef
  245. var marker = $(`.goaf-icon-box[data-layer='${layerId}']`)
  246. if (type === 1) {
  247. // 添加隐患预警
  248. marker.addClass('ico-warning ')
  249. } else if (type === 3) {
  250. // 修改矿坑体积
  251. } else {
  252. marker.removeClass('ico-warning ')
  253. }
  254. },
  255. unique(arr = [], name = 'name') {
  256. const res = new Map()
  257. return arr.filter((item) => !res.has(item[name]) && res.set(item[name], 1))
  258. },
  259. deeepClone(params) {
  260. return JSON.parse(JSON.stringify(params))
  261. }
  262. }
  263. }
  264. </script>
  265. <style>
  266. .leaflet-control-attribution.leaflet-control{
  267. display: none;
  268. }
  269. </style>
  270. <style lang="scss" scoped>
  271. .map-container{
  272. height: 100%;
  273. nav{
  274. display: flex;
  275. justify-content: space-between;
  276. align-items: center;
  277. padding: 10px 16px;
  278. box-sizing: border-box;
  279. background-color: #193142;
  280. }
  281. .layout-map{
  282. display: flex;
  283. justify-content: space-between;
  284. height: calc(100% - 58px);
  285. position: relative;
  286. #vmap {
  287. height: 100%;
  288. flex: 1;
  289. background: #8c939d;
  290. box-sizing: border-box;
  291. }
  292. #marker-tip{
  293. width: 200px;
  294. height: 200px;
  295. background-image: url(./tip.png);
  296. background-size: 100% 100%;
  297. background-repeat: no-repeat;
  298. position: absolute;
  299. z-index: 99999;
  300. padding: 15px 20px 0 20px;
  301. box-sizing: border-box;
  302. display: none;
  303. .head{
  304. font-size: 24px;
  305. color: #fff;
  306. }
  307. .item{
  308. padding-top: 15px;
  309. padding-bottom: 5px;
  310. &.item{
  311. padding-top: 8px;
  312. }
  313. .title{
  314. font-size: 16px;
  315. color: rgba(230, 247, 255, 0.6);
  316. padding-bottom: 5px;
  317. }
  318. span{
  319. font-size: 14px;
  320. padding-right: 15px;
  321. color: #fff;
  322. .warn{
  323. color: red;
  324. }
  325. }
  326. }
  327. }
  328. }
  329. }
  330. </style>
  331. <style lang="scss">
  332. .layout-map .goaf-icon-box,.layout-map .leaflet-marker-icon{
  333. background-color: transparent;
  334. border-color: transparent;
  335. }
  336. .layout-map .goaf-icon-box:hover{
  337. border: 1px dashed rgb(133, 131, 131);
  338. border-radius: 50%;
  339. }
  340. </style>