forked from drone/command-center-dashboard

罗广辉
2025-04-19 243e0266d7bd1dad2224fefd9a1d3ef8ced6345e
feat: 优化返航按钮
6 files modified
172 ■■■■■ changed files
src/api/drc.js 5 ●●●●● patch | view | raw | blame | history
src/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue 10 ●●●● patch | view | raw | blame | history
src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue 110 ●●●● patch | view | raw | blame | history
src/components/CurrentTaskDetails/CurrentTaskDetails.vue 37 ●●●● patch | view | raw | blame | history
src/components/CurrentTaskDetails/TaskDetailsHead.vue 2 ●●● patch | view | raw | blame | history
src/components/CurrentTaskDetails/TaskDetailsRight.vue 8 ●●●● patch | view | raw | blame | history
src/api/drc.js
@@ -57,9 +57,10 @@
}
// 取消返航
export async function returnHomeCancel(sn) {
export async function returnHomeCancel(data) {
  return request({
    url: `/drone-device-core/dp/home/${sn}/drc/returnHomeCancel`,
    url: `/drone-device-core/dp/home/${data.dock_sn}/drc/returnHomeCancel`,
    method: 'post',
    data,
  })
}
src/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue
@@ -8,7 +8,7 @@
        </div>
        <div class="instrument-center">
            <div class="compass-box" :style="{ transform: `rotate(${props?.options?.yawAngle || 0}deg)` }">
            <div class="compass-box" :style="compassStyle">
                <div v-for="(item, index) in str" :key="index" class="scale" :style="{ '--rotate': 30 * index + 'deg' }">
                    <span class="text">{{ item }}</span>
                </div>
@@ -41,10 +41,14 @@
    }
})
const compassStyle = computed(() => {
    return { transform: `rotate(${props?.options?.yawAngle || 0}deg)` }
})
const trueAltitudeStyle = computed(() => {
    const trueAltitude = props?.options?.trueAltitude || 0
    // 将 [-240,240] 映射到 [0%, 100%]
    const percentage = (((trueAltitude + 240) / 480) * 100).toFixed(2)
    // 将 [0,240] 映射到 [0%, 100%]
    const percentage = ((trueAltitude / 240) * 100).toFixed(2)
    return {
        bottom: `${percentage}%`,
    }
src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue
@@ -84,7 +84,7 @@
            <div class="ptzControlBtnBox">
                <div class="ptzControlBtn b-r">
                    <div
                        v-for="(item, index) in list5"
                        v-for="(item, index) in ptzBtns"
                        :style="item.style"
                        class="ptzControlItem"
                        @mousedown="onMouseDown(item.key)"
@@ -93,7 +93,7 @@
                    <div
                        class="ptzControlItemIcon"
                        v-for="(item, index) in list5"
                        v-for="(item, index) in ptzBtns"
                        :style="{ transform: `rotate(${index * 90}deg)` }"
                    >
                        <el-icon>
@@ -116,7 +116,7 @@
            </div>
            <div class="divider"></div>
            <div v-for="arr in baseInfo" class="info">
            <div v-for="arr in baseInfoList" class="info">
                <div v-for="item in arr" class="infoItem">
                    <div class="infoName">{{ item.name }}</div>
                    <div class="infoValue">{{ item.value + (item.unit || '') }}</div>
@@ -156,8 +156,17 @@
const taskDetails = inject('taskDetails')
const dockSn = inject('dockSn')
const droneSn = inject('droneSn')
const trueAltitude = inject('trueAltitude')
const client_id = inject('client_id')
const deviceTopicInfo = ref({
    pubTopic: '',
    subTopic: '',
})
const flightController = ref(false)
// 控制对象
let manualControl = {}
const isAutoControl = inject('isAutoControl')
const compassOptions = computed(() => {
    return {
@@ -168,7 +177,6 @@
})
let mqttState = null
const client_id = ref('')
const valueTime = ref('00:00:00')
let timer = null
let totalSeconds = 0
@@ -188,31 +196,25 @@
const speed = ref(5)
provide('speed', speed)
const list5 = [
const ptzBtns = [
    { name: '上', key: KeyCode.ARROW_UP, operate: 'up', style: { top: '-70%' } },
    { name: '右', key: KeyCode.ARROW_RIGHT, operate: 'right', style: { left: '70%' } },
    { name: '下', key: KeyCode.ARROW_DOWN, operate: 'down', style: { top: '70%' } },
    { name: '左', key: KeyCode.ARROW_LEFT, operate: 'left', style: { left: '-70%' } },
]
const baseInfo = computed(() => {
    const usedStorage = dock_osd_host.value?.storage?.used || baseInfo.value?.[1]?.[1]?.value || 0
    const zoom_factor = device_osd_host.value?.cameras?.[0]?.zoom_factor || 0
    const usedStorageGB = _.round(usedStorage / 1024 / 1024, 2)
    return [
        [
            { name: '焦距倍数', value: zoom_factor },
            { name: '俯仰角度', value: pitchAngle.value.angle, unit: '°' },
            { name: '横向角度', value: yawAngle.value.angle, unit: '°' },
        ],
        [
            { name: '储存', value: usedStorageGB, unit: 'G' },
            { name: '方向', value: pitchAngle.value.direction },
            { name: '方向', value: yawAngle.value.direction },
        ],
    ]
})
const baseInfoList = ref([
    [
        { name: '焦距倍数', value: 0 },
        { name: '俯仰角度', value: 0, unit: '°' },
        { name: '横向角度', value: 0, unit: '°' },
    ],
    [
        { name: '储存', value: 0, unit: 'G' },
        { name: '方向', value: 0 },
        { name: '方向', value: 0 },
    ],
])
const pitchAngle = computed(() => {
    const { payloads } = device_osd_host?.value || {}
@@ -234,7 +236,6 @@
        direction,
    }
})
const yawAngle = computed(() => {
    let { payloads, attitude_head } = device_osd_host?.value || {}
    const gimbal_yaw = payloads?.[0]?.gimbal_yaw || 0
@@ -255,12 +256,12 @@
    if ((yaw > -2 && yaw < 2) || parseInt(attitude_head) === parseInt(gimbal_yaw)) {
        result = attitude_head < 0 ? 180 + (180 + attitude_head) : attitude_head
    }
    const roundResult = Math.round(result);
    let direction = '';
    const roundResult = Math.round(result)
    let direction = ''
    for (const item of directionMap) {
        if (roundResult >= item.min && roundResult <= item.max) {
            direction = item.value;
            break;
            direction = item.value
            break
        }
    }
    return {
@@ -269,14 +270,25 @@
    }
})
const deviceTopicInfo = ref({
    pubTopic: '',
    subTopic: '',
})
const flightController = ref(false)
// 控制对象
let manualControl = {}
const isAutoControl = inject('isAutoControl')
const baseInfoChange = () => {
    const newUsedStorage = dock_osd_host.value?.storage?.used
    const zoom_factor = device_osd_host.value?.cameras?.[0]?.zoom_factor || 0
    const usedStorageGB = _.round(newUsedStorage / 1024 / 1024, 2)
    baseInfoList.value[0][0].value = _.round(zoom_factor, 0)
    baseInfoList.value[0][1].value = pitchAngle.value.angle
    baseInfoList.value[0][2].value = yawAngle.value.angle
    if (newUsedStorage !== undefined) baseInfoList.value[1][0].value = usedStorageGB
    baseInfoList.value[1][1].value = pitchAngle.value.direction
    baseInfoList.value[1][2].value = yawAngle.value.direction
}
watch(
    wsInfo,
    () => {
        baseInfoChange()
    },
    { immediate: true, deep: true }
)
const timeStart = () => {
    stop() // 避免重复启动
@@ -346,18 +358,20 @@
    })
}
const isBackDock = ref(false)
// 返航
function onBackDock() {
    returnHome(dockSn?.value).then(res => {
        ElMessage.success('返航操作成功')
    })
async function onBackDock() {
    await returnHome(dockSn?.value)
    ElMessage.success('返航操作成功')
    isBackDock.value = true
}
// 取消返航
function cancelBackDock() {
    returnHomeCancel(dockSn?.value).then(res => {
        ElMessage.success('取消返航成功')
    })
async function cancelBackDock() {
    await returnHomeCancel({ dock_sn: dockSn?.value, client_id: client_id.value })
    ElMessage.success('取消返航成功')
    isBackDock.value = false
}
// 创建mqtt连接
@@ -382,11 +396,7 @@
// 返航或取消返航
const returnOrCancelReturn = () => {
    if (device_osd_host?.value?.mode_code === 9) {
        cancelBackDock()
    } else {
        onBackDock()
    }
    isBackDock.value ? cancelBackDock() : onBackDock()
}
// useManualControl里面用的参数
src/components/CurrentTaskDetails/CurrentTaskDetails.vue
@@ -58,15 +58,28 @@
const trueAltitude = ref('') // 真实高度
const isAiLive = ref(false) // 是ai直播
const video_id = ref('') // 直播视频id
const isShow = defineModel('show') // 是否显示当前任务详情
const props = defineProps(['id'])
const currentLiveUrl = ref('') // 当前直播地址
const isTakeOff = ref(false) // 是在飞行中
const isMaxMap = ref(false) //是大地图
const client_id = ref('') //是大地图
const workspace_id = ref('')
let { wsInfo,removeWS } = useDroneWS(workspace_id) //ws信息,是一个ref对象
let { wsInfo, removeWS } = useDroneWS(workspace_id) //ws信息,是一个ref对象
provide('wsInfo', wsInfo)
provide('deviceOsdInfo', deviceOsdInfo)
provide('dockOsdInfo', wsInfo?.value?.dock_osd)
provide('dockSn', dockSn)
provide('droneSn', droneSn)
provide('isAutoControl', isAutoControl)
provide('lineQuality', lineQuality)
provide('taskDetailsViewer', taskDetailsViewer)
provide('taskDetails', taskDetails)
provide('trueAltitude', trueAltitude)
provide('isAiLive', isAiLive)
provide('video_id', video_id)
provide('client_id', client_id)
watch(
    wsInfo,
    () => {
@@ -75,19 +88,6 @@
    },
    { deep: true }
)
provide('wsInfo', wsInfo)
provide('isAutoControl', isAutoControl)
provide('lineQuality', lineQuality)
provide('taskDetailsViewer', taskDetailsViewer)
provide('taskDetails', taskDetails)
provide('deviceOsdInfo', deviceOsdInfo)
provide('dockOsdInfo', wsInfo?.value?.dock_osd)
provide('dockSn', dockSn)
provide('droneSn', droneSn)
provide('trueAltitude', trueAltitude)
provide('isAiLive', isAiLive)
provide('video_id', video_id)
// 获取机巢直播
const getDeviceLiveUrl = async () => {
@@ -106,11 +106,14 @@
}
// 获取无人机直播url
async function getDroneLiveUrl() {
async function getDroneLiveUrl(reset = false) {
    currentLiveUrl.value = ''
    await nextTick()
    const res = await liveStart(droneSn.value, lineQuality.value)
    currentLiveUrl.value = res.data.data.rtcs_url
    video_id.value = res.data.data.video_id
    isAiLive.value = false
    reset && ElMessage.success('刷新成功')
}
// 无人机直播画质切换
src/components/CurrentTaskDetails/TaskDetailsHead.vue
@@ -62,7 +62,7 @@
}
function refreshLive() {
    EventBus.emit('CurrentTaskDetails-getDroneLiveUrl')
    EventBus.emit('CurrentTaskDetails-getDroneLiveUrl',true)
}
function getFlightStatisticsFun() {
src/components/CurrentTaskDetails/TaskDetailsRight.vue
@@ -37,6 +37,10 @@
    () => {
        list.value.forEach(item => {
            item.value = taskDetails?.value?.[item.field] || ''
            if (item.name === '任务频次') {
                const { rep_rule_type = '', rep_rule_val = '' } = taskDetails?.value || {}
                item.value = rep_rule_type + ' -- ' + rep_rule_val
            }
        })
    },
    {
@@ -44,8 +48,6 @@
        deep: true,
    }
)
</script>
<style scoped lang="scss">
@@ -107,6 +109,8 @@
            .itemValue {
                font-weight: bold;
                color: #ffffff;
                word-break: break-all;     /* 强制在任意字符断行 */
                white-space: normal;       /* 允许正常换行 */
            }
        }
    }