|
|
@@ -1,208 +1,349 @@
|
|
|
<template>
|
|
|
- <div v-drag-window class="content infoModal-content">
|
|
|
- <div class="content-title">
|
|
|
- <div class="drag-title">
|
|
|
- <span>{{ osdInfo.callsign }}</span>
|
|
|
- </div>
|
|
|
- <a class="fz16" style="color: white;" @click="() => osdInfo.visible = false">
|
|
|
+ <div v-drag-window class="osd-panel fz12">
|
|
|
+ <div class="drag-title fz16 pl5 pr5 flex-align-center flex-row flex-justify-between"
|
|
|
+ style="border-bottom: 1px solid #515151; height: 10%;">
|
|
|
+ <span>{{ osdInfo.gateway_callsign }}</span>
|
|
|
+ </div>
|
|
|
+ <span>
|
|
|
+ <a style="color: white; position: absolute; top: 5px; right: 5px;" @click="() => osdInfo.visible = false">
|
|
|
<CloseOutlined />
|
|
|
</a>
|
|
|
- </div>
|
|
|
- <div class="content-osd">
|
|
|
- <div class="content-osd-head">
|
|
|
- <div class="content-osd-head-icon">
|
|
|
- <div class="content-osd-head-icon-image">
|
|
|
- <a-image :src="M30Src" :preview="false" />
|
|
|
+ </span>
|
|
|
+ <!-- 机场 -->
|
|
|
+ <div class="flex-display" style="border-bottom: 1px solid #515151;">
|
|
|
+ <div class="flex-column flex-align-stretch flex-justify-center" style="width: 60px; background: #2d2d2d;">
|
|
|
+ <a-tooltip :title="osdInfo.model">
|
|
|
+ <div class="flex-column flex-align-center flex-justify-center" style="width: 90%;">
|
|
|
+ <span>
|
|
|
+ <RobotFilled style="font-size: 48px;" />
|
|
|
+ </span>
|
|
|
+ <span class="mt10">Dock</span>
|
|
|
</div>
|
|
|
- <a-tooltip :title="osdInfo.model">
|
|
|
- <div class="content-osd-head-icon-text">
|
|
|
- {{ osdInfo.model }}
|
|
|
- </div>
|
|
|
- </a-tooltip>
|
|
|
- </div>
|
|
|
- <div class="content-osd-head-right">
|
|
|
- <div class="content-osd-head-right-top">
|
|
|
- <div class="content-osd-head-right-top-style">
|
|
|
- 航线飞行
|
|
|
- </div>
|
|
|
- <div class="content-osd-head-right-top-status">
|
|
|
- {{ getTextByModeCode(deviceInfo.device.mode_code) }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="content-osd-head-right-bottom">
|
|
|
- <div class="content-osd-head-right-bottom-button">
|
|
|
- <span class="openLiveButton" @click="state.deviceLiveStatus = true" v-if="!state.deviceLiveStatus">
|
|
|
- 开启直播
|
|
|
+ </a-tooltip>
|
|
|
+ </div>
|
|
|
+ <div class="osd flex-1" style="flex: 1">
|
|
|
+ <a-row>
|
|
|
+ <a-col span="16"
|
|
|
+ :style="deviceInfo.dock.basic_osd?.mode_code === EDockModeCode.Disconnected ? 'color: red; font-weight: 700;' : 'color: rgb(25,190,107)'">
|
|
|
+ {{ EDockModeCode[deviceInfo.dock.basic_osd?.mode_code] }}</a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-row>
|
|
|
+ <a-col span="12">
|
|
|
+ <a-tooltip title="Accumulated Running Time">
|
|
|
+ <span>
|
|
|
+ <HistoryOutlined />
|
|
|
</span>
|
|
|
- <span class="openLiveButton" @click="state.deviceLiveStatus = false" v-else>
|
|
|
- 关闭直播
|
|
|
+ <span class="ml10">
|
|
|
+ <span v-if="deviceInfo.dock.work_osd?.acc_time >= 2592000"> {{
|
|
|
+ Math.floor(deviceInfo.dock.work_osd?.acc_time / 2592000) }}m </span>
|
|
|
+ <span v-if="(deviceInfo.dock.work_osd?.acc_time % 2592000) >= 86400"> {{
|
|
|
+ Math.floor((deviceInfo.dock.work_osd?.acc_time % 2592000) / 86400) }}d </span>
|
|
|
+ <span v-if="(deviceInfo.dock.work_osd?.acc_time % 2592000 % 86400) >= 3600"> {{
|
|
|
+ Math.floor((deviceInfo.dock.work_osd?.acc_time % 2592000 % 86400) / 3600) }}h </span>
|
|
|
+ <span v-if="(deviceInfo.dock.work_osd?.acc_time % 2592000 % 86400 % 3600) >= 60"> {{
|
|
|
+ Math.floor((deviceInfo.dock.work_osd?.acc_time % 2592000 % 86400 % 3600) / 60) }}min </span>
|
|
|
+ <span>{{ Math.floor(deviceInfo.dock.work_osd?.acc_time % 2592000 % 86400 % 3600 % 60) }} s</span>
|
|
|
</span>
|
|
|
- </div>
|
|
|
- <div class="content-osd-head-right-bottom-text">
|
|
|
- 如需切换直播请停止后重新发起
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="content-osd-head-right-select">
|
|
|
- <div v-if="state.deviceLiveStatus">
|
|
|
- <a-select style="width: 130px;margin-right: 5px;" placeholder="摄像头" v-model:value="state.cameraValue">
|
|
|
- <a-select-option v-for="item in state.cameraList" :key="item.value" :value="item.value"
|
|
|
- @click="onCameraSelect(item)">
|
|
|
- {{ item.label }}
|
|
|
- </a-select-option>
|
|
|
- </a-select>
|
|
|
- <a-select style="width: 130px;margin-right: 5px;" placeholder="清晰度" v-model:value="state.clarityValue"
|
|
|
- @select="onClaritySelect">
|
|
|
- <a-select-option v-for="item in clarityList" :key="item.value" :value="item.value">
|
|
|
- {{ item.label }}
|
|
|
- </a-select-option>
|
|
|
- </a-select>
|
|
|
- <a-button style="margin-right: 5px;" :icon="h(PlaySquareOutlined)" @click="onStart" />
|
|
|
- <a-button :icon="h(PoweroffOutlined)" @click="onStop" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="12">
|
|
|
+ <a-tooltip title="Activation time">
|
|
|
+ <span>
|
|
|
+ <FieldTimeOutlined />
|
|
|
+ </span>
|
|
|
+ <span class="ml10">{{ new Date((deviceInfo.dock.work_osd?.activation_time ?? 0) * 1000).toLocaleString()
|
|
|
+ }}
|
|
|
+ </span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-row>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Network State">
|
|
|
+ <span :style="qualityStyle">
|
|
|
+ <span v-if="deviceInfo.dock.basic_osd?.network_state?.type === NetworkStateTypeEnum.FOUR_G">
|
|
|
+ <SignalFilled />
|
|
|
+ </span>
|
|
|
+ <span v-else>
|
|
|
+ <GlobalOutlined />
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ <span class="ml10">{{ deviceInfo.dock.basic_osd?.network_state?.rate }} kb/s</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="The total number of times the dock has performed missions.">
|
|
|
+ <span>
|
|
|
+ <CarryOutOutlined />
|
|
|
+ </span>
|
|
|
+ <span class="ml10">{{ deviceInfo.dock.work_osd?.job_number }} </span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Media File Remain Upload">
|
|
|
+ <span>
|
|
|
+ <CloudUploadOutlined class="fz14" />
|
|
|
+ </span>
|
|
|
+ <span class="ml10">{{ deviceInfo.dock.link_osd?.media_file_detail?.remain_upload }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip>
|
|
|
+ <template #title>
|
|
|
+ <p>total: {{ deviceInfo.dock.basic_osd?.storage?.total }}</p>
|
|
|
+ <p>used: {{ deviceInfo.dock.basic_osd?.storage?.used }}</p>
|
|
|
+ </template>
|
|
|
+ <span>
|
|
|
+ <FolderOpenOutlined />
|
|
|
+ </span>
|
|
|
+ <span class="ml10" v-if="deviceInfo.dock.basic_osd?.storage?.total > 0">
|
|
|
+ <a-progress type="circle" :width="20"
|
|
|
+ :percent="deviceInfo.dock.basic_osd?.storage?.used * 100 / deviceInfo.dock.basic_osd?.storage?.total"
|
|
|
+ :strokeWidth="20" :showInfo="false"
|
|
|
+ :strokeColor="deviceInfo.dock.basic_osd?.storage?.used * 100 / deviceInfo.dock.basic_osd?.storage?.total > 80 ? 'red' : '#00ee8b'" />
|
|
|
+ </span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-row>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Wind Speed">
|
|
|
+ <span>W.S</span>
|
|
|
+ <span class="ml10">{{ (deviceInfo.dock.basic_osd?.wind_speed ?? str) + ' m/s' }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Rainfall">
|
|
|
+ <span>🌧</span>
|
|
|
+ <span class="ml10">{{ RainfallEnum[deviceInfo.dock.basic_osd?.rainfall] }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Environment Temperature">
|
|
|
+ <span>°C</span>
|
|
|
+ <span class="ml10">{{ deviceInfo.dock.basic_osd?.environment_temperature }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Dock Temperature">
|
|
|
+ <span>°C</span>
|
|
|
+ <span class="ml10">{{ deviceInfo.dock.basic_osd?.temperature }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-row>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Dock Humidity">
|
|
|
+ <span>💦</span>
|
|
|
+ <span class="ml10">{{ deviceInfo.dock.basic_osd?.humidity }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Working Voltage">
|
|
|
+ <span
|
|
|
+ style="border: 1px solid; border-radius: 50%; width: 18px; height: 18px; line-height: 16px; text-align: center; float: left;">V</span>
|
|
|
+ <span class="ml10">{{ (deviceInfo.dock.work_osd?.working_voltage ?? str) + ' mV' }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Working Current">
|
|
|
+ <span
|
|
|
+ style="border: 1px solid; border-radius: 50%; width: 18px; height: 18px; line-height: 15px; text-align: center; float: left;">A</span>
|
|
|
+ <span class="ml10">{{ (deviceInfo.dock.work_osd?.working_current ?? str) + ' mA' }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Drone in dock">
|
|
|
+ <span>
|
|
|
+ <RocketOutlined />
|
|
|
+ </span>
|
|
|
+ <span class="ml10">{{ deviceInfo.dock.basic_osd?.drone_in_dock }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-row class="p5">
|
|
|
+ <a-col span="24">
|
|
|
+ <a-button type="primary" :disabled="dockControlPanelVisible" size="small"
|
|
|
+ @click="setDockControlPanelVisible(true)">
|
|
|
+ 操作
|
|
|
+ </a-button>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
</div>
|
|
|
- <div class="battery-slide">
|
|
|
- <div style="background: #535759;" class="width-100"></div>
|
|
|
- <div class="capacity-percent" :style="{ width: deviceInfo.device.battery.capacity_percent + '%' }"></div>
|
|
|
+ </div>
|
|
|
+ <!-- 飞机-->
|
|
|
+ <div class="flex-display">
|
|
|
+ <div class="flex-column flex-align-stretch flex-justify-center" style="width: 60px; background: #2d2d2d;">
|
|
|
+ <a-tooltip :title="osdInfo.model">
|
|
|
+ <div style="width: 90%;" class="flex-column flex-align-center flex-justify-center">
|
|
|
+ <span><a-image :src="M30Src" :preview="false" /></span>
|
|
|
+ <span>M30</span>
|
|
|
+ </div>
|
|
|
+ </a-tooltip>
|
|
|
</div>
|
|
|
- <LivePlayer :text="state.playerText" :url="state.playerUrl" v-if="state.deviceLiveStatus" />
|
|
|
- <div class="content-osd-info">
|
|
|
- <a-row style="margin-bottom: 5px;">
|
|
|
+ <div class="osd flex-1">
|
|
|
+ <a-row>
|
|
|
+ <a-col span="16"
|
|
|
+ :style="!deviceInfo.device || deviceInfo.device?.mode_code === EModeCode.Disconnected ? 'color: red; font-weight: 700;' : 'color: rgb(25,190,107)'">
|
|
|
+ {{ !deviceInfo.device ? EModeCode[EModeCode.Disconnected] : EModeCode[deviceInfo.device?.mode_code] }}
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-row>
|
|
|
<a-col span="6">
|
|
|
- <div style="margin-top: -3px;" class="content-osd-info-item">
|
|
|
- <a-tooltip title="遥控器信号">
|
|
|
- <div style="display: flex;align-items: flex-end;">
|
|
|
- <img style="margin-right: 5px;" :src="controllerSrc" v-if="controllerSignal > 0">
|
|
|
- <img style="margin-right: 5px;" :src="controllerErrorSrc" v-else>
|
|
|
- <div>
|
|
|
- <img :src="signalThreeSrc" v-if="controllerSignal <= 3">
|
|
|
- <img :src="signalFourSrc" v-else-if="controllerSignal === 4">
|
|
|
- <img :src="signalFiveSrc" v-else-if="controllerSignal === 5">
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </a-tooltip>
|
|
|
- <a-tooltip title="飞行器信号">
|
|
|
- <div style="display: flex;align-items: flex-end;">
|
|
|
- <img style="width: 15px;margin-right: 5px;" :src="networkSrc" v-if="aircraftSignal > 0">
|
|
|
- <img style="width: 15px;margin-right: 5px;" :src="networkErrorSrc" v-else>
|
|
|
- <div>
|
|
|
- <img :src="signalThreeSrc" v-if="aircraftSignal <= 3">
|
|
|
- <img :src="signalFourSrc" v-else-if="aircraftSignal === 4">
|
|
|
- <img :src="signalFiveSrc" v-else-if="aircraftSignal === 5">
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </a-tooltip>
|
|
|
- </div>
|
|
|
+ <a-tooltip title="Upward Quality">
|
|
|
+ <span>
|
|
|
+ <SignalFilled />
|
|
|
+ <ArrowUpOutlined style="font-size: 9px; vertical-align: top;" />
|
|
|
+ </span>
|
|
|
+ <span class="ml10">{{ deviceInfo.dock.link_osd?.sdr?.up_quality }}</span>
|
|
|
+ </a-tooltip>
|
|
|
</a-col>
|
|
|
<a-col span="6">
|
|
|
- <div class="content-osd-info-item">
|
|
|
- <a-tooltip title="RTK">
|
|
|
- <div style="display: flex;align-items: center;margin-right: 5px;">
|
|
|
- <img style="width: 24px;margin-right: 5px;" :src="rtkSrc" v-if="RTK > 0">
|
|
|
- <img style="width: 24px; margin-right: 5px;" :src="rtkErrorSrc" v-else>
|
|
|
- <div>
|
|
|
- {{ RTK }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </a-tooltip>
|
|
|
- <a-tooltip title="GPS">
|
|
|
- <div style="display: flex;align-items: center;">
|
|
|
- <img style="margin-right: 5px;" :src="gpsSrc" v-if="GPS > 0">
|
|
|
- <img style="margin-right: 5px;" :src="gpsErrorSrc" v-else>
|
|
|
- <div>
|
|
|
- {{ GPS }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </a-tooltip>
|
|
|
- </div>
|
|
|
+ <a-tooltip title="Downward Quality">
|
|
|
+ <span>
|
|
|
+ <SignalFilled />
|
|
|
+ <ArrowDownOutlined style="font-size: 9px; vertical-align: top;" />
|
|
|
+ </span>
|
|
|
+ <span class="ml10">{{ deviceInfo.dock.link_osd?.sdr?.down_quality }}</span>
|
|
|
+ </a-tooltip>
|
|
|
</a-col>
|
|
|
<a-col span="6">
|
|
|
- <a-tooltip title="电量">
|
|
|
- <div class="content-osd-info-item">
|
|
|
- <div style="margin-right: 5px;">
|
|
|
- <!-- <img :src="batteryOneSrc" v-if="capacity >= 75">
|
|
|
- <img :src="batteryTwoSrc" v-else-if="capacity >= 50 && capacity < 75">
|
|
|
- <img :src="batteryThreeSrc" v-else-if="capacity >= 25 && capacity < 50">
|
|
|
- <img :src="batteryFourSrc" v-else-if="capacity < 25"> -->
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- {{ capacity + '%' }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <a-tooltip title="Drone Battery Level">
|
|
|
+ <span>
|
|
|
+ <ThunderboltOutlined class="fz14" />
|
|
|
+ </span>
|
|
|
+ <span class="ml10">{{ deviceInfo.device && deviceInfo.device.battery.capacity_percent !== str ?
|
|
|
+ deviceInfo.device?.battery.capacity_percent + ' %' : str }}</span>
|
|
|
</a-tooltip>
|
|
|
</a-col>
|
|
|
<a-col span="6">
|
|
|
- <a-tooltip title="风向速度">
|
|
|
- <div class="content-osd-info-item">
|
|
|
- <img style="margin-right: 5px;" :src="windSrc">
|
|
|
- <div style="font-weight: bold;margin-right: 5px;">
|
|
|
- W.S
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- {{ windSpeed }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <a-tooltip>
|
|
|
+ <template #title>
|
|
|
+ <p>total: {{ deviceInfo.device?.storage?.total }}</p>
|
|
|
+ <p>used: {{ deviceInfo.device?.storage?.used }}</p>
|
|
|
+ </template>
|
|
|
+ <span>
|
|
|
+ <FolderOpenOutlined />
|
|
|
+ </span>
|
|
|
+ <span class="ml10" v-if="deviceInfo.device?.storage?.total > 0">
|
|
|
+ <a-progress type="circle" :width="20"
|
|
|
+ :percent="deviceInfo.device?.storage?.used * 100 / deviceInfo.device?.storage?.total"
|
|
|
+ :strokeWidth="20" :showInfo="false"
|
|
|
+ :strokeColor="deviceInfo.device?.storage?.used * 100 / deviceInfo.device?.storage?.total > 80 ? 'red' : '#00ee8b'" />
|
|
|
+ </span>
|
|
|
</a-tooltip>
|
|
|
</a-col>
|
|
|
</a-row>
|
|
|
<a-row>
|
|
|
+ <a-tooltip title="RTK Fixed">
|
|
|
+ <a-col span="6" class="flex-row flex-align-center flex-justify-start">
|
|
|
+ <span>Fixed</span>
|
|
|
+ <span class="ml10 circle"
|
|
|
+ :style="deviceInfo.device?.position_state.is_fixed === 1 ? 'backgroud: rgb(25,190,107);' : ' background: red;'"></span>
|
|
|
+ </a-col>
|
|
|
+ </a-tooltip>
|
|
|
<a-col span="6">
|
|
|
- <a-tooltip title="海拔高度">
|
|
|
- <div class="content-osd-info-item">
|
|
|
- <div style="font-weight: bold;margin-right: 5px;">
|
|
|
- ASL
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- {{ ASL }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <a-tooltip title="GPS">
|
|
|
+ <span>GPS</span>
|
|
|
+ <span class="ml10">{{ deviceInfo.device ? deviceInfo.device.position_state.gps_number : str }}</span>
|
|
|
</a-tooltip>
|
|
|
</a-col>
|
|
|
<a-col span="6">
|
|
|
- <a-tooltip title="离地高度">
|
|
|
- <div class="content-osd-info-item">
|
|
|
- <div style="font-weight: bold;margin-right: 5px;">
|
|
|
- AGL
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- {{ AGL }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <a-tooltip title="RTK">
|
|
|
+ <span>
|
|
|
+ <TrademarkOutlined class="fz14" />
|
|
|
+ </span>
|
|
|
+ <span class="ml10">{{ deviceInfo.device ? deviceInfo.device.position_state.rtk_number : str }}</span>
|
|
|
</a-tooltip>
|
|
|
</a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-row>
|
|
|
<a-col span="6">
|
|
|
- <a-tooltip title="水平速度">
|
|
|
- <div class="content-osd-info-item">
|
|
|
- <div style="font-weight: bold;margin-right: 5px;">
|
|
|
- H.S
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- {{ HS }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <a-tooltip title="Flight Mode">
|
|
|
+ <span>
|
|
|
+ <ControlOutlined class="fz16" />
|
|
|
+ </span>
|
|
|
+ <span class="ml10">{{ deviceInfo.device ? EGear[deviceInfo.device?.gear] : str }}</span>
|
|
|
</a-tooltip>
|
|
|
</a-col>
|
|
|
<a-col span="6">
|
|
|
- <a-tooltip title="当前高度">
|
|
|
- <div class="content-osd-info-item">
|
|
|
- <img style="margin-right: 5px;" :src="homeSrc">
|
|
|
- <div>
|
|
|
- {{ homeDistance }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <a-tooltip title="Altitude above sea level">
|
|
|
+ <span>ASL</span>
|
|
|
+ <span class="ml10">{{ !deviceInfo.device || deviceInfo.device.height === str ? str :
|
|
|
+ deviceInfo.device?.height.toFixed(2) + ' m' }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Altitude above takeoff level">
|
|
|
+ <span>ALT</span>
|
|
|
+ <span class="ml10">{{ !deviceInfo.device || deviceInfo.device.elevation === str ? str :
|
|
|
+ deviceInfo.device?.elevation.toFixed(2) + ' m' }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Distance to Home Point">
|
|
|
+ <span
|
|
|
+ style="border: 1px solid; border-radius: 50%; width: 18px; height: 18px; line-height: 15px; text-align: center; display: block; float: left;">H</span>
|
|
|
+ <span class="ml10">{{ !deviceInfo.device || deviceInfo.device.home_distance === str ? str :
|
|
|
+ deviceInfo.device?.home_distance.toFixed(2) + ' m' }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-row>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Horizontal Speed">
|
|
|
+ <span>H.S</span>
|
|
|
+ <span class="ml10">{{ !deviceInfo.device || deviceInfo.device?.horizontal_speed === str ? str :
|
|
|
+ deviceInfo.device?.horizontal_speed.toFixed(2) + ' m/s' }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Vertical Speed">
|
|
|
+ <span>V.S</span>
|
|
|
+ <span class="ml10">{{ !deviceInfo.device || deviceInfo.device.vertical_speed === str ? str :
|
|
|
+ deviceInfo.device?.vertical_speed.toFixed(2) + ' m/s' }}</span>
|
|
|
+ </a-tooltip>
|
|
|
+ </a-col>
|
|
|
+ <a-col span="6">
|
|
|
+ <a-tooltip title="Wind Speed">
|
|
|
+ <span>W.S</span>
|
|
|
+ <span class="ml10">{{ !deviceInfo.device || deviceInfo.device.wind_speed === str ? str :
|
|
|
+ (deviceInfo.device?.wind_speed / 10).toFixed(2) + ' m/s' }}</span>
|
|
|
</a-tooltip>
|
|
|
</a-col>
|
|
|
</a-row>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <div class="battery-slide" v-if="deviceInfo.device && deviceInfo.device.battery.remain_flight_time !== 0"
|
|
|
+ style="border: 1px solid red">
|
|
|
+ <div style="background: #535759;" class="width-100"></div>
|
|
|
+ <div class="capacity-percent" :style="{ width: deviceInfo.device.battery.capacity_percent + '%' }"></div>
|
|
|
+ <div class="return-home" :style="{ width: deviceInfo.device.battery.return_home_power + '%' }"></div>
|
|
|
+ <div class="landing" :style="{ width: deviceInfo.device.battery.landing_power + '%' }"></div>
|
|
|
+ <div class="white-point" :style="{ left: deviceInfo.device.battery.landing_power + '%' }"></div>
|
|
|
+ <div class="battery" :style="{ left: deviceInfo.device.battery.capacity_percent + '%' }">
|
|
|
+ {{ Math.floor(deviceInfo.device.battery.remain_flight_time / 60) }}:
|
|
|
+ {{ 10 > (deviceInfo.device.battery.remain_flight_time % 60) ? '0' : '' }}{{
|
|
|
+ deviceInfo.device.battery.remain_flight_time % 60 }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 机场控制面板 -->
|
|
|
+ <DockControlPanel v-if="dockControlPanelVisible" :sn="osdInfo.gateway_sn" :deviceInfo="deviceInfo"
|
|
|
+ @close-control-panel="onCloseControlPanel" />
|
|
|
+ <!-- 飞行指令 -->
|
|
|
+ <DroneControlPanel :sn="osdInfo.gateway_sn" :deviceInfo="deviceInfo" :payloads="osdInfo.payloads" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
import { h, computed, reactive, onMounted } from 'vue';
|
|
|
import { message } from 'ant-design-vue';
|
|
|
-import { CloseOutlined, PlaySquareOutlined, PoweroffOutlined } from '@ant-design/icons-vue'
|
|
|
+import {
|
|
|
+ BorderOutlined, LineOutlined, CloseOutlined, AimOutlined, ControlOutlined, TrademarkOutlined, ArrowDownOutlined,
|
|
|
+ ThunderboltOutlined, SignalFilled, GlobalOutlined, HistoryOutlined, CloudUploadOutlined, RocketOutlined,
|
|
|
+ FieldTimeOutlined, CloudOutlined, CloudFilled, FolderOpenOutlined, RobotFilled, ArrowUpOutlined, CarryOutOutlined
|
|
|
+} from '@ant-design/icons-vue'
|
|
|
+
|
|
|
import LivePlayer from '/@/components/livePlayer/index.vue';
|
|
|
import M30Src from '/@/assets/icons/m30.png';
|
|
|
import controllerSrc from '../icons/info/controller.svg';
|
|
|
@@ -224,7 +365,13 @@ import windSrc from '../icons/info/wind.svg';
|
|
|
import homeSrc from '../icons/info/home.svg';
|
|
|
import { CURRENT_CONFIG as config } from '/@/api/http/config';
|
|
|
import { getLiveCapacity, startLivestream, stopLivestream } from '/@/api/manage';
|
|
|
-import { getTextByModeCode } from '/@/utils/index'
|
|
|
+import DockControlPanel from '../../g-map/DockControlPanel.vue'
|
|
|
+import DroneControlPanel from '../../g-map/DroneControlPanel.vue'
|
|
|
+import {
|
|
|
+ DeviceOsd, DeviceStatus, DockOsd, EGear, EModeCode, GatewayOsd, EDockModeCode,
|
|
|
+ NetworkStateQualityEnum, NetworkStateTypeEnum, RainfallEnum, DroneInDockEnum
|
|
|
+} from '/@/types/device'
|
|
|
+import { useDockControl } from '../../g-map/use-dock-control';
|
|
|
|
|
|
interface Props {
|
|
|
osdInfo: any
|
|
|
@@ -235,6 +382,13 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
|
|
|
});
|
|
|
|
|
|
+// dock 控制面板
|
|
|
+const {
|
|
|
+ dockControlPanelVisible,
|
|
|
+ setDockControlPanelVisible,
|
|
|
+ onCloseControlPanel,
|
|
|
+} = useDockControl()
|
|
|
+
|
|
|
// 遥控器信号
|
|
|
const controllerSignal = computed(() => {
|
|
|
const info = props.deviceInfo.gateway;
|
|
|
@@ -255,70 +409,18 @@ const aircraftSignal = computed(() => {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
-const RTK = computed(() => {
|
|
|
- const info = props.deviceInfo.device;
|
|
|
- return info.position_state.rtk_number;
|
|
|
-});
|
|
|
-
|
|
|
-const GPS = computed(() => {
|
|
|
- const info = props.deviceInfo.device;
|
|
|
- return info.position_state.gps_number;
|
|
|
-});
|
|
|
-
|
|
|
-// 电池容量
|
|
|
-const capacity = computed(() => {
|
|
|
- const info = props.deviceInfo.device;
|
|
|
- if (info) {
|
|
|
- return info.battery.capacity_percent;
|
|
|
- } else {
|
|
|
- return 0;
|
|
|
- }
|
|
|
-});
|
|
|
-
|
|
|
-const windSpeed = computed(() => {
|
|
|
- const info = props.deviceInfo.device;
|
|
|
- if (info.wind_speed === '--') {
|
|
|
- return info.wind_speed;
|
|
|
- } else {
|
|
|
- return (info.wind_speed / 10).toFixed(2) + ' m/s';
|
|
|
- }
|
|
|
-});
|
|
|
-
|
|
|
-const ASL = computed(() => {
|
|
|
- const info = props.deviceInfo.device;
|
|
|
- if (info.height === '--') {
|
|
|
- return info.height;
|
|
|
- } else {
|
|
|
- return info.height.toFixed(2) + ' m';
|
|
|
- }
|
|
|
-});
|
|
|
-
|
|
|
-const AGL = computed(() => {
|
|
|
- const info = props.deviceInfo.device;
|
|
|
- if (info.elevation === '--') {
|
|
|
- return info.elevation;
|
|
|
- } else {
|
|
|
- return info.elevation.toFixed(2) + ' m';
|
|
|
- }
|
|
|
-});
|
|
|
+const str: string = '--'
|
|
|
|
|
|
-const HS = computed(() => {
|
|
|
- const info = props.deviceInfo.device;
|
|
|
- if (info.horizontal_speed === '--') {
|
|
|
- return info.horizontal_speed;
|
|
|
- } else {
|
|
|
- return info.horizontal_speed.toFixed(2) + ' m/s';
|
|
|
+const qualityStyle = computed(() => {
|
|
|
+ if (props.deviceInfo.dock.basic_osd?.network_state?.type === NetworkStateTypeEnum.ETHERNET ||
|
|
|
+ (props.deviceInfo.dock.basic_osd?.network_state?.quality || 0) > NetworkStateQualityEnum.FAIR) {
|
|
|
+ return 'color: #00ee8b'
|
|
|
}
|
|
|
-});
|
|
|
-
|
|
|
-const homeDistance = computed(() => {
|
|
|
- const info = props.deviceInfo.device;
|
|
|
- if (info.home_distance === '--') {
|
|
|
- return info.home_distance;
|
|
|
- } else {
|
|
|
- return info.home_distance.toFixed(2) + ' m';
|
|
|
+ if ((props.deviceInfo.dock.basic_osd?.network_state?.quality || 0) === NetworkStateQualityEnum.FAIR) {
|
|
|
+ return 'color: yellow'
|
|
|
}
|
|
|
-});
|
|
|
+ return 'color: red'
|
|
|
+})
|
|
|
|
|
|
interface SelectOption {
|
|
|
value: any,
|
|
|
@@ -374,27 +476,27 @@ const state: State = reactive({
|
|
|
})
|
|
|
|
|
|
const fetchLiveCapacity = async () => {
|
|
|
- try {
|
|
|
- const res = await getLiveCapacity({});
|
|
|
- if (res.code === 0) {
|
|
|
- const deviceInfo = res.data.filter((item: any) => item.sn === props.osdInfo.sn)[0];
|
|
|
- const cameras_list = deviceInfo.cameras_list || [];
|
|
|
- const cameraList = cameras_list.map((item: any) => {
|
|
|
- return {
|
|
|
- label: item.name,
|
|
|
- value: item.index,
|
|
|
- more: item.videos_list
|
|
|
- }
|
|
|
- })
|
|
|
- state.cameraList = cameraList;
|
|
|
- }
|
|
|
- } catch (e: any) {
|
|
|
- console.error(e);
|
|
|
- }
|
|
|
+ // try {
|
|
|
+ // const res = await getLiveCapacity({});
|
|
|
+ // if (res.code === 0) {
|
|
|
+ // const deviceInfo = res.data.filter((item: any) => item.sn === props.osdInfo.sn)[0];
|
|
|
+ // const cameras_list = deviceInfo.cameras_list || [];
|
|
|
+ // const cameraList = cameras_list.map((item: any) => {
|
|
|
+ // return {
|
|
|
+ // label: item.name,
|
|
|
+ // value: item.index,
|
|
|
+ // more: item.videos_list
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+ // state.cameraList = cameraList;
|
|
|
+ // }
|
|
|
+ // } catch (e: any) {
|
|
|
+ // console.error(e);
|
|
|
+ // }
|
|
|
}
|
|
|
|
|
|
onMounted(async () => {
|
|
|
- await fetchLiveCapacity()
|
|
|
+ // await fetchLiveCapacity()
|
|
|
})
|
|
|
|
|
|
const onCameraSelect = (record: SelectOption) => {
|
|
|
@@ -467,167 +569,64 @@ const onStop = async () => {
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.content {
|
|
|
- width: 420px;
|
|
|
- color: #fff;
|
|
|
- border-radius: 4px;
|
|
|
- overflow: hidden;
|
|
|
- // background-color: rgba(0, 0, 0, 0.8);
|
|
|
- background-color: #232323;
|
|
|
+.osd-panel {
|
|
|
position: absolute;
|
|
|
- left: 10px;
|
|
|
+ margin-left: 10px;
|
|
|
+ left: 0;
|
|
|
top: 10px;
|
|
|
-
|
|
|
- &-title {
|
|
|
- padding: 5px;
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- border: 1px solid #535759;
|
|
|
- }
|
|
|
-
|
|
|
- &-osd {
|
|
|
- font-size: 12px;
|
|
|
-
|
|
|
- &-head {
|
|
|
- display: flex;
|
|
|
-
|
|
|
- &-icon {
|
|
|
- width: 80px;
|
|
|
- padding: 5px;
|
|
|
- background: #3d3d3d;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- &-image {
|
|
|
- width: 80%;
|
|
|
- }
|
|
|
-
|
|
|
- &-text {
|
|
|
- text-align: center;
|
|
|
- white-space: nowrap;
|
|
|
- overflow: hidden;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &-right {
|
|
|
- width: 100%;
|
|
|
- padding: 5px;
|
|
|
-
|
|
|
- &-top {
|
|
|
- margin: 10px 0;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- &-style {
|
|
|
- width: 100px;
|
|
|
- color: #2a994b;
|
|
|
- border-right: 1px solid #535759;
|
|
|
- margin-right: 5px;
|
|
|
- }
|
|
|
-
|
|
|
- &-status {
|
|
|
- flex: 1;
|
|
|
- padding-left: 5px;
|
|
|
- background: #4a4d4e;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &-bottom {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- &-button {
|
|
|
- width: 100px;
|
|
|
- border-right: 1px solid #535759;
|
|
|
- margin-right: 5px;
|
|
|
-
|
|
|
- .openLiveButton {
|
|
|
- padding: 2px 4px;
|
|
|
- border: 1.5px solid #535759;
|
|
|
- border-radius: 2px;
|
|
|
- cursor: pointer;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &-text {
|
|
|
- color: #535759;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &-select {
|
|
|
- margin: 10px 0 5px;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &-info {
|
|
|
- padding: 5px;
|
|
|
-
|
|
|
- &-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- img {
|
|
|
- width: 13px;
|
|
|
- height: 13px;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ width: 480px;
|
|
|
+ background: #000;
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 2px;
|
|
|
+ background-color: rgba(0, 0, 0, 0.8);
|
|
|
}
|
|
|
-</style>
|
|
|
-
|
|
|
-<style lang="scss">
|
|
|
-.infoModal-content {
|
|
|
|
|
|
- // 修改按钮样式
|
|
|
- .ant-btn {
|
|
|
- color: #FFFFFF;
|
|
|
- background: transparent;
|
|
|
- border: 1px solid #535759;
|
|
|
+.osd>div:not(.dock-control-panel) {
|
|
|
+ margin-top: 5px;
|
|
|
+ padding: 5px;
|
|
|
+}
|
|
|
|
|
|
- &:hover {
|
|
|
- color: #fff;
|
|
|
- background-color: transparent;
|
|
|
- border-color: #535759;
|
|
|
- }
|
|
|
+.circle {
|
|
|
+ border-radius: 50%;
|
|
|
+ width: 10px;
|
|
|
+ height: 10px;
|
|
|
+}
|
|
|
|
|
|
- &:focus {
|
|
|
- color: #fff;
|
|
|
- background-color: transparent;
|
|
|
- border-color: #535759;
|
|
|
- }
|
|
|
+.battery-slide {
|
|
|
+ .capacity-percent {
|
|
|
+ background: #00ee8b;
|
|
|
}
|
|
|
|
|
|
- .ant-select-selector {
|
|
|
- color: #FFFFFF;
|
|
|
- background: transparent !important;
|
|
|
- border: 1px solid #535759 !important;
|
|
|
- box-shadow: none !important;
|
|
|
+ .return-home {
|
|
|
+ background: #ff9f0a;
|
|
|
}
|
|
|
|
|
|
- .ant-select-arrow {
|
|
|
- color: #fff;
|
|
|
+ .landing {
|
|
|
+ background: #f5222d;
|
|
|
}
|
|
|
|
|
|
- .ant-select-dropdown {
|
|
|
- background-color: transparent;
|
|
|
-
|
|
|
- .ant-select-item {
|
|
|
- background-color: #000000 !important;
|
|
|
- color: #fff;
|
|
|
-
|
|
|
- &:hover {
|
|
|
- background-color: #4a4a4a !important;
|
|
|
- }
|
|
|
- }
|
|
|
+ .white-point {
|
|
|
+ width: 4px;
|
|
|
+ height: 4px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: white;
|
|
|
+ bottom: -0.5px;
|
|
|
+ }
|
|
|
|
|
|
- .ant-select-item-option-selected {
|
|
|
- background-color: #3a3a3a;
|
|
|
- }
|
|
|
+ .battery {
|
|
|
+ background: #141414;
|
|
|
+ color: #00ee8b;
|
|
|
+ margin-top: -10px;
|
|
|
+ height: 20px;
|
|
|
+ width: auto;
|
|
|
+ border-left: 1px solid #00ee8b;
|
|
|
+ padding: 0 5px;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+.battery-slide>div {
|
|
|
+ position: absolute;
|
|
|
+ min-height: 2px;
|
|
|
+ border-radius: 2px;
|
|
|
+}
|
|
|
</style>
|