forked from drone/command-center-dashboard

罗广辉
2025-04-21 2800fa4f32f3900509cb4d6eefaf2bfaf54efdd7
src/views/SignMachineNest/MachineRight/MachineStatus/MachineStatus.vue
@@ -1,378 +1,340 @@
<!-- 机巢状态 -->
<template>
  <CommonTitle title="机巢状态" @details="detailsFun" />
  <div :style="{ marginLeft: pxToRem(14) }">
    <div class="machine-status">
      <div class="info">
        <img src="../../../../assets/images/signMachineNest/machineRight/wrj.png" alt="">
        <div class="info-right">
          <div class="name">{{ osdVisible?.callsign || '--' }}</div>
          <div class="wz">
            <span class="left">当前位置:</span>
            <span class="right">{{ detailInfo.longitude }},{{ detailInfo.latitude }}</span>
          </div>
          <div class="close-wb">
            <div class="close">{{ AircraftStatus ? AircraftStatus : '舱内关机' }}</div>
            <!-- <div class="wb">需要维保</div> -->
          </div>
        </div>
      </div>
      <div class="status">
        <div class="card">
          <div>
            <img src="../../../../assets/images/signMachineNest/machineRight/height.png" alt="">
            <span class="text">实时真高</span>
          </div>
          <div class="text-data">{{ detailInfo.height || '--' }}<span class="text">米</span></div>
        </div>
        <div class="card">
          <div>
            <img src="../../../../assets/images/signMachineNest/machineRight/speed.png" alt="">
            <span class="text">飞行速度</span>
          </div>
          <div class="text-data">{{ detailInfo.horizontal_speed }}<span class="text">米/秒</span></div>
        </div>
        <div class="card">
          <div>
            <img src="../../../../assets/images/signMachineNest/machineRight/signal.png" alt="">
            <span class="text">信号强度</span>
          </div>
          <div class="text-data">{{ detailInfo.quality }}</div>
        </div>
        <div class="card">
          <div>
            <img src="../../../../assets/images/signMachineNest/machineRight/electricity.png" alt="">
            <span class="text">电池电量</span>
          </div>
          <div v-if="drone_charge_state.capacity_percent != 0" class="text-data">
            {{ drone_charge_state.capacity_percent }}<span class="text">%</span>
          </div>
          <div v-else class="text-data">{{ detailInfo.capacity_percent }}<span class="text">%</span></div>
        </div>
        <div class="card">
          <div>
            <img src="../../../../assets/images/signMachineNest/machineRight/distance.png" alt="">
            <span class="text">飞行距离</span>
          </div>
          <div class="text-data">{{ singleTotal.flight_mileage }}<span class="text">km</span></div>
        </div>
        <div class="card">
          <div>
            <img src="../../../../assets/images/signMachineNest/machineRight/duration.png" alt="">
            <span class="text">飞行时长</span>
          </div>
          <div class="text-data">{{ singleTotal.hour_count }}<span class="text">h</span></div>
        </div>
      </div>
    </div>
  </div>
   <MachineTableDetails v-model:show="isShowDetails"/>
   <CommonTitle title="机巢状态" @details="detailsFun" />
   <div :style="{ marginLeft: pxToRem(14) }">
      <div class="machine-status">
         <div class="info">
            <img src="../../../../assets/images/signMachineNest/machineRight/wrj.png" alt="" />
            <div class="info-right">
               <!-- <div class="name">{{ osdVisible?.callsign || '--' }}</div> -->
               <div class="name">{{ dockDetails?.nickname || '--' }}</div>
               <div class="wz">
                  <span class="left">当前位置:</span>
                  <span class="right">{{ detailInfo.longitude }},{{ detailInfo.latitude }}</span>
               </div>
               <div class="close-wb">
                  <div class="close" :class="AircraftStatus == undefined ? '' : 'other'">
                     {{ AircraftStatus == undefined ? '舱内关机' : AircraftStatus }}
                  </div>
                  <!-- <div class="wb">需要维保</div> -->
               </div>
            </div>
         </div>
         <div class="status">
            <div class="card">
               <div>
                  <img src="../../../../assets/images/signMachineNest/machineRight/height.png" alt="" />
                  <span class="text">实时真高</span>
               </div>
               <div class="text-data">
                  {{ detailInfo.height || '--' }}
                  <span class="text">米</span>
               </div>
            </div>
            <div class="card">
               <div>
                  <img src="../../../../assets/images/signMachineNest/machineRight/speed.png" alt="" />
                  <span class="text">飞行速度</span>
               </div>
               <div class="text-data">
                  {{ detailInfo.horizontal_speed }}
                  <span class="text">米/秒</span>
               </div>
            </div>
            <div class="card">
               <div>
                  <img src="../../../../assets/images/signMachineNest/machineRight/signal.png" alt="" />
                  <span class="text">信号强度</span>
               </div>
               <div class="text-data">{{ detailInfo.quality }}</div>
            </div>
            <div class="card">
               <div>
                  <img src="../../../../assets/images/signMachineNest/machineRight/electricity.png" alt="" />
                  <span class="text">电池电量</span>
               </div>
               <div v-if="drone_charge_state.capacity_percent != 0" class="text-data">
                  {{ drone_charge_state.capacity_percent }}
                  <span class="text">%</span>
               </div>
               <div v-else class="text-data">
                  {{ detailInfo.capacity_percent }}
                  <span class="text">%</span>
               </div>
            </div>
            <div class="card">
               <div>
                  <img src="../../../../assets/images/signMachineNest/machineRight/distance.png" alt="" />
                  <span class="text">飞行距离</span>
               </div>
               <div class="text-data">
                  {{ singleTotal.flight_mileage }}
                  <span class="text">km</span>
               </div>
            </div>
            <div class="card">
               <div>
                  <img src="../../../../assets/images/signMachineNest/machineRight/duration.png" alt="" />
                  <span class="text">飞行时长</span>
               </div>
               <div class="text-data">
                  {{ singleTotal.hour_count }}
                  <span class="text">h</span>
               </div>
            </div>
         </div>
      </div>
   </div>
   <MachineTableDetails v-model:show="isShowDetails" />
</template>
<script setup>
import CommonTitle from '@/components/CommonTitle.vue';
import { EDeviceTypeName } from '@/utils/staticData/enums.js';
import { EModeCode, EDockModeText, EModeText } from '@/utils/staticData/device';
import { getLnglatAltitude } from '@/utils/cesium/mapUtil.js';
import { useStore } from 'vuex';
import MachineTableDetails from '@/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/MachineTableDetails.vue';
import CommonTitle from '@/components/CommonTitle.vue'
import { EDeviceTypeName } from '@/utils/staticData/enums.js'
import { EModeCode, EDockModeText, EModeText } from '@/utils/staticData/device'
import { getLnglatAltitude } from '@/utils/cesium/mapUtil.js'
import { useStore } from 'vuex'
import MachineTableDetails from '@/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/MachineTableDetails.vue'
const store = useStore();
// 获取机巢信息
let osdVisible = computed(() => store.state.home.osdVisible);
const wsInfo = inject('wsInfo')
const dockDetails = inject('dockDetails')
let device_osd_info = computed(() => wsInfo.value?.device_osd || {})
let device_osd_host = computed(() => device_osd_info?.value?.data?.host || {})
let dock_osd_info = computed(() => wsInfo.value?.dock_osd || {})
let dock_osd_host = computed(() => dock_osd_info.value?.data?.host || {})
// 单个机巢统计数据
const singleTotal = computed(() => store.state.home.singleTotal);
const singleTotal = inject('singleTotal')
// 是否展示机机巢状态详情
let isShowDetails = ref(false);
let isShowDetails = ref(false)
let str = '--';
let drone_charge_state = ref({
  capacity_percent: '--',
  state: 0
   capacity_percent: '--',
   state: 0,
})
let AircraftStatus = ref(null);
let AircraftStatus = ref(null)
let detailInfo = ref({
  longitude: '--',
  latitude: '--',
  home_distance: '--',
  quality: '--',
  horizontal_speed: '--',
  height: '--',
  remain_flight_time: '--',
  capacity_percent: '--',
});
let quality = ref(['弱', '较弱', '中等', '较强', '强']);
let deviceInfo = ref({
  gateway: {
    capacity_percent: str,
    transmission_signal_quality: str,
  },
  dock: {},
  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,
  },
});
let mode_code = ref('已断开连接');
   longitude: '--',
   latitude: '--',
   home_distance: '--',
   quality: '--',
   horizontal_speed: '--',
   height: '--',
   remain_flight_time: '--',
   capacity_percent: '--',
})
let quality = ref(['弱', '较弱', '中等', '较强', '强'])
// 监听实时信息
watch(
  () => store.state.home.wsMessage,
  (newValue) => {
    if (newValue.mode_code === 14) return
    if (Object.keys(newValue).length === 0) return
    // console.log(newValue, '顶顶顶111')
    detailInfo.value.longitude = newValue?.longitude.toFixed(6) || '--';
      detailInfo.value.latitude = newValue?.latitude.toFixed(6) || '--';
    getLnglatAltitude(Number(detailInfo.value.longitude), Number(detailInfo.value.latitude)).then((res) => {
      console.log(res, '顶顶顶')
      const height = newValue?.height - res?.height;
      //针对西安实时高度进行降低
      const wId = localStorage.getItem('bs_workspace_id');
      if (wId === 'f47ac10b-58cc-4372-a567-0e02b2c3d479') {
        detailInfo.value.height = reduceHeight(height);
      } else {
        detailInfo.value.height = height.toFixed(1) || '--';
      }
   device_osd_host,
   newValue => {
      if (!newValue) return
      if (newValue?.mode_code === 14) return
      if (Object.keys(newValue).length === 0) return
      detailInfo.value.longitude = newValue?.longitude.toFixed(6) || '--'
      detailInfo.value.latitude = newValue?.latitude.toFixed(6) || '--'
      getLnglatAltitude(Number(detailInfo.value.longitude), Number(detailInfo.value.latitude), window.$viewer).then(
         res => {
            const height = newValue?.height - res?.height
            //针对西安实时高度进行降低
            const wId = localStorage.getItem('bs_workspace_id')
            if (wId === 'f47ac10b-58cc-4372-a567-0e02b2c3d479') {
               detailInfo.value.height = reduceHeight(height)
            } else {
               detailInfo.value.height = height.toFixed(1) || '--'
            }
      detailInfo.value.quality = quality.value[newValue?.position_state.quality - 1] || '--';
      detailInfo.value.horizontal_speed = newValue?.horizontal_speed.toFixed(1) || '--';
      detailInfo.value.remain_flight_time = (newValue?.battery.remain_flight_time / 60).toFixed(0) || '--';
      detailInfo.value.capacity_percent = (newValue?.battery.capacity_percent).toFixed(0) || '--';
    });
  },
  { immediate: true, deep: true }
);
            detailInfo.value.quality = quality.value[newValue?.position_state.quality - 1] || '--'
            detailInfo.value.horizontal_speed = newValue?.horizontal_speed.toFixed(1) || '--'
            detailInfo.value.remain_flight_time = (newValue?.battery.remain_flight_time / 60).toFixed(0) || '--'
            detailInfo.value.capacity_percent = (newValue?.battery.capacity_percent).toFixed(0) || '--'
         }
      )
   },
   { immediate: true, deep: true }
)
// EDeviceTypeName.Dock
// 获取最新机场状态
watch(store.state.home.deviceState, (newValue) => {
    // if (data.currentSn !== osdVisible.gateway_sn) return;
    if (newValue.currentType === EDeviceTypeName.Dock && newValue.dockInfo[newValue.currentSn]) {
      // 机场状态
      mode_code.value = EDockModeText[newValue.dockInfo[newValue.currentSn]?.basic_osd?.mode_code];
      // this.$emit('updateModeCode', mode_code.value);
      // 舱内状态
      AircraftStatus.value =
        EModeText[newValue.deviceInfo[
            deviceInfo.value.dock.basic_osd?.sub_device?.device_sn ??
            osdVisible.sn
          ]?.mode_code
        ];
      // 舱内关机时显示的电量
      let child_sn = newValue.dockInfo[newValue.currentSn].basic_osd.sub_device.device_sn;
      // 飞机在线时取飞机中的电量
      if(newValue.deviceInfo[child_sn]) {
        drone_charge_state.value = {
          capacity_percent: newValue.deviceInfo[child_sn].battery.capacity_percent,
          state: newValue.deviceInfo[child_sn].battery.landing_power
        }
      } else{
        // 遥控器这里拿不到值data.drone_charge_state_new == undefined 会一直报错
        if (newValue.drone_charge_state_new) {
          drone_charge_state.value = newValue.drone_charge_state_new;
        }
      }
      if (osdVisible.visible && osdVisible.is_dock && osdVisible.gateway_sn !== '') {
        deviceInfo.value.dock = newValue.dockInfo[osdVisible.gateway_sn];
        deviceInfo.value.device =
        newValue.deviceInfo[deviceInfo.value.dock.basic_osd?.sub_device?.device_sn ??
            osdVisible.sn
          ];
        // 设备关机即不显示信息
        // 兼容遥控器 关闭无人机 mode_code返回的是14 不是undefined
        if (
          newValue.deviceInfo[
            deviceInfo.value.dock.basic_osd?.sub_device?.device_sn ??
            osdVisible.sn
          ]?.mode_code === undefined || newValue.deviceInfo[
            deviceInfo.value.dock.basic_osd?.sub_device?.device_sn ??
            osdVisible.sn
          ]?.mode_code == 14
        ) {
          detailInfo.value = {
            longitude: '--',
            latitude: '--',
            home_distance: '--',
            quality: '--',
            horizontal_speed: '--',
            remain_flight_time: '--',
            height: '--',
            capacity_percent: '--',
          };
        }
      }
    }
  },
  { immediate: true, deep: true }
);
watch(
   wsInfo,
   () => {
      if (device_osd_host.value?.mode_code !== undefined) {
         AircraftStatus.value = EModeText?.[device_osd_host.value?.mode_code] || '--'
      }
      // 飞机在线时取飞机中的电量
      if (device_osd_host.value?.battery) {
         drone_charge_state.value = {
            capacity_percent: device_osd_host.value.battery.capacity_percent,
            state: device_osd_host.value.battery.landing_power,
         }
      }
      if (device_osd_host.value?.mode_code === undefined || device_osd_host.value?.mode_code === 14) {
         detailInfo.value = {
            longitude: '--',
            latitude: '--',
            home_distance: '--',
            quality: '--',
            horizontal_speed: '--',
            remain_flight_time: '--',
            height: '--',
            capacity_percent: '--',
         }
      }
   },
   { immediate: true, deep: true }
)
const reduceHeight = (height) => {
  if (!Number(height)) return '--';
  let theFinheight = 0;
  if (height < 120) {
    theFinheight = height;
  } else if (height > 220) {
    theFinheight = height - 110;
  } else if (height > 210) {
    theFinheight = height - 100;
  } else if (height > 200) {
    theFinheight = height - 90;
  } else if (height > 190) {
    theFinheight = height - 80;
  } else if (height > 180) {
    theFinheight = height - 70;
  } else if (height > 170) {
    theFinheight = height - 60;
  } else if (height > 160) {
    theFinheight = height - 50;
  } else if (height > 150) {
    theFinheight = height - 40;
  } else if (height > 140) {
    theFinheight = height - 30;
  } else if (height > 130) {
    theFinheight = height - 20;
  } else if (height > 120) {
    theFinheight = height - 10;
  }
  return theFinheight.toFixed(1);
};
const reduceHeight = height => {
   if (!Number(height)) return '--'
   let theFinheight = 0
   if (height < 120) {
      theFinheight = height
   } else if (height > 220) {
      theFinheight = height - 110
   } else if (height > 210) {
      theFinheight = height - 100
   } else if (height > 200) {
      theFinheight = height - 90
   } else if (height > 190) {
      theFinheight = height - 80
   } else if (height > 180) {
      theFinheight = height - 70
   } else if (height > 170) {
      theFinheight = height - 60
   } else if (height > 160) {
      theFinheight = height - 50
   } else if (height > 150) {
      theFinheight = height - 40
   } else if (height > 140) {
      theFinheight = height - 30
   } else if (height > 130) {
      theFinheight = height - 20
   } else if (height > 120) {
      theFinheight = height - 10
   }
   return theFinheight.toFixed(1)
}
// 详情
const detailsFun = () => {
  isShowDetails.value = true;
};
   isShowDetails.value = true
}
</script>
<style lang="scss" scoped>
  .machine-status {
    width: 390px;
    height: 230px;
    background: linear-gradient(
      270deg,
      #1f3e7a 0%,
      rgba(31, 62, 122, 0.35) 79%,
      rgba(31, 62, 122, 0) 100%
    );
    opacity: 0.85;
    margin: 2px 0 13 0;
.machine-status {
   width: 390px;
   height: 230px;
   background: linear-gradient(270deg, #1f3e7a 0%, rgba(31, 62, 122, 0.35) 79%, rgba(31, 62, 122, 0) 100%);
   opacity: 0.85;
   margin: 2px 0 13 0;
    padding: 8px 0px 20px 18px;
    .info {
      display: flex;
      // justify-content: ce;
      height: 88px;
      display: flex;
      align-items: center;
      img {
        width: 94px;
        height: 88px;
        margin-right: 22px;
      }
      .info-right {
        .name {
          width: 184px;
          height: 31px;
          font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
          font-weight: 400;
          font-size: 24px;
          color: #0BE5F5;
          line-height: 28px;
        }
        .wz {
          font-family: Source Han Sans CN, Source Han Sans CN;
          font-size: 14px;
          color: #FFFFFF;
            line-height: 16px;
          .left {
            width: 70px;
            height: 21px;
            font-weight: 400;
            opacity: 0.6;
          }
          .right {
            width: 100px;
            height: 21px;
            font-weight: bold;
          }
        }
        .close-wb {
          display: flex;
          margin-top: 10px;
          text-align: center;
          line-height: 16px;
          .close {
            width: 60px;
            height: 20px;
            background: rgba(255,178,106,0.2);
            border-radius: 4px 4px 4px 4px;
            border: 1px solid #FFB26A;
            color: #FFB26A;
            margin-right: 10px;
          }
          .wb {
            width: 60px;
            height: 20px;
            background: rgba(255,106,106,0.2);
            border-radius: 4px 4px 4px 4px;
            border: 1px solid #FF6A6A;
            color: #FF6A6A;
          }
        }
      }
    }
    .status {
      display: flex;
      flex-wrap: wrap;
      gap: 10px 20px;
      margin-top: 18px;
      .card {
        width: calc(33.33% - 14px);
      }
      img {
        width: 16px;
        height: 16px;
        // margin-right: 0px;
        // margin-top: 2px;
      }
      .text {
        width: 56px;
        height: 21px;
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 14px;
        color: #FFFFFF;
        line-height: 16px;
      }
      .text-data {
        // width: 40px;
        margin-left: 20px;
        height: 23px;
        font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
        font-weight: 400;
        font-size: 18px;
        color: #0BE5F5;
        line-height: 21px;
      }
    }
 }
   padding: 8px 0px 20px 18px;
   .info {
      display: flex;
      // justify-content: ce;
      height: 88px;
      display: flex;
      align-items: center;
      img {
         width: 94px;
         height: 88px;
         margin-right: 22px;
      }
      .info-right {
         .name {
            width: 184px;
            height: 31px;
            font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
            font-weight: 400;
            font-size: 24px;
            color: #0be5f5;
            line-height: 28px;
            overflow: hidden; // 添加溢出隐藏
            text-overflow: ellipsis; // 显示省略号
            white-space: nowrap; // 不换行
         }
         .wz {
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-size: 14px;
            color: #ffffff;
            line-height: 16px;
            .left {
               width: 70px;
               height: 21px;
               font-weight: 400;
               opacity: 0.6;
            }
            .right {
               width: 100px;
               height: 21px;
               font-weight: bold;
            }
         }
         .close-wb {
            display: flex;
            margin-top: 10px;
            text-align: center;
            line-height: 16px;
            .close {
               width: 60px;
               height: 20px;
               background: rgba(255, 178, 106, 0.2);
               border-radius: 4px 4px 4px 4px;
               border: 1px solid #ffb26a;
               color: #ffb26a;
               margin-right: 10px;
            }
            .other {
               border: 1px solid #8effac;
               color: #8effac;
            }
            .wb {
               width: 60px;
               height: 20px;
               background: rgba(255, 106, 106, 0.2);
               border-radius: 4px 4px 4px 4px;
               border: 1px solid #ff6a6a;
               color: #ff6a6a;
            }
         }
      }
   }
   .status {
      display: flex;
      flex-wrap: wrap;
      gap: 10px 20px;
      margin-top: 18px;
      .card {
         width: calc(33.33% - 14px);
      }
      img {
         width: 16px;
         height: 16px;
         // margin-right: 0px;
         // margin-top: 2px;
      }
      .text {
         width: 56px;
         height: 21px;
         font-family: Source Han Sans CN, Source Han Sans CN;
         font-weight: 400;
         font-size: 14px;
         color: #ffffff;
         line-height: 16px;
      }
      .text-data {
         // width: 40px;
         margin-left: 20px;
         height: 23px;
         font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
         font-weight: 400;
         font-size: 18px;
         color: #0be5f5;
         line-height: 21px;
      }
   }
}
</style>