Newer
Older
laserPTZFrontV2.0 / src / views / map / map.vue
bairujie on 7 Jun 2023 9 KB bug修改
<script lang="ts" setup name="Map">
import { Ref } from "vue"
import dayjs from 'dayjs'
import type { DateModelType } from 'element-plus'
import type { PointListInfo } from '../device/dev-interface'
import aMap from '@/components/aMap/index.vue'
import { getDataHisList, getDevMap, getDevInfo } from '@/api/ptz/dev'
import useWebsocketStore from '@/store/modules/websocket'
import config from 'public/config/config.json'
const websocket = useWebsocketStore()
const toParentsMap = ref({
  city: '北京市',
  detailedAddress: '',
  districtCode: '440304',
  id: 'B02F37TV2J',
  lat: '39.9',
  lng: '116.4',
  province: '北京市',
  zone: '海淀区',
  points: [],
})
const keyword = ref('')
const refreshMarker = ref(false)
const isRightShow = ref(false)
const pointList: Ref<PointListInfo[]> = ref([])

function search() {
  refreshMarker.value = false
  getDevMap(keyword.value).then((res) => {
    pointList.value = res.data.map((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
        case '2':
          icon = './marker/red.png'
          color = 'red'
          break
      }
      return {
        ...item,
        icon,
        message:
          `<div style="padding: 10px;width: 230px">
            <div style="font-size: 16px;font-weight: bold;margin-bottom: 10px">${item.monitorName || ''}</div>
            <div><span>所在场站:</span>${item.stationName || ''}</div>
            <div style="color: ` + `${color}` + `">
            <span style="color: black">设备状态:</span>${item.deviceStatusName || ''}</div>
            <div style="margin-bottom: 10px; word-break: break-all; "><span>详细位置:</span>${item.location || ''}</div>
            <div class="btnDetail" style="color: #3776ff;margin-left: 170px;cursor: pointer;font-size: 15px" id="btnDetail_${item.monitorId || ''}">详情</div>
         </div>`,
      }
    })
    refreshMarker.value = true
  })
  // pointList.value = [
  //   {
  //     id: '1',
  //     stationName: '1',
  //     monitorName: '云台名称',
  //     longitude: '116.4',
  //     latitude: '39.9',
  //     location: '1111111111111111111111111',
  //     deviceStatus: '1',
  //     deviceStatusName: '1'
  //   },{
  //     id: '1',
  //     stationName: '1',
  //     monitorName: '云台名称',
  //     longitude: '116.41',
  //     latitude: '39.91',
  //     location: '11111111111111111111111111',
  //     deviceStatus: '2',
  //     deviceStatusName: '1'
  //   }
  // ]
}
search()

// onMounted(() => {
//   document.addEventListener('click',(e)=>{
//     console.log(e.target.id.search('btnDetail') !== -1)
//   })
// })

const currentName = ref('')
const monitorId = ref('')
const deviceIp = ref('')
const devCH4Loading = ref(false)
const devCH4XData: Ref<string[]> = ref([])
const devCH4Data: Ref<lineDataI[]> = ref([])
const devCH4YDataMax = ref()
const webRtcServer = ref(null)

function clickRecall(item: any) {
  webRtcServer.value = null
  const pressTimer = setTimeout(() => {
    document.getElementsByClassName('btnDetail')[0].onclick = function () {
      isRightShow.value = true
      currentName.value = item.monitorName
      monitorId.value = item.monitorId
      deviceIp.value = item.deviceIp
      monitorId.value && getDevInfo(monitorId.value).then(res =>{
        const devInfo = res.data;
        webRtcServer.value = new WebRtcStreamer("video", config.rtspServer);
        webRtcServer.value.connect(`rtsp://${devInfo.deviceUser}:${devInfo.devicePassword}@${devInfo.deviceIp}`);
      })
      nextTick(() => {
        // 构造视频
        // const res1 = [{
        //   logTime: '08:00:23',
        //   num: 2,
        // }, {
        //   logTime: '08:15:23',
        //   num: 3,
        // },
        // {
        //   logTime: '08:00:23',
        //   num: 5,
        // }, {
        //   logTime: '08:15:23',
        //   num: 4,
        // },
        // {
        //   logTime: '08:00:23',
        //   num: 2,
        // }, {
        //   logTime: '08:15:23',
        //   num: 3,
        // },
        // ]
        // const yValue = res1.map((item: DateReturn) => Number(item.num))
        // devCH4YDataMax.value = Math.max(yValue) > 10 ? Math.max(yValue) : 10
        // devCH4XData.value = res1.map((item: TypeReturn) => item.logTime)
        // devCH4Data.value = [{ name: 'CH4', data: yValue }]
        // devCH4Loading.value = false
        // return
        devCH4Loading.value = true
        const param = {
          monitorId: item.monitorId,
          startTime: dayjs(Date.now() - 1 * 60 * 1000).format('YYYY-MM-DD HH:mm:ss'),
          endTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
        }
        getDataHisList(param).then((res) => {
          const yValue = res.data.reverse().map((item: DateReturn) => {
            if(Object.keys(item).toString().includes('num')){
              Number(item.num)
            } else {
              Number(item.concentration)
            }
          })
          devCH4YDataMax.value = Math.max(yValue) > 10 ? Math.max(yValue) : 10
          devCH4XData.value = res.data.map((item: TypeReturn) => item.logTime ? item.logTime.split(' ')[1] : '')
          devCH4Data.value = [{ name: 'CH4', data: yValue }]
          devCH4Loading.value = false
        })
      })
    }
  }, 500)
}


// watch监听websocket变化
const unwatch = watch(websocket, (newVal) => {
  if (newVal.lineData && Object.keys(newVal.lineData).length >= 1 && isRightShow.value) {
    console.log('监测到新的数据,并且右侧面板开启!')
    // 匹配id
    if (newVal.lineData.deviceIp === deviceIp.value) {
      devCH4Loading.value = true
      // 判断数据长度
      if(devCH4XData.value.length > 300) {
        devCH4XData.value.splice(0,100)
        devCH4Data.value[0].data.splice(0,100)
      }
      devCH4XData.value = [...devCH4XData.value, dayjs(newVal.lineData.time).format('HH:mm:ss')]
      devCH4Data.value = [{ name: 'CH4', data: devCH4Data.value[0].data.concat(newVal.lineData.gasData) }]
      devCH4Loading.value = false
    }
  }
})

onBeforeUnmount(() => {
  if(webRtcServer.value && typeof webRtcServer.value.disconnect === 'function'){
    webRtcServer.value.disconnect();
    webRtcServer.value = null
  }
  // 在需要取消监听的地方调用 unwatch() 函数
  unwatch();
})

</script>

<template>
  <a-map
    :to-parents-map="toParentsMap" :zoom="12" :points="pointList" :refresh-marker="refreshMarker" class="map"
    @clickRecall="clickRecall"
  />
  <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="red" />
    <div class="item">
      正常
    </div>
    <div class="item">
      离线
    </div>
    <div class="item">
      报警
    </div>
  </div>
  <div v-if="isRightShow" class="right">
    <svg-icon name="icon-close" class="close" @click="isRightShow = false" />
    <div class="devName">
      {{ currentName }}
    </div>
    <bench-col icon="icon-video" id="home" title="视频监控" height="250px" style="background: #faefe0;padding: 0;">
    <video id="video" autoPlay style="width: 100%;
    height: 100%;background:currentColor;"></video>
    </bench-col>
    <bench-col
      v-loading="devCH4Loading" icon="icon-line" title="浓度监控(ppm·m)" height="250px"
      style="background: #faefe0;padding: 0;"
    >
      <line-chart
        :x-axis-data="devCH4XData" width="340px" :data="devCH4Data" unit="" :grid="{
          top: 10,
          left: 10,
          right: 30,
          bottom: 20,
          containLabel: true, // 是否包含坐标轴的刻度标签
        }
        "
      />
    </bench-col>
  </div>
</template>

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

.cover {
  position: absolute;
  bottom: 25px;
  left: 5px;
  width: 120px;
  height: 170px;
  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>