Newer
Older
safe_production_front / src / views / map / map.vue
<script lang="ts" setup name="Map">
import { ElMessage } from 'element-plus'
import type { Ref } from 'vue'
import { getCurrentInstance, ref } from 'vue'
import dayjs from 'dayjs'
import L from 'leaflet'
// import aMap from '@/components/aMap/aMap.vue'
import { getDataHisList, getDevInfo, getDevMap } from '@/api/ptz/dev'
import useWebsocketStore from '@/store/modules/websocket'
import type { lineDataI } from '@/components/Echart/echart-interface'
import 'leaflet/dist/leaflet.css'
import 'leaflet.label'
import { getDevListPage } from '@/api/monitor/dev'

const { proxy } = getCurrentInstance()
const websocket = useWebsocketStore()

const toParentsMap = ref({
  lat: '',
  lng: '',
})

const map: any = ref(null)
const baseLayer = ref([])
const ciLayer: any = ref(null)
const keyword = ref('')
const isRightShow = ref(false)
const pointList: Ref<any[]> = ref([])
const currentName = ref('')
const monitorId = ref('')
const deviceIp = ref('')
const device = ref({})
const devCH4Loading = ref(false)
const devCH4XData: Ref<string[]> = ref([])
const devCH4Data: Ref<lineDataI[]> = ref([])
const devCH4YDataMax = ref()
const webRtcServer = ref(null)
const amap = ref() // 组件

function search(init = true) {
  map.value.eachLayer((layer: any) => {
    if (layer !== baseLayer.value[0]) {
      layer.remove()
    }
  })

  // if (ciLayer.value) {
  //   console.log('清理图层')
  //   map.value.removeLayer(ciLayer.value)
  // }
  // ciLayer.value = L.layerGroup([]).addLayer(map.value)

  getDevListPage({
    keyword: keyword.value,
    devType: '',
    offset: 1,
    limit: 1000,
  }).then((res) => {
    res.data.rows.forEach((item: any) => {
      let icon
      let color
      switch (item.deviceStatus) {
        case 0:
          icon = './marker/gray.png'
          color = 'gray'
          break
        case 1:
          icon = './marker/green.png'
          color = 'green'
          break
      }
      const Icon = L.icon({
        iconUrl: icon,
        iconAnchor: [18, 15],
        iconSize: [30, 30],
      })
      const message
        = `<div style="padding: 10px;width: 230px;font-size: 16px;">
              <div style="font-weight: bold;margin-bottom: 10px">${item.monitorName || ''}</div>
              <div style="color: ` + `${color}` + `"><span style="color: black">设备状态:</span>${item.deviceStatusName || ''}</div>
              <div style="word-break: break-all; "><span>密级:</span>${item.secretLevelName || ''}</div>
              <div style="word-break: break-all; "><span>详细位置:</span>${item.location || ''}</div>
           </div>`
      const popup = L.popup().setContent(message)
      const divIcon = L.divIcon({
        html: `<div>
                <image src="${icon}" width="30" height="30" style="margin-bottom: -3px">
                <div style="margin-left: calc(-50% - 5px);border-radius:5px;display: inline-block;white-space: nowrap;background: rgb(255,255,255);text-align: left;height: 20px;padding: 0 4px">${item.monitorName || ''}</div>
              </div>`,
        className: 'my-div-icon',
        iconSize: [30, 30],
      })
      const marker = L.marker([item.latitude, item.longitude], { icon: divIcon }).addTo(map.value)
      marker.bindPopup(popup)
      // // 关闭popup时,重置地图中心点
      // marker.on('popupclose', () => {
      //   map.value.panTo(marker.getLatLng())
      // })

      // map.value.on('zoomend', (e: any) => {
      //   if (map.value) {
      //     map.value.getLayers().forEach(marker => {
      //       var newLatLng = marker.getLatLng()
      //       marker.setLatLng(newLatLng)
      //     })
      //   }
      // })

      // const marker = L.marker([item.latitude, item.longitude], { icon: divIcon }).addTo(ciLayer.value)
      // ciLayer.value!.addLayer(marker)
    })
    if (init && res && res.data && res.data.rows) {
      if (!res.data.rows.length) {
        ElMessage.warning('查无结果')
      }
      else {
        let lat = proxy.$position.lat
        let lng = proxy.$position.lng
        console.log('执行定位, 默认北京', lat, lng)
        for (let i = 0; i < res.data.rows.length; i++) {
          if (res.data.rows[i].latitude && res.data.rows[i].longitude) {
            lat = res.data.rows[i].latitude
            lng = res.data.rows[i].longitude
            console.log('lat, lng', lat, lng)
            break
          }
        }
        map.value.setView([lat, lng])
      }
    }
  })
}

onBeforeMount(() => {
  toParentsMap.value.lat = proxy.$position.lat
  toParentsMap.value.lng = proxy.$position.lng
})

onMounted(() => {
  map.value = L.map('map', {
    minZoom: Number(proxy.$zoom.minZoom),
    maxZoom: Number(proxy.$zoom.maxZoom),
    center: [toParentsMap.value.lat, toParentsMap.value.lng],
    zoom: Number(proxy.$zoom.zoom),
    zoomControl: false,
    attributionControl: false,
    crs: L.CRS.EPSG3857,
  })
  const str = '/static/tiles/{z}/{x}/{y}.png'
  baseLayer.value.push(L.tileLayer(str).addTo(map.value))
  search(false)

  // 当地图缩放结束后更新标记点位置
  map.value.on('zoomend', () => {
    console.log('监听缩放结束')
    search(false)
  })
})

onBeforeUnmount(() => {
})
</script>

<template>
  <div id="map" style="height: calc(100vh - 110px);" />
  <div class="input">
    <el-input v-model="keyword" type="text" placeholder="设备名称关键字" clearable style="width: 200px;" />
    <el-button type="primary" style="margin-left: 5px;" @click="search">
      查询
    </el-button>
  </div>
  <div class="cover">
    <div class="green" />
    <div class="gray" />
    <div class="item">
      正常
    </div>
    <div class="item">
      离线
    </div>
  </div>
  <div v-if="isRightShow" class="right" />
</template>

<style lang="scss">
.leaflet-popup {
  margin-bottom: 35px !important;
}
</style>

<style lang="scss" scoped>
.map {
  width: 100%;
  height: 100%;
}

.right {
  z-index: 1000 !important;
  position: absolute;
  right: 20px;
  top: 10px;
  width: 350px;
  height: calc(100vh - var(--g-topbar-height) - var(--g-header-height) - 20px);
  background: #faefe0;
  border-radius: 10px;
  padding: 20px 0;

  .devName {
    padding-left: 10px;
    margin-bottom: 10px;
    font-size: 19px;
    font-weight: bold;
  }

  .title {
    font-size: 17px;
    font-weight: bold;
    margin: 10px 0;
    color: #464646;
  }

  .close {
    width: 20px;
    height: 20px;
    position: absolute;
    right: 10px;
    top: 20px;
  }
}

.input {
  position: absolute;
  top: 20px;
  left: 20px;
  width: 280px;
  height: 34px;
  display: flex;
  z-index: 11111111111111;
}

.cover {
  position: absolute;
  bottom: 25px;
  left: 5px;
  width: 120px;
  height: 120px;
  border-radius: 10px;
  background: #faefe0;
  z-index: 1111;
  display: flex;
  flex-flow: column wrap;
  justify-content: space-evenly;
  align-items: center;

  .item {
    width: 50px;
    height: 45px;
    padding-top: 10px;
    font-weight: bold;
    color: #5f5f5f;
  }

  .green {
    background: url("../../assets/images/marker/green.png") no-repeat center / cover;
    width: 45px;
    height: 45px;
  }

  .red {
    background: url("../../assets/images/marker/red.png") no-repeat center / cover;
    width: 45px;
    height: 45px;
  }

  .gray {
    background: url("../../assets/images/marker/gray.png") no-repeat center / cover;
    width: 45px;
    height: 45px;
  }
}
</style>

<style>
.my-div-icon {
  color: black;
  font-size: 14px;
  text-align: center;
  pointer-events: none; /* Prevent mouse events from firing */
}
</style>