forked from drone/command-center-dashboard

张含笑
2025-04-19 54cca8780ee531afafdaf9a288f3a6f722db1b3d
Merge remote-tracking branch 'origin/master'
3 files modified
282 ■■■■■ changed files
src/hooks/useTaskViewInfo/useTaskViewInfo.js 25 ●●●● patch | view | raw | blame | history
src/hooks/useTaskWayline/useTaskWayline.js 33 ●●●●● patch | view | raw | blame | history
src/views/SignMachineNest/MachineRight/MachineStatus/MachineStatus.vue 224 ●●●● patch | view | raw | blame | history
src/hooks/useTaskViewInfo/useTaskViewInfo.js
@@ -3,7 +3,7 @@
import CreateFrustum from '@/utils/cesium/frustum/CreateFrustum'
export function useTaskViewInfo (viewer, wsInfo, removeEntitys) {
  const newViewer = unref(viewer)
  const newViewer = isRef(viewer) ? viewer : ref(viewer)
  let viewInfoFrustum
  // 设置视椎
@@ -14,7 +14,7 @@
    const attitude_head = 180 + host.attitude_head
    const gimbal_pitch = 90 - Number(host?.payloads[0]?.gimbal_pitch) || 0
    viewInfoFrustum = new CreateFrustum(newViewer, {
    viewInfoFrustum = new CreateFrustum(newViewer.value, {
      position: {
        longitude: host.longitude,
        latitude: host.latitude,
@@ -33,14 +33,14 @@
  function setAircraftGltf () {
    const host = deviceOsdInfo.value?.data?.host
    const aircraftEntity = newViewer.entities.getById('aircraftGltf')
    const aircraftEntity = newViewer.value?.entities.getById('aircraftGltf')
    const position = Cesium.Cartesian3.fromDegrees(host.longitude, host.latitude, host.height)
    if (aircraftEntity) {
      aircraftEntity.position = new Cesium.ConstantPositionProperty(position)
      return
    }
    newViewer.entities.add({
    newViewer.value?.entities.add({
      id: 'aircraftGltf',
      position,
      model: {
@@ -55,8 +55,18 @@
  // 视椎加载处理
  const deviceOsdInfo = computed(() => wsInfo.value?.device_osd)
  watch(deviceOsdInfo, () => {
  watch(
    [
      () => deviceOsdInfo.value,
      () => newViewer.value
    ],
    (
      [curDeviceOsdInfo, curViewer],
    ) => {
    const host = deviceOsdInfo.value?.data?.host
      if (!curViewer) return
    if ([14, 0].includes(host.mode_code)) {
      mapEntityRemove()
@@ -65,12 +75,13 @@
    setCreateFrustum(host)
    setAircraftGltf()
  })
    }
  )
  const mapEntityRemove = () => {
    viewInfoFrustum?.clear()
    newViewer.entities.removeById('aircraftGltf')
    newViewer.value?.entities.removeById('aircraftGltf')
    removeEntitys && removeEntitys()
  }
src/hooks/useTaskWayline/useTaskWayline.js
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2025-04-19 14:24:34
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2025-04-19 15:23:57
 * @LastEditTime: 2025-04-19 17:21:58
 * @FilePath: \command-center-dashboard\src\hooks\useTaskWayline\useTaskWayline.js
 * @Description: 
 * 
@@ -20,7 +20,7 @@
import { Cartesian3 } from 'cesium'
export function useTaskWayline (viewer, taskDetails) {
  const newViewer = unref(viewer)
  const newViewer = isRef(viewer) ? viewer : ref(viewer)
  // 解析kmz文件
  const parsingFiles = async url => {
@@ -30,7 +30,7 @@
    const waylinesXMLObj = removeTextKey(waylinesXMLJSON.Folder)
    if (!waylinesXMLObj.Placemark.length) return
    const allPoint = waylinesXMLObj.Placemark.map(item => item.Point.coordinates.split(','))
    flyVisual(allPoint, newViewer)
    flyVisual(allPoint, newViewer.value)
    drawWayline(waylinesXMLObj)
  }
@@ -40,7 +40,7 @@
      return Cartesian3.fromDegrees(Number(lon), Number(lat))
    })
    // 起点
    newViewer.entities.add({
    newViewer.value.entities.add({
      id: 'drone-job-wayline-start',
      position: positions[0],
      billboard: {
@@ -51,7 +51,7 @@
    })
    // 终点
    newViewer.entities.add({
    newViewer.value.entities.add({
      id: 'drone-job-wayline-end',
      position: positions[positions.length - 1],
      billboard: {
@@ -63,7 +63,7 @@
    })
    // 路径线
    newViewer.entities.add({
    newViewer.value.entities.add({
      id: 'drone-job-wayline-polyline',
      polyline: {
        width: 4,
@@ -79,17 +79,26 @@
    })
  }
  watch(taskDetails, () => {
    if (taskDetails.value?.way_lines?.length) {
  watch(
    [
      () => taskDetails.value?.way_lines?.length,
      () => newViewer.value
    ],
    (
      [wayLinesLength, curViewer],
    ) => {
      if (wayLinesLength && wayLinesLength > 0 && curViewer) {
      parsingFiles(taskDetails.value.way_lines[0].url)
    }
  }, { immediate: true })
    },
    { immediate: true }
  )
  const removeEntitys = () => {
    const entitiesIDs = newViewer?.entities.values.map(i => i.id)
    const entitiesIDs = newViewer.value?.entities.values.map(i => i.id)
    entitiesIDs.forEach(item => {
      item.includes('drone-job-wayline-') && newViewer?.entities.removeById(item)
    Array.isArray(entitiesIDs) && entitiesIDs.forEach(item => {
      item.includes('drone-job-wayline-') && newViewer.value?.entities.removeById(item)
    })
  }
src/views/SignMachineNest/MachineRight/MachineStatus/MachineStatus.vue
@@ -4,7 +4,7 @@
  <div :style="{ marginLeft: pxToRem(14) }">
    <div class="machine-status">
      <div class="info">
        <img src="../../../../assets/images/signMachineNest/machineRight/wrj.png" alt="">
                <img src="../../../../assets/images/signMachineNest/machineRight/wrj.png" alt="" />
        <div class="info-right">
          <!-- <div class="name">{{ osdVisible?.callsign || '--' }}</div> -->
          <div class="name">{{ osdVisible?.nickname || '--' }}</div>
@@ -23,48 +23,64 @@
      <div class="status">
        <div class="card">
          <div>
            <img src="../../../../assets/images/signMachineNest/machineRight/height.png" alt="">
                        <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 class="text-data">
                        {{ detailInfo.height || '--' }}
                        <span class="text">米</span>
                    </div>
        </div>
        <div class="card">
          <div>
            <img src="../../../../assets/images/signMachineNest/machineRight/speed.png" alt="">
                        <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 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="">
                        <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="">
                        <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>
                        {{ 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 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="">
                        <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 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="">
                        <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 class="text-data">
                        {{ singleTotal.hour_count }}
                        <span class="text">h</span>
                    </div>
        </div>
      </div>
    </div>
@@ -73,28 +89,28 @@
</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();
const store = useStore()
// 获取机巢信息
let osdVisible = ref({});//computed(() => store.state.home.osdVisible);
const singleUavHome = computed(() => store.state.home.singleUavHome);
let osdVisible = ref({}) //computed(() => store.state.home.osdVisible);
const singleUavHome = computed(() => store.state.home.singleUavHome)
// 单个机巢统计数据
const singleTotal = computed(() => store.state.home.singleTotal);
const singleTotal = computed(() => store.state.home.singleTotal)
// 是否展示机机巢状态详情
let isShowDetails = ref(false);
let isShowDetails = ref(false)
let str = '--';
let str = '--'
let drone_charge_state = ref({
  capacity_percent: '--',
  state: 0
    state: 0,
})
let AircraftStatus = ref(null);
let AircraftStatus = ref(null)
let detailInfo = ref({
  longitude: '--',
  latitude: '--',
@@ -104,8 +120,8 @@
  height: '--',
  remain_flight_time: '--',
  capacity_percent: '--',
});
let quality = ref(['弱', '较弱', '中等', '较强', '强']);
})
let quality = ref(['弱', '较弱', '中等', '较强', '强'])
let deviceInfo = ref({
  gateway: {
    capacity_percent: str,
@@ -136,84 +152,84 @@
    latitude: 0,
    longitude: 0,
  },
});
let mode_code = ref('已断开连接');
})
let mode_code = ref('已断开连接')
watch(() => store.state.home.osdVisible, (newValue) => {
  osdVisible.value = newValue;
});
watch(
    () => store.state.home.osdVisible,
    newValue => {
        osdVisible.value = newValue
    }
)
// 监听实时信息
watch(
  () => store.state.home.wsMessage,
  (newValue) => {
    newValue => {
    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) || '--';
        detailInfo.value.longitude = newValue?.longitude.toFixed(6) || '--'
        detailInfo.value.latitude = newValue?.latitude.toFixed(6) || '--'
    // console.log(window.$viewer)
    getLnglatAltitude(Number(detailInfo.value.longitude), Number(detailInfo.value.latitude),window.$viewer).then((res) => {
      const height = newValue?.height - res?.height;
        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');
                const wId = localStorage.getItem('bs_workspace_id')
      if (wId === 'f47ac10b-58cc-4372-a567-0e02b2c3d479') {
        detailInfo.value.height = reduceHeight(height);
                    detailInfo.value.height = reduceHeight(height)
      } else {
        detailInfo.value.height = height.toFixed(1) || '--';
                    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) || '--';
    });
                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 }
);
)
// 获取最新机场状态
watch(store.state.home.deviceState, (newValue) => {
watch(
    store.state.home.deviceState,
    newValue => {
  // console.log('newValue', newValue);
    if (newValue.currentType === EDeviceTypeName.Dock && newValue?.dockInfo[newValue.currentSn]) {
      // 机场状态
      mode_code.value = EDockModeText[newValue?.dockInfo[newValue.currentSn]?.basic_osd?.mode_code];
            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
        ];
                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;
            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
                    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;
                    drone_charge_state.value = newValue.drone_charge_state_new
        }
      }
      if (osdVisible.value.visible && osdVisible.value.is_dock && osdVisible.value.gateway_sn !== '') {
        deviceInfo.value.dock = newValue.dockInfo[osdVisible.value.gateway_sn];
                deviceInfo.value.dock = newValue.dockInfo[osdVisible.value.gateway_sn]
        deviceInfo.value.device =
        newValue.deviceInfo[deviceInfo.value.dock.basic_osd?.sub_device?.device_sn ??
        osdVisible.value.sn
          ];
                    newValue.deviceInfo[deviceInfo.value.dock.basic_osd?.sub_device?.device_sn ?? osdVisible.value.sn]
        // 设备关机即不显示信息
        // 兼容遥控器 关闭无人机 mode_code返回的是14 不是undefined
        if (
          newValue.deviceInfo[
            deviceInfo.value.dock.basic_osd?.sub_device?.device_sn ??
            osdVisible.value.sn
          ]?.mode_code === undefined || newValue.deviceInfo[
            deviceInfo.value.dock.basic_osd?.sub_device?.device_sn ??
            osdVisible.value  .sn
          ]?.mode_code == 14
                    newValue.deviceInfo[deviceInfo.value.dock.basic_osd?.sub_device?.device_sn ?? osdVisible.value.sn]
                        ?.mode_code === undefined ||
                    newValue.deviceInfo[deviceInfo.value.dock.basic_osd?.sub_device?.device_sn ?? osdVisible.value.sn]
                        ?.mode_code == 14
        ) {
          detailInfo.value = {
            longitude: '--',
@@ -224,61 +240,56 @@
            remain_flight_time: '--',
            height: '--',
            capacity_percent: '--',
          };
                    }
        }
      }
    }
  },
  { immediate: true, deep: true }
);
)
const reduceHeight = (height) => {
  if (!Number(height)) return '--';
  let theFinheight = 0;
const reduceHeight = height => {
    if (!Number(height)) return '--'
    let theFinheight = 0
  if (height < 120) {
    theFinheight = height;
        theFinheight = height
  } else if (height > 220) {
    theFinheight = height - 110;
        theFinheight = height - 110
  } else if (height > 210) {
    theFinheight = height - 100;
        theFinheight = height - 100
  } else if (height > 200) {
    theFinheight = height - 90;
        theFinheight = height - 90
  } else if (height > 190) {
    theFinheight = height - 80;
        theFinheight = height - 80
  } else if (height > 180) {
    theFinheight = height - 70;
        theFinheight = height - 70
  } else if (height > 170) {
    theFinheight = height - 60;
        theFinheight = height - 60
  } else if (height > 160) {
    theFinheight = height - 50;
        theFinheight = height - 50
  } else if (height > 150) {
    theFinheight = height - 40;
        theFinheight = height - 40
  } else if (height > 140) {
    theFinheight = height - 30;
        theFinheight = height - 30
  } else if (height > 130) {
    theFinheight = height - 20;
        theFinheight = height - 20
  } else if (height > 120) {
    theFinheight = height - 10;
        theFinheight = height - 10
  }
  return theFinheight.toFixed(1);
};
    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%
    );
    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;
@@ -301,7 +312,7 @@
          font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
          font-weight: 400;
          font-size: 24px;
          color: #0BE5F5;
                color: #0be5f5;
          line-height: 28px;
          overflow: hidden;          // 添加溢出隐藏
          text-overflow: ellipsis;   // 显示省略号
@@ -310,7 +321,7 @@
        .wz {
          font-family: Source Han Sans CN, Source Han Sans CN;
          font-size: 14px;
          color: #FFFFFF;
                color: #ffffff;
            line-height: 16px;
          .left {
            width: 70px;
@@ -335,24 +346,23 @@
            line-height: 20px;
            background: rgba(255,178,106,0.2);
            border-radius: 4px 4px 4px 4px;
            border: 1px solid #FFB26A;
            color: #FFB26A;
                    border: 1px solid #ffb26a;
                    color: #ffb26a;
            margin-right: 10px;
          }
          .other {
            border: 1px solid #8EFFAC;
            color: #8EFFAC;
                    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;
                    border: 1px solid #ff6a6a;
                    color: #ff6a6a;
          }
        }
      }
    }
    .status {
@@ -375,7 +385,7 @@
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 14px;
        color: #FFFFFF;
            color: #ffffff;
        line-height: 16px;
      }
      .text-data {
@@ -385,7 +395,7 @@
        font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
        font-weight: 400;
        font-size: 18px;
        color: #0BE5F5;
            color: #0be5f5;
        line-height: 21px;
      }
    }