吉安感知网项目-前端
chenyao
2026-01-31 d60b1396df45de76c6bae6aa75c15602dd4c2570
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -266,7 +266,7 @@
const formRef = ref(null) // 表单实例
const formData = ref(initForm()) // 表单数据
const visible = defineModel() // 弹框显隐
const dialogMode = ref('add') // 弹框模式
const dialogMode = ref() // 弹框模式
const submitting = ref(false) // 提交中
const readonly = computed(() => dialogMode.value === 'view')
const route = useRoute()
@@ -301,6 +301,9 @@
let shapeDisplaySource
const deviceRangePrimitiveMap = new Map()
const activeToolMode = ref('')
const suppressDeviceFly = ref(false)
let lastSelectedDeviceIds = []
let deviceRangeRenderToken = 0
const rules = {
   areaName: fieldRules(true, 50),
@@ -482,6 +485,8 @@
async function renderDeviceRanges (rows) {
   if (!viewer) return
   deviceRangeRenderToken += 1
   const renderToken = deviceRangeRenderToken
   const selectedRows = Array.isArray(rows) ? rows : []
   const nextIds = new Set(selectedRows.map(row => String(row?.id)))
   for (const [id, primitive] of deviceRangePrimitiveMap.entries()) {
@@ -504,9 +509,11 @@
         return { row, primitive }
      })
   )
   if (renderToken !== deviceRangeRenderToken) return
   primitives.forEach(({ row, primitive }) => {
      if (!primitive) return
      const id = String(row?.id)
      if (!nextIds.has(id)) return
      deviceRangePrimitiveMap.set(id, primitive)
      viewer.scene.primitives.add(primitive)
   })
@@ -668,6 +675,69 @@
            material: style.outline,
         },
      })
   })
}
function pushRadiusBoundingPoints (positions, center, radius) {
   if (!center || !Number.isFinite(Number(radius)) || radius <= 0) return
   const resolved = resolveLngLatPoint(center) || {}
   const lng = Number(resolved.lng ?? resolved.longitude)
   const lat = Number(resolved.lat ?? resolved.latitude)
   if (!Number.isFinite(lng) || !Number.isFinite(lat)) return
   const baseLat = Cesium.Math.toRadians(lat)
   const earthRadius = Cesium.Ellipsoid.WGS84.maximumRadius
   const deltaLat = radius / earthRadius
   const deltaLng = radius / (earthRadius * Math.max(Math.cos(baseLat), 0.000001))
   const points = [
      { lng: Cesium.Math.toDegrees(Cesium.Math.toRadians(lng) + deltaLng), lat },
      { lng: Cesium.Math.toDegrees(Cesium.Math.toRadians(lng) - deltaLng), lat },
      { lng, lat: Cesium.Math.toDegrees(baseLat + deltaLat) },
      { lng, lat: Cesium.Math.toDegrees(baseLat - deltaLat) },
   ]
   points.forEach(point => {
      positions.push(Cesium.Cartesian3.fromDegrees(point.lng, point.lat, resolved.height || 0))
   })
}
function collectShapeBoundingPositions () {
   const positions = []
   if (!viewer || !shapeList.value.length) return positions
   shapeList.value.forEach(shape => {
      let points = getShapeDisplayPoints(shape)
      if (!Array.isArray(points) || !points.length) {
         points = resolveControlPoints(shape?.meta, shape?.drawType)
      }
      if (Array.isArray(points) && points.length) {
         points.forEach(point => {
            const resolved = resolveLngLatPoint(point)
            const normalized = normalizeShapePoint(resolved)
            if (!normalized) return
            positions.push(Cesium.Cartesian3.fromDegrees(normalized.lng, normalized.lat, normalized.height))
         })
      }
      if (shape?.drawType === 'buffer' && shape?.meta?.center && Array.isArray(shape?.meta?.bufferRadii)) {
         const maxRadius = Math.max(...shape.meta.bufferRadii.filter(item => Number.isFinite(item)))
         pushRadiusBoundingPoints(positions, shape.meta.center, maxRadius)
      }
      if (shape?.drawType === 'ellipse' && shape?.meta?.center) {
         const major = Number(shape?.meta?.semiMajor)
         const minor = Number(shape?.meta?.semiMinor)
         const radius = Number.isFinite(major) && Number.isFinite(minor) ? Math.max(major, minor) : null
         pushRadiusBoundingPoints(positions, shape.meta.center, radius)
      }
   })
   return positions
}
function fitViewToShapeList () {
   if (!viewer || !shapeList.value.length) return
   const positions = collectShapeBoundingPositions()
   if (positions.length < 2) return
   const boundingSphere = Cesium.BoundingSphere.fromPoints(positions)
   const range = Math.max(boundingSphere.radius * 2.4, 200)
   viewer.camera.flyToBoundingSphere(boundingSphere, {
      duration: 0,
      offset: new Cesium.HeadingPitchRange(viewer.camera.heading, Cesium.Math.toRadians(-90), range),
   })
}
@@ -970,6 +1040,7 @@
   if (!viewer) return
   if (shapeList.value.length) {
      renderShapeList()
      fitViewToShapeList()
      return
   }
   if (!formData.value?.geom) return
@@ -1010,9 +1081,15 @@
   const ids = rows.map(item => item.id)
   formData.value.deviceIds = ids.join(',')
   renderDeviceRanges(rows)
   const target = rows[rows.length - 1]
   if (target) {
      void flyToDevice(target)
   if (suppressDeviceFly.value) {
      lastSelectedDeviceIds = [...ids]
      return
   }
   const prevSet = new Set(lastSelectedDeviceIds)
   const addedRow = rows.find(row => !prevSet.has(row.id))
   lastSelectedDeviceIds = [...ids]
   if (addedRow) {
      void flyToDevice(addedRow)
   }
}
@@ -1074,7 +1151,11 @@
      viewPolygon()
   }
   await nextTick()
   suppressDeviceFly.value = true
   syncDeviceSelection()
   lastSelectedDeviceIds = selectedDeviceRows.value.map(row => row.id)
   await nextTick()
   suppressDeviceFly.value = false
   if (!readonly.value) {
      renderDeviceRanges(selectedDeviceRows.value)
   }