无人机管理后台前端(已迁走)
shuishen
2025-09-12 ea6e49ccb4d3bdb510ccf87844490823a96ebf08
src/views/airspace/components/AirspaceMap.vue
@@ -6,7 +6,8 @@
            <avue-form ref="formEle" :option="option" v-model="form"></avue-form>
         </div>
         <div class="map-container">
         <div class="map-container" v-loading="mapLoading" element-loading-text="地形初始化中,请稍后..."
            element-loading-background="rgba(0, 0, 0, 0.7)">
            <div class="tool-tip warning" v-show="isShowWaringTip">
               <span class="icon">
                  <el-icon>
@@ -31,15 +32,33 @@
import * as Cesium from 'cesium'
import * as turf from '@turf/turf'
import { getPointPositionsHeight } from '@/utils/cesium/mapUtil'
import { DrawPolygon } from '@/utils/drawPolygon/drawPolygon'
import { PublicCesium } from '@/utils/cesium/publicCesium'
import { ElMessageBox, ElMessage } from 'element-plus'
import {
   airspaceEnteringAdd,
   airspaceEnteringUpdate
} from '@/api/airspace/airspace'
const props = defineProps({
   title: {
      type: String,
      default: '新增空域',
   },
   type: {
      type: String,
      default: 'add',
   },
   curEditRow: {
      type: Object,
      default: () => { },
   }
})
const emit = defineEmits(['submitClick'])
@@ -47,7 +66,9 @@
const dialogShow = defineModel('show')
const formEle = ref(null)
const form = ref({})
const form = ref({
   height: 120,
})
const option = ref({
   submitBtn: false,
   emptyBtn: false,
@@ -70,23 +91,38 @@
         label: '高度',
         prop: 'height',
         type: 'input',
         value: 120,
         min: 5,
         max: 500,
         type: 'number',
         change ({ column, value }) {
            drawPolygonExample?.setPolygonHeight?.(value)
         },
         rules: [
            {
               required: true,
               message: '请输入高度',
               trigger: 'blur'
            },
            {
               pattern: /^(?:[5-9]|[1-9]\d|[1-4]\d{2}|500)$/, // 5-500
               message: '高度需在5-500之间',
               trigger: ['blur', 'change']
            }
         ]
      },
      {
         label: '类型',
         prop: 'type',
         prop: 'flight_type',
         type: 'select',
         dicUrl: `/blade-system/dict/dictionary?code=flow`,
         dicUrl: `/drone-device-core/airspace/page?current=1&size=10000&typeName=`,
         props: {
            label: 'dictValue',
            value: 'dictKey',
            label: 'type_name',
            value: 'id',
         },
         dicFormatter (res) {
            return res.data.records
         },
         rules: [
            {
@@ -98,7 +134,7 @@
      },
      {
         label: '管控时段',
         prop: 'daterange',
         prop: 'time_period',
         type: 'daterange',
         format: 'YYYY-MM-DD',
         valueFormat: 'YYYY-MM-DD',
@@ -130,11 +166,13 @@
let publicCesiumInstance = null
let viewer = null
// 地图
const mapLoading = ref(true)
const isShowWaringTip = ref(false)
const curDrawPolygonData = ref([])
const initMap = () => {
const initMap = async () => {
   if (!document.getElementById('AirspaceMap')) {
      return
   }
@@ -145,24 +183,36 @@
      layerMode: 4,
      contour: true,
      flyToContour: true,
      terrainInit () {
         setTimeout(async () => {
            initDrawPolygon()
            mapLoading.value = false
         }, 1500)
      }
   })
   viewer = publicCesiumInstance.getViewer()
   drawPolygonExample = new DrawPolygon()
   drawPolygonExample.initHandler(viewer)
   drawPolygonExample?.subscribe('getShowWaringTip', data => {
   drawPolygonExample.subscribe('getShowWaringTip', data => {
      isShowWaringTip.value = data
   })
   drawPolygonExample?.subscribe('getPolygonPositions', data => {
   drawPolygonExample.subscribe('getPolygonPositions', data => {
      curDrawPolygonData.value = data.map(item => {
         let cartographic = Cesium.Cartographic.fromCartesian(item)
         let lng = Cesium.Math.toDegrees(cartographic.longitude) // 经度
         let lat = Cesium.Math.toDegrees(cartographic.latitude) // 纬度
         let height = cartographic.height
         return {
            lng: _.round(lng, 6),
            lat: _.round(lat, 6),
            height
         }
      })
   })
@@ -170,11 +220,32 @@
watch(dialogShow, async (show) => {
   if (show) {
      if (props.type === 'edit') {
         form.value = { ...props.curEditRow }
      }
      initDrawPolygon()
      if (viewer) return
      await nextTick()
      cesiumContextMenu()
      initMap()
   }
})
const initDrawPolygon = async () => {
   if (props.type === 'edit' && drawPolygonExample) {
      drawPolygonExample?.setPolygonHeight?.(props.curEditRow.height)
      let polygon = JSON.parse(props.curEditRow.flight_range)
      if (polygon.length > 0) {
         const aslData = await getPointPositionsHeight(polygon, viewer)
         drawPolygonExample?.initPolygon(viewer, aslData.map(item => ({ ...item, height: item.ASL })))
      }
   }
}
const handleSubmit = () => {
   if (ElMessage.value) {
@@ -201,8 +272,38 @@
            let area = turf.area(polygon)
            emit('submitClick')
            done()
            if (props.type === 'edit') {
               airspaceEnteringUpdate({
                  id: props.curEditRow.id,
                  name: form.value.name,
                  flight_range: JSON.stringify(curDrawPolygonData.value),
                  height: form.value.height,
                  time_period: form.value.time_period.join('~'),
                  flight_type: form.value.flight_type,
                  remark: form.value.remark,
                  area: area
               }).then(res => {
                  ElMessage.success('更新成功')
                  dialogShow.value = false
                  emit('submitClick')
                  done()
               })
            } else {
               airspaceEnteringAdd({
                  name: form.value.name,
                  flight_range: JSON.stringify(curDrawPolygonData.value),
                  height: form.value.height,
                  time_period: form.value.time_period.join('~'),
                  flight_type: form.value.flight_type,
                  remark: form.value.remark,
                  area: area
               }).then(res => {
                  ElMessage.success('新增成功')
                  dialogShow.value = false
                  emit('submitClick')
                  done()
               })
            }
         } else {
            return false
         }
@@ -211,15 +312,12 @@
}
const handleClose = () => {
   drawPolygonExample?.delPolygon()
   isShowWaringTip.value = false
   curDrawPolygonData.value = []
   cesiumContextMenu(false)
   drawPolygonExample?.destroy()
   publicCesiumInstance?.viewerDestroy()
   publicCesiumInstance = null
   viewer = null
   drawPolygonExample = null
   form.value = {}
   form.value = {
      height: 120
   }
   formEle.value.resetForm()
   dialogShow.value = false
}
@@ -239,6 +337,15 @@
      cesium.removeEventListener('contextmenu', preventDefault)
   }
}
onBeforeUnmount(() => {
   drawPolygonExample?.destroy()
   drawPolygonExample = null
   cesiumContextMenu(false)
   publicCesiumInstance?.viewerDestroy()
   publicCesiumInstance = null
   viewer = null
})
</script>
<style scoped lang="scss">