<script lang="ts" setup name="Map"> import type { Ref } from 'vue' import { getCurrentInstance, ref } from 'vue' import dayjs from 'dayjs' import type { PointListInfo } from '../device/dev-interface' 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 type { DateReturn, TypeReturn } from '@/views/statistics/statistics-interface' import HKVideo from '@/components/HKVideo/index.vue' const { proxy } = getCurrentInstance() const websocket = useWebsocketStore() const toParentsMap = ref({ lat: '', lng: '', }) const keyword = ref('') const refreshMarker = ref(false) const isRightShow = ref(false) const pointList: Ref<PointListInfo[]> = 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() { 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, label: { content: item.monitorName, // 标签文本 offset: new AMap.Pixel(35, 5), style: { color: 'red', fontSize: '12px', }, }, 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 // 定位 if (pointList.value.length > 0) { console.log(pointList.value[0].latitude, pointList.value[0].longitude) toParentsMap.value = { lat: pointList.value[0].latitude, lng: pointList.value[0].longitude, } } }) } search() onMounted(() => { toParentsMap.value.lat = proxy.$position.lat toParentsMap.value.lng = proxy.$position.lng }) 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) => { device.value = {} device.value = res.data // const devInfo = res.data; // webRtcServer.value = new WebRtcStreamer("video", proxy.rtspServer); // webRtcServer.value.connect(`rtsp://${devInfo.deviceUser}:${devInfo.devicePassword}@${devInfo.deviceIp}`); // console.log(`rtsp://${devInfo.deviceUser}:${devInfo.devicePassword}@${devInfo.deviceIp}`) }) nextTick(() => { 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.refreshMap) { search() } 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() }) </script> <template> <a-map ref="amap" :to-parents-map="toParentsMap" :zoom="proxy.$zoom.zoom" :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 id="home" icon="icon-video" title="视频监控" height="250px" style="background: #faefe0;padding: 0;"> <h-k-video id="map" style="width: 100%;height: 100%;background: currentcolor;" :device="device" /> <!-- <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 { cursor: pointer; 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>