GuLiMmo
2024-04-01 3d954cd30c42279fa50e3f52a46b06a19afe3369
update:参数和相机直播问题修改
8 files modified
1 files added
328 ■■■■■ changed files
src/api/drone-control/drone.ts 6 ●●●● patch | view | raw | blame | history
src/components/GMap.vue 10 ●●●● patch | view | raw | blame | history
src/components/g-map/DroneControlPanel.vue 43 ●●●●● patch | view | raw | blame | history
src/components/waylinetool/component/interval-shoot.vue 234 ●●●●● patch | view | raw | blame | history
src/components/waylinetool/component/take-photo.vue 10 ●●●●● patch | view | raw | blame | history
src/components/waylinetool/event-edit.vue 8 ●●●● patch | view | raw | blame | history
src/components/waylinetool/route-profile.vue 2 ●●● patch | view | raw | blame | history
src/pages/page-web/projects/wayline.vue 1 ●●●● patch | view | raw | blame | history
src/types/drone-control.ts 14 ●●●●● patch | view | raw | blame | history
src/api/drone-control/drone.ts
@@ -48,7 +48,11 @@
  max_speed: number; // flyto过程中能达到的最大速度, 单位m/s 跟飞机档位有关
  rc_lost_action: LostControlActionInCommandFLight; // 失控行为
  rth_altitude: number; // 返航高度
  exit_wayline_when_rc_lost: WaylineLostControlActionInCommandFlight
  exit_wayline_when_rc_lost: WaylineLostControlActionInCommandFlight,
  rth_mode?: number,
  commander_mode_lost_action?: number,
  commander_flight_mode?: number,
  commander_flight_height?: number
}
// 一键起飞
src/components/GMap.vue
@@ -585,7 +585,7 @@
                  type="primary"
                  size="small"
                  @click="openAircra(1)">
                  M30T相机
                  {{ osdVisible.model || 'M30T' }}相机
                </a-button>
              </a-col>
            </a-row>
@@ -1167,7 +1167,13 @@
                  vadeosList: v.videos_list,
                }
              })
              aircraSelected.value = aircraftList.value[index].value
              // 展示这样写, fpv有问题
              if (aircraftList.value[index]) {
                aircraSelected.value = aircraftList.value[index].value
              } else {
                const i = aircraftList.value.length - 1
                aircraSelected.value = aircraftList.value[i].value
              }
              flyOnStart()
            } else {
              showAircraft.value = false
src/components/g-map/DroneControlPanel.vue
@@ -135,6 +135,34 @@
                                    <a-input-number v-model:value="takeoffToPointPopoverData.rthAltitude"/>
                                </div>
                                <div>
                                    <span class="form-label">指点飞行高度(m):</span>
                                    <a-input-number :min="2" :max="8000" v-model:value="takeoffToPointPopoverData.commanderFlightHeight"/>
                                </div>
                                <div>
                                  <span class="form-label">返航模式:</span>
                                  <a-select
                                    v-model:value="takeoffToPointPopoverData.rthMode"
                                    style="width: 120px"
                                    :options="RthModeOptions"
                                  ></a-select>
                                </div>
                                <div>
                                  <span class="form-label">指点飞行模式:</span>
                                  <a-select
                                    v-model:value="takeoffToPointPopoverData.commanderFlightMode"
                                    style="width: 120px"
                                    :options="CommanderFlightModeOptions"
                                  ></a-select>
                                </div>
                                <div>
                                  <span class="form-label">指点飞行失控动作:</span>
                                  <a-select
                                    v-model:value="takeoffToPointPopoverData.commanderModeLostAction"
                                    style="width: 120px"
                                    :options="CommanderModeLostActionOptions"
                                  ></a-select>
                                </div>
                                <div>
                                    <span class="form-label">失控操作:</span>
                                    <a-select
                                            v-model:value="takeoffToPointPopoverData.rcLostAction"
@@ -308,6 +336,9 @@
} from '/@/api/drone-control/drone'
import { useDroneControl } from './use-drone-control'
import {
  RthModeOptions,
  CommanderModeLostActionOptions,
  CommanderFlightModeOptions,
  GimbalResetMode,
  GimbalResetModeOptions,
  LostControlActionInCommandFLightOptions,
@@ -429,7 +460,11 @@
  maxSpeed: MAX_SPEED,
  rthAltitude: 100 as null | number,
  rcLostAction: LostControlActionInCommandFLight.RETURN_HOME,
  exitWaylineWhenRcLost: WaylineLostControlActionInCommandFlight.EXEC_LOST_ACTION
  exitWaylineWhenRcLost: WaylineLostControlActionInCommandFlight.EXEC_LOST_ACTION,
  rthMode: 0 as number,
  commanderModeLostAction: 1 as number,
  commanderFlightMode: 0 as number,
  commanderFlightHeight: 100 as number
})
function onShowTakeoffToPointPopover () {
@@ -462,7 +497,11 @@
        rth_altitude: takeoffToPointPopoverData.rthAltitude,
        max_speed: takeoffToPointPopoverData.maxSpeed,
        rc_lost_action: takeoffToPointPopoverData.rcLostAction,
        exit_wayline_when_rc_lost: takeoffToPointPopoverData.exitWaylineWhenRcLost
        exit_wayline_when_rc_lost: takeoffToPointPopoverData.exitWaylineWhenRcLost,
        rth_mode: takeoffToPointPopoverData.rthMode,
        commander_mode_lost_action: takeoffToPointPopoverData.commanderModeLostAction,
        commander_flight_mode: takeoffToPointPopoverData.commanderFlightMode,
        commander_flight_height: takeoffToPointPopoverData.commanderFlightHeight
      })
    } catch (error) {
    }
src/components/waylinetool/component/interval-shoot.vue
New file
@@ -0,0 +1,234 @@
<!--
 * @Author: GuLiMmo 2820890765@qq.com
 * @Date: 2024-03-27 15:15:50
 * @LastEditors: GuLiMmo 2820890765@qq.com
 * @LastEditTime: 2024-03-28 09:36:06
 * @FilePath: /drone-web/src/components/waylinetool/component/interval-shoot.vue
 * @Description: 航点事件-单拍
 * Copyright (c) 2024 by GuLiMmo, All Rights Reserved.
-->
<template>
  <div class="container">
    <div :class="['fileSuffix', isInputShow && 'no-select']">
      <span>DJI_YYYYMMDDhhmm_XXX_</span>
      <span class="icon" @click="isInputShow = !isInputShow"><EditOutlined /></span>
    </div>
    <div class="fileSuffix-input" v-if="isInputShow">
      <a-input v-model:value="fileSuffix" placeholder="请输入文件后缀名称" size="small"></a-input>
      <a-button type="primary" shape="circle" size="small" @click="confirmInput">
        <template #icon>
          <CheckOutlined />
        </template>
      </a-button>
      <a-button type="danger" shape="circle" size="small" @click="cencalInput">
        <template #icon>
          <CloseOutlined />
        </template>
      </a-button>
    </div>
    <ul class="btn-group">
      <li
        :class="[
          'btn',
          isGlobalPhotoFormat && 'disabled-btn',
          !defaultParams.payloadLensIndex?.['#text'].includes('wide') && 'no-btn-selected',
        ]"
        @click="!isGlobalPhotoFormat && addFormatEvent('wide')">
        广角照片
      </li>
      <li
        :class="[
          'btn',
          isGlobalPhotoFormat && 'disabled-btn',
          !defaultParams.payloadLensIndex?.['#text'].includes('zoom') && 'no-btn-selected',
        ]"
        @click="!isGlobalPhotoFormat && addFormatEvent('zoom')">
        变焦照片
      </li>
      <li :class="['btn', !isGlobalPhotoFormat && 'no-btn-selected']" @click="addFormatEvent('global')">跟随全局</li>
    </ul>
  </div>
</template>
<script lang="ts" setup>
import _ from 'lodash'
import { defineProps, ref } from 'vue'
import { template as xmlJson } from '/@/utils/cesium/use-kmz-tsa'
import { EditOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
interface serialProp {
  placemark: number
  action: number
}
interface text {
  '#text': any
}
interface takePhoto {
  fileSuffix?: text
  payloadLensIndex: text
  payloadPositionIndex: text
  useGlobalPayloadLensIndex: text
}
const isInputShow = ref<boolean>(false)
const fileSuffix = ref<string>('')
const defaultParams = ref<takePhoto | any>({
  fileSuffix: { '#text': null },
  payloadLensIndex: { '#text': null },
  payloadPositionIndex: { '#text': null },
  useGlobalPayloadLensIndex: { '#text': null },
})
const confirmInput = () => {
  defaultParams.value.fileSuffix['#text'] = fileSuffix.value
  message.success('修改拍摄照片文件后缀成功!!')
}
const cencalInput = () => {
  fileSuffix.value = defaultFileSuffix.value
  defaultParams.value.fileSuffix['#text'] = defaultFileSuffix.value
  message.success('恢复初始拍摄照片文件后缀成功!!')
}
const props = defineProps<{
  serial: serialProp
}>()
const defaultFileSuffix = ref<string>('')
const getDefaultParams = (serial: serialProp) => {
  const placemarkJson = xmlJson.value.Folder.Placemark[serial.placemark]
  let action = placemarkJson.actionGroup.action
  if (Array.isArray(action)) {
    action = action[serial.action]
  }
  const actionActuatorFuncParam = action.actionActuatorFuncParam
  defaultParams.value = actionActuatorFuncParam
  fileSuffix.value = actionActuatorFuncParam.fileSuffix?.['#text'] || ''
  defaultFileSuffix.value = _.cloneDeep(fileSuffix.value)
  isInputShow.value = !!defaultParams.value.fileSuffix
}
// 判断当前是否使用全局照片设置
const isGlobalPhotoFormat = computed(() => Number(defaultParams.value.useGlobalPayloadLensIndex['#text']))
// 照片格式
const addFormatEvent = (value: string) => {
  if (value === 'global') {
    defaultParams.value.useGlobalPayloadLensIndex['#text'] = Number(!isGlobalPhotoFormat.value)
    if (!isGlobalPhotoFormat.value) {
      defaultParams.value.payloadLensIndex = { '#text': 'zoom,wide' }
    } else {
      delete defaultParams.value.payloadLensIndex
    }
  } else {
    if (!defaultParams.value.payloadLensIndex) {
      defaultParams.value.payloadLensIndex = { '#text': '' }
    }
    const payloadLensIndex = defaultParams.value.payloadLensIndex['#text']
    const payloadLensIndexArr = payloadLensIndex.split(',')
    if (!payloadLensIndex) {
      defaultParams.value.payloadLensIndex['#text'] = value
    } else {
      const index = payloadLensIndexArr.findIndex((item: string) => item === value)
      if (index === -1) {
        payloadLensIndexArr.push(value)
      } else {
        payloadLensIndexArr.splice(index, 1)
      }
      defaultParams.value.payloadLensIndex['#text'] = payloadLensIndexArr.join(',')
    }
  }
}
// 最新值
watch(
  () => defaultParams.value,
  (newParams) => {
    console.log(xmlJson.value)
  },
  {
    deep: true,
  },
)
// 默认值
watch(
  () => props.serial,
  (newVal: serialProp) => {
    getDefaultParams(newVal)
  },
  {
    deep: true,
    immediate: true,
  },
)
</script>
<style lang="scss" scoped>
.container {
  width: 100%;
  height: 100%;
  .fileSuffix {
    display: flex;
    align-items: center;
    justify-content: space-between;
    .icon {
      cursor: pointer;
      &:hover {
        color: #409eff;
      }
    }
  }
  .fileSuffix-input {
    margin-top: 10px;
    display: flex;
    input {
      background-color: transparent;
      color: #fff;
    }
    .ant-btn {
      margin-left: 10px;
    }
  }
  .btn-group {
    list-style-type: none;
    margin: 15px 0 0 0;
    padding: 0;
    display: flex;
    gap: 10px;
    justify-content: flex-start;
    .btn {
      font-size: 13px;
      padding: 2px 10px;
      background-color: #409eff;
      border-radius: 999px;
      cursor: pointer;
      font-weight: bold;
      &:last-child {
        margin-left: auto;
      }
    }
  }
}
.no-select {
  color: hsla(0, 0%, 100%, 0.45);
}
.no-btn-selected {
  background-color: hsla(0, 0%, 100%, 0.45) !important;
  border: hsla(0, 0%, 100%, 0.45) !important;
}
.disabled-btn {
  cursor: not-allowed !important;
  background-color: #314768 !important;
  border: #314768 !important;
  color: #ccc;
}
</style>
src/components/waylinetool/component/take-photo.vue
@@ -2,7 +2,7 @@
 * @Author: GuLiMmo 2820890765@qq.com
 * @Date: 2024-03-27 15:15:50
 * @LastEditors: GuLiMmo 2820890765@qq.com
 * @LastEditTime: 2024-03-27 17:31:10
 * @LastEditTime: 2024-03-28 09:30:55
 * @FilePath: /drone-web/src/components/waylinetool/component/take-photo.vue
 * @Description: 航点事件-单拍
 * Copyright (c) 2024 by GuLiMmo, All Rights Reserved.
@@ -55,6 +55,7 @@
</template>
<script lang="ts" setup>
import _ from 'lodash'
import { defineProps, ref } from 'vue'
import { template as xmlJson } from '/@/utils/cesium/use-kmz-tsa'
import { EditOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons-vue'
@@ -94,6 +95,7 @@
const cencalInput = () => {
  fileSuffix.value = defaultFileSuffix.value
  defaultParams.value.fileSuffix['#text'] = defaultFileSuffix.value
  message.success('恢复初始拍摄照片文件后缀成功!!')
}
@@ -110,8 +112,8 @@
  }
  const actionActuatorFuncParam = action.actionActuatorFuncParam
  defaultParams.value = actionActuatorFuncParam
  fileSuffix.value = actionActuatorFuncParam.fileSuffix['#text']
  defaultFileSuffix.value = actionActuatorFuncParam.fileSuffix['#text']
  fileSuffix.value = actionActuatorFuncParam.fileSuffix?.['#text'] || ''
  defaultFileSuffix.value = _.cloneDeep(fileSuffix.value)
  isInputShow.value = !!defaultParams.value.fileSuffix
}
@@ -151,7 +153,7 @@
watch(
  () => defaultParams.value,
  (newParams) => {
    console.log(newParams)
    console.log(xmlJson.value)
  },
  {
    deep: true,
src/components/waylinetool/event-edit.vue
@@ -11,8 +11,13 @@
          <span @click="handleDelAction"><DeleteOutlined /></span>
        </div>
      </div>
      {{ currentPointEvent.aciton }}
      <div class="event-edit">
        <takePhoto v-model:serial="serial" v-if="currentPointEvent.aciton.key === 'takePhoto'" />
        <take-photo
          v-model:serial="serial"
          v-if="['takePhoto', 'startRecord'].includes(currentPointEvent.aciton.key)"
        />
        <interval-shoot v-model:serial="serial" />
      </div>
    </div>
    <div class="map-box"></div>
@@ -25,6 +30,7 @@
import { useMyStore } from '/@/store'
import { template as xmlTemplate } from '/@/utils/cesium/use-kmz-tsa'
import takePhoto from './component/take-photo.vue'
import intervalShoot from './component/interval-shoot.vue'
const store = useMyStore()
// 事件编辑是否显示
src/components/waylinetool/route-profile.vue
@@ -26,7 +26,7 @@
const details = ref<any>([])
const route = useRoute()
const isShow = computed(() => !kmlStr.value && isWaylineRoute && author.fileName && author.author && details.value.length > 0)
const isShow = computed(() => !kmlStr.value && isWaylineRoute.value && author.fileName && author.author && details.value.length > 0)
watch(
  () => fileAuthor,
src/pages/page-web/projects/wayline.vue
@@ -264,7 +264,6 @@
    pagination.page++
    getWaylines()
  }, 1000)
  console.log(workspaceId.value)
})
onUnmounted(() => {
src/types/drone-control.ts
@@ -52,6 +52,20 @@
  { label: '着陆', value: LostControlActionInCommandFLight.Land }
]
export const RthModeOptions = [
  { label: '智能高度', value: 0 },
  { label: '设定高度', value: 1 }
]
export const CommanderModeLostActionOptions = [
  { label: '继续执行指点飞行任务', value: 0 },
  { label: '退出指点飞行任务,执行普通失控行为', value: 1 },
]
export const CommanderFlightModeOptions = [
  { label: '智能高度飞行', value: 0 },
  { label: '设定高度飞行', value: 1 }
]
// 云台重置模式
export enum GimbalResetMode {
  Recenter = 0,