Browse Source

initial v1.3.0-beta2

1.3.0-beta2
sean.zhou 2 years ago
parent
commit
1f522544d6
  1. 1
      .gitignore
  2. 3
      package.json
  3. 24
      src/api/device-setting/index.ts
  4. 11
      src/api/wayline.ts
  5. 23
      src/components/GMap.vue
  6. 4
      src/components/devices/device-log/DeviceLogDetailModal.vue
  7. 242
      src/components/g-map/DeviceSettingBox.vue
  8. 106
      src/components/g-map/DeviceSettingPopover.vue
  9. 45
      src/components/g-map/DockControlPanel.vue
  10. 56
      src/components/g-map/useDeviceSetting.ts
  11. 5
      src/components/g-map/useDockControl.ts
  12. 5
      src/components/livestream-agora.vue
  13. 3
      src/components/livestream-others.vue
  14. 6
      src/hooks/use-g-map-tsa.ts
  15. 12
      src/pages/page-pilot/pilot-home.vue
  16. 75
      src/pages/page-web/projects/wayline.vue
  17. 13
      src/store/index.ts
  18. 148
      src/types/device-setting.ts
  19. 12
      src/types/device.ts
  20. 193
      src/utils/device-setting.ts

1
.gitignore vendored

@ -23,3 +23,4 @@ yarn-error.log* @@ -23,3 +23,4 @@ yarn-error.log*
/coverage
/backup
node_modules
./src/api/http/config.ts

3
package.json

@ -75,6 +75,7 @@ @@ -75,6 +75,7 @@
"ant-design-vue/es/empty/style/css",
"ant-design-vue/es/form/style/css",
"ant-design-vue/es/image/style/css",
"ant-design-vue/es/input-number/style/css",
"ant-design-vue/es/input/style/css",
"ant-design-vue/es/layout/style/css",
"ant-design-vue/es/menu/style/css",
@ -94,7 +95,9 @@ @@ -94,7 +95,9 @@
"ant-design-vue/es/tag/style/css",
"ant-design-vue/es/tooltip/style/css",
"ant-design-vue/es/tree/style/css",
"ant-design-vue/es/upload/style/css",
"axios",
"lodash",
"mitt",
"moment",
"reconnecting-websocket",

24
src/api/device-setting/index.ts

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
import request, { IWorkspaceResponse } from '/@/api/http/request'
import { ELocalStorageKey } from '/@/types'
import { NightLightsStateEnum, DistanceLimitStatus, ObstacleAvoidance } from '/@/types/device-setting'
const MNG_API_PREFIX = '/manage/api/v1'
const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || ''
export interface PutDevicePropsBody {
night_lights_state?: NightLightsStateEnum;// 夜航灯开关
height_limit?: number;// 限高设置
distance_limit_status?: DistanceLimitStatus;// 限远开关
obstacle_avoidance?: ObstacleAvoidance;// 飞行器避障开关设置
}
/**
*
* @param params
* @returns
*/
// /manage/api/v1/devices/{{workspace_id}}/devices/{{device_sn}}/property
export async function putDeviceProps (deviceSn: string, body: PutDevicePropsBody): Promise<IWorkspaceResponse<{}>> {
const resp = await request.put(`${MNG_API_PREFIX}/devices/${workspaceId}/devices/${deviceSn}/property`, body)
return resp.data
}

11
src/api/wayline.ts

@ -89,3 +89,14 @@ export async function deleteTask (workspaceId: string, params: DeleteTaskParams) @@ -89,3 +89,14 @@ export async function deleteTask (workspaceId: string, params: DeleteTaskParams)
})
return result.data
}
// Upload Wayline file
export const importKmzFile = async function (workspaceId: string, file: {}): Promise<IWorkspaceResponse<any>> {
const url = `${HTTP_PREFIX}/workspaces/${workspaceId}/waylines/file/upload`
const result = await request.post(url, file, {
headers: {
'Content-Type': 'multipart/form-data',
}
})
return result.data
}

23
src/components/GMap.vue

@ -182,12 +182,12 @@ @@ -182,12 +182,12 @@
<a-row>
<a-col span="12">
<a-tooltip title="Network State">
<span :style="deviceInfo.dock.network_state.quality === 2 ? 'color: #00ee8b' :
deviceInfo.dock.network_state.quality === 1 ? 'color: yellow' : 'color: red'">
<span v-if="deviceInfo.dock.network_state.type === 1"><SignalFilled /></span>
<span :style="deviceInfo.dock.network_state?.quality === 2 ? 'color: #00ee8b' :
deviceInfo.dock.network_state?.quality === 1 ? 'color: yellow' : 'color: red'">
<span v-if="deviceInfo.dock.network_state?.type === 1"><SignalFilled /></span>
<span v-else><GlobalOutlined /></span>
</span>
<span class="ml10" >{{ deviceInfo.dock.network_state.rate }} KB/S</span>
<span class="ml10" >{{ deviceInfo.dock.network_state?.rate }} KB/S</span>
</a-tooltip>
</a-col>
<a-col span="6">
@ -199,13 +199,13 @@ @@ -199,13 +199,13 @@
<a-col span="6">
<a-tooltip>
<template #title>
<p>total: {{ deviceInfo.dock.storage.total }}</p>
<p>used: {{ deviceInfo.dock.storage.used }}</p>
<p>total: {{ deviceInfo.dock.storage?.total }}</p>
<p>used: {{ deviceInfo.dock.storage?.used }}</p>
</template>
<span><FolderOpenOutlined /></span>
<span class="ml10" v-if="deviceInfo.dock.storage.total > 0">
<a-progress type="circle" :width="20" :percent="deviceInfo.dock.storage.used * 100/ deviceInfo.dock.storage.total"
:strokeWidth="20" :showInfo="false" :strokeColor="deviceInfo.dock.storage.used * 100 / deviceInfo.dock.storage.total > 80 ? 'red' : '#00ee8b' "/>
<span class="ml10" v-if="deviceInfo.dock.storage?.total > 0">
<a-progress type="circle" :width="20" :percent="deviceInfo.dock.storage?.used * 100/ deviceInfo.dock.storage?.total"
:strokeWidth="20" :showInfo="false" :strokeColor="deviceInfo.dock.storage?.used * 100 / deviceInfo.dock.storage?.total > 80 ? 'red' : '#00ee8b' "/>
</span>
</a-tooltip>
</a-col>
@ -264,8 +264,8 @@ @@ -264,8 +264,8 @@
</a-row>
<a-row class="p5">
<a-col span="24">
<a-button type="primary" :disabled="controlPanelVisible" size="small" @click="dockDebugOnOff(osdVisible.gateway_sn, true)">
远程调试
<a-button type="primary" :disabled="controlPanelVisible" size="small" @click="setControlPanelVisible(true)">
设备操作
</a-button>
</a-col>
</a-row>
@ -840,6 +840,7 @@ export default defineComponent({ @@ -840,6 +840,7 @@ export default defineComponent({
EDockModeCode,
controlPanelVisible,
dockDebugOnOff,
setControlPanelVisible,
}
}
})

4
src/components/devices/device-log/DeviceLogDetailModal.vue

@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
<div class="device-log-detail-wrap">
<div class="device-log-list">
<div class="log-list-item">
<a-button type="primary" class="download-btn" :disabled="!airportTableLogState.logList?.file_id" size="small" @click="onDownloadLog(airportTableLogState.logList.file_id)">
<a-button type="primary" class="download-btn" :disabled="!airportTableLogState.logList?.file_id || !airportTableLogState.logList?.object_key" size="small" @click="onDownloadLog(airportTableLogState.logList.file_id)">
下载机场日志
</a-button>
<a-table :columns="airportLogColumns"
@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
</a-table>
</div>
<div class="log-list-item">
<a-button type="primary" class="download-btn" :disabled="!droneTableLogState.logList?.file_id" size="small" @click="onDownloadLog(droneTableLogState.logList.file_id)">
<a-button type="primary" class="download-btn" :disabled="!droneTableLogState.logList?.file_id || !droneTableLogState.logList?.object_key" size="small" @click="onDownloadLog(droneTableLogState.logList.file_id)">
下载飞行器日志
</a-button>
<a-table :columns="droneLogColumns"

242
src/components/g-map/DeviceSettingBox.vue

@ -0,0 +1,242 @@ @@ -0,0 +1,242 @@
<template>
<div class="device-setting-wrapper">
<div class="device-setting-header">设备属性设置</div>
<div class="device-setting-box">
<!-- 飞行器夜航灯 -->
<div class="control-setting-item">
<div class="control-setting-item-left">
<div class="item-label">{{ deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].label }}</div>
<div class="item-status">{{ deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].value }}</div>
</div>
<div class="control-setting-item-right">
<DeviceSettingPopover
:visible="deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].popConfirm.visible"
:loading="deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].popConfirm.loading"
@confirm="onConfirm(deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].settingKey)"
@cancel="onCancel(deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].settingKey)"
>
<template #formContent>
<div class="form-content">
<span class="form-label">{{ deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].label }}:</span>
<a-switch checked-children="" un-checked-children="" v-model:checked="deviceSettingFormModel.nightLightsState" />
</div>
</template>
<a @click="onShowPopConfirm(deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].settingKey)">Edit</a>
</DeviceSettingPopover>
</div>
</div>
<!-- 限高 -->
<div class="control-setting-item">
<div class="control-setting-item-left">
<div class="item-label">{{ deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].label }}</div>
<div class="item-status">{{ deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].value }}</div>
</div>
<div class="control-setting-item-right">
<DeviceSettingPopover
:visible="deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].popConfirm.visible"
:loading="deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].popConfirm.loading"
@confirm="onConfirm(deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].settingKey)"
@cancel="onCancel(deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].settingKey)"
>
<template #formContent>
<div class="form-content">
<span class="form-label">{{ deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].label }}:</span>
<a-input-number v-model:value="deviceSettingFormModel.heightLimit" :min="20" :max="1500" />
m
</div>
</template>
<a @click="onShowPopConfirm(deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].settingKey)">Edit</a>
</DeviceSettingPopover>
</div>
</div>
<!-- 限远 -->
<div class="control-setting-item">
<div class="control-setting-item-left">
<div class="item-label">{{ deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].label }}</div>
<div class="item-status">{{ deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].value }}</div>
</div>
<div class="control-setting-item-right">
<DeviceSettingPopover
:visible="deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].popConfirm.visible"
:loading="deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].popConfirm.loading"
@confirm="onConfirm(deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].settingKey)"
@cancel="onCancel(deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].settingKey)"
>
<template #formContent>
<div class="form-content">
<span class="form-label">{{ deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].label }}:</span>
<a-switch style="margin-right: 10px;" checked-children="" un-checked-children="" v-model:checked="deviceSettingFormModel.distanceLimitStatus.state" />
<a-input-number v-model:value="deviceSettingFormModel.distanceLimitStatus.distanceLimit" :min="15" :max="8000" />
m
</div>
</template>
<a @click="onShowPopConfirm(deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].settingKey)">Edit</a>
</DeviceSettingPopover>
</div>
</div>
<!-- 水平避障 -->
<div class="control-setting-item">
<div class="control-setting-item-left">
<div class="item-label">{{ deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].label }}</div>
<div class="item-status">{{ deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].value }}</div>
</div>
<div class="control-setting-item-right">
<DeviceSettingPopover
:visible="deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].popConfirm.visible"
:loading="deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].popConfirm.loading"
@confirm="onConfirm(deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].settingKey)"
@cancel="onCancel(deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].settingKey)"
>
<template #formContent>
<div class="form-content">
<span class="form-label">{{ deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].label }}:</span>
<a-switch checked-children="" un-checked-children="" v-model:checked="deviceSettingFormModel.obstacleAvoidanceHorizon" />
</div>
</template>
<a @click="onShowPopConfirm(deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].settingKey)">Edit</a>
</DeviceSettingPopover>
</div>
</div>
<!-- 上视避障 -->
<div class="control-setting-item">
<div class="control-setting-item-left">
<div class="item-label">{{ deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].label }}</div>
<div class="item-status">{{ deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].value }}</div>
</div>
<div class="control-setting-item-right">
<DeviceSettingPopover
:visible="deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].popConfirm.visible"
:loading="deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].popConfirm.loading"
@confirm="onConfirm(deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].settingKey)"
@cancel="onCancel(deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].settingKey)"
>
<template #formContent>
<div class="form-content">
<span class="form-label">{{ deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].label }}:</span>
<a-switch checked-children="" un-checked-children="" v-model:checked="deviceSettingFormModel.obstacleAvoidanceUpside" />
</div>
</template>
<a @click="onShowPopConfirm(deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].settingKey)">Edit</a>
</DeviceSettingPopover>
</div>
</div>
<!-- 下视避障 -->
<div class="control-setting-item">
<div class="control-setting-item-left">
<div class="item-label">{{ deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].label }}</div>
<div class="item-status">{{ deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].value }}</div>
</div>
<div class="control-setting-item-right">
<DeviceSettingPopover
:visible="deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].popConfirm.visible"
:loading="deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].popConfirm.loading"
@confirm="onConfirm(deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].settingKey)"
@cancel="onCancel(deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].settingKey)"
>
<template #formContent>
<div class="form-content">
<span class="form-label">{{ deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].label }}:</span>
<a-switch checked-children="" un-checked-children="" v-model:checked="deviceSettingFormModel.obstacleAvoidanceDownside" />
</div>
</template>
<a @click="onShowPopConfirm(deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].settingKey)">Edit</a>
</DeviceSettingPopover>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { defineProps, ref, watch } from 'vue'
import { DeviceInfoType } from '/@/types/device'
import { useMyStore } from '/@/store'
import { cloneDeep } from 'lodash'
import { initDeviceSetting, initDeviceSettingFormModel, DeviceSettingKeyEnum } from '/@/types/device-setting'
import { updateDeviceSettingInfoByOsd, updateDeviceSettingFormModelByOsd } from '/@/utils/device-setting'
import { useDeviceSetting } from './useDeviceSetting'
import DeviceSettingPopover from './DeviceSettingPopover.vue'
const props = defineProps<{
sn: string,
deviceInfo: DeviceInfoType,
}>()
const store = useMyStore()
const deviceSetting = ref(cloneDeep(initDeviceSetting))
const deviceSettingFormModelFromOsd = ref(cloneDeep(initDeviceSettingFormModel))
const deviceSettingFormModel = ref(cloneDeep(initDeviceSettingFormModel)) // 使formModel
// osd
watch(() => props.deviceInfo, (value) => {
updateDeviceSettingInfoByOsd(deviceSetting.value, value)
updateDeviceSettingFormModelByOsd(deviceSettingFormModelFromOsd.value, value)
// console.log('deviceInfo', value)
}, {
immediate: true,
deep: true
})
function onShowPopConfirm (settingKey: DeviceSettingKeyEnum) {
deviceSetting.value[settingKey].popConfirm.visible = true
deviceSettingFormModel.value = cloneDeep(deviceSettingFormModelFromOsd.value)
}
function onCancel (settingKey: DeviceSettingKeyEnum) {
deviceSetting.value[settingKey].popConfirm.visible = false
}
async function onConfirm (settingKey: DeviceSettingKeyEnum) {
deviceSetting.value[settingKey].popConfirm.loading = true
const body = genDevicePropsBySettingKey(settingKey, deviceSettingFormModel.value)
await setDeviceProps(props.sn, body)
deviceSetting.value[settingKey].popConfirm.loading = false
deviceSetting.value[settingKey].popConfirm.visible = false
}
//
const {
genDevicePropsBySettingKey,
setDeviceProps,
} = useDeviceSetting()
</script>
<style lang='scss' scoped>
.device-setting-wrapper{
border-bottom: 1px solid #515151;
.device-setting-header{
font-size: 14px;
font-weight: 600;
padding: 10px 10px 0px;
}
.device-setting-box{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 4px 10px;
.control-setting-item{
width: 220px;
height: 58px;
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid #666;
margin: 4px 0;
padding: 0 8px;
.control-setting-item-left{
display: flex;
flex-direction: column;
.item-label{
font-weight: 700;
}
}
}
}
}
</style>

106
src/components/g-map/DeviceSettingPopover.vue

@ -0,0 +1,106 @@ @@ -0,0 +1,106 @@
<template>
<a-popover :visible="state.sVisible"
trigger="click"
v-bind="$attrs"
:overlay-class-name="overlayClassName"
placement="bottom"
@visibleChange=";"
v-on="$attrs">
<template #content>
<div class="title-content">
</div>
<slot name="formContent" />
<div class="uranus-popconfirm-btns">
<a-button size="sm"
@click="onCancel">
{{ cancelText || '取消'}}
</a-button>
<a-button size="sm"
:loading="loading"
type="primary"
class="confirm-btn"
@click="onConfirm">
{{ okText || '确定' }}
</a-button>
</div>
</template>
<template v-if="$slots.default">
<slot></slot>
</template>
</a-popover>
</template>
<script lang="ts" setup>
import { defineProps, defineEmits, reactive, watch, computed } from 'vue'
const props = defineProps<{
visible?: boolean,
loading?: Boolean,
disabled?: Boolean,
title?: String,
okText?: String,
cancelText?: String,
width?: Number,
}>()
const emit = defineEmits(['cancel', 'confirm'])
const state = reactive({
sVisible: false,
loading: false,
})
watch(() => props.visible, (val) => {
state.sVisible = val || false
})
const loading = computed(() => {
return props.loading
})
const okLabel = computed(() => {
return props.loading ? '' : '确定'
})
const overlayClassName = computed(() => {
const classList = ['device-setting-popconfirm']
return classList.join(' ')
})
function onConfirm (e: Event) {
if (props.disabled) {
return
}
emit('confirm', e)
}
function onCancel (e: Event) {
state.sVisible = false
emit('cancel', e)
}
</script>
<style lang="scss">
.device-setting-popconfirm {
min-width: 300px;
.uranus-popconfirm-btns{
display: flex;
padding: 10px 0px;
justify-content: flex-end;
.confirm-btn{
margin-left: 10px;
}
}
.form-content{
display: inline-flex;
align-items: center;
.form-label{
padding-right: 10px;
}
}
}
</style>

45
src/components/g-map/DockControlPanel.vue

@ -2,25 +2,33 @@ @@ -2,25 +2,33 @@
<div class="dock-control-panel">
<!-- title -->
<div class="dock-control-panel-header fz16 pl5 pr5 flex-align-center flex-row flex-justify-between">
<span>远程调试 {{ props.sn}}</span>
<span>设备操作 {{ props.sn}}</span>
<span @click="closeControlPanel">
<CloseOutlined />
</span>
</div>
<!-- setting -->
<DeviceSettingBox :sn="props.sn" :deviceInfo="props.deviceInfo"></DeviceSettingBox>
<!-- cmd -->
<div class="control-cmd-wrapper">
<div class="control-cmd-header">
远程调试
<a-switch class="debug-btn" checked-children="" un-checked-children="" v-model:checked="debugStatus" @change="onDeviceStatusChange"/>
</div>
<div class="control-cmd-box">
<div v-for="(cmdItem, index) in cmdList" :key="cmdItem.cmdKey" class="control-cmd-item">
<div class="control-cmd-item-left">
<div class="item-label">{{ cmdItem.label }}</div>
<div class="item-status">{{ cmdItem.status }}</div>
</div>
<div class="control-cmd-item-right">
<a-button :loading="cmdItem.loading" size="small" type="primary" @click="sendControlCmd(cmdItem, index)">
<a-button :disabled="!debugStatus" :loading="cmdItem.loading" size="small" type="primary" @click="sendControlCmd(cmdItem, index)">
{{ cmdItem.operateText }}
</a-button>
</div>
</div>
</div>
</div>
</div>
</template>
@ -35,6 +43,7 @@ import { DeviceInfoType } from '/@/types/device' @@ -35,6 +43,7 @@ import { DeviceInfoType } from '/@/types/device'
import { cmdList as baseCmdList, DeviceCmdItem } from '/@/types/device-cmd'
import { useMyStore } from '/@/store'
import { updateDeviceCmdInfoByOsd, updateDeviceCmdInfoByExecuteInfo } from '/@/utils/device-cmd'
import DeviceSettingBox from './DeviceSettingBox.vue'
const props = defineProps<{
sn: string,
@ -71,8 +80,27 @@ function closeControlPanel () { @@ -71,8 +80,27 @@ function closeControlPanel () {
}
// dock
const debugStatus = ref(false)
async function onDeviceStatusChange (status: boolean) {
let result = false
if (status) {
result = await dockDebugOnOff(props.sn, true)
} else {
result = await dockDebugOnOff(props.sn, false)
}
if (!result) {
if (status) {
debugStatus.value = false
} else {
debugStatus.value = true
}
}
}
const {
sendDockControlCmd,
dockDebugOnOff
} = useDockControl()
async function sendControlCmd (cmdItem: DeviceCmdItem, index: number) {
@ -103,6 +131,18 @@ async function sendControlCmd (cmdItem: DeviceCmdItem, index: number) { @@ -103,6 +131,18 @@ async function sendControlCmd (cmdItem: DeviceCmdItem, index: number) {
}
.control-cmd-wrapper{
.control-cmd-header{
font-size: 14px;
font-weight: 600;
padding: 10px 10px 0px;
.debug-btn{
margin-left: 10px;
border:1px solid #585858;
}
}
.control-cmd-box{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
@ -127,5 +167,6 @@ async function sendControlCmd (cmdItem: DeviceCmdItem, index: number) { @@ -127,5 +167,6 @@ async function sendControlCmd (cmdItem: DeviceCmdItem, index: number) {
}
}
}
}
}
</style>

56
src/components/g-map/useDeviceSetting.ts

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
import { message } from 'ant-design-vue'
import { putDeviceProps, PutDevicePropsBody } from '/@/api/device-setting'
import { DeviceSettingKeyEnum, DeviceSettingFormModel, ObstacleAvoidanceStatusEnum, NightLightsStateEnum, DistanceLimitStatusEnum } from '/@/types/device-setting'
export function useDeviceSetting () {
// 生成参数
function genDevicePropsBySettingKey (key: DeviceSettingKeyEnum, fromModel: DeviceSettingFormModel) {
const body = {} as PutDevicePropsBody
if (key === DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET) {
body.night_lights_state = fromModel.nightLightsState ? NightLightsStateEnum.OPEN : NightLightsStateEnum.CLOSE
} else if (key === DeviceSettingKeyEnum.HEIGHT_LIMIT_SET) {
body.height_limit = fromModel.heightLimit
} else if (key === DeviceSettingKeyEnum.DISTANCE_LIMIT_SET) {
body.distance_limit_status = {}
if (fromModel.distanceLimitStatus.state) {
body.distance_limit_status.state = DistanceLimitStatusEnum.SET
body.distance_limit_status.distance_limit = fromModel.distanceLimitStatus.distanceLimit
} else {
body.distance_limit_status.state = DistanceLimitStatusEnum.UNSET
}
} else if (key === DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON) {
body.obstacle_avoidance = {
horizon: fromModel.obstacleAvoidanceHorizon ? ObstacleAvoidanceStatusEnum.OPEN : ObstacleAvoidanceStatusEnum.CLOSE
}
} else if (key === DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE) {
body.obstacle_avoidance = {
upside: fromModel.obstacleAvoidanceUpside ? ObstacleAvoidanceStatusEnum.OPEN : ObstacleAvoidanceStatusEnum.CLOSE
}
} else if (key === DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE) {
body.obstacle_avoidance = {
downside: fromModel.obstacleAvoidanceDownside ? ObstacleAvoidanceStatusEnum.OPEN : ObstacleAvoidanceStatusEnum.CLOSE
}
}
return body
}
// 设置设备属性
async function setDeviceProps (sn: string, body: PutDevicePropsBody) {
try {
const { code, message: msg } = await putDeviceProps(sn, body)
if (code === 0) {
// message.success('指令发送成功')
return true
}
throw (msg)
} catch (e) {
message.error('设备属性设置失败')
return false
}
}
return {
genDevicePropsBySettingKey,
setDeviceProps
}
}

5
src/components/g-map/useDockControl.ts

@ -12,13 +12,14 @@ export function useDockControl () { @@ -12,13 +12,14 @@ export function useDockControl () {
// 远程调试开关
async function dockDebugOnOff (sn: string, on: boolean) {
const success = await sendDockControlCmd({
const result = await sendDockControlCmd({
sn: sn,
cmd: on ? DeviceCmd.DebugModeOpen : DeviceCmd.DebugModeClose
}, false)
if (success) {
if (result) {
setControlPanelVisible(on)
}
return result
}
// 发送指令

5
src/components/livestream-agora.vue

@ -298,6 +298,11 @@ const onStart = async () => { @@ -298,6 +298,11 @@ const onStart = async () => {
})
}
const onStop = async () => {
livePara.videoId =
dronePara.droneSelected +
'/' +
dronePara.cameraSelected + '/' + (dronePara.videoSelected || nonSwitchable + '-0')
stopLivestream({
video_id: livePara.videoId
}).then(res => {

3
src/components/livestream-others.vue

@ -318,6 +318,9 @@ const onStart = async () => { @@ -318,6 +318,9 @@ const onStart = async () => {
})
}
const onStop = () => {
videoId.value =
droneSelected.value + '/' + cameraSelected.value + '/' + (videoSelected.value || nonSwitchable + '-0')
stopLivestream({
video_id: videoId.value
}).then(res => {

6
src/hooks/use-g-map-tsa.ts

@ -41,7 +41,11 @@ export function deviceTsaUpdate () { @@ -41,7 +41,11 @@ export function deviceTsaUpdate () {
}
function initMarker (type: string, name: string, sn: string, lng?: number, lat?: number) {
if (markers[sn] || AMap === undefined) {
if (AMap === undefined) {
location.reload()
return
}
if (markers[sn]) {
return
}
markers[sn] = new AMap.Marker({

12
src/pages/page-pilot/pilot-home.vue

@ -252,6 +252,12 @@ onMounted(() => { @@ -252,6 +252,12 @@ onMounted(() => {
apiPilot.onBackClickReg()
apiPilot.onStopPlatform()
window.connectCallback = arg => {
connectCallback(arg)
}
window.wsConnectCallback = arg => {
wsConnectCallback(arg)
}
device.data.gateway_sn = apiPilot.getRemoteControllerSN()
if (device.data.gateway_sn === EStatusValue.DISCONNECT.toString()) {
message.warn('Data is not available, please restart the remote control.')
@ -296,12 +302,6 @@ onMounted(() => { @@ -296,12 +302,6 @@ onMounted(() => {
bindParam.user_id = res.data.user_id
bindParam.workspace_id = res.data.workspace_id
})
window.connectCallback = arg => {
connectCallback(arg)
}
window.wsConnectCallback = arg => {
wsConnectCallback(arg)
}
})
const connectCallback = async (arg: any) => {

75
src/pages/page-web/projects/wayline.vue

@ -3,12 +3,24 @@ @@ -3,12 +3,24 @@
<div style="height: 50px; line-height: 50px; border-bottom: 1px solid #4f4f4f; font-weight: 450;">
<a-row>
<a-col :span="1"></a-col>
<a-col :span="22">Flight Route Library</a-col>
<a-col :span="1"></a-col>
<a-col :span="15">Flight Route Library</a-col>
<a-col :span="8" class="flex-row flex-justify-end flex-align-center">
<a-upload
name="file"
:multiple="false"
:before-upload="beforeUpload"
:show-upload-list="false"
:customRequest="uploadFile"
>
<a-button type="text" style="color: white;" @click="() => importVisible = !importVisible">
<SelectOutlined />
</a-button>
</a-upload>
</a-col>
</a-row>
</div>
<div class="height-100">
<a-spin :spinning="loading" :delay="1000" tip="downloading" size="large">
<a-spin :spinning="loading" :delay="300" tip="downloading" size="large">
<div class="scrollbar uranus-scrollbar" v-if="waylinesData.data.length !== 0" @scroll="onScroll">
<div v-for="wayline in waylinesData.data" :key="wayline.id">
<div class="wayline-panel" style="padding-top: 5px;" @click="selectRoute(wayline)">
@ -72,14 +84,16 @@ @@ -72,14 +84,16 @@
import { reactive } from '@vue/reactivity'
import { message } from 'ant-design-vue'
import { onMounted, onUpdated, ref } from 'vue'
import { deleteWaylineFile, downloadWaylineFile, getWaylineFiles } from '/@/api/wayline'
import { deleteWaylineFile, downloadWaylineFile, getWaylineFiles, importKmzFile } from '/@/api/wayline'
import { ELocalStorageKey } from '/@/types'
import { EllipsisOutlined, RocketOutlined, CameraFilled, UserOutlined } from '@ant-design/icons-vue'
import { EllipsisOutlined, RocketOutlined, CameraFilled, UserOutlined, SelectOutlined } from '@ant-design/icons-vue'
import { EDeviceType } from '/@/types/device'
import { useMyStore } from '/@/store'
import { WaylineFile } from '/@/types/wayline'
import { downloadFile } from '/@/utils/common'
import { IPage } from '/@/api/http/type'
import { CURRENT_CONFIG } from '/@/api/http/config'
import { load } from '@amap/amap-jsapi-loader'
const loading = ref(false)
const store = useMyStore()
@ -97,15 +111,24 @@ const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId)! @@ -97,15 +111,24 @@ const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId)!
const deleteTip = ref(false)
const deleteWaylineId = ref<string>('')
const canRefresh = ref(true)
const importVisible = ref(false)
const urlUpload = `${CURRENT_CONFIG.baseURL}wayline/api/v1/workspaces/${workspaceId}/waylines/file/upload`
onMounted(() => {
getWaylines()
setTimeout(() => {
const element = document.getElementsByClassName('scrollbar').item(0) as HTMLDivElement
const parent = element?.parentNode as HTMLDivElement
console.info(element, parent)
// console.info(element.scrollHeight, parent.clientHeight)
}, 1000)
})
onUpdated(() => {
const element = document.getElementsByClassName('scrollbar').item(0) as HTMLDivElement
const parent = element?.parentNode as HTMLDivElement
setTimeout(() => {
console.info(element, parent)
if (element?.scrollHeight < parent?.clientHeight && pagination.total > waylinesData.data.length) {
if (canRefresh.value) {
pagination.page++
@ -130,6 +153,7 @@ function getWaylines () { @@ -130,6 +153,7 @@ function getWaylines () {
if (res.code !== 0) {
return
}
waylinesData.data = []
res.data.list.forEach((wayline: WaylineFile) => waylinesData.data.push(wayline))
pagination.total = res.data.pagination.total
pagination.page = res.data.pagination.page
@ -151,8 +175,7 @@ function deleteWayline () { @@ -151,8 +175,7 @@ function deleteWayline () {
deleteWaylineId.value = ''
deleteTip.value = false
pagination.total--
waylinesData.data = []
setTimeout(getWaylines, 500)
getWaylines()
})
}
@ -175,12 +198,50 @@ function selectRoute (wayline: WaylineFile) { @@ -175,12 +198,50 @@ function selectRoute (wayline: WaylineFile) {
function onScroll (e: any) {
const element = e.srcElement
console.info(element)
if (element.scrollTop + element.clientHeight === element.scrollHeight && Math.ceil(pagination.total / pagination.page_size) > pagination.page && canRefresh.value) {
pagination.page++
getWaylines()
}
}
interface FileItem {
uid: string;
name?: string;
status?: string;
response?: string;
url?: string;
}
interface FileInfo {
file: FileItem;
fileList: FileItem[];
}
const fileList = ref<FileItem[]>([])
function beforeUpload (file: FileItem) {
fileList.value = [file]
loading.value = true
return true
}
const uploadFile = async () => {
console.info(loading.value)
fileList.value.forEach(async (file: FileItem) => {
const fileData = new FormData()
fileData.append('file', file, file.name)
await importKmzFile(workspaceId, fileData).then((res) => {
if (res.code === 0) {
message.success(`${file.name} file uploaded successfully`)
canRefresh.value = true
getWaylines()
}
}).finally(() => {
loading.value = false
fileList.value = []
})
})
}
</script>
<style lang="scss" scoped>

13
src/store/index.ts

@ -108,16 +108,23 @@ const mutations: MutationTree<RootStateType> = { @@ -108,16 +108,23 @@ const mutations: MutationTree<RootStateType> = {
state.deviceState.currentType = EDeviceTypeName.Gateway
},
SET_DOCK_INFO (state, info) {
if (Object.keys(info.host).length === 0) {
return
}
if (!state.deviceState.dockInfo[info.sn]) {
state.deviceState.dockInfo[info.sn] = info.host
return
}
state.deviceState.currentSn = info.sn
state.deviceState.currentType = EDeviceTypeName.Dock
const dock = state.deviceState.dockInfo[info.sn]
if (info.host.sdr && state.deviceState.dockInfo[info.sn]) {
if (info.host.sdr) {
dock.sdr = info.host.sdr
dock.media_file_detail = info.host.media_file_detail
return
}
const sdr = dock?.sdr
const mediaFileDetail = dock?.media_file_detail
const sdr = dock.sdr
const mediaFileDetail = dock.media_file_detail
state.deviceState.dockInfo[info.sn] = info.host
state.deviceState.dockInfo[info.sn].sdr = sdr
state.deviceState.dockInfo[info.sn].media_file_detail = mediaFileDetail

148
src/types/device-setting.ts

@ -0,0 +1,148 @@ @@ -0,0 +1,148 @@
// 夜航灯开关
export enum NightLightsStateEnum {
CLOSE = 0, // 0-关闭
OPEN = 1, // 1-打开
}
// 限远开关
export enum DistanceLimitStatusEnum {
UNSET = 0, // 0-未设置
SET = 1, // 1-已设置
}
export interface DistanceLimitStatus {
state?: DistanceLimitStatusEnum;
distance_limit?: number; // 限远
}
// 避障
export enum ObstacleAvoidanceStatusEnum {
CLOSE = 0, // 0-关闭
OPEN = 1, // 1-开启
}
export interface ObstacleAvoidance {
horizon?: ObstacleAvoidanceStatusEnum;// 水平避障开关
upside?: ObstacleAvoidanceStatusEnum;// 上行方向避障开关
downside?: ObstacleAvoidanceStatusEnum;// 下行方向避障开关
}
// 设备管理设置key
export enum DeviceSettingKeyEnum {
NIGHT_LIGHTS_MODE_SET = 'night_lights_state', // 夜航灯开关
HEIGHT_LIMIT_SET = 'height_limit', // 限高设置
DISTANCE_LIMIT_SET = 'distance_limit_status', // 限远开关
OBSTACLE_AVOIDANCE_HORIZON = 'obstacle_avoidance_horizon', // 水平避障状态
OBSTACLE_AVOIDANCE_UPSIDE = 'obstacle_avoidance_upside', // 上视避障状态
OBSTACLE_AVOIDANCE_DOWNSIDE = 'obstacle_avoidance_downside', // 下视避障状态
}
export type DeviceSettingType = Record<DeviceSettingKeyEnum, any>
export const initDeviceSetting = {
[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET]:
{
label: '飞行器夜航灯',
value: '',
trueValue: NightLightsStateEnum.CLOSE,
editable: false,
popConfirm: {
visible: false,
loading: false,
// content: '为保证飞行器的作业安全,建议打开夜航灯',
label: '飞行器夜航灯',
},
settingKey: DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET,
},
[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET]:
{
label: '限高',
value: '',
trueValue: 120,
editable: false,
popConfirm: {
visible: false,
loading: false,
// content: '限高:20 - 1500m',
// info: '修改限高会影响当前机场的所有作业任务,建议确认作业情况后再进行修改',
label: '限高',
},
settingKey: DeviceSettingKeyEnum.HEIGHT_LIMIT_SET,
},
[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET]:
{
label: '限远',
value: '',
trueValue: DistanceLimitStatusEnum.UNSET,
// info: '限远(15 - 8000m)是约束飞行器相对机场的最大作业距离',
editable: false,
popConfirm: {
visible: false,
loading: false,
// content: '限远 (15- 8000m) 是约束飞行器相对机场的最大作业距离',
// info: '修改限远会影响当前机场的所有作业任务,建议确认作业情况后再进行修改',
label: '限远',
},
settingKey: DeviceSettingKeyEnum.DISTANCE_LIMIT_SET,
},
[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON]:
{
label: '水平避障',
value: '',
trueValue: ObstacleAvoidanceStatusEnum.CLOSE,
// info: '飞行器的避障工作状态显示,可以快速开启/关闭飞行器避障,如需进一步设置请在设备运维页面设置',
editable: false,
popConfirm: {
visible: false,
loading: false,
// content: '飞行器避障是保障飞行作业安全的基础功能,建议保持飞行器避障开启',
label: '水平避障',
},
settingKey: DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON,
},
[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE]:
{
label: '上视避障',
value: '',
trueValue: ObstacleAvoidanceStatusEnum.CLOSE,
// info: '飞行器的避障工作状态显示,可以快速开启/关闭飞行器避障,如需进一步设置请在设备运维页面设置',
editable: false,
popConfirm: {
visible: false,
loading: false,
// content: '飞行器避障是保障飞行作业安全的基础功能,建议保持飞行器避障开启',
label: '上视避障',
},
settingKey: DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE,
},
[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE]:
{
label: '下视避障',
value: '',
trueValue: ObstacleAvoidanceStatusEnum.CLOSE,
// info: '飞行器的避障工作状态显示,可以快速开启/关闭飞行器避障,如需进一步设置请在设备运维页面设置',
editable: false,
popConfirm: {
visible: false,
loading: false,
// content: '飞行器避障是保障飞行作业安全的基础功能,建议保持飞行器避障开启',
label: '下视避障',
},
settingKey: DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE,
},
} as DeviceSettingType
export const initDeviceSettingFormModel = {
nightLightsState: false, // 夜航灯开关
heightLimit: 20, // 限高设置
distanceLimitStatus: { state: false, distanceLimit: 15 }, // 限远开关
obstacleAvoidanceHorizon: false, // 飞行器避障-水平开关设置
obstacleAvoidanceUpside: false, // 飞行器避障-上视开关设置
obstacleAvoidanceDownside: false, // 飞行器避障-下视开关设置
}
export type DeviceSettingFormModel = typeof initDeviceSettingFormModel

12
src/types/device.ts

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import { commonColor } from '/@/utils/color'
import { NightLightsStateEnum, DistanceLimitStatus, ObstacleAvoidance } from './device-setting'
export interface DeviceValue {
key: string; // 'domain-type-subtype'
domain: string; // 表示一个领域,作为一个命名空间,暂时分 飞机类-0, 负载类-1,RC类-2,机场类-3 4种
@ -235,7 +235,11 @@ export interface DeviceOsd { @@ -235,7 +235,11 @@ export interface DeviceOsd {
landing_power: string,
remain_flight_time: number,
return_home_power: string,
}
},
night_lights_state?: NightLightsStateEnum;// 夜航灯开关
height_limit?: number;// 限高设置
distance_limit_status?: DistanceLimitStatus;// 限远开关
obstacle_avoidance?: ObstacleAvoidance;// 飞行器避障开关设置
}
export interface DockOsd {
@ -343,6 +347,10 @@ export enum EDeviceType { @@ -343,6 +347,10 @@ export enum EDeviceType {
H20N = '1-61-0' as any,
DJI_Dock_Camera = '1-165-0' as any,
L1 = '1-90742-0' as any,
M3E = '0-77-0' as any,
M3D = '0-77-1' as any,
M3E_Camera = '1-66-0' as any,
M3T_Camera = '1-67-0' as any,
}
export enum EDockModeCode {

193
src/utils/device-setting.ts

@ -0,0 +1,193 @@ @@ -0,0 +1,193 @@
import { DeviceInfoType } from '/@/types/device'
import { DeviceSettingType, DeviceSettingKeyEnum, DistanceLimitStatusEnum, ObstacleAvoidanceStatusEnum, DeviceSettingFormModel, NightLightsStateEnum } from '/@/types/device-setting'
import { DEFAULT_PLACEHOLDER } from './constants'
import { isNil } from 'lodash'
const Unit_M = ' m'
/**
* osd
* @param deviceSetting
* @param deviceInfo
* @returns
*/
export function updateDeviceSettingInfoByOsd (deviceSetting: DeviceSettingType, deviceInfo: DeviceInfoType) {
const { device, dock, gateway } = deviceInfo || {}
if (!deviceSetting) {
return
}
// 夜航灯
let nightLightsState = '' as any
if (isNil(device?.night_lights_state)) {
deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].editable = false
deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].value = DEFAULT_PLACEHOLDER
nightLightsState = DEFAULT_PLACEHOLDER
} else {
deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].editable = true
nightLightsState = device?.night_lights_state
if (nightLightsState === NightLightsStateEnum.CLOSE) {
deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].value = '关闭'
} else if (nightLightsState === NightLightsStateEnum.OPEN) {
deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].value = '开启'
} else {
deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].value = DEFAULT_PLACEHOLDER
}
}
deviceSetting[DeviceSettingKeyEnum.NIGHT_LIGHTS_MODE_SET].trueValue = nightLightsState
// 限高
let heightLimit = device?.height_limit as any
if (isNil(heightLimit) || heightLimit === 0) {
heightLimit = DEFAULT_PLACEHOLDER
deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].editable = false
} else {
deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].editable = true
}
deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].trueValue = heightLimit
deviceSetting[DeviceSettingKeyEnum.HEIGHT_LIMIT_SET].value = heightLimit + Unit_M
// 限远
let distanceLimitStatus = '' as any
if (isNil(device?.distance_limit_status?.state)) {
distanceLimitStatus = DEFAULT_PLACEHOLDER
deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].editable = false
deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].value = DEFAULT_PLACEHOLDER
} else {
deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].editable = true
distanceLimitStatus = device?.distance_limit_status?.state
if (distanceLimitStatus === DistanceLimitStatusEnum.UNSET) {
deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].value = '关闭'
} else if (distanceLimitStatus === DistanceLimitStatusEnum.SET) {
const distanceLimit = device?.distance_limit_status?.distance_limit
if (distanceLimit) {
deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].value = distanceLimit + Unit_M
} else {
deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].value = DEFAULT_PLACEHOLDER
}
} else {
deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].value = DEFAULT_PLACEHOLDER
}
}
deviceSetting[DeviceSettingKeyEnum.DISTANCE_LIMIT_SET].trueValue = distanceLimitStatus
// 避障
if (isNil(device?.obstacle_avoidance)) {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].editable = false
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].value = DEFAULT_PLACEHOLDER
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].trueValue = DEFAULT_PLACEHOLDER
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].editable = false
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].value = DEFAULT_PLACEHOLDER
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].trueValue = DEFAULT_PLACEHOLDER
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].editable = false
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].value = DEFAULT_PLACEHOLDER
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].trueValue = DEFAULT_PLACEHOLDER
} else {
const { horizon, upside, downside } = device.obstacle_avoidance || {}
if (isNil(horizon)) {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].editable = false
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].value = DEFAULT_PLACEHOLDER
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].trueValue = DEFAULT_PLACEHOLDER
} else {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].editable = false
if (horizon === ObstacleAvoidanceStatusEnum.CLOSE) {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].value = '关闭'
} else if (horizon === ObstacleAvoidanceStatusEnum.OPEN) {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].value = '开启'
} else {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].value = DEFAULT_PLACEHOLDER
}
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_HORIZON].trueValue = horizon
}
if (isNil(upside)) {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].editable = false
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].value = DEFAULT_PLACEHOLDER
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].trueValue = DEFAULT_PLACEHOLDER
} else {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].editable = false
if (upside === ObstacleAvoidanceStatusEnum.CLOSE) {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].value = '关闭'
} else if (upside === ObstacleAvoidanceStatusEnum.OPEN) {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].value = '开启'
} else {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].value = DEFAULT_PLACEHOLDER
}
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_UPSIDE].trueValue = upside
}
if (isNil(downside)) {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].editable = false
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].value = DEFAULT_PLACEHOLDER
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].trueValue = DEFAULT_PLACEHOLDER
} else {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].editable = false
if (downside === ObstacleAvoidanceStatusEnum.CLOSE) {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].value = '关闭'
} else if (downside === ObstacleAvoidanceStatusEnum.OPEN) {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].value = '开启'
} else {
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].value = DEFAULT_PLACEHOLDER
}
deviceSetting[DeviceSettingKeyEnum.OBSTACLE_AVOIDANCE_DOWNSIDE].trueValue = downside
}
}
return deviceSetting
}
// 更新formModel
export function updateDeviceSettingFormModelByOsd (deviceSettingFormModelFromOsd: DeviceSettingFormModel, deviceInfo: DeviceInfoType) {
const { device, dock, gateway } = deviceInfo || {}
if (!deviceSettingFormModelFromOsd) {
return
}
// 夜航灯
const nightLightsState = device?.night_lights_state as any
if (!isNil(nightLightsState) && nightLightsState === NightLightsStateEnum.OPEN) {
deviceSettingFormModelFromOsd.nightLightsState = true
} else {
deviceSettingFormModelFromOsd.nightLightsState = false
}
// 限高
const heightLimit = device?.height_limit as any
if (isNil(heightLimit) || heightLimit === 0) {
deviceSettingFormModelFromOsd.heightLimit = 20
} else {
deviceSettingFormModelFromOsd.heightLimit = heightLimit
}
// 限远
const distanceLimitStatus = device?.distance_limit_status?.state as any
if (!isNil(distanceLimitStatus) && distanceLimitStatus === DistanceLimitStatusEnum.SET) {
deviceSettingFormModelFromOsd.distanceLimitStatus.state = true
deviceSettingFormModelFromOsd.distanceLimitStatus.distanceLimit = device?.distance_limit_status?.distance_limit || 15
} else {
deviceSettingFormModelFromOsd.distanceLimitStatus.state = false
deviceSettingFormModelFromOsd.distanceLimitStatus.distanceLimit = 15
}
// 避障
if (isNil(device?.obstacle_avoidance)) {
deviceSettingFormModelFromOsd.obstacleAvoidanceHorizon = false
deviceSettingFormModelFromOsd.obstacleAvoidanceUpside = false
deviceSettingFormModelFromOsd.obstacleAvoidanceDownside = false
} else {
const { horizon, upside, downside } = device.obstacle_avoidance || {}
if (!isNil(horizon) && horizon === ObstacleAvoidanceStatusEnum.OPEN) {
deviceSettingFormModelFromOsd.obstacleAvoidanceHorizon = true
} else {
deviceSettingFormModelFromOsd.obstacleAvoidanceHorizon = false
}
if (!isNil(upside) && upside === ObstacleAvoidanceStatusEnum.OPEN) {
deviceSettingFormModelFromOsd.obstacleAvoidanceUpside = true
} else {
deviceSettingFormModelFromOsd.obstacleAvoidanceUpside = false
}
if (!isNil(downside) && downside === ObstacleAvoidanceStatusEnum.OPEN) {
deviceSettingFormModelFromOsd.obstacleAvoidanceDownside = true
} else {
deviceSettingFormModelFromOsd.obstacleAvoidanceDownside = false
}
}
return deviceSettingFormModelFromOsd
}
Loading…
Cancel
Save