forked from drone/command-center-dashboard

罗广辉
2025-04-15 2888173145d91e465a25bea276acaa41f9a7b124
src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel.vue
@@ -2,86 +2,93 @@
   <div class="pointControl">
      <div class="direction">
         <div class="blackBg directionUp">
            <div v-for="item in upperRowButton" :key="item.text">
               <el-icon :class="item.icon"></el-icon>
               <div
                  :class="{ hotkeyBtn: true, activeKey: currentKey === item.text }"
                  @click="() => mousedown(item.text)"
                  v-hold="() => mousedown(item.text)"
               >
                  {{ item.text }}
               </div>
            </div>
            <el-button type="primary" @click="control">控制</el-button>
            <el-button type="primary" @click="cancelControl">取消控制</el-button>
            <el-button type="primary" ghost @mousedown="onMouseDown(KeyCode.KEY_Q)" @mouseup="onMouseUp">q</el-button>
         </div>
         <div class="blackBg directionDown">
            <div v-for="item in lowerRowButton" :key="item.text">
               <el-icon :class="item.icon"></el-icon>
               <div
                  :class="{ hotkeyBtn: true, activeKey: currentKey === item.text }"
                  @click="() => mousedown(item.text)"
                  v-hold="() => mousedown(item.text)"
               >
                  {{ item.text }}
               </div>
            </div>
         </div>
         <div class="blackBg directionDown"></div>
      </div>
      <ControlComPass />
      <div class="height-direction">
         <div class="blackBg height-direction-btn">
            <el-icon class="el-icon-top" />
            <div :class="{ hotkeyBtn: true, activeKey: currentKey === 'C' }" v-hold="() => mousedown('C')">C</div>
         </div>
         <div class="blackBg height-direction-btn">
            <div :class="{ hotkeyBtn: true, activeKey: currentKey === 'Z' }" v-hold="() => mousedown('Z')">Z</div>
            <el-icon class="el-icon-bottom" />
         </div>
      </div>
   </div>
</template>
<script setup>
import vHold from '@/directive/hold'
import ControlComPass from './ControlComPass/ControlComPass.vue'
import {
   KeyCode,
   useManualControl,
} from '@/hooks/controlDrone/useManualControl'
import { useMqtt } from '@/hooks/controlDrone/useMqtt'
import { useConnectDrone } from '@/hooks/controlDrone/useConnectDrone'
import { droneController, exitController, postDrcExit } from '@/api/drc'
import { ElMessage } from 'element-plus'
import { useStore } from 'vuex'
const lowerRowButton = [
   { icon: 'el-icon-arrow-left', text: 'A' },
   { icon: 'el-icon-arrow-down', text: 'S' },
   { icon: 'el-icon-arrow-right', text: 'D' },
]
const upperRowButton = [
   { icon: 'el-icon-refresh-left', text: 'Q' },
   { icon: 'el-icon-arrow-up', text: 'W' },
   { icon: 'el-icon-refresh-right', text: 'E' },
]
let currentKey = ref('')
let keyReset = null
let visible = false
const deviceOsdInfo = inject('deviceOsdInfo')
const taskDetails = inject('taskDetails')
function mousedown(key) {
   if (key === 'Q') {
      console.log(6666666666)
   }
}
function handleKeydown(e) {
   currentKey.value = e.key.toUpperCase()
   mousedown(e.key.toUpperCase())
}
function handleKeyup() {
   currentKey.value = null
}
onMounted(() => {
   window.addEventListener('keydown', handleKeydown)
   window.addEventListener('keyup', handleKeyup)
const deviceTopicInfo = ref({
   sn: deviceOsdInfo.value?.data?.sn,
   pubTopic: '',
   subTopic: '',
})
onBeforeUnmount(() => {
   window.removeEventListener('keydown', handleKeydown)
   window.removeEventListener('keyup', handleKeyup)
})
const flightController = ref(false)
console.log('控制面板')
// 连接无人机mqtt 成功获得有效控制
useConnectDrone()
// 订阅消息
useMqtt(deviceTopicInfo.value)
// 使用手动控制
const { handleKeyup, handleEmergencyStop, resetControlState } = useManualControl(
   deviceTopicInfo.value,
   flightController
)
function onMouseDown(type) {
   console.log('anxia')
   handleKeyup(type)
}
const store = useStore()
const clientId = computed(() => store.state.common.clientId)
const dock_sn = computed(() => taskDetails.value.device_sns[0])
function cancelControl() {
   exitController({ client_id: clientId.value, dock_sn:dock_sn.value })
      .then(res => {
         flightController.value = false
         deviceTopicInfo.value.subTopic = ''
         deviceTopicInfo.value.pubTopic = ''
         ElMessage.success('退出飞行控制成功')
      })
      .catch(e => {})
}
// 控制
function control() {
   if (!clientId.value) return ElMessage.error('无人机不在空中,不能进入指挥飞行模式。')
   if (!dock_sn.value) return ElMessage.error('系统错误,未获取到dock_sn')
   droneController({ client_id: clientId.value, dock_sn:dock_sn.value }).then(res => {
      flightController.value = true
      const { data } = res.data
      if (data.sub && data.sub?.length > 0) {
         deviceTopicInfo.value.subTopic = data.sub[0]
      }
      if (data.pub && data.pub?.length > 0) {
         deviceTopicInfo.value.pubTopic = data.pub[0]
      }
      ElMessage.success('控制成功')
   })
}
function onMouseUp() {
   console.log('弹起')
   resetControlState()
}
</script>
<style scoped lang="scss">
@@ -90,111 +97,19 @@
   align-items: center;
}
//变量
$FSColor: #00ee8b;
.hotkeyBtn {
   background: #3c3c3c;
   border-radius: 2px;
   width: 24px;
   height: 24px;
   font-size: 14px;
   line-height: 24px;
   text-align: center;
   color: #fff;
   cursor: pointer;
   -webkit-user-select: none;
   user-select: none;
   &:hover {
      background: $FSColor;
   }
}
.pointControl {
   position: absolute;
   bottom: 0;
   right: 0;
   width: 1540px;
   height: 217px;
   background: rgba(255, 255, 255, 0.3);
   border-radius: 40px 0px 40px 40px;
   display: flex;
   justify-content: center;
   align-items: flex-end;
   color: white;
   gap: 0 10px;
   pointer-events: all;
   width: 100%;
   height: 200px;
   .activeKey {
      background: $FSColor;
   }
   .blackBg {
      background: rgba(0, 0, 0, 0.65);
      padding: 5px 5px;
      border-radius: 5px;
   }
   .direction {
      display: flex;
      flex-direction: column;
      width: 100px;
      .speedBox {
         color: $FSColor;
         font-size: 16px;
         font-weight: 600;
         margin: 5px 0;
         gap: 0 5px;
      }
      .editBox {
         display: flex;
         justify-content: end;
         gap: 0 5px;
         margin-bottom: 5px;
         .current-point {
            font-size: 20px;
            display: flex;
            align-items: center;
            color: $FSColor;
         }
         .editPointBtn {
            &:hover {
               cursor: pointer;
               background: $FSColor;
            }
         }
      }
      .directionUp,
      .directionDown {
         display: flex;
         justify-content: space-around;
         text-align: center;
         height: 55px;
         > div {
            display: flex;
            flex-direction: column;
            justify-content: space-between;
         }
      }
   }
   .height-direction {
      width: 100px;
      display: flex;
      flex-direction: column;
      align-items: end;
      gap: 5px 0;
      .height-direction-btn {
         width: 35px;
         height: 55px;
         text-align: center;
         display: flex;
         flex-direction: column;
         justify-content: space-between;
      }
   }
}
</style>