吉安感知网项目-前端
张含笑
2026-01-27 9e0f0ee575c7b490e768af0188a494eec7944492
applications/drone-command/src/components/map-container/device-map-container.vue
@@ -39,7 +39,7 @@
         @close="closePopup" />
      <DronePopup :visible="popupVisible && isDronePopup" :position="popupPosition" :drone="selectedDevice"
         :favorite="Boolean(selectedDevice?.isFavorite)" @close="closePopup" @toggle-favorite="toggleDroneFavorite"
         :favorite="Boolean(selectedDevice?.isFavorite)" @close="closePopup" @toggle-favorite="handleDroneFavorite"
         @signal="handleDroneSignal" @counter="handleDroneCounter" />
   </div>
</template>
@@ -78,6 +78,10 @@
      type: Array,
      default: () => [],
   },
   alarmDrones: {
      type: Array,
      default: () => [],
   },
   leftCollapsed: {
      type: Boolean,
      default: false,
@@ -91,7 +95,7 @@
      default: true,
   },
})
const emit = defineEmits(['droneSignal', 'droneCounter'])
const emit = defineEmits(['droneSignal', 'droneCounter', 'droneFavorite'])
const DEFAULT_ZONE_PAGE_SIZE = 999
@@ -363,44 +367,86 @@
   })
}
const buildSimulatedTrackPoints = () => {
   return [
      {
         longitude: 114.963191,
         latitude: 27.136716,
         height: 120
      },
      {
         longitude: 114.957308,
         latitude: 27.138452,
         height: 120
      },
      {
         longitude: 114.952,
         latitude: 27.136317,
         height: 120
      },
      {
         longitude: 114.949293,
         latitude: 27.133864,
         height: 120
      },
      {
         longitude: 114.944666,
         latitude: 27.130526,
         height: 120
      },
      {
         longitude: 114.945909,
         latitude: 27.127845,
         height: 120
      },
      {
         longitude: 114.962974,
         latitude: 27.136242,
         height: 120
      },
const buildSimulatedTrackPoints = center => {
   const basePoints = [
      [
         {
            longitude: 114.963191,
            latitude: 27.136716,
            height: 120
         },
         {
            longitude: 114.957308,
            latitude: 27.138452,
            height: 120
         },
         {
            longitude: 114.952,
            latitude: 27.136317,
            height: 120
         },
         {
            longitude: 114.949293,
            latitude: 27.133864,
            height: 120
         },
         {
            longitude: 114.944666,
            latitude: 27.130526,
            height: 120
         },
         {
            longitude: 114.945909,
            latitude: 27.127845,
            height: 120
         },
         {
            longitude: 114.962974,
            latitude: 27.136242,
            height: 120
         },
      ],
      [
         {
            longitude: 114.931063,
            latitude: 27.095052,
            height: 120
         },
         {
            longitude: 114.928653,
            latitude: 27.096307,
            height: 120
         },
         {
            longitude: 114.925958,
            latitude: 27.096963,
            height: 120
         },
         {
            longitude: 114.925836,
            latitude: 27.096102,
            height: 120
         },
         {
            longitude: 114.928384,
            latitude: 27.095866,
            height: 120
         },
         {
            longitude: 114.929874,
            latitude: 27.096095,
            height: 120
         },
         {
            longitude: 114.931048,
            latitude: 27.097666,
            height: 120
         },
      ]
   ]
   return basePoints[center.trackIndex]
}
@@ -486,70 +532,67 @@
   droneTrackTickHandler = null
}
const renderSimulatedDroneTrack = () => {
const renderSimulatedDroneTrack = (list) => {
   if (!viewer) return
   clearDroneTrackEntities()
   if (!list?.length) return
   ensureDroneTrackCollections()
   droneTrackBillboardCollection.show = detailVisible.value
   droneTrackPolylineCollection.show = detailVisible.value
   droneTrackRuntime = []
   const baseCenters = [['默认区域', { longitude: 114.958541, latitude: 27.121917 }]]
   const segmentDuration = 6
   const baseTrackColor = Cesium.Color.fromCssColorString('red')
   baseCenters.forEach(([centerName, center], trackIndex) => {
      const points = buildSimulatedTrackPoints(center)
      if (points.length < 2) return
      const positions = points.map(point =>
         Cesium.Cartesian3.fromDegrees(point.longitude, point.latitude, point.height)
      )
      let trackMaterial = createDroneTrackMaterial({
         color: baseTrackColor,
         speed: 4.5,
         headWidth: 0.2,
         glowPower: 1.8,
         backgroundAlpha: 0.34,
      ; (list || []).forEach((item, trackIndex) => {
         const position = getDevicePosition(item)
         if (!position) return
         const points = buildSimulatedTrackPoints({ ...position, height: item.flightHeightM, trackIndex })
         if (points.length < 2) return
         const positions = points.map(point =>
            Cesium.Cartesian3.fromDegrees(point.longitude, point.latitude, point.height)
         )
         let trackMaterial = createDroneTrackMaterial({
            color: baseTrackColor,
            speed: 4.5,
            headWidth: 0.2,
            glowPower: 1.8,
            backgroundAlpha: 0.34,
         })
         if (!trackMaterial) {
            trackMaterial = Cesium.Material.fromType('Color', { color: baseTrackColor })
         }
         droneTrackPolylineCollection.add({
            positions,
            width: 3,
            material: trackMaterial,
         })
         const droneId = `drone-alarm-${item?.alarmRecordId ?? item?.id ?? trackIndex}`
         const billboard = droneTrackBillboardCollection.add({
            position: positions[positions.length - 1],
            image: droneIcon,
            width: 36,
            height: 36,
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
         })
         billboard.id = droneId
         const speedMs = Math.round(Cesium.Cartesian3.distance(positions[0], positions[1]) / segmentDuration)
         dronePickMap.set(droneId, {
            data: {
               ...item,
               flightHeightM: item.flightHeightM ?? points[0].height,
               flightSpeedMs: item.flightSpeedMs ?? speedMs,
               longitude: item.longitude ?? points[0].longitude,
               latitude: item.latitude ?? points[0].latitude,
            },
            billboard,
         })
         droneTrackRuntime.push({
            positions,
            billboard,
            segmentDuration,
            duration: (points.length - 1) * segmentDuration,
         })
      })
      if (!trackMaterial) {
         trackMaterial = Cesium.Material.fromType('Color', { color: baseTrackColor })
      }
      droneTrackPolylineCollection.add({
         positions,
         width: 3,
         material: trackMaterial,
      })
      const droneId = `drone-track-${trackIndex}`
      const billboard = droneTrackBillboardCollection.add({
         position: positions[positions.length - 1],
         image: droneIcon,
         width: 36,
         height: 36,
         verticalOrigin: Cesium.VerticalOrigin.CENTER,
         disableDepthTestDistance: Number.POSITIVE_INFINITY,
      })
      billboard.id = droneId
      const speedMs = Math.round(Cesium.Cartesian3.distance(positions[0], positions[1]) / segmentDuration)
      dronePickMap.set(droneId, {
         data: {
            droneName: `无人机-${trackIndex + 1}`,
            droneSerialNo: `UAV-${trackIndex + 1}`,
            flightHeightM: points[0].height,
            flightSpeedMs: speedMs,
            longitude: points[0].longitude,
            latitude: points[0].latitude,
            flightStatus: 1,
            deviceName: centerName,
            dataSource: centerName,
            counterDeviceName: centerName,
         },
         billboard,
      })
      droneTrackRuntime.push({
         positions,
         billboard,
         segmentDuration,
         duration: (points.length - 1) * segmentDuration,
      })
   })
   viewer.clock.multiplier = 1
   startDroneTrackAnimation()
   reorderCockpitPrimitives()
@@ -860,9 +903,9 @@
const popupPosition = ref({ x: 0, y: 0 })
const popupVisible = computed(() => Boolean(selectedDevice.value))
const isDronePopup = computed(() => selectedTargetType.value === 'drone')
const toggleDroneFavorite = () => {
const handleDroneFavorite = () => {
   if (!selectedDevice.value) return
   selectedDevice.value.isFavorite = !selectedDevice.value.isFavorite
   emit('droneFavorite', selectedDevice.value)
}
const handleDroneSignal = () => emit('droneSignal', selectedDevice.value)
const handleDroneCounter = () => emit('droneCounter', selectedDevice.value)
@@ -911,6 +954,19 @@
   () => props.onlineDevices,
   devices => {
      renderDeviceEntities(devices || [])
   },
   { deep: true }
)
watch(
   () => props.alarmDrones,
   list => {
      renderSimulatedDroneTrack(list || [])
      if (selectedTargetType.value === 'drone' && selectedDevice.value) {
         const selectedId = selectedDevice.value.alarmRecordId ?? selectedDevice.value.id
         const match = (list || []).find(item => (item?.alarmRecordId ?? item?.id) === selectedId)
         if (match) selectedDevice.value = { ...selectedDevice.value, ...match }
      }
   },
   { deep: true }
)
@@ -970,7 +1026,7 @@
   loadPartitions()
   loadAggregation()
   loadCommandPosts()
   renderSimulatedDroneTrack()
   renderSimulatedDroneTrack(props.alarmDrones)
   initDeviceClickHandler()
}