gr 1 месяц назад
Родитель
Сommit
f5368613eb

+ 1 - 1
src/assets/styles/element.scss

@@ -266,4 +266,4 @@
   .el-input__inner {
     font-size: 16px;
   }
-}
+}

+ 24 - 0
src/service/http.js

@@ -231,6 +231,14 @@ export function GetAreaList() {
     })
 }
 
+// 新增空域
+export function AddArea(data) {
+    return requestNetPost({
+        url: '/pg/airSpace/add',
+        data
+    })
+}
+
 // 航线列表
 export function GetRouteList() {
     return requestNetPost({
@@ -250,3 +258,19 @@ export function GetPlotList() {
         }
     })
 }
+
+// 新增起降场
+export function AddPlot(data) {
+    return requestNetPost({
+        url: '/pg/airPort/add',
+        data
+    })
+}
+
+// 行政区划
+export function GetDistrictTree() {
+    return requestNetPost({
+        method: 'get',
+        url: '/area/info/tree',
+    })
+}

+ 12 - 2
src/utils/map/addLayer.js

@@ -1115,7 +1115,7 @@ export function drawLayering(params) {
         "symbol": {
           "height": heightArr[0],
           "size": heightArr[1] - heightArr[0],
-          "color": params.id.startsWith('big') ? [255, 0, 255, 0.2] : [0, 255, 0, 0.2]
+          "color": params.color
         },
         "geometry": {
           rings: params.rings.map(s => {
@@ -1160,4 +1160,14 @@ export function QueryCube(params) {
     rings: params.rings,
     token: "",
   })
-}
+}
+
+// 查询行政区划
+export function QueryDistrict(districtArr) {
+  const type = districtArr.length===1? "区县": "街道"
+  invokeParams('QueryIn2D', {
+    type,
+    where: `${type}名称='${districtArr.at(-1)}'`,
+    token: ""
+  })
+}

+ 13 - 15
src/utils/options.js

@@ -4,12 +4,15 @@ export const areaList = [
   { label: '净空区', color: '#FF0000' },
   { label: '起降场', color: '#00FF00' },
   { label: '航线', color: '#0000FF' },
+]
 
-  // { label: '禁飞区', value: '1', color: '#FF0000' },
-  // { label: '净空区', value: '2', color: '#FF0000' },
-  // { label: '适飞区', value: '3', color: '#FF0000' },
-  // { label: '管制区', value: '4', color: '#FF0000' },
-  // { label: '临时管制区', value: '5', color: '#FF0000' },
+// 空域类型
+export const airSpaceTypes = [
+  { label: '禁飞区', value: '1', color: '#FF0000' },
+  { label: '净空区', value: '2', color: '#0000FF' },
+  { label: '适飞区', value: '3', color: '#00FF00' },
+  { label: '管制区', value: '4', color: '#FF5500' },
+  { label: '临时管制区', value: '5', color: '#FFFF00' },
 ]
 
 export const areaUseList = [
@@ -18,14 +21,9 @@ export const areaUseList = [
 ]
 
 export const uavList = [
-  { id:"1",label: '微型无人机', checked: false },
-  { id:"2",label: '轻型无人机', checked: false },
-  { id:"3",label: '小型无人机', checked: false },
-  { id:"4",label: '中型无人机', checked: false },
-  { id:"5",label: '大型无人机', checked: false },
+  { label: '微型无人机', value: '01' },
+  { label: '轻型无人机', value: '02' },
+  { label: '小型无人机', value: '03' },
+  { label: '中型无人机', value: '04' },
+  { label: '大型无人机', value: '05' },
 ]
-
-// 行政区划
-export const districtList = [
-
-]

+ 71 - 23
src/views/home/cpns/FloatPanelFcky.vue

@@ -6,16 +6,14 @@
 
       <el-form v-model="form" class="form-top mt-3" label-position="left">
         <el-form-item label="分层范围" prop="rangeType">
-          <el-radio-group v-model="form.rangeType">
+          <el-radio-group v-model="form.rangeType" @change="handleRangeChange">
             <el-radio label="行政区划" value="行政区划" />
             <el-radio label="自定义绘制" value="自定义绘制" />
           </el-radio-group>
         </el-form-item>
         <el-form-item label="绘制/选择" prop="range">
           <el-button v-if="form.rangeType === '自定义绘制'" @click="handleDraw" class="btn-secondary small">绘制</el-button>
-          <el-select v-else v-model="form.range" placeholder="">
-            <el-option v-for="item in districtList" :label="item.label" :value="item.label" />
-          </el-select>
+          <el-cascader v-else v-model="form.range" @change="handleSelectDistrict" :options="districtList" :props="cascaderProps" class="w-full" />
         </el-form-item>
         <el-form-item label="分层方式" prop="layeringType">
           <el-radio-group v-model="form.layeringType">
@@ -59,9 +57,9 @@
 <script setup>
 import { computed, onBeforeUnmount, ref, watch } from 'vue';
 import useLayoutStore from '@/store/layout';
-import { districtList } from '@/utils/options';
-import { DrawPolygon, clearLayering, drawLayering, clearDraw } from '@/utils/map/addLayer'
+import { DrawPolygon, clearLayering, drawLayering, clearDraw, QueryDistrict } from '@/utils/map/addLayer'
 import { useMapStore } from '@/store/map';
+import { GetDistrictTree } from '@/service/http';
 
 const layoutStore = useLayoutStore()
 const mapStore = useMapStore()
@@ -73,19 +71,60 @@ const form = ref({
   layersSmall: [],
 })
 
+const colorArr = [
+  [255,0,255,0.2],
+  [255,255,0,0.2],
+  [0,255,0,0.2],
+]
+
 function handleDraw() {
+  clearAll()
   DrawPolygon()
 }
 
-watch(form, () => {
+function handleSelectDistrict(val) {
+  clearAll()
+  QueryDistrict(val)
+}
+
+function handleRangeChange() {
+  clearAll()
+}
+
+const districtList = ref([])
+
+const cascaderProps = {
+  expandTrigger: 'hover',
+  checkStrictly: true
+}
+
+watch(form, (val) => {
+  if (val.rangeType === '行政区划' && !districtList.value.length) {
+    GetDistrictTree().then(res => {
+      if (!Array.isArray(res.data)) {
+        ElMessage({ offset: 90, type: 'warning', message: '行政区划获取失败' })
+        return
+      }
+      districtList.value = res.data
+    }).catch(() => {
+      ElMessage({ offset: 90, type: 'warning', message: '行政区划获取失败' })
+    })
+  }
   handleLayering()
 }, { deep: true })
 
 let drawResult
+let queryResult
 
 watch(() => mapStore.draw_geometry, (val) => {
-  drawResult = val?.rings
-  // console.log('drawResult', val)
+  drawResult = val.rings
+  console.log('drawResult', val)
+  handleLayering()
+}, { deep: true })
+
+watch(() => mapStore.queryResult, (val) => {
+  queryResult = val[0].geometry.rings
+  console.log('queryResult', val)
   handleLayering()
 }, { deep: true })
 
@@ -98,12 +137,13 @@ function handleLayering() {
   }
   timer_handleLayering = setTimeout(() => {
     const { layeringType, layersBig, layersSmall, rangeType, range } = form.value
-    if (rangeType === '自定义绘制' && !drawResult) return
-    if (rangeType === '行政区划' && !range) return
+    const rings = rangeType === '自定义绘制'? drawResult: queryResult
+    if(!rings) return
     console.log('start draw')
+    console.log('range', range)
 
     if (layeringType === '广域分层') {
-      if (rangeType === '自定义绘制') {
+      // if (rangeType === '自定义绘制') {
         layersListSmall.value.forEach(i => {
           if (lastSmallLayers.includes(i.value)) {
             clearLayering(i.id)
@@ -115,17 +155,21 @@ function handleLayering() {
             drawLayering({
               id: i.id,
               height: i.value,
-              rings: drawResult
+              rings,
+              color: i.color
             })
           } else if (!layersBig.includes(i.value) && lastBigLayers.includes(i.value)) {
             clearLayering(i.id)
           }
         })
         lastBigLayers = JSON.parse(JSON.stringify(layersBig))
-      }
+
+      // } else {
+        
+      // }
     } else {
       // 细微分层
-      if (rangeType === '自定义绘制') {
+      // if (rangeType === '自定义绘制') {
         layersListBig.forEach(i => {
           if (lastBigLayers.includes(i.value)) {
             clearLayering(i.id)
@@ -137,23 +181,24 @@ function handleLayering() {
             drawLayering({
               id: i.id,
               height: i.value,
-              rings: drawResult
+              rings,
+              color: i.color
             })
           } else if (!layersSmall.includes(i.value) && lastSmallLayers.includes(i.value)) {
             clearLayering(i.id)
           }
         })
         lastSmallLayers = JSON.parse(JSON.stringify(layersSmall))
-      }
+      // }
     }
 
   }, 1000);
 }
 
 const layersListBig = [
-  { label: '120以下', id: 'big_1', value: '0,120' },
-  { label: '120-300', id: 'big_2', value: '120,300' },
-  { label: '300-600', id: 'big_3', value: '300,600' },
+  { label: '120以下', id: 'big_1', value: '0,120', color: colorArr[0] },
+  { label: '120-300', id: 'big_2', value: '120,300', color: colorArr[1] },
+  { label: '300-600', id: 'big_3', value: '300,600', color: colorArr[2] },
 ]
 
 const layersListSmall = computed(() => {
@@ -165,7 +210,8 @@ const layersListSmall = computed(() => {
     res.push({
       label: `${last}-${end}`,
       value: `${last},${end}`,
-      id: `small_${i + 1}`
+      id: `small_${i + 1}`,
+      color: i<6? colorArr[0]: i>14? colorArr[2]: colorArr[1]
     })
     last = end
   }
@@ -173,12 +219,14 @@ const layersListSmall = computed(() => {
 })
 
 function clearAll() {
-  const currentList = form.value.layeringType === '广域分层' ? layersListBig: layersListSmall.value
+  const currentList = form.value.layeringType === '广域分层' ? layersListBig : layersListSmall.value
   currentList.forEach(i => {
-    if([...lastBigLayers, ...lastSmallLayers].includes(i.value)) {
+    if ([...lastBigLayers, ...lastSmallLayers].includes(i.value)) {
       clearLayering(i.id)
     }
   })
+  lastBigLayers = []
+  lastSmallLayers = []
   clearDraw()
 }
 

+ 95 - 32
src/views/home/cpns/PanelKyhs.vue

@@ -10,13 +10,13 @@
     <div class="flex-1 relative mb-4">
       <Transition name="emerge-left">
         <el-form ref="formRef" v-show="currentStep === 0" :model="form" :rules="rules" label-position="left"
-          size="large" class="p-form p-main">
+          size="large" class="p-form p-main" hide-required-asterisk>
           <el-form-item label="名称" prop="name">
             <el-input v-model="form.name" clearable></el-input>
           </el-form-item>
           <el-form-item label="类型" prop="areaType">
             <el-select v-model="form.areaType" placeholder="">
-              <el-option v-for="item in areaList" :label="item.label" :value="item.label" />
+              <el-option v-for="item in airSpaceTypes" :label="item.label" :value="item.value" />
             </el-select>
           </el-form-item>
           <el-form-item label="类型" prop="type">
@@ -49,11 +49,7 @@
           </template>
           <el-form-item label="类型" prop="drawType" v-if="form.dataType === '手动划设'">
             <el-radio-group v-model="form.drawType" size="large" class="content-between h-24">
-              <el-radio-button label="矩形" value="rectangle" />
-              <el-radio-button label="圆台" value="mesh" />
-              <el-radio-button label="圆锥" value="point" />
-              <el-radio-button label="圆柱" value="circle" />
-              <el-radio-button label="多面体" value="polygon" />
+              <el-radio-button v-for="item in drawTypes" :label="item.label" :value="item.value" />
             </el-radio-group>
           </el-form-item>
           <el-form-item label="上传文件" prop="file" v-else>
@@ -120,20 +116,16 @@
               </tbody>
             </table>
           </div>
-
-
         </div>
       </Transition>
     </div>
-
-
     <div class="text-center">
       <template v-if="currentStep === 0">
         <el-button :disabled="!hasDraw" class="btn-main" @click="toNext">下一步</el-button>
       </template>
       <template v-if="currentStep === 1">
         <el-button class="btn-main" @click="toPrev">上一步</el-button>
-        <el-button class="btn-main" @click="handleSave">保存</el-button>
+        <el-button class="btn-main" @click="handleSave" :loading="loading.save">保存</el-button>
       </template>
     </div>
 
@@ -141,29 +133,42 @@
 </template>
 
 <script setup>
-import { onBeforeUnmount, ref, watch } from 'vue';
+import { onBeforeUnmount, reactive, ref, watch } from 'vue';
 import { drawArea, clearDraw } from '@/utils/map/addLayer'
-import { areaList } from '@/utils/options';
+import { airSpaceTypes } from '@/utils/options';
 import { hexToRgb } from '@/utils/tools';
 import { useMapStore } from '@/store/map';
+import { AddArea } from '@/service/http';
 
 const mapStore = useMapStore()
 
 const currentStep = ref(0)
 
 const form = ref({
-  areaType: '适飞区',
+  areaType: '1',
   dataType: '手动划设',
   type: '长期',
-  drawType: 'rectangle'
+  drawType: 'rectangle',
+  height: '100',
+  topRadius: '150',
+  bottomRadius: '50'
 })
 
-const rules = [
+const rules = {
+  name: [{ required: true, message: '请输入空域名称', trigger: 'none' }],
+  height: [{ required: true, message: '此项不可为空', trigger: 'none' }],
+  topRadius: [{ required: true, message: '此项不可为空', trigger: 'none' }],
+  bottomRadius: [{ required: true, message: '此项不可为空', trigger: 'none' }],
+}
 
+const drawTypes = [
+  { label: '矩形', value: 'rectangle', geoType: '2' },
+  { label: '圆柱', value: 'circle', geoType: '1' },
+  { label: '多面体', value: 'polygon', geoType: '3' },
+  { label: '圆台', value: 'mesh', geoType: '6' },
+  { label: '圆锥', value: 'point', geoType: '4' },
 ]
 
-const formRef = ref(null)
-
 const results = ref([
   {
     title: '空域评估',
@@ -206,25 +211,34 @@ const results = ref([
 
 const hasDraw = ref(false)
 
-async function handleDraw() {
-  if (hasDraw.value) {
-    clearDraw()
-    await new Promise((res) => {
-      setTimeout(() => res(), 500);
+function handleDraw() {
+  formRef.value.validateField(['height', 'topRadius', 'bottomRadius'], async (isValid) => {
+    if (!isValid) return
+    if (hasDraw.value) {
+      clearDraw()
+      await new Promise((res) => {
+        setTimeout(() => res(), 500);
+      })
+    }
+    // 处理绘制
+    const color = hexToRgb(airSpaceTypes.find(i => i.value === form.value.areaType).color, 0.5)
+    drawArea({
+      ...form.value,
+      color
     })
-  }
-  // 处理绘制
-  const color = hexToRgb(areaList.find(i => i.label === form.value.areaType).color, 0.5)
-  drawArea({
-    ...form.value,
-    color
   })
 }
 
-watch(() => mapStore.draw_geometry, () => {
+let drawGeometry
+
+watch(() => mapStore.draw_geometry, (val) => {
+  console.log('draw_geometry:', val)
+  drawGeometry = val
   hasDraw.value = true
 }, { deep: true })
 
+const formRef = ref(null)
+
 function toNext() {
   formRef.value.validate(valid => {
     if (valid) {
@@ -237,8 +251,57 @@ function toPrev() {
   currentStep.value = 0
 }
 
-function handleSave() {
+const loading = reactive({
+  save: false
+})
 
+function handleSave() {
+  loading.save = true
+  let params = {
+    ...form.value,
+    spaceType: form.value.areaType,
+    geoType: drawTypes.find(i => i.value === form.value.drawType).geoType,
+    upRadius: form.value.topRadius,
+    downRadius: form.value.bottomRadius,
+    shape: ''
+  }
+  const { x, y, z } = drawGeometry
+  switch (params.geoType) {
+    case '1':
+    case '2':
+    case '3':
+      params.shape = JSON.stringify({
+        height: params.height,
+        rings: drawGeometry.rings
+      })
+      break;
+    case '4':
+      params.shape = JSON.stringify({
+        point: { x, y, z },
+        height: params.height,
+        radius: params.upRadius
+      })
+      break;
+    case '6':
+      params.shape = JSON.stringify({
+        point: { x, y, z },
+        height: params.height,
+        topRadius: params.upRadius,
+        bottomRadius: params.downRadius
+      })
+      break;
+  }
+  AddArea(params).then(({data: res}) => {
+    if(res.msg==='success') {
+      ElMessage({ offset: 90, type: 'success', message: '保存成功' })
+    } else {
+      ElMessage({ offset: 90, type: 'error', message: `保存失败,${res.msg}` })
+    }
+  }).catch((e) => {
+    ElMessage({ offset: 90, type: 'error', message: `保存失败,${e}` })
+  }).finally(() => {
+    loading.save = false
+  })
 }
 
 onBeforeUnmount(() => {

+ 46 - 25
src/views/home/cpns/PanelKypm.vue

@@ -6,12 +6,12 @@
     <el-form ref="formRef" class="p-form mt-7" :model="form" :rules="rules" label-position="left" size="large">
       <el-form-item label="计算层级" prop="level">
         <el-select v-model="form.level" placeholder="">
-          <el-option label="23级" value="23" />
+          <el-option label="23级" value="23" />
         </el-select>
       </el-form-item>
       <el-form-item label="高度" prop="height">
         <el-input v-model="form.height" type="number" class="flex-1"></el-input>
-        <el-button class="btn-secondary ml-3 -mb-1">绘制剖面</el-button>
+        <el-button class="btn-secondary ml-3 -mb-1" @click="handleDraw">绘制剖面</el-button>
       </el-form-item>
       <el-form-item label="评价系数">
         <el-checkbox v-model="form.evaluation">展示</el-checkbox>
@@ -30,9 +30,9 @@
       <tbody style="max-height: 580px;">
         <tr v-for="(row, index) in tableData">
           <td class="w-16">{{ index + 1 }}</td>
-          <td>{{ row.lon }}</td>
-          <td>{{ row.lat }}</td>
-          <td class="w-24">{{ row.altitude }}</td>
+          <td>{{ row[0] }}</td>
+          <td>{{ row[1] }}</td>
+          <td class="w-24">{{ row[2] }}</td>
         </tr>
       </tbody>
     </table>
@@ -45,39 +45,60 @@
 </template>
 
 <script setup>
-import { ref } from 'vue';
+import { onBeforeUnmount, ref, watch } from 'vue';
+import { DrawPolygon, QueryCube, clearDraw } from '@/utils/map/addLayer'
+import { useMapStore } from '@/store/map';
+
+const mapStore = useMapStore()
 
 const form = ref({
-  level: '23级',
+  level: '23',
   height: '50',
+  evaluation: false
 })
 
 const rules = []
 
-const tableData = ref([
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-  { lon: '121.22345', lat: '31.21456', altitude: '0-200' },
-])
+function handleDraw() {
+  DrawPolygon({ hasZ: true })
+}
+
+let drawResult = []
+const tableData = ref([])
 
-function handleClear() {
+watch(() => mapStore.draw_geometry, (val) => {
+  drawResult = val?.rings
+  tableData.value = drawResult.flat()
+}, { deep: true })
 
+function handleClear(clearAll) {
+  if(clearAll) {
+    clearDraw()
+  }
+  QueryCube({
+    show: false,
+  })
 }
 
 function handleCalc() {
-
+  if (!drawResult) return
+  if (!form.value.height) return
+  handleClear()
+  setTimeout(() => {
+    QueryCube({
+      ...form.value,
+      minZ: Number(form.value.height) - 0.01,
+      maxZ: Number(form.value.height) + 0.01,
+      show: true,
+      rings: drawResult
+    })
+  }, 300);
 }
 
+onBeforeUnmount(() => {
+  handleClear(true)
+})
+
 </script>
 
 <style lang="scss" scoped>
@@ -86,4 +107,4 @@ function handleCalc() {
     width: 105px;
   }
 }
-</style>
+</style>

+ 96 - 30
src/views/home/cpns/PanelQjchs.vue

@@ -10,13 +10,13 @@
     <div class="flex-1 relative mb-4">
       <Transition name="emerge-left">
         <el-form ref="formRef" v-show="currentStep === 0" :model="form" :rules="rules" label-position="left"
-          size="large" class="p-form p-main">
+          size="large" class="p-form p-main" hide-required-asterisk>
           <el-form-item label="名称" prop="name">
             <el-input v-model="form.name" clearable></el-input>
           </el-form-item>
-          <el-form-item label="无人机类型" prop="uavType">
-            <el-select v-model="form.uavType" placeholder="">
-              <el-option label="微型无人机" value="微型无人机" />
+          <el-form-item label="无人机类型" prop="aircraftType">
+            <el-select v-model="form.aircraftType" placeholder="">
+              <el-option v-for="item in uavList" :label="item.label" :value="item.value" />
             </el-select>
           </el-form-item>
           <el-form-item label="类型" prop="type">
@@ -132,18 +132,14 @@
               </tbody>
             </table>
           </div>
-
-
         </div>
       </Transition>
     </div>
-
-
     <div class="text-center">
       <el-button v-if="currentStep === 0" :disabled="!hasDraw" class="btn-main" @click="toNext">下一步</el-button>
       <template v-if="currentStep === 1">
         <el-button class="btn-main" @click="toPrev">上一步</el-button>
-        <el-button class="btn-main" @click="handleSave">保存</el-button>
+        <el-button class="btn-main" @click="handleSave" :loading="loading.save">保存</el-button>
       </template>
     </div>
 
@@ -151,32 +147,42 @@
 </template>
 
 <script setup>
-import { onBeforeUnmount, ref, watch } from 'vue';
+import { onBeforeUnmount, ref, watch, reactive } from 'vue';
 import { drawArea, clearDraw } from '@/utils/map/addLayer'
 import { useMapStore } from '@/store/map';
+import { uavList } from '@/utils/options';
+import { AddPlot } from '@/service/http';
 
 const mapStore = useMapStore()
 
 const currentStep = ref(0)
 
 const form = ref({
-  uavType: '微型无人机',
+  aircraftType: '01',
   dataType: '手动划设',
   type: '长期',
-  drawType: 'funnel',
-  topHeight: 110,
-  bottomHeight: 60,
-  topRadius: 150,
-  bottomRadius: 50
+  drawType: 'mesh',
+  height: '100',
+  topHeight: '110',
+  bottomHeight: '60',
+  topRadius: '150',
+  bottomRadius: '50'
 })
 
 const drawTypes = [
-  { label: '圆台', value: 'mesh', geoType: 'frustum-cone' },
-  { label: '圆锥', value: 'point', geoType: 'inverted-cone' },
-  { label: '漏斗', value: 'funnel', geoType: 'funnel' },
+  { label: '圆台', value: 'mesh', geoType: '6' },
+  { label: '圆锥', value: 'point', geoType: '4' },
+  { label: '漏斗', value: 'funnel', geoType: '5' },
 ]
 
-const rules = []
+const rules = {
+  name: [{ required: true, message: '请输入空域名称', trigger: 'none' }],
+  height: [{ required: true, message: '此项不可为空', trigger: 'none' }],
+  topRadius: [{ required: true, message: '此项不可为空', trigger: 'none' }],
+  bottomRadius: [{ required: true, message: '此项不可为空', trigger: 'none' }],
+  topHeight: [{ required: true, message: '此项不可为空', trigger: 'none' }],
+  bottomHeight: [{ required: true, message: '此项不可为空', trigger: 'none' }],
+}
 
 const formRef = ref(null)
 
@@ -223,19 +229,27 @@ const results = ref([
 const hasDraw = ref(false)
 
 async function handleDraw() {
-  if (hasDraw.value) {
-    clearDraw()
-    await new Promise((res) => {
-      setTimeout(() => res(), 500);
+  formRef.value.validateField(['height', 'topRadius', 'bottomRadius','topHeight','bottomHeight'], async (isValid) => {
+    if (!isValid) return
+    if (hasDraw.value) {
+      clearDraw()
+      await new Promise((res) => {
+        setTimeout(() => res(), 500);
+      })
+    }
+    // 处理绘制
+    drawArea({
+      ...form.value,
+      color: [0, 255, 0, 0.5]
     })
-  }
-  drawArea({
-    ...form.value,
-    color: [0, 255, 0, 0.5]
   })
 }
 
-watch(() => mapStore.draw_geometry, () => {
+let drawGeometry
+
+watch(() => mapStore.draw_geometry, (val) => {
+  console.log('draw_geometry:', val)
+  drawGeometry = val
   hasDraw.value = true
 }, { deep: true })
 
@@ -251,8 +265,60 @@ function toPrev() {
   currentStep.value = 0
 }
 
-function handleSave() {
+const loading = reactive({
+  save: false
+})
 
+function handleSave() {
+  loading.save = true
+  let params = {
+    ...form.value,
+    spaceType: form.value.areaType,
+    geoType: drawTypes.find(i => i.value === form.value.drawType).geoType,
+    upRadius: form.value.topRadius,
+    downRadius: form.value.bottomRadius,
+    nature: form.value.type,
+    drawType: '01',
+    shape: ''
+  }
+  const { x, y, z } = drawGeometry
+  switch (params.geoType) {
+    case '4':
+      params.shape = JSON.stringify({
+        point: { x, y, z },
+        height: params.height,
+        radius: params.upRadius
+      })
+      break;
+    case '5':
+      params.shape = JSON.stringify({
+        point: { x, y, z },
+        coneHeight: form.value.topHeight,
+        cylinderHeight: form.value.bottomHeight,
+        topRadius: params.upRadius,
+        bottomRadius: params.downRadius
+      })
+      break;
+    case '6':
+      params.shape = JSON.stringify({
+        point: { x, y, z },
+        height: params.height,
+        topRadius: params.upRadius,
+        bottomRadius: params.downRadius
+      })
+      break;
+  }
+  AddPlot(params).then(({data: res}) => {
+    if(res.msg==='success') {
+      ElMessage({ offset: 90, type: 'success', message: '保存成功' })
+    } else {
+      ElMessage({ offset: 90, type: 'error', message: `保存失败,${res.msg}` })
+    }
+  }).catch((e) => {
+    ElMessage({ offset: 90, type: 'error', message: `保存失败,${e}` })
+  }).finally(() => {
+    loading.save = false
+  })
 }
 
 onBeforeUnmount(() => {

+ 14 - 5
src/views/home/cpns/PanelSjwg.vue

@@ -80,6 +80,8 @@ import { getAssetsFile, getData } from '@/utils/require';
 import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue';
 import { showShapes, heatMap, AddSingleLayer, InspectCube } from '@/utils/map/addLayer'
 import { GetAreaList, GetPlotList, GetRouteList } from '@/service/http'
+import { airSpaceTypes } from '@/utils/options';
+import { hexToRgb } from '@/utils/tools';
 
 onBeforeMount(() => {
   getLists()
@@ -165,17 +167,24 @@ async function handleBaseClick(layer) {
 const areaList = ref([])
 
 function handleCheck(item, type) {
+  console.log(item)
   item.check = !item.check
-  const colorMap = {
-    'area': [0, 255, 0, 0.5],
-    'plot': [0, 0, 255, 0.5],
-    'route': [255, 255, 0, 0.5]
+  let color
+  switch(type) {
+    case 'area':
+      color = hexToRgb(airSpaceTypes.find(i => i.value === item.spaceType).color, 0.5)
+      break;
+    case 'plot':
+      color = [0, 0, 255, 0.5]
+      break;
+    case 'route':
+      color = [255, 255, 0, 0.5]
   }
   const data = [{
     type: type === 'route' ? item.type : item.geoType,
     shape: {
       ...JSON.parse(item.shape),
-      color: colorMap[type]
+      color
     }
   }]
   showShapes({