husq
2023-09-27 2c2bc8614c8ea0ce386369eb4924da1e6aa052d1
src/components/GMap.vue
@@ -1,22 +1,635 @@
<template>
  <div class="g-map-wrapper">
    <div id="g-container" :style="{ width: '100%', height: '100%' }" />
    <div
      class="g-action-panle"
      :style="{ right: drawVisible ? '316px' : '16px' }"
    >
      <div class="g-action-item" @click="draw('pin', true)">
        <a-button type="primary">PIN</a-button>
    <!-- 地图区域 -->
    <!-- <div id="g-container" :style="{ width: '100%', height: '100%' }" /> -->
    <Cesium />
    <!-- 绘制面板 -->
    <!-- <div class="g-action-panel" :style="{ right: drawVisible ? '316px' : '16px' }">
      <div :class="state.currentType === 'pin' ? 'g-action-item selection' : 'g-action-item'" @click="draw('pin', true)">
        <a><a-image :src="pin" :preview="false" /></a>
      </div>
      <div class="g-action-item" @click="draw('polyline', true)">
        <a-button type="primary">Line</a-button>
      <div :class="state.currentType === 'polyline' ? 'g-action-item selection' : 'g-action-item'"
        @click="draw('polyline', true)">
        <a>
          <LineOutlined :rotate="135" class="fz20" />
        </a>
      </div>
      <div class="g-action-item" @click="draw('polygon', true)">
        <a-button type="primary">Poly</a-button>
      <div :class="state.currentType === 'polygon' ? 'g-action-item selection' : 'g-action-item'"
        @click="draw('polygon', true)">
        <a>
          <BorderOutlined class="fz18" />
        </a>
      </div>
      <div v-if="mouseMode" class="g-action-item" @click="draw('off', false)">
        <a-button type="primary" danger>X</a-button>
        <a style="color: red;">
          <CloseOutlined />
        </a>
      </div>
    </div> -->
    <!-- 飞机OSD -->
    <div v-if="osdVisible.visible && !osdVisible.is_dock" class="osd-panel fz12">
      <div class="pl5 pr5 flex-align-center flex-row flex-justify-between"
        style="border-bottom: 1px solid #515151; height: 18%;">
        <span>{{ osdVisible.callsign }}</span>
        <span><a class="fz16" style="color: white;" @click="() => osdVisible.visible = false">
            <CloseOutlined />
          </a></span>
      </div>
      <div style="height: 82%;">
        <div class="flex-column flex-align-center flex-justify-center"
          style="margin-top: -5px; padding-top: 25px; float: left; width: 60px; background: #2d2d2d;">
          <a-tooltip :title="osdVisible.model">
            <div style="width: 90%;" class="flex-column flex-align-center flex-justify-center">
              <span><a-image :src="M30" :preview="false" /></span>
              <span>{{ osdVisible.model }}</span>
            </div>
          </a-tooltip>
        </div>
        <div class="osd">
          <a-row>
            <a-col span="16"
              :style="deviceInfo.device.mode_code === EModeCode.Disconnected ? 'color: red; font-weight: 700;' : 'color: rgb(25,190,107)'">{{
                EModeText[deviceInfo.device.mode_code] }}</a-col>
          </a-row>
          <a-row>
            <a-col span="6">
              <a-tooltip title="Signal strength">
                <span>HD</span>
                <span class="ml5">{{ deviceInfo.gateway?.transmission_signal_quality }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="RC Battery Level">
                <span>
                  <ThunderboltOutlined class="fz14" />
                </span>
                <span class="ml5">{{ deviceInfo.gateway && deviceInfo.gateway.capacity_percent !== str ?
                  deviceInfo.gateway.capacity_percent + ' %' : deviceInfo.gateway.capacity_percent }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="无人机电池电量">
                <span>
                  <ThunderboltOutlined class="fz14" />
                </span>
                <span class="ml5">{{ deviceInfo.device.battery.capacity_percent !== str ?
                  deviceInfo.device.battery.capacity_percent + ' %' : deviceInfo.device.battery.capacity_percent }}</span>
              </a-tooltip>
            </a-col>
          </a-row>
          <a-row>
            <a-tooltip title="RTK固定">
              <a-col span="6" class="flex-row flex-align-center flex-justify-start">
                <span>Fixed</span>
                <span class="ml5 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="GPS">
                <span>GPS</span>
                <span class="ml5">{{ deviceInfo.device.position_state.gps_number }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="RTK">
                <span>
                  <TrademarkOutlined class="fz14" />
                </span>
                <span class="ml5">{{ deviceInfo.device.position_state.rtk_number }}</span>
              </a-tooltip>
            </a-col>
          </a-row>
          <a-row>
            <a-col span="6">
              <a-tooltip title="飞行模式">
                <span>
                  <ControlOutlined class="fz16" />
                </span>
                <span class="ml5">{{ EGear[deviceInfo.device.gear] }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="海拔高度">
                <span>ASL</span>
                <span class="ml5">{{ deviceInfo.device.height === str ? str : deviceInfo.device.height.toFixed(2) + ' m'}}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="高于起飞高度">
                <span>ALT</span>
                <span class="ml5">{{ deviceInfo.device.elevation === str ? str : deviceInfo.device.elevation.toFixed(2) +' m' }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="到起点距离">
                <span>H</span>
                <span class="ml5">{{ 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="水平速度">
                <span>H.S</span>
                <span class="ml5">{{ 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="垂直速度">
                <span>V.S</span>
                <span class="ml5">{{ 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="风速">
                <span>W.S</span>
                <span class="ml5">{{ 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.battery.remain_flight_time !== 0">
        <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>
    </div>
    <!-- 机场OSD -->
    <!--  && osdVisible.is_dock -->
    <div class="osd-panel fz12" v-if="osdVisible.visible">
      <div class="fz16 pl5 pr5 flex-align-center flex-row flex-justify-between"
        style="border-bottom: 1px solid #515151; height: 10%;">
        <span>{{ osdVisible.gateway_callsign }}</span>
        <span><a style="color: white;" @click="closeOsdWindow">
            <CloseOutlined />
          </a></span>
      </div>
      <!-- 机场 -->
      <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="osdVisible.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>
        </div>
        <div class="osd flex-1" style="flex: 1">
          <a-row justify="space-between" class="mr-20">
            <a-col span="9"
              :style="deviceInfo.dock.basic_osd?.mode_code === EDockModeCode.Disconnected ? 'color: red; font-weight: 700;' : 'color: rgb(25,190,107)'">
              {{ EDockModeText[deviceInfo.dock.basic_osd?.mode_code] }}</a-col>
            <!-- <a-col span="1">{{ hmsInfo[sn]?.length || 1 }}</a-col> -->
            <a-col span="1" class="num" v-if="hmsInfo[sn]">{{ hmsInfo[sn]?.length }}</a-col>
            <a-col span="14" v-if="hmsInfo[sn] && hmsInfo[sn].length>0" style="width: 100%;padding-left:5px ;">
              <a-tooltip :title="hmsInfo[sn][0].message_zh">
              <div class="overflow">{{ hmsInfo[sn][0].message_zh }}</div>
            </a-tooltip>
            </a-col>
          </a-row>
          <a-row>
            <!-- <a-col span="12">
                <a-tooltip title="累计运行时间">
                  <span><HistoryOutlined /></span>
                  <span class="ml5">
                    <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>
                </a-tooltip>
              </a-col> -->
            <a-col span="9">
              <a-tooltip title="降雨量">
                <span>🌧</span>
                <span class="ml5">{{ RainfallEnum[deviceInfo.dock.basic_osd?.rainfall] }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="15" style="width: 100%;">
              <div class="env-box span5">
                <div class="span-box mr-20">
                  <a-tooltip title="环境温度">
                    <span>°C</span>
                    <span class="ml5">{{ deviceInfo.dock.basic_osd?.environment_temperature }}</span>
                  </a-tooltip>
                </div>
                <div class="span-box mr-20">
                  <a-tooltip title="网络状态">
                    <span
                      :style="deviceInfo.dock.basic_osd?.network_state?.type === NetworkStateTypeEnum.ETHERNET || deviceInfo.dock.basic_osd?.network_state?.quality === NetworkStateQualityEnum.GOOD ?
                        'color: #00ee8b' : deviceInfo.dock.basic_osd?.network_state?.quality === NetworkStateQualityEnum.MEDIUM ? 'color: yellow' : 'color: red'">
                      <span v-if="deviceInfo.dock.basic_osd?.network_state?.type === NetworkStateTypeEnum.FOUR_G">
                        <SignalFilled />
                      </span>
                      <span v-else>
                        <GlobalOutlined />
                      </span>
                    </span>
                    <span class="ml5">{{ deviceInfo.dock.basic_osd?.network_state?.rate }} kb/s</span>
                  </a-tooltip>
                </div>
                <div class="span-box mr-20">
                  <a-tooltip title="媒体文件剩余上传">
                    <span>
                      <CloudUploadOutlined class="fz14" />
                    </span>
                    <span class="ml5">{{ deviceInfo.dock.link_osd?.media_file_detail?.remain_upload }}</span>
                  </a-tooltip>
                </div>
              </div>
            </a-col>
            <!-- <a-col span="12">
                <a-tooltip title="激活时间">
                  <span><FieldTimeOutlined /></span>
                  <span class="ml5">{{ 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="网络状态">
                  <span :style="deviceInfo.dock.basic_osd?.network_state?.type === NetworkStateTypeEnum.ETHERNET || deviceInfo.dock.basic_osd?.network_state?.quality === NetworkStateQualityEnum.GOOD ?
                    'color: #00ee8b' : deviceInfo.dock.basic_osd?.network_state?.quality === NetworkStateQualityEnum.MEDIUM ? 'color: yellow' : 'color: red'">
                    <span v-if="deviceInfo.dock.basic_osd?.network_state?.type === NetworkStateTypeEnum.FOUR_G"><SignalFilled /></span>
                    <span v-else><GlobalOutlined /></span>
                  </span>
                  <span class="ml5" >{{ deviceInfo.dock.basic_osd?.network_state?.rate }} kb/s</span>
                </a-tooltip>
              </a-col>
              <a-col span="6">
                <a-tooltip title="设备执行任务总次数">
                  <span><CarryOutOutlined /></span>
                  <span class="ml5" >{{ deviceInfo.dock.work_osd?.job_number }} </span>
                </a-tooltip>
              </a-col>
              <a-col span="6">
                <a-tooltip title="媒体文件剩余上传">
                  <span><CloudUploadOutlined class="fz14"/></span>
                  <span class="ml5">{{ deviceInfo.dock.link_osd?.media_file_detail?.remain_upload }}</span>
                </a-tooltip>
              </a-col>
              <a-col span="6">
                <a-tooltip>
                  <template #title>
                    <p>总共: {{ deviceInfo.dock.basic_osd?.storage?.total }}</p>
                    <p>已使用: {{ deviceInfo.dock.basic_osd?.storage?.used  }}</p>
                  </template>
                  <span><FolderOpenOutlined /></span>
                  <span class="ml5" 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="风速">
                  <span>W.S</span>
                  <span class="ml5">{{ (deviceInfo.dock.basic_osd?.wind_speed ?? str) + ' m/s'}}</span>
                </a-tooltip>
              </a-col>
              <a-col span="6">
                <a-tooltip title="降雨量">
                  <span>🌧</span>
                  <span class="ml5">{{ RainfallEnum[deviceInfo.dock.basic_osd?.rainfall] }}</span>
                </a-tooltip>
              </a-col>
              <a-col span="6">
                <a-tooltip title="环境温度">
                  <span>°C</span>
                  <span class="ml5">{{ deviceInfo.dock.basic_osd?.environment_temperature }}</span>
                </a-tooltip>
              </a-col>
              <a-col span="6">
                <a-tooltip title="设备温度">
                  <span>°C</span>
                  <span class="ml5">{{ deviceInfo.dock.basic_osd?.temperature }}</span>
                </a-tooltip>
              </a-col>
            </a-row>
            <a-row>
              <a-col span="6">
                <a-tooltip title="设备湿度">
                  <span>💦</span>
                  <span class="ml5">{{ deviceInfo.dock.basic_osd?.humidity }}</span>
                </a-tooltip>
              </a-col>
              <a-col span="6">
                <a-tooltip title="工作电压">
                  <span style="border: 1px solid; border-radius: 50%; width: 18px; height: 18px; line-height: 16px; text-align: center; float: left;">V</span>
                  <span class="ml5">{{ (deviceInfo.dock.work_osd?.working_voltage ?? str) + ' mV' }}</span>
                </a-tooltip>
              </a-col>
              <a-col span="6">
                <a-tooltip title="工作电流">
                  <span style="border: 1px solid; border-radius: 50%; width: 18px; height: 18px; line-height: 15px; text-align: center; float: left;" >A</span>
                  <span class="ml5">{{ (deviceInfo.dock.work_osd?.working_current ?? str) + ' mA' }}</span>
                </a-tooltip>
              </a-col>
              <a-col span="6">
                <a-tooltip title="设备上的无人机">
                  <span><RocketOutlined /></span>
                  <span class="ml5">{{ DroneInDockEnum[deviceInfo.dock.basic_osd?.drone_in_dock] }}</span>
                </a-tooltip>
              </a-col>
            </a-row> -->
          <a-row class="p5" justify="space-between">
            <a-col span="11">
              <a-button :class="[showMonitor?'active-color':'unactive-color']" class="width-100" type="primary" size="small" @click="openMonitor">
                监控
              </a-button>
            </a-col>
            <a-col span="11">
              <a-button :class="[showOption?'active-color':'unactive-color']" class="width-100" type="primary" :disabled="dockControlPanelVisible" size="small"
                @click="openFlySetting">
                操作
              </a-button>
            </a-col>
          </a-row>
          <!-- 机场控制面板 -->
          <DockControlPanel v-if="dockControlPanelVisible" :sn="osdVisible.gateway_sn" :deviceInfo="deviceInfo"
            @close-control-panel="closeOperate">
          </DockControlPanel>
        </div>
      </div>
      <a-row class="p5" v-if="showMonitor" justify="center" align="middle">
        <!-- <a-spin :spinning="spinning"> -->
          <Jessibuca v-if="airPortUrl" @timeout="airTimeout" :videoUrl="airPortUrl" width="100%" height="300px" />
        <!-- </a-spin> -->
      </a-row>
      <!--  飞机-->
      <div class="flex-display">
        <div class="flex-column flex-align-stretch flex-justify-center" style="width: 60px;  background: #2d2d2d;">
          <a-tooltip :title="osdVisible.model">
            <div style="width: 90%;" class="flex-column flex-align-center flex-justify-center">
              <span><a-image :src="M30" :preview="false" /></span>
              <span>M30</span>
            </div>
          </a-tooltip>
        </div>
        <div class="osd flex-1">
          <a-row class="mr-20" align="middle">
            <a-col span="9"
              :style="!deviceInfo.device || deviceInfo.device?.mode_code === EModeCode.Disconnected ? 'color: red; font-weight: 700;' : 'color: rgb(25,190,107)'">
              {{ !deviceInfo.device ? EModeText[EModeCode.Disconnected] : EModeText[deviceInfo.device?.mode_code]
              }}</a-col>
            <a-col span="15">
              <a-select :showArrow="false" v-model:value="aircraSelected" :bordered="false" :options="aircraftList" :placeholder="aircraftList.length==0?'N/A':'请选择'" :disabled="aircraftList.length==0?true:false" size="small" style="width:100%;background-color: #5d5f61;color: #fff;" @change="selectChange"></a-select>
            </a-col>
          </a-row>
          <a-row align="middle" justify="center">
            <a-col span="24"> <div v-if="deviceInfo.device?.mode_code == 14 || !deviceInfo.device" style="color:#494949;" class="flex-display flex-justify-center mt5 mb5">当前设备已关机,无法进行直播</div> </a-col>
          </a-row>
          <a-row class="p5" align="middle" justify="space-between">
            <a-col span="11">
              <a-button :disabled="deviceInfo.device?.mode_code == 14 || !deviceInfo.device?true:false" :class="[showAircraft?'active-color':'unactive-color']" class="width-100" type="primary"  size="small" @click="openAircra">
                飞行控制
              </a-button>
            </a-col>
            <a-col span="11">
              <a-button :class="[openDroneControl?'active-color':'unactive-color']" class="width-100" type="primary"  size="small"
                @click="openDeviceSetting">
                操作
              </a-button>
            </a-col>
          </a-row>
        </div>
      </div>
      <!-- 飞机直播 -->
      <a-row class="p5" v-if="showAircraft">
        <!-- <a-spin :spinning="spinning"> -->
          <Jessibuca v-if="aircraftUrl" @timeout="flyTimeout" :videoUrl="aircraftUrl" width="100%" height="300px" />
        <!-- </a-spin> -->
      </a-row>
      <!-- 飞机图标信息 -->
      <div class="osd-info flex-1">
          <!-- <a-row align="middle">
            <a-col span="6">
              <a-tooltip title="向上质量">
                <span>
                  <SignalFilled />
                  <ArrowUpOutlined style="font-size: 9px; vertical-align: top;" />
                </span>
                <span class="ml5">{{ deviceInfo.dock.link_osd?.sdr?.up_quality }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="向下质量">
                <span>
                  <SignalFilled />
                  <ArrowDownOutlined style="font-size: 9px; vertical-align: top;" />
                </span>
                <span class="ml5">{{ deviceInfo.dock.link_osd?.sdr?.down_quality }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="无人机电池电量">
                <span>
                  <ThunderboltOutlined class="fz14" />
                </span>
                <span class="ml5">{{ 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>
                <template #title>
                  <p>总供: {{ deviceInfo.device?.storage?.total }}</p>
                  <p>已使用: {{ deviceInfo.device?.storage?.used }}</p>
                </template>
                <span>
                  <FolderOpenOutlined />
                </span>
                <span class="ml5" 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固定">
              <a-col span="6" class="flex-row flex-align-center flex-justify-start">
                <span>Fixed</span>
                <span class="ml5 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="GPS">
                <span>GPS</span>
                <span class="ml5">{{ deviceInfo.device ? deviceInfo.device.position_state.gps_number : str }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="RTK">
                <span>
                  <TrademarkOutlined class="fz14" />
                </span>
                <span class="ml5">{{ 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="飞行模式">
                <span>
                  <ControlOutlined class="fz16" />
                </span>
                <span class="ml5">{{ deviceInfo.device ? EGear[deviceInfo.device?.gear] : str }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="海拔高度">
                <span>ASL</span>
                <span class="ml5">{{ !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="高于起飞高度">
                <span>ALT</span>
                <span class="ml5">{{ !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="到起点距离">
                <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="ml5">{{ !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="水平速度">
                <span>H.S</span>
                <span class="ml5">{{ !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="垂直速度">
                <span>V.S</span>
                <span class="ml5">{{ !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="风速">
                <span>W.S</span>
                <span class="ml5">{{ !deviceInfo.device || deviceInfo.device.wind_speed === str ? str :
                  (deviceInfo.device?.wind_speed / 10).toFixed(2) + ' m/s' }}</span>
              </a-tooltip>
            </a-col>
          </a-row> -->
          <a-row align="middle">
              <a-col span="6" class="flex-row flex-align-center flex-justify-start">
                <a-tooltip title="飞行模式">
                <span>
                  <ControlOutlined class="fz16" />
                </span>
                <span class="ml5">{{ deviceInfo.device ? EGear[deviceInfo.device?.gear] : str }}</span>
              </a-tooltip>
              </a-col>
            <a-col span="6">
              <a-tooltip title="RTK">
                <span>
                  <TrademarkOutlined class="fz14" />
                </span>
                <span class="ml5">{{ deviceInfo.device ? deviceInfo.device.position_state.rtk_number : str }}</span>
              </a-tooltip>
            </a-col>
            <a-col span="6">
              <a-tooltip title="无人机电池电量">
                <span>
                  <ThunderboltOutlined class="fz14" />
                </span>
                <span class="ml5">{{ deviceInfo.device && deviceInfo.device.battery.capacity_percent !== str ?
                  deviceInfo.device?.battery.capacity_percent + ' %' : str }}</span>
              </a-tooltip>
            </a-col>
          </a-row>
          <a-row align="middle" class="mt10">
            <a-col span="6">
              <a-tooltip title="海拔高度">
                <span>ASL</span>
                <span class="ml5">{{ !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="高于起飞高度">
                <span>ALT</span>
                <span class="ml5">{{ !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="水平速度">
                <span>H.S</span>
                <span class="ml5">{{ !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="垂直速度">
                <span>V.S</span>
                <span class="ml5">{{ !deviceInfo.device || deviceInfo.device.vertical_speed === str ? str :
                  deviceInfo.device?.vertical_speed.toFixed(2) + ' m/s' }}</span>
              </a-tooltip>
            </a-col>
          </a-row>
      </div>
      <!-- 飞行控制 -->
      <!-- <div class="fly-control flex-display">
        <div class="flex-column flex-align-stretch flex-justify-center" style="width: 100px;  background: #2d2d2d;">
            <div style="cursor: pointer;" class="p10 flex-column flex-align-center flex-justify-center">
              <span><a-image :src="M30" :preview="false" /></span>
              <span>一键起飞</span>
            </div>
        </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>
      <!-- 飞行指令 -->
      <DroneControlPanel v-model="openDroneControl" :sn="osdVisible.gateway_sn" :deviceInfo="deviceInfo" :payloads="osdVisible.payloads">
      </DroneControlPanel>
    </div>
  </div>
</template>
@@ -28,31 +641,141 @@
  generatePointContent,
  generatePolyContent
} from '../utils/map-layer-utils'
import { message } from 'ant-design-vue'
import { postElementsReq } from '/@/api/layer'
import { MapDoodleType, MapElementEnum } from '/@/constants/map'
import { useGMapManage } from '/@/hooks/use-g-map'
import { useGMapCover } from '/@/hooks/use-g-map-cover'
import { useMouseTool } from '/@/hooks/use-mouse-tool'
import { getApp } from '/@/root'
import { getApp, getRoot } from '/@/root'
import { useMyStore } from '/@/store'
import { GeojsonCoordinate } from '/@/types/map'
import { MapDoodleEnum } from '/@/types/map-enum'
import { PostElementsBody } from '/@/types/mapLayer'
import { uuidv4 } from '/@/utils/uuid'
import { gcj02towgs84, wgs84togcj02 } from '/@/vendors/coordtransform'
import { deviceTsaUpdate } from '/@/hooks/use-g-map-tsa'
import Jessibuca from '/@/components/Jessibuca/Jessibuca.vue'
import { CURRENT_CONFIG as config } from '/@/api/http/config'
import { getLiveCapacity, startLivestream, stopLivestream } from '/@/api/manage'
import {
  DeviceOsd, DeviceStatus, DockOsd, EGear, EModeCode, GatewayOsd, EDockModeCode, EDockModeText, EModeText,
  NetworkStateQualityEnum, NetworkStateTypeEnum, RainfallEnum, DroneInDockEnum
} from '/@/types/device'
import pin from '/@/assets/icons/pin-2d8cf0.svg'
import M30 from '/@/assets/icons/m30.png'
import {
  BorderOutlined, LineOutlined, CloseOutlined, ControlOutlined, TrademarkOutlined, ArrowDownOutlined,
  ThunderboltOutlined, SignalFilled, GlobalOutlined, HistoryOutlined, CloudUploadOutlined, RocketOutlined,
  FieldTimeOutlined, CloudOutlined, CloudFilled, FolderOpenOutlined, RobotFilled, ArrowUpOutlined, CarryOutOutlined
} from '@ant-design/icons-vue'
import { EDeviceTypeName } from '../types'
import DockControlPanel from './g-map/DockControlPanel.vue'
import { useDockControl } from './g-map/use-dock-control'
import DroneControlPanel from './g-map/DroneControlPanel.vue'
import { useConnectMqtt } from './g-map/use-connect-mqtt'
import Cesium from './cesiumMap/cesium.vue'
export default defineComponent({
  components: {
    BorderOutlined,
    LineOutlined,
    CloseOutlined,
    ControlOutlined,
    TrademarkOutlined,
    ThunderboltOutlined,
    SignalFilled,
    GlobalOutlined,
    HistoryOutlined,
    CloudUploadOutlined,
    FieldTimeOutlined,
    CloudOutlined,
    CloudFilled,
    FolderOpenOutlined,
    RobotFilled,
    ArrowUpOutlined,
    ArrowDownOutlined,
    DockControlPanel,
    DroneControlPanel,
    CarryOutOutlined,
    RocketOutlined
  },
  name: 'GMap',
  props: {},
  setup () {
    const useMouseToolHook = useMouseTool()
    const useGMapManageHook = useGMapManage()
    const deviceTsaUpdateHook = deviceTsaUpdate()
    interface SelectOption {
  value: any,
  label: string,
  more?: any
}
    // 打开飞行控制
    const openDroneControl = ref(false)
    const root = getRoot()
    // 监控显示
    const showMonitor = ref(false)
    // 操作显示
    const showOption = ref(false)
    const mouseMode = ref(false)
    const store = useMyStore()
    // 机场直播地址
    const airPortUrl = ref('')
    // 设备列表
    const droneList = ref()
    // 设备相机
    const cameraList = ref()
    // 相机设备选择值
    const cameraIndex = ref(0)
    // 设备列表选择值
    const droneIndex = ref(0)
    // 视频列表选择值
    const videoList = ref()
    const videoIndex = ref(0)
    // 飞机视频播放地址
    const aircraftUrl = ref('')
    const showAircraft = ref(false)
    // 飞机视频列表
    const aircraftList = ref([])
    const aircraSelected = ref('')
    const state = reactive({
      currentType: '',
      coverIndex: 0
    })
    const str: string = '--'
    const deviceInfo = reactive({
      gateway: {
        capacity_percent: str,
        transmission_signal_quality: str,
      } as GatewayOsd,
      dock: {
      } as DockOsd,
      device: {
        gear: -1,
        mode_code: EModeCode.Disconnected,
        height: str,
        home_distance: str,
        horizontal_speed: str,
        vertical_speed: str,
        wind_speed: str,
        wind_direction: str,
        elevation: str,
        position_state: {
          gps_number: str,
          is_fixed: 0,
          rtk_number: str
        },
        battery: {
          capacity_percent: str,
          landing_power: str,
          remain_flight_time: 0,
          return_home_power: str,
        },
        latitude: 0,
        longitude: 0,
      } as DeviceOsd
    })
    const shareId = computed(() => {
      return store.state.layerBaseInfo.share
@@ -62,6 +785,272 @@
    })
    const drawVisible = computed(() => {
      return store.state.drawVisible
    })
    const osdVisible = computed(() => JSON.parse(JSON.stringify(store.state.osdVisible)))
    const sn = computed(() => {
      return store.state.hmsInfoDetailSn
    })
    const hmsInfo = computed({
      get: () => store.state.hmsInfo,
      set: (val) => {
        return val
      }
    })
    // 关闭窗口
    const closeOsdWindow = () => {
      store.commit('SET_OSD_VISIBLE_INFO', false)
    }
    // 打开监控权限
    const openMonitor = () => {
      showMonitor.value = !showMonitor.value
      if (showMonitor.value) {
        loadVideo()
      } else {
        onClose()
      }
    }
    // 打开飞机监控
    const openAircra = () => {
      showAircraft.value = !showAircraft.value
      if (showAircraft.value) {
        loadDroneVideo()
      } else {
        closeFly()
      }
    }
    // 加载该设备的视频信息
    const loadVideo = async () => {
      droneList.value = []
      cameraList.value = []
      videoList.value = []
      droneIndex.value = 0
      cameraIndex.value = 0
      await getLiveCapacity({ id: store.state.common.projectId })
        .then(res => {
          if (res.code === 0) {
            if (res.data === null) {
              console.warn('warning: get live capacity is null!!!')
              return
            }
            // 机场数据
            const airport = res.data.find(v => v.sn === sn.value)
            const temp: Array<SelectOption> = []
            if (airport) {
              temp.push({ label: airport.name, value: airport.sn, more: airport.cameras_list })
              // 设备列表
              droneList.value = temp.filter(v => v.value === sn.value)
              // 设备直播处理
              if (droneList.value[0].more && droneList.value[0].more.length > 0) {
                cameraList.value = droneList.value[droneIndex.value].more.map((v: { name: any; index: any; videos_list: any }) => {
                  return {
                    label: v.name,
                    value: v.index,
                    more: v.videos_list
                  }
                })
                videoList.value = cameraList.value[cameraIndex.value].more.map((v) => {
                  return {
                    label: v.type,
                    value: v.index,
                  }
                })
                onStart()
              } else {
                showMonitor.value = false
                message.error('该设备暂无直播设备开启')
              }
            }
          }
        })
        .catch(error => {
          message.error(error)
        })
    }
    // 加载无人机的视频信息
    const loadDroneVideo = async () => {
      aircraftList.value = []
      await getLiveCapacity({ id: store.state.common.projectId })
        .then(res => {
          if (res.code === 0) {
            if (res.data === null) {
              console.warn('warning: get live capacity is null!!!')
              return
            }
            const resData: Array<[]> = res.data
            const drone = res.data.find(v => v.sn === deviceInfo.dock.basic_osd.sub_device?.device_sn)
            const temp: Array<SelectOption> = []
            if (drone) {
              temp.push({ label: drone.name, value: drone.sn, more: drone.cameras_list })
            } // 无人机列表
            const airList = temp.filter(v => v.value === deviceInfo.dock.basic_osd?.sub_device?.device_sn)
            // 无人机设备处理
            if (airList[0].more && airList[0].more.length > 0) {
              aircraftList.value = airList[0].more.map(v => {
                return {
                  label: v.name,
                  value: v.index,
                  vadeosList: v.videos_list
                }
              })
              aircraSelected.value = aircraftList.value[0].value
              flyOnStart()
            } else {
              showAircraft.value = false
              message.error('该无人机暂无直播设备开启')
            }
          }
        })
        .catch(error => {
          message.error(error)
        })
    }
    // 机场视频超时说明可能直播被关闭需要重新开启直播
    const airTimeout = () => {
      try {
        onStart()
      } catch (e) {
        onClose()
      }
    }
    const flyTimeout = () => {
      try {
        flyOnStart()
      } catch (e) {
        closeFly()
      }
    }
    // 设备开始播放
    const onStart = async () => {
      airPortUrl.value = ''
      const videoId = droneList.value[droneIndex.value].value + '/' + cameraList.value[cameraIndex.value].value + '/' + videoList.value[videoIndex.value].value
      const streamId = droneList.value[droneIndex.value].value + '-' + cameraList.value[cameraIndex.value].value + '-' + videoList.value[videoIndex.value].value
      const liveURL = config.rtmpURL + streamId
      await startLivestream({
        url: liveURL,
        video_id: videoId,
        url_type: 1,
        video_quality: 0
      })
        .then(res => {
          if (res.code !== 0) return
          airPortUrl.value = res.data.url
        })
    }
    // 下拉框选择变化
    const selectChange = async (e) => {
      // await closeFly()
      // setTimeout(async () => {
      await flyOnStart()
      // }, 500)
    }
    // 关闭设备直播
    const onClose = async () => {
      const videoId = droneList.value[droneIndex.value].value + '/' + cameraList.value[cameraIndex.value].value + '/' + videoList.value[videoIndex.value].value
      stopLivestream({
        video_id: videoId
      }).then(res => {
        if (res.code === 0) {
          airPortUrl.value = ''
        }
      })
    }
    // 飞机设备播放
    const flyOnStart = async () => {
      aircraftUrl.value = ''
      const videoId = deviceInfo.dock.basic_osd?.sub_device?.device_sn + '/' + aircraSelected.value + '/' + 'normal-0'
      const streamId = deviceInfo.dock.basic_osd?.sub_device?.device_sn + '-' + aircraSelected.value + '-' + 'normal-0'
      const liveURL = config.rtmpURL + streamId
      await startLivestream({
        url: liveURL,
        video_id: videoId,
        url_type: 1,
        video_quality: 0
      })
        .then(res => {
          if (res.code !== 0) return
          aircraftUrl.value = res.data.url
        })
    }
    // 飞行设备关闭
    const closeFly = async () => {
      aircraftList.value.forEach(item => {
        const videoId = deviceInfo.dock.basic_osd?.sub_device?.device_sn + '/' + item.value + '/' + 'normal-0'
        stopLivestream({
          video_id: videoId
        }).then(res => {
          if (res.code === 0) {
            aircraftUrl.value = ''
          }
        }).catch(e => {
          console.log(e, 'errrrrrrrrrrrrrr')
        })
      })
      // const videoId = deviceInfo.dock.basic_osd?.sub_device?.device_sn + '/' + aircraSelected.value + '/' + 'normal-0'
      aircraftList.value = []
      aircraSelected.value = ''
    }
    // 打开机场操作
    const openFlySetting = () => {
      openDroneControl.value = false
      setDockControlPanelVisible(true)
    }
    // 打开无人机操作
    const openDeviceSetting = () => {
      setDockControlPanelVisible(false)
      openDroneControl.value = !openDroneControl.value
    }
    watch(() => store.state.deviceStatusEvent,
      data => {
        if (Object.keys(data.deviceOnline).length !== 0) {
          // deviceTsaUpdateHook.initMarker(data.deviceOnline.domain, data.deviceOnline.device_callsign, data.deviceOnline.sn)
          store.state.deviceStatusEvent.deviceOnline = {} as DeviceStatus
        }
        if (Object.keys(data.deviceOffline).length !== 0) {
          store.state.deviceStatusEvent.deviceOffline = {}
        }
      },
      {
        deep: true
      }
    )
    watch(() => store.state.deviceState, data => {
      if (data.currentType === EDeviceTypeName.Gateway && data.gatewayInfo[data.currentSn]) {
        if (osdVisible.value.visible && osdVisible.value.gateway_sn !== '') {
          deviceInfo.gateway = data.gatewayInfo[osdVisible.value.gateway_sn]
        }
      }
      if (data.currentType === EDeviceTypeName.Aircraft && data.deviceInfo[data.currentSn]) {
        if (osdVisible.value.visible && osdVisible.value.sn !== '') {
          deviceInfo.device = data.deviceInfo[osdVisible.value.sn]
        }
      }
      if (data.currentType === EDeviceTypeName.Dock && data.dockInfo[data.currentSn]) {
        if (osdVisible.value.visible && osdVisible.value.is_dock && osdVisible.value.gateway_sn !== '') {
          deviceInfo.dock = data.dockInfo[osdVisible.value.gateway_sn]
          deviceInfo.device = data.deviceInfo[deviceInfo.dock.basic_osd.sub_device?.device_sn ?? osdVisible.value.sn]
        }
      }
    }, {
      deep: true,
    })
    watch(() => osdVisible.value, (data, oldData) => {
      showMonitor.value = false
      aircraftUrl.value = ''
      showAircraft.value = false
      aircraftList.value = []
      aircraSelected.value = ''
      airPortUrl.value = ''
      droneList.value = []
      if (deviceInfo.dock.basic_osd?.mode_code === 2) {
        onCloseControlPanel(oldData.gateway_sn)
      } else {
        setDockControlPanelVisible(false)
      }
    }, {
      deep: true,
    })
    watch(
      () => store.state.wsEvent,
@@ -122,10 +1111,29 @@
      useMouseToolHook.mouseTool(type, getDrawCallback)
      mouseMode.value = bool
    }
    // dock 控制面板
    const {
      dockControlPanelVisible,
      setDockControlPanelVisible,
      onCloseControlPanel,
    } = useDockControl()
    // 关闭设备控制方法
    const closeOperate = (sn:string) => {
      if (deviceInfo.dock.basic_osd?.mode_code === 2) {
        onCloseControlPanel(sn)
      } else {
        setDockControlPanelVisible(false)
      }
    }
    // 连接或断开drc
    useConnectMqtt()
    onMounted(() => {
      const app = getApp()
      useGMapManageHook.globalPropertiesConfig(app)
      // const app = getApp()
      // useGMapManageHook.globalPropertiesConfig(app)
    })
    function getDrawCallback ({ obj }) {
      switch (state.currentType) {
        case MapDoodleEnum.PIN:
@@ -141,16 +1149,18 @@
          break
      }
    }
    async function postPinPositionResource (obj) {
    async function postPinPositionResource (obj: { setExtData: (arg0: { id: string; name: any }) => void }) {
      const req = getPinPositionResource(obj)
      setLayers(req)
      updateCoordinates('gcj02-wgs84', req)
      const coordinates = req.resource.content.geometry.coordinates
      updateCoordinates('gcj02-wgs84', req);
      (req.resource.content.geometry.coordinates as GeojsonCoordinate).push((coordinates as GeojsonCoordinate)[2])
      const result = await postElementsReq(shareId.value, req)
      obj.setExtData({ id: req.id, name: req.name })
      store.state.coverList.push(obj)
      // console.log(store.state.coverList)
    }
    async function postPolylineResource (obj) {
    async function postPolylineResource (obj: { setExtData: (arg0: { id: string; name: any }) => void }) {
      const req = getPolylineResource(obj)
      setLayers(req)
      updateCoordinates('gcj02-wgs84', req)
@@ -159,7 +1169,7 @@
      store.state.coverList.push(obj)
      // console.log(store.state.coverList)
    }
    async function postPolygonResource (obj) {
    async function postPolygonResource (obj: { setExtData: (arg0: { id: string; name: any }) => void }) {
      const req = getPoygonResource(obj)
      setLayers(req)
      updateCoordinates('gcj02-wgs84', req)
@@ -169,7 +1179,7 @@
      // console.log(store.state.coverList)
    }
    function getPinPositionResource (obj) {
    function getPinPositionResource (obj: { getPosition: () => any; _originOpts: { title: any } }) {
      const position = obj.getPosition()
      const resource = generatePointContent(position)
      const name = obj._originOpts.title
@@ -180,7 +1190,7 @@
        resource
      }
    }
    function getPolylineResource (obj) {
    function getPolylineResource (obj: { getPath: () => any; _opts: any }) {
      const path = obj.getPath()
      const resource = generateLineContent(path)
      const { name, id } = getBaseInfo(obj._opts)
@@ -190,7 +1200,7 @@
        resource
      }
    }
    function getPoygonResource (obj) {
    function getPoygonResource (obj: { getPath: () => any; _opts: any }) {
      const path = obj.getPath()
      const resource = generatePolyContent(path)
      const { name, id } = getBaseInfo(obj._opts)
@@ -200,7 +1210,7 @@
        resource
      }
    }
    function getBaseInfo (obj) {
    function getBaseInfo (obj: { title: any }) {
      const name = obj.title
      const id = uuidv4()
      return { name, id }
@@ -211,7 +1221,7 @@
      // layer.id = 'private_layer' + uuidv4()
      // layer?.elements.push(resource)
      if (layer?.elements) {
        ;(layer?.elements as any[]).push(resource)
        ; (layer?.elements as any[]).push(resource)
      }
      console.log('layers', layers)
      store.commit('SET_LAYER_INFO', layers)
@@ -281,7 +1291,45 @@
    return {
      draw,
      mouseMode,
      drawVisible
      drawVisible,
      osdVisible,
      pin,
      state,
      M30,
      deviceInfo,
      EGear,
      EModeCode,
      str,
      EDockModeCode,
      EDockModeText,
      EModeText,
      dockControlPanelVisible,
      setDockControlPanelVisible,
      onCloseControlPanel,
      NetworkStateTypeEnum,
      NetworkStateQualityEnum,
      RainfallEnum,
      DroneInDockEnum,
      hmsInfo,
      sn,
      showMonitor,
      showOption,
      airPortUrl,
      openMonitor,
      droneIndex,
      openAircra,
      showAircraft,
      aircraftUrl,
      aircraftList,
      aircraSelected,
      selectChange,
      closeOperate,
      closeOsdWindow,
      openDroneControl,
      openFlySetting,
      openDeviceSetting,
      airTimeout,
      flyTimeout
    }
  }
})
@@ -291,21 +1339,122 @@
.g-map-wrapper {
  height: 100%;
  width: 100%;
  .g-action-panle {
  .g-action-panel {
    position: absolute;
    top: 16px;
    right: 16px;
    .g-action-item {
      padding-top: 8px;
      width: 28px;
      height: 28px;
      background: white;
      color: $primary;
      border-radius: 2px;
      line-height: 28px;
      text-align: center;
      margin-bottom: 2px;
    }
    .g-action-item:hover {
      border: 1px solid $primary;
      border-radius: 2px;
    }
  }
  .selection {
    border: 1px solid $primary;
    border-radius: 2px;
  }
  // antd button 光晕
  &:deep(.ant-btn) {
    &::after {
      display: none;
    }
  }
}
</style>
<style lang="scss">
.amap-logo {
  opacity: 0;
.osd-panel {
  position: absolute;
  left: 10px;
  top: 10px;
  width: 480px;
  background: #000;
  color: #fff;
  border-radius: 2px;
  opacity: 0.8;
}
.amap-copyright {
  opacity: 0;
.overflow {
  width: 100%;
  overflow: hidden;
  background-color: #ff9900;
  // padding: 2px 5px;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.osd-info {
  margin: 15px 10px;
}
.num {
  padding: 0 5px;
  background-color: #ff9900;
  color: #fff;
}
.span5 {
  display: flex;
  align-items: center;
  padding-right: 20px;
}
.osd>div:not(.dock-control-panel) {
  margin-top: 5px;
  padding-left: 5px;
}
.circle {
  border-radius: 50%;
  width: 10px;
  height: 10px;
}
.battery-slide {
  .capacity-percent {
    background: #00ee8b;
  }
  .return-home {
    background: #ff9f0a;
  }
  .landing {
    background: #f5222d;
  }
  .white-point {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: white;
    bottom: -0.5px;
  }
  .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>