吉安感知网项目-前端
shuishen
2026-02-03 89380e6260a75d1d3b94de687ebcc2f50d50659d
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -160,7 +160,8 @@
               </el-form-item>
               <el-form-item label="关联派出所" prop="policeStationId">
                  <el-select class="command-select" popper-class="command-select-popper"
                     v-model="formData.policeStationId" placeholder="请选择" clearable>
                     v-model="formData.policeStationId" placeholder="请选择" clearable filterable remote
                     :remote-method="handlePoliceStationSearch" :loading="policeStationLoading">
                     <el-option v-for="item in policeStationOptions" :key="item.id" :label="item.stationName"
                        :value="item.id" />
                  </el-select>
@@ -252,13 +253,14 @@
} from '@/utils/cesium/deviceRange'
import * as Cesium from 'cesium'
import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants'
import { fwPoliceStationQueryByPolygonsApi } from '@/views/areaManage/precinctInfo/precinctInfoApi'
import { fwPoliceStationListApi } from '@/views/areaManage/precinctInfo/precinctInfoApi'
import { fwDeviceListByPolygonsApi } from '@/views/basicManage/deviceStock/fwDevice'
import polygonIcon from '@/assets/images/areaMap/polygon.png'
import rectIcon from '@/assets/images/areaMap/rect.png'
import ellipseIcon from '@/assets/images/areaMap/ellipse.png'
import bufferIcon from '@/assets/images/areaMap/buffer.png'
import trashIcon from '@/assets/images/areaMap/trash.png'
import equipmentIcon from '@/assets/images/dataCockpit/map/equipment.png'
const initForm = () => ({
   areaName: '', // 区域名称
@@ -285,6 +287,10 @@
const searchName = ref('')
const selectedDeviceRows = ref([])
const policeStationOptions = ref([]) // 关联派出所
const policeStationAllOptions = ref([])
const policeStationLoading = ref(false)
const policeStationSearchTimer = ref(null)
const policeStationSearchKeyword = ref('')
const deviceOptions = ref([]) // 关联设备
const dictObj = inject('dictObj')
const mapRef = ref(null)
@@ -309,6 +315,7 @@
let viewEntity
let shapeDisplaySource
const deviceRangePrimitiveMap = new Map()
const deviceIconEntityMap = new Map()
const activeToolMode = ref('')
const suppressDeviceFly = ref(false)
const isDialogInitializing = ref(false)
@@ -316,8 +323,6 @@
let deviceRangeRenderToken = 0
let deviceListTimer = null
let deviceListRequestToken = 0
let policeStationListTimer = null
let policeStationRequestToken = 0
const rules = {
   areaName: fieldRules(true, 50),
@@ -424,9 +429,9 @@
            clearTimeout(deviceListTimer)
            deviceListTimer = null
         }
         if (policeStationListTimer) {
            clearTimeout(policeStationListTimer)
            policeStationListTimer = null
         if (policeStationSearchTimer.value) {
            clearTimeout(policeStationSearchTimer.value)
            policeStationSearchTimer.value = null
         }
         viewEntity && viewer?.entities?.remove(viewEntity)
         viewEntity = null
@@ -434,6 +439,7 @@
         hideTypePanel()
         clearShapeDisplay()
         clearDeviceRangePrimitives()
         clearDeviceIconEntities()
      }
   }
)
@@ -448,7 +454,6 @@
   () => {
      if (isDialogInitializing.value) return
      queueDeviceListRefresh()
      queuePoliceStationRefresh()
   },
   { deep: true }
)
@@ -502,18 +507,23 @@
   deviceRangePrimitiveMap.clear()
}
function clearDeviceIconEntities () {
   if (!viewer || !deviceIconEntityMap.size) return
   for (const entity of deviceIconEntityMap.values()) {
      viewer.entities.remove(entity)
   }
   deviceIconEntityMap.clear()
}
function clearDeviceListState () {
   deviceOptions.value = []
   selectedDeviceRows.value = []
   formData.value.deviceIds = ''
   clearDeviceRangePrimitives()
   clearDeviceIconEntities()
   if (deviceTableRef.value) {
      deviceTableRef.value.clearSelection()
   }
}
function clearPoliceStationState () {
   policeStationOptions.value = []
   formData.value.policeStationId = ''
}
function formatWktNumber (value) {
@@ -602,8 +612,10 @@
async function renderDeviceRangeSingle (device) {
   if (!viewer) return
   clearDeviceRangePrimitives()
   clearDeviceIconEntities()
   const position = getDeviceLngLat(device)
   if (!position) return
   addDeviceIconEntity(device, position)
   const rangeMeters = normalizeDeviceRange(device.effectiveRangeKm)
   const primitive = await createDeviceRangePrimitive(viewer, position, rangeMeters)
   if (!primitive) return
@@ -623,6 +635,12 @@
         deviceRangePrimitiveMap.delete(id)
      }
   }
   for (const [id, entity] of deviceIconEntityMap.entries()) {
      if (!nextIds.has(id)) {
         viewer.entities.remove(entity)
         deviceIconEntityMap.delete(id)
      }
   }
   const pendingRows = selectedRows.filter(row => {
      const id = String(row?.id)
      return id && !deviceRangePrimitiveMap.has(id)
@@ -631,14 +649,17 @@
   const primitives = await Promise.all(
      pendingRows.map(async row => {
         const position = getDeviceLngLat(row)
         if (!position) return { row, primitive: null }
         if (!position) return { row, primitive: null, position: null }
         const rangeMeters = normalizeDeviceRange(row.effectiveRangeKm)
         const primitive = await createDeviceRangePrimitive(viewer, position, rangeMeters)
         return { row, primitive }
         return { row, primitive, position }
      })
   )
   if (renderToken !== deviceRangeRenderToken) return
   primitives.forEach(({ row, primitive }) => {
   primitives.forEach(({ row, primitive, position }) => {
      if (position) {
         addDeviceIconEntity(row, position)
      }
      if (!primitive) return
      const id = String(row?.id)
      if (!nextIds.has(id)) return
@@ -668,6 +689,23 @@
function clearShapeDisplay () {
   if (!shapeDisplaySource) return
   shapeDisplaySource.entities.removeAll()
}
function addDeviceIconEntity (device, position) {
   if (!viewer || !position) return
   const id = String(device?.id ?? '')
   if (!id || deviceIconEntityMap.has(id)) return
   const entity = viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(position.lng, position.lat, position.height || 0),
      billboard: {
         image: equipmentIcon,
         width: 28,
         height: 38,
         verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
         heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
      },
   })
   deviceIconEntityMap.set(id, entity)
}
function normalizeShapePoint (point) {
@@ -1203,36 +1241,45 @@
}
// 获取派出所列表
function queuePoliceStationRefresh () {
async function getPoliceStationList (keyword = '') {
   if (!visible.value) return
   if (policeStationListTimer) {
      clearTimeout(policeStationListTimer)
   policeStationLoading.value = true
   try {
      const res = await fwPoliceStationListApi({
         stationName: keyword || undefined,
      })
      const list = res?.data?.data ?? []
      policeStationOptions.value = list
      if (!keyword) {
         policeStationAllOptions.value = list
      }
      await nextTick()
      if (!keyword) {
         const matched = policeStationOptions.value.find(
            item => String(item.id) === String(formData.value.policeStationId)
         )
         if (!matched) {
            formData.value.policeStationId = ''
         }
      }
   } finally {
      policeStationLoading.value = false
   }
   policeStationListTimer = setTimeout(() => {
      policeStationListTimer = null
      void getPoliceStationListByPolygons()
   }, 200)
}
async function getPoliceStationListByPolygons () {
   if (!visible.value) return
   const polygons = resolveShapePolygonsWkt()
   if (!polygons.length) {
      clearPoliceStationState()
function handlePoliceStationSearch (query) {
   policeStationSearchKeyword.value = (query || '').trim()
   if (!policeStationSearchKeyword.value) {
      policeStationOptions.value = [...policeStationAllOptions.value]
      return
   }
   policeStationRequestToken += 1
   const requestToken = policeStationRequestToken
   const res = await fwPoliceStationQueryByPolygonsApi({ polygons })
   if (requestToken !== policeStationRequestToken) return
   policeStationOptions.value = res?.data?.data ?? []
   await nextTick()
   const matched = policeStationOptions.value.find(
      item => String(item.id) === String(formData.value.policeStationId)
   )
   if (!matched) {
      formData.value.policeStationId = ''
   if (policeStationSearchTimer.value) {
      clearTimeout(policeStationSearchTimer.value)
   }
   policeStationSearchTimer.value = setTimeout(() => {
      policeStationSearchTimer.value = null
      void getPoliceStationList(policeStationSearchKeyword.value)
   }, 300)
}
// 获取设备列表
@@ -1337,6 +1384,12 @@
   selectedDeviceRows.value = []
   deviceOptions.value = []
   policeStationOptions.value = []
   policeStationAllOptions.value = []
   policeStationSearchKeyword.value = ''
   if (policeStationSearchTimer.value) {
      clearTimeout(policeStationSearchTimer.value)
      policeStationSearchTimer.value = null
   }
   shapeList.value = []
   activeShapeId.value = null
   activeAreaType.value = ''
@@ -1345,6 +1398,7 @@
   initMap()
   clearShapeDisplay()
   clearDeviceRangePrimitives()
   clearDeviceIconEntities()
   viewEntity && viewer?.entities?.remove(viewEntity)
   viewEntity = null
   clearActiveTool()
@@ -1386,7 +1440,7 @@
   }
   isDialogInitializing.value = false
   queueDeviceListRefresh()
   queuePoliceStationRefresh()
   void getPoliceStationList()
}
onBeforeUnmount(() => {
@@ -1394,9 +1448,9 @@
      clearTimeout(deviceListTimer)
      deviceListTimer = null
   }
   if (policeStationListTimer) {
      clearTimeout(policeStationListTimer)
      policeStationListTimer = null
   if (policeStationSearchTimer.value) {
      clearTimeout(policeStationSearchTimer.value)
      policeStationSearchTimer.value = null
   }
   hideTypePanel()
})