<script lang="ts" setup name="videoControl"> import type { FormInstance, FormRules } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus' import type { Ref } from 'vue' import { getCurrentInstance, reactive, ref } from 'vue' import dayjs from 'dayjs' import LineChart from '@/components/Echart/LineChart.vue' import useWebsocketStore from '@/store/modules/websocket' import { initPlugin, login, logout, onlyLogin, preview } from '@/utils/HKVideo' import controlImg from '@/assets/images/control.png' import type { lineDataI } from '@/components/Echart/echart-interface' import { delAlarm, getAlarmListPage } from '@/api/ptz/alarm' import { getDataHisList, getDevInfo, restartDev } from '@/api/ptz/dev' import ThreeMap from '@/components/ThreeMap/index.vue' import {getRobotList, robotDetail, robotFour} from "@/api/home/robot/robot"; import useSettingsStore from "@/store/modules/settings"; import {ptzFour} from "@/api/home/robot/ptz"; import {getDevList, hsList} from "@/api/home/tcy/tcy"; // 竖轴 const threeMap = ref() // 组件 const settingsStore = useSettingsStore() // const mapSize = ref(260) // const mapNum = ref(20) const gridHeight = ref(200) const gridWidth = ref(200) const resolution = ref(4) const pcdUrl = ref('') const websocket = useWebsocketStore() const $route = useRoute() const wiper = ref(true) const realppm = ref('****') const xinput = ref('0') const jinput = ref('0') const realh = ref('****') const realv = ref('****') const clickType = ref(true) const devCH4XData: Ref<string[]> = ref([]) const devCH4Data: Ref<lineDataI[]> = ref([{name: '检测数值', data: []}]) const tableData = ref([]) const instance = getCurrentInstance() const selectPoint = ref('') // control const robotRun = ref({w: 0, v: 0, isStop: true}) const timer = ref() const wv = ref({w: 0, v: 0}) const divPlugin = ref(null) const lineList: Ref<any[]> = ref([]) const pointList: Ref<any[]> = ref([]) const addData = ref({ speed: '', time: '', alarm: '', }) const activeName= ref('0') const pointName = ref('') const showAdd = ref(false) const x1 = ref(0) const x2 = ref(4095) const x3 = ref(0) const x4 = ref(4095) const mcaData: Ref<any[]> = ref([ {name: 'mca', data: []}, {name: '', data: []} ]) const psdData: Ref<any[]> = ref([ {name: 'psd', data: []}, {name: '', data: []} ]) let mcaobj0 = {} let mcaobj1 = {} let psdobj0 = {} let psdobj1 = {} // socket更新数据 // socket更新数据 const unwatch = watch(websocket, (newVal) => { if (newVal.psdData && Object.keys(newVal.psdData).length >= 1 && settingsStore.robot.id === newVal.psdData.robotId ) { // 判断折现数据长度 if (devCH4XData.value.length > 300) { devCH4XData.value.splice(0, 100) devCH4Data.value[0].data.splice(0, 100) } devCH4XData.value = [...devCH4XData.value, newVal.psdData.time] devCH4Data.value = [{name: '检测数值', data: devCH4Data.value[0].data.concat(newVal.psdData.psd)}] } else if (newVal.alarmData && Object.keys(newVal.alarmData).length >= 1 ) { newVal.alarmData.position = newVal.alarmData.x + ',' + newVal.alarmData.y tableData.value.push(newVal.alarmData) } else if (newVal.detectorHData && Object.keys(newVal.detectorHData).length >= 1 ) { if(mcaobj0.hasOwnProperty(newVal.detectorHData.mcaX)) { mcaobj0[newVal.detectorHData.mcaX] += newVal.detectorHData.mcaY } else { mcaobj0[newVal.detectorHData.mcaX] = newVal.detectorHData.mcaY } if(mcaobj1.hasOwnProperty(newVal.detectorHData.mcaX1)) { mcaobj1[newVal.detectorHData.mcaX1] += newVal.detectorHData.mcaY1 } else { mcaobj1[newVal.detectorHData.mcaX1] = newVal.detectorHData.mcaY1 } if(psdobj0.hasOwnProperty(newVal.detectorHData.psdX)) { psdobj0[newVal.detectorHData.psdX] += newVal.detectorHData.psdY } else { psdobj0[newVal.detectorHData.psdX] = newVal.detectorHData.psdY } if(psdobj1.hasOwnProperty(newVal.detectorHData.psdX1)) { psdobj1[newVal.detectorHData.psdX1] += newVal.detectorHData.psdY1 } else { psdobj1[newVal.detectorHData.psdX1] = newVal.detectorHData.psdY1 } } }) // 云台上下左右 function controlWithSpeed( type: any, isStop: any) { // console.log(type) const params = { deviceIp: settingsStore.robot.ptzInfo.deviceIp, robotId: settingsStore.robot.id, command: type, isStop, // speed: controlSpeed.value.toString(), } ptzFour(params).then(() => {}) } const ptzClick = ref({ up: 0, down: 0, left: 0, right: 0, }) function controlWithSpeedClick(type: string) { if(type === 'up' || type === 'down' || type === 'left' || type === 'right' ) { ptzClick.value[type] = (ptzClick.value[type] + 1) % 2 const params = { deviceIp: settingsStore.robot.ptzInfo?.deviceIp, robotId: settingsStore.robot.id, command: type, isStop : ptzClick.value[type], // speed: controlSpeed.value.toString(), } ptzFour(params).then(() => {}) } } function getWV() { robotDetail({ id: settingsStore.robot.id, }).then((res) => { if(res.code === 200) { wv.value.w = res.data.robotW wv.value.v = res.data.robotV } }) } // 调整大小 const resize = () => { WebVideoCtrl.I_Resize(divPlugin.value.clientWidth, divPlugin.value.clientHeight) } function formatTooltip(val) { return `转动速度:${val}` } function tableRowClassName({ row, rowIndex }) { if (rowIndex % 2 === 1) { return 'e-row' } return '' } // 登录设备 function loginDevice() { login( settingsStore.robot.ptzInfo?.deviceIp, '80', settingsStore.robot.ptzInfo?.deviceUser, settingsStore.robot.ptzInfo?.devicePassword, 0) } // 复位 function fw() { restartDev(settingsStore.robot.ptzInfo?.doorIp, settingsStore.robot.ptzInfo?.doorSn).then(() => { ElMessage.success('复位成功') }) } const keydownRun = ref({ w: false, a: false, s: false, d: false, ArrowUp: false, ArrowLeft: false, ArrowDown: false, ArrowRight: false }) function keydown(event: { key: string }) { if (event.key === 'w' && !keydownRun.value[event.key]) { keydownRun.value[event.key] = true controlWithSpeed('up', 0) } else if (event.key === 'a' && !keydownRun.value[event.key]) { keydownRun.value[event.key] = true controlWithSpeed('left', 0) } else if (event.key === 's' && !keydownRun.value[event.key]) { keydownRun.value[event.key] = true controlWithSpeed('down', 0) } else if (event.key === 'd' && !keydownRun.value[event.key]) { keydownRun.value[event.key] = true controlWithSpeed('right', 0) } else if (event.key === 'ArrowUp' && !keydownRun.value[event.key]) { keydownRun.value[event.key] = true robotRun.value = {w: 0,v: wv.value.v, isStop: false} } else if (event.key === 'ArrowLeft' && !keydownRun.value[event.key]) { keydownRun.value[event.key] = true robotRun.value = {v: 0,w: wv.value.w, isStop: false} } else if (event.key === 'ArrowDown' && !keydownRun.value[event.key]) { keydownRun.value[event.key] = true robotRun.value = {w: 0,v: -wv.value.v, isStop: false} } else if (event.key === 'ArrowRight' && !keydownRun.value[event.key]) { keydownRun.value[event.key] = true robotRun.value = {v: 0,w: -wv.value.w, isStop: false} } } function keyup(event: { key: string }) { if (event.key === 'w') { keydownRun.value[event.key] = false controlWithSpeed('up', 1) } else if (event.key === 'a') { keydownRun.value[event.key] = false controlWithSpeed('left', 1) } else if (event.key === 's') { keydownRun.value[event.key] = false controlWithSpeed('down', 1) } else if (event.key === 'd') { keydownRun.value[event.key] = false controlWithSpeed('right', 1) } else if (event.key === 'ArrowUp') { keydownRun.value[event.key] = false robotRun.value = {w: 0,v: wv.value.v, isStop: true} } else if (event.key === 'ArrowLeft') { keydownRun.value[event.key] = false robotRun.value = {v: 0,w: wv.value.w, isStop: true} } else if (event.key === 'ArrowDown') { keydownRun.value[event.key] = false robotRun.value = {w: 0,v: -wv.value.v, isStop: true} } else if (event.key === 'ArrowRight') { keydownRun.value[event.key] = false robotRun.value = {v: 0,w: -wv.value.w, isStop: true} } } // 获取历史甲烷浓度 function getCH4() { const param = { monitorId: $route.query.id, 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: any) => { 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: any) => item.logTime ? item.logTime.split(' ')[1] : '') // devCH4Data.value = [{ name: 'CH4', data: yValue }] }) } onMounted(() => { setTimeout(() => { getRobotList({}).then((response) => { if(response.code === 200) { const robot = response.data.filter((item: any) => item.id === settingsStore.robot.id)[0] pcdUrl.value = window.localStorage.getItem('baseurl-robot') + '/static/finalCloud_' + robot.id + '.pcd' // mapSize.value = Number(robot.gridSize) // mapNum.value = Number(robot.gridNumber) gridHeight.value = Number(robot.gridHeight) gridWidth.value = Number(robot.gridWidth) resolution.value = Number(robot.resolution) setTimeout(() => { threeMap.value.initMap() }, 100) getWV() } }) initPlugin(1, '', false, loginDevice, null) divPlugin.value = document.getElementById('divPlugin') // 机器人控制 timer.value = setInterval(function() { if(robotRun.value.isStop) return const params = { action: 0, priority: 0, robotId: settingsStore.robot.id, w: robotRun.value.w, v: robotRun.value.v, } robotFour(params).then(() => {}) }, 500); // 每隔0.5秒执行一次 // 甲烷历史浓度 // getCH4() window.addEventListener('resize', resize) // WASD ↑.←.↓.→ document.addEventListener('keydown', keydown) document.addEventListener('keyup', keyup) updateTimer() getDevList({}).then((response) => { if(response.code === 200) { robot.value = response.data.filter((item: { robotId: any; }) => item.robotId === settingsStore.robot.id)[0] hs(1) } }) }, 200) }) const updateTimer = () => { mcaData.value[0].data = Object.entries(mcaobj0) mcaData.value[1].data = Object.entries(mcaobj1) psdData.value[0].data = Object.entries(psdobj0) psdData.value[1].data = Object.entries(psdobj1) }; const timer1 = setInterval(updateTimer, 1000); const robot = ref({}) function hs(type: any) { hsList({ detectorId: robot.value.id, type, x1: x1.value, x2: x2.value, x3: x3.value, x4: x4.value, }).then((res) => { if(res.code === 200) { ElMessage.success('指令下发成功') } }) } onBeforeUnmount(() => { // WebVideoCtrl.JS_HideWnd() WebVideoCtrl.I_Resize(0, 0) unwatch() logout(settingsStore.robot.ptzInfo?.deviceIp) timer.value && clearInterval(timer.value) timer1 && clearInterval(timer1) window.location.reload() window.removeEventListener('resize', resize) document.removeEventListener('keydown', keydown) document.removeEventListener('keyup', keyup) }) </script> <template> <div class="video-wrap"> <div class="left-container"> <three-map ref="threeMap" class="map-kzt" id="pcdcontainer-kzt" :gridHeight="gridHeight" :gridWidth="gridWidth" :resolution="resolution" :pcdUrl="pcdUrl"/> <el-table style="width: 100%;height: 200px;margin-top: 5px;" :data="tableData" :row-class-name="tableRowClassName" height="200" size="small" border> <el-table-column prop="robotName" label="设备名称" align="center" /> <el-table-column prop="taskTypeName" label=任务类型 align="center" /> <el-table-column prop="discernTypeName" label="识别类型" align="center" /> <el-table-column prop="monitorVal" label="检测数值" align="center" /> <el-table-column prop="position" label="告警位置" align="center" /> <el-table-column prop="alarmTime" label="告警时间" align="center" /> </el-table> <div style="width: 160px;color: #2a3746;font-family: 微软雅黑;font-size: 14px;position: absolute;right: 40%;bottom: 220px;z-index: 99999999;" v-if="activeName !== '0'"> <div>X1:<el-input-number v-model="x1" :precision="0" :step="1" :min="0" :max="4095" size="small"/></div> <div style="margin-top: 6px">X2:<el-input-number v-model="x2" :precision="0" :step="1" :min="0" :max="4095" size="small"/></div> <div style="margin-top: 6px">X3:<el-input-number v-model="x3" :precision="0" :step="1" :min="0" :max="4095" size="small"/></div> <div style="margin-top: 6px">X4:<el-input-number v-model="x4" :precision="0" :step="1" :min="0" :max="4095" size="small"/></div> </div> </div> <div class="right-container"> <div id="divPlugin" class="videoControl" /> <el-tabs v-model="activeName" style="margin-left: 10px"> <el-tab-pane label="检测数值" name="0"/> <el-tab-pane label="mca" name="mca"/> <el-tab-pane label="psd" name="psd"/> </el-tabs> <div class="ppm-line"> <line-chart v-if="activeName==='0'" :x-axis-data="devCH4XData" width="100%" :data="devCH4Data" unit="" :grid="{ top: 10, left: 10, right: 10, bottom: 20, containLabel: true }" /> <bar-chart-vertical v-if="activeName==='mca'" id="mca" width="100%" :isDataZoom="false" :data="mcaData" unit="" :grid="{ top: 10, left: 10, right: 10, bottom: 20, containLabel: true }" /> <bar-chart-vertical v-if="activeName==='psd'" id="psd" width="100%" :isDataZoom="false" :data="psdData" unit="" :grid="{ top: 10, left: 10, right: 10, bottom: 20, containLabel: true }" /> </div> <div class="bottom"> <el-switch style="margin: 10px" v-model="clickType" active-text="连续" inactive-text="点动"> </el-switch> <div style="margin-left: 10px;color: #4f4f4f;margin-bottom: 8px"><svg-icon name="icon-keyboard" style="width: 16px;height: 16px;margin-right: 8px"/>可由键盘控制</div> <div style="margin-left: 10px;font-weight: bolder;color: #555555;margin-bottom: 2px;font-size:14px">云   台: W.A.S.D</div> <div style="margin-left: 10px;font-weight: bolder;color: #555555;font-size:14px">机器人: ↑.←.↓.→</div> <div class="control-title" style="right: 360px">云台控制</div> <el-image style="width: 130px; height: 130px;position: absolute;bottom: 10px;right: 220px" :src="controlImg" fit="fill" /> <!-- <el-icon style="position: absolute;bottom: 62px;right: 272px;z-index: 1111111;color: #626262;font-size: 24px;font-weight: bold;cursor: pointer" title="复位" @click="fw"><Refresh/></el-icon>--> <div v-show="clickType"> <div class="round-btn" style="bottom: 95px;right: 265px" @mousedown="controlWithSpeed('up', 0)" @mouseup="controlWithSpeed('up', 1)" /> <div class="round-btn" style="bottom: 13px;right: 265px" @mousedown="controlWithSpeed('down', 0)" @mouseup="controlWithSpeed('down', 1)"/> <div class="round-btn" style="bottom: 53px;right: 223px" @mousedown="controlWithSpeed('right', 0)" @mouseup="controlWithSpeed('right', 1)"/> <div class="round-btn" style="bottom: 53px;right: 305px" @mousedown="controlWithSpeed('left', 0)" @mouseup="controlWithSpeed('left', 1)"/> </div> <div v-show="!clickType"> <div class="round-btn" style="bottom: 95px;right: 265px" @click="controlWithSpeedClick('up')" /> <div class="round-btn" style="bottom: 13px;right: 265px" @click="controlWithSpeedClick('down')"/> <div class="round-btn" style="bottom: 53px;right: 223px" @click="controlWithSpeedClick('right')"/> <div class="round-btn" style="bottom: 53px;right: 305px" @click="controlWithSpeedClick('left')"/> </div> <div class="control-title" style="right: 150px">机器人控制</div> <el-image style="width: 130px; height: 130px;position: absolute;bottom: 10px;right: 10px" :src="controlImg" fit="fill" /> <div v-show="clickType"> <div class="round-btn" style="bottom: 13px;right: 55px" @mousedown="robotRun={w: 0,v: -wv.v,isStop: false}" @mouseup="robotRun={w: 0,v: -wv.v,isStop: true}"/> <div class="round-btn" style="bottom: 95px;right: 55px" @mousedown="robotRun={w: 0,v: wv.v,isStop: false}" @mouseup="robotRun={w: 0,v: wv.v,isStop: true}"/> <div class="round-btn" style="bottom: 53px;right: 95px" @mousedown="robotRun={w: wv.w,v: 0,isStop: false}" @mouseup="robotRun={w: wv.w,v: 0,isStop: true}"/> <div class="round-btn" style="bottom: 53px;right: 13px" @mousedown="robotRun={w: -wv.w,v: 0,isStop: false}" @mouseup="robotRun={w: -wv.w,v: 0,isStop: true}"/> </div> <div v-show="!clickType"> <div class="round-btn" style="bottom: 13px;right: 55px" @click="robotRun={w: 0,v: -wv.v,isStop: !robotRun.isStop}"/> <div class="round-btn" style="bottom: 95px;right: 55px" @click="robotRun={w: 0,v: wv.v,isStop: !robotRun.isStop}"/> <div class="round-btn" style="bottom: 53px;right: 95px" @click="robotRun={w: wv.w,v: 0,isStop: !robotRun.isStop}"/> <div class="round-btn" style="bottom: 53px;right: 13px" @click="robotRun={w: -wv.w,v: 0,isStop: !robotRun.isStop}"/> </div> </div> </div> </div> </template> <style lang="scss" > .el-table .e-row { background: #f0f4fe; } </style> <style lang="scss" scoped> .map-kzt { width: 100%; height: calc(100% - 205px); } .video-wrap { width: 100%; height: calc(100vh - 60px); display: flex; flex-wrap: wrap; background: white; } .left-container { width: calc(60% - 15px); height: calc(100% - 10px); border-radius: 10px; margin: 5px; } .right-container { width: 40%; height: calc(100% - 10px); border-radius: 10px; margin: 5px 0px; } .ppm-line { width: calc(100% - 0px); height: calc(55% - 185px); margin-top: -10px; flex: 1; } .videoControl { //float: right; height: 45%; width: 100%; //position: relative; } .bottom { width: 100%; height: 135px; background: #eef2fd; border-radius: 10px; } .box-card { width: 100%; height: calc(50% - 5px); margin-bottom: 5px; padding: 5px !important; box-shadow: 0 2px 12px 0 rgba(0,0,0,.1); overflow: hidden; } .control-title { color: white; background-color: #ff9f11; border-bottom-right-radius: 10px; border-top-right-radius: 10px; writing-mode: vertical-rl; text-orientation: upright; width: 30px; height: 100px; line-height: 30px; font-weight: bold; text-align: center; letter-spacing: 1px; position: absolute; bottom: 40px; font-family: Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,SimSun,sans-serif; } .set-btn { margin-left: 10px; width: 80px; } .btn-contain { margin-left: 10%; width: 55%; display: flex; flex-wrap: wrap; align-content: space-around; justify-content: center; } .btn { width: 20%; height: 40px; font-size: 16px; } .data-monitor { margin: 0px 5px; color: #a6cbff; font-weight: bold; letter-spacing: 1px; padding: 5px; width: 44%; h { padding-left: 10px; color: white; font-weight: normal; font-size: 16px; } } .el-message-box { position: absolute !important; top: calc(50% - 68px) !important; left: 100px !important; } .ptz-control { width: 400px; position: absolute; right: 18%; top: 5px; display: flex; justify-content: center; align-items: flex-start; flex-wrap: wrap; } .round-btn { position: absolute; width: 42px; height: 42px; z-index: 111111; border-radius: 21px; cursor: pointer; } .round-btn:hover { background-color: rgba(61, 125, 254, 0.53); } .icon-button { background-color: #d6e5fc; border-color: #d6e5fc; padding: 6px; border-radius: 6px; color: #4384ff; :deep(.el-icon) { width: 18px; height: 18px; } &:hover { background-color: #c3dafd; color: #fff; } } </style>