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