吉安感知网项目-前端
shuishen
2026-01-30 8c450d784fe7bab2b27e3345ef9263e9f295ecaa
applications/drone-command/src/components/map-container/device-map-container.vue
@@ -48,8 +48,10 @@
import * as Cesium from 'cesium'
import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import { geomAnalysis } from '@ztzf/utils'
import { buildEllipsePositions } from '@/utils/cesium/shapeTools'
import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants'
import { fwDefenseZonePageApi } from '@/views/areaManage/defenseZone/defenseZoneApi'
import { fwAreaDividePageApi } from '@/views/areaManage/partition/partitionApi'
import { fwAreaDivideListApi } from '@/views/areaManage/partition/partitionApi'
import { fwDefenseSceneListApi } from '@/views/areaManage/sceneConfig/sceneConfigApi'
import { cockpitAggregationApi } from '@/api/dataCockpit'
import layerControlIcon from '@/assets/images/dataCockpit/layerControl.png'
@@ -791,6 +793,10 @@
   return list.map(item => Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude))
}
const getAreaTypeStyle = areaType => {
   return AREA_TYPE_STYLE_MAP?.[String(areaType)] || DEFAULT_AREA_STYLE
}
const buildZonePrimitives = (zones, lineColor, fillColor1, fillColor2) => {
   if (!viewer) return { primitive: null, outlinePrimitive: null }
   const polygonInstances = []
@@ -849,6 +855,146 @@
   return { primitive, outlinePrimitive }
}
const buildPartitionPrimitives = shapes => {
   if (!viewer) return { primitive: null, outlinePrimitive: null }
   const polygonInstances = []
   const lineInstances = []
   const vertexFormat = Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
      ; (shapes || []).forEach(shape => {
         if (!shape?.positions || shape.positions.length < 3) return
         const positions = shape.positions
         const polygon = new Cesium.PolygonGeometry({
            polygonHierarchy: new Cesium.PolygonHierarchy(positions),
            vertexFormat,
         })
         polygonInstances.push(
            new Cesium.GeometryInstance({
               geometry: polygon,
               attributes: {
                  color: Cesium.ColorGeometryInstanceAttribute.fromColor(shape.fillColor),
               },
            })
         )
         const linePositions = positions.length > 1 ? [...positions, positions[0]] : positions
         lineInstances.push(
            new Cesium.GeometryInstance({
               geometry: new Cesium.GroundPolylineGeometry({
                  positions: linePositions,
                  width: 2,
               }),
               attributes: {
                  color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                     shape.outlineColor
                  ),
               },
            })
         )
      })
   let primitive = null
   if (polygonInstances.length) {
      primitive = new Cesium.GroundPrimitive({
         geometryInstances: polygonInstances,
         appearance: new Cesium.PerInstanceColorAppearance({ translucent: true, flat: true }),
      })
      addCockpitPrimitive(primitive)
   }
   let outlinePrimitive = null
   if (lineInstances.length) {
      outlinePrimitive = new Cesium.GroundPolylinePrimitive({
         geometryInstances: lineInstances,
         appearance: new Cesium.PolylineColorAppearance(),
      })
      addCockpitPrimitive(outlinePrimitive)
   }
   return { primitive, outlinePrimitive }
}
const parseGeomJson = geomJson => {
   if (!geomJson) return null
   if (typeof geomJson === 'object') return geomJson
   if (typeof geomJson !== 'string') return null
   const trimmed = geomJson.trim()
   if (!trimmed) return null
   try {
      return JSON.parse(trimmed)
   } catch (error) {}
   return null
}
const normalizeShapePoint = point => {
   if (!point) return null
   const lng = point?.lng ?? point?.longitude
   const lat = point?.lat ?? point?.latitude
   const height = Number.isFinite(Number(point?.height)) ? Number(point.height) : 0
   if (!Number.isFinite(Number(lng)) || !Number.isFinite(Number(lat))) return null
   return { lng: Number(lng), lat: Number(lat), height }
}
const buildShapePositions = (points = []) => {
   const normalized = points.map(normalizeShapePoint).filter(Boolean)
   return normalized.map(point => Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height))
}
const getShapeDisplayPoints = shape => {
   if (Array.isArray(shape?.displayPoints) && shape.displayPoints.length) {
      return shape.displayPoints
   }
   return shape?.points || []
}
const resolvePartitionShapes = areas => {
   const shapes = []
      ; (areas || []).forEach(area => {
         const extList = Array.isArray(area?.fwAreaDivideExtList) ? area.fwAreaDivideExtList : []
         extList.forEach((item, index) => {
            const isShapePayload = item?.drawType || item?.points
            const parsed = isShapePayload ? item : parseGeomJson(item?.geomJson)
            if (!parsed) return
            const shape = {
               id: parsed?.id || `shape_${Date.now()}_${index}_${Math.random().toString(16).slice(2, 6)}`,
               drawType: parsed?.drawType ?? 'polygon',
               areaType: parsed?.areaType ?? item?.areaTypeKey ?? item?.areaType ?? '',
               points: Array.isArray(parsed?.points) ? parsed.points : [],
               displayPoints: Array.isArray(parsed?.displayPoints) ? parsed.displayPoints : null,
               meta: parsed?.meta ?? null,
            }
            if (shape.drawType === 'buffer' && shape.meta?.bufferRadii?.length && shape.meta?.center) {
               const center = shape.meta.center
               const centerCartesian = Cesium.Cartesian3.fromDegrees(
                  center.lng,
                  center.lat,
                  center.height || 0
               )
               const radii = shape.meta.bufferRadii
                  .map(radius => Number(radius))
                  .filter(radius => Number.isFinite(radius) && radius > 0)
               radii.forEach((radius, levelIndex) => {
                  const positions = buildEllipsePositions(centerCartesian, radius, radius)
               const style = BUFFER_LEVEL_STYLES[levelIndex] || BUFFER_LEVEL_STYLES[BUFFER_LEVEL_STYLES.length - 1]
                  if (positions.length >= 3) {
                     shapes.push({
                        positions,
                        fillColor: style.fill,
                        outlineColor: style.outline,
                     })
                  }
               })
               return
            }
            const positions = buildShapePositions(getShapeDisplayPoints(shape))
            if (positions.length >= 3) {
               const style = getAreaTypeStyle(shape.areaType)
               shapes.push({
                  positions,
                  fillColor: style.fill,
                  outlineColor: style.outline,
               })
            }
         })
      })
   return shapes
}
const renderDefenseZones = zones => {
   if (!viewer) return
   clearDefenseZoneEntities()
@@ -863,7 +1009,8 @@
const renderPartitions = zones => {
   if (!viewer) return
   clearPartitionEntities()
   const result = buildZonePrimitives(zones, '#FFD772', '#FFD772', '#A86B00')
   const shapes = resolvePartitionShapes(zones)
   const result = buildPartitionPrimitives(shapes)
   partitionPrimitive = result.primitive
   partitionOutlinePrimitive = result.outlinePrimitive
   if (partitionPrimitive) partitionPrimitive.show = detailVisible.value
@@ -884,8 +1031,8 @@
const loadPartitions = async () => {
   if (!viewer) return
   try {
      const res = await fwAreaDividePageApi({ current: 1, size: DEFAULT_ZONE_PAGE_SIZE })
      renderPartitions(res?.data?.data?.records ?? [])
      const res = await fwAreaDivideListApi()
      renderPartitions(res?.data?.data ?? [])
   } catch (error) {
      renderPartitions([])
   }