Kaynağa Gözat

地图功能接入

gr 1 ay önce
ebeveyn
işleme
156da4beff

+ 4 - 1
src/components/MapView.vue

@@ -29,8 +29,11 @@ export default {
       myBridge.bridgeContent = bridge = new CityGis.Bridge({
         id: "i_map",
         // url: 'http://58.34.215.19:8095/map-tool-widget/#/jk_map',
-        url: 'http://localhost:5173/map-tool-widget/',
+        // url: 'http://localhost:5173/map-tool-widget/',
+        // url: 'http://10.1.163.210:5173/map-tool-widget/#/jk_map',
+        // url: 'http://58.34.215.19:8100/map-tool-widget/',
         // url: 'https://cimweb.zjw.sh.cegn.cn:2007/map-tool-widget/#/',
+        url: 'http://58.34.215.19:8095/map-tool-widget/#/jk_map',
         onReady: function () {
           console.log("地图创建完成")
         }

+ 136 - 103
src/service/http.js

@@ -1,219 +1,252 @@
-import {requestGet,requestPost} from "./index.js";
+import { requestGet, requestPost } from "./index.js";
+import { requestNetPost } from "@/service/index.js";
 
 
 //查询服务列表
-export function getServiceTree(params){
+export function getServiceTree(params) {
     return requestPost({
-        url:'/class-tags/queryMapTree',
-        data:{
+        url: '/class-tags/queryMapTree',
+        data: {
             ...params
         }
     })
 }
 
 
-export function getResourceDirDetailInfo(CODE){
+export function getResourceDirDetailInfo(CODE) {
     return requestPost({
-        url:'/ptjkInterface/selectMenuData',
-        data:{
+        url: '/ptjkInterface/selectMenuData',
+        data: {
             CODE
         }
     })
 }
-export function getMetaDetailInfo(CODE){
+export function getMetaDetailInfo(CODE) {
     return requestPost({
-        url:'/ptjkInterface/selectMetaData',
-        data:{
+        url: '/ptjkInterface/selectMetaData',
+        data: {
             CODE
         }
     })
 }
 
-export function queryDataItem(CODE){
+export function queryDataItem(CODE) {
     return requestPost({
-        url:'/Analysis/queryDataItem',
-        data:{
-            SERVICE_CODE:CODE
+        url: '/Analysis/queryDataItem',
+        data: {
+            SERVICE_CODE: CODE
         }
     })
 }
 
 
 //市政设施类型/fwgl/queryMunicipalFacilityTypes
-export function getMunicipalFacilityTypes(){
+export function getMunicipalFacilityTypes() {
     return requestPost({
-        url:'/fwzt/queryMunicipalFacilityTypes',
-		data:{
-			
-		}
+        url: '/fwzt/queryMunicipalFacilityTypes',
+        data: {
+
+        }
     })
 }
 //道路预警/fwzt/queryRoadWarning
-export function getQueryRoadWarning(){
+export function getQueryRoadWarning() {
     return requestPost({
-        url:'/fwzt/queryRoadWarning',
-		data:{
-			
-		}
+        url: '/fwzt/queryRoadWarning',
+        data: {
+
+        }
     })
 }
 
 //道路等级/fwzt/selectDldjCount
-export function getSelectDldjCount(){
+export function getSelectDldjCount() {
     return requestPost({
-        url:'/fwzt/selectDldjCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectDldjCount',
+        data: {
+
+        }
     })
 }
 
 //桥梁类别/fwzt/selectQllbCount
-export function getSelectQllbCount(){
+export function getSelectQllbCount() {
     return requestPost({
-        url:'/fwzt/selectQllbCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectQllbCount',
+        data: {
+
+        }
     })
 }
 
 //桥梁隐患/fwzt/selectQlyhCount
-export function getSelectQlyhCount(){
+export function getSelectQlyhCount() {
     return requestPost({
-        url:'/fwzt/selectQlyhCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectQlyhCount',
+        data: {
+
+        }
     })
 }
 
 //供水管线敷设方式/fwzt/selectFsfsCount
-export function getSelectFsfsCount(){
+export function getSelectFsfsCount() {
     return requestPost({
-        url:'/fwzt/selectFsfsCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectFsfsCount',
+        data: {
+
+        }
     })
 }
 
 //供水管线灾害隐患/fwzt/selectYxzhyhCount
-export function getSelectYxzhyhCount(){
+export function getSelectYxzhyhCount() {
     return requestPost({
-        url:'/fwzt/selectYxzhyhCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectYxzhyhCount',
+        data: {
+
+        }
     })
 }
 
 //供水管线风险/fwzt/selectGsgxFxCount
-export function getSelectGsgxFxCount(){
+export function getSelectGsgxFxCount() {
     return requestPost({
-        url:'/fwzt/selectGsgxFxCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectGsgxFxCount',
+        data: {
+
+        }
     })
 }
 
 //道路路幅/fwzt/selectDllfCount
-export function getSelectDllfCount(){
+export function getSelectDllfCount() {
     return requestPost({
-        url:'/fwzt/selectDllfCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectDllfCount',
+        data: {
+
+        }
     })
 }
 
 //建筑概览/fwzt/selectJzgsCount
-export function getSelectJzgsCount(){
+export function getSelectJzgsCount() {
     return requestPost({
-        url:'/fwzt/selectJzgsCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectJzgsCount',
+        data: {
+
+        }
     })
 }
 
 //房屋风险/fwzt/selectFwsfczfxCount
-export function getSelectFwsfczfxCount(){
+export function getSelectFwsfczfxCount() {
     return requestPost({
-        url:'/fwzt/selectFwsfczfxCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectFwsfczfxCount',
+        data: {
+
+        }
     })
 }
 
 //抗震加固/fwzt/selectKzjgCount
-export function getSelectKzjgCount(){
+export function getSelectKzjgCount() {
     return requestPost({
-        url:'/fwzt/selectKzjgCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectKzjgCount',
+        data: {
+
+        }
     })
 }
 
 //农村房屋安全鉴定/fwzt/selectNcfwAqjdCount
-export function getSelectNcfwAqjdCount(){
+export function getSelectNcfwAqjdCount() {
     return requestPost({
-        url:'/fwzt/selectNcfwAqjdCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectNcfwAqjdCount',
+        data: {
+
+        }
     })
 }
 
 //城镇房屋设防烈度/fwzt/selectCzfwsfldCount
-export function getSelectCzfwsfldCount(){
+export function getSelectCzfwsfldCount() {
     return requestPost({
-        url:'/fwzt/selectCzfwsfldCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectCzfwsfldCount',
+        data: {
+
+        }
     })
 }
 
 //结构类型占比/fwzt/selectJglxzbCount
-export function getSelectJglxzbCount(){
+export function getSelectJglxzbCount() {
     return requestPost({
-        url:'/fwzt/selectJglxzbCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectJglxzbCount',
+        data: {
+
+        }
     })
 }
 
 //各年代建筑结构类型统计/fwzt/selectJzncJzjgCount
-export function getSelectJzncJzjgCount(){
+export function getSelectJzncJzjgCount() {
     return requestPost({
-        url:'/fwzt/selectJzncJzjgCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectJzncJzjgCount',
+        data: {
+
+        }
     })
 }
 
 //建筑层数/fwzt/selectJzcsCount
-export function getSelectJzcsCount(){
+export function getSelectJzcsCount() {
     return requestPost({
-        url:'/fwzt/selectJzcsCount',
-		data:{
-			
-		}
+        url: '/fwzt/selectJzcsCount',
+        data: {
+
+        }
     })
 }
 
 //建筑高度
-export function selectJzgdCount(){
+export function selectJzgdCount() {
     return requestPost({
-        url:'/fwzt/selectJzgdCount',
-        data:{
+        url: '/fwzt/selectJzgdCount',
+        data: {
+
+        }
+    })
+}
+
+/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ new add ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
+
+// 空域列表
+export function GetAreaList() {
+    return requestNetPost({
+        url: '/pg/airSpace/query',
+        data: {
+            "fullExport": true
+        }
+    })
+}
+
+// 航线列表
+export function GetRouteList() {
+    return requestNetPost({
+        url: '/pg/airLine/query',
+        data: {
+            "fullExport": true
+        }
+    })
+}
 
+// 起降场列表
+export function GetPlotList() {
+    return requestNetPost({
+        url: '/pg/airPort/query',
+        data: {
+            "fullExport": true
         }
     })
-}
+}

+ 34 - 1
src/utils/map/addLayer.js

@@ -1080,10 +1080,11 @@ export function showShapes({ id, data }) {
 }
 
 // 绘制区域
-export function DrawPolygon() {
+export function DrawPolygon(params) {
   invokeParams('Draw', {
     type: "polygon",
     clear: true,
+    hasZ: params?.hasZ || false,
     token: ""
   })
 }
@@ -1128,3 +1129,35 @@ export function drawLayering(params) {
     "token": ""
   })
 }
+
+// 核查网格
+export function InspectCube(params) {
+  const actionMap = {
+    'polygon': 'GetPrismCube',
+    'funnel': 'GetFunnelCube',
+    'frustum-cone': 'GetFrustumConeCube',
+    'inverted-cone': 'GetInvertedConeCube',
+    'polyline': 'GetPathCube',
+  }
+  if (!actionMap[params?.type]) return
+  invokeParams(actionMap[params.type], {
+    id: params.id.toString(),
+    status: params.show ? 'show' : 'hide',
+    level: 23,
+    token: "",
+    ...params.shape
+  })
+}
+
+// 栅格占用查询、空域剖面查询
+export function QueryCube(params) {
+  invokeParams(params.evaluation ? 'GetPowerCube' : 'GetOccupyCube', {
+    id: params.id || 'QueryCube',
+    status: params.show ? 'show' : 'hide',
+    level: params.level,
+    minZ: params.minZ,
+    maxZ: params.maxZ,
+    rings: params.rings,
+    token: "",
+  })
+}

+ 2 - 4
src/views/home/cpns/FloatPanelFcky.vue

@@ -98,8 +98,6 @@ function handleLayering() {
   }
   timer_handleLayering = setTimeout(() => {
     const { layeringType, layersBig, layersSmall, rangeType, range } = form.value
-    if (layeringType === '广域分层' && !layersBig.length) return
-    if (layeringType === '细微分层' && !layersSmall.length) return
     if (rangeType === '自定义绘制' && !drawResult) return
     if (rangeType === '行政区划' && !range) return
     console.log('start draw')
@@ -154,8 +152,8 @@ function handleLayering() {
 
 const layersListBig = [
   { label: '120以下', id: 'big_1', value: '0,120' },
-  { label: '60-80', id: 'big_2', value: '60,80' },
-  { label: '80-100', id: 'big_3', value: '80,100' },
+  { label: '120-300', id: 'big_2', value: '120,300' },
+  { label: '300-600', id: 'big_3', value: '300,600' },
 ]
 
 const layersListSmall = computed(() => {

+ 7 - 5
src/views/home/cpns/PanelQjchs.vue

@@ -49,9 +49,7 @@
           </template>
           <el-form-item label="类型" prop="drawType" v-if="form.dataType === '手动划设'">
             <el-radio-group v-model="form.drawType" size="large">
-              <el-radio-button label="圆台" value="mesh" />
-              <el-radio-button label="圆锥" value="point" />
-              <el-radio-button label="漏斗" value="funnel" />
+              <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>
@@ -172,10 +170,14 @@ const form = ref({
   bottomRadius: 50
 })
 
-const rules = [
-
+const drawTypes = [
+  { label: '圆台', value: 'mesh', geoType: 'frustum-cone' },
+  { label: '圆锥', value: 'point', geoType: 'inverted-cone' },
+  { label: '漏斗', value: 'funnel', geoType: 'funnel' },
 ]
 
+const rules = []
+
 const formRef = ref(null)
 
 const results = ref([

+ 48 - 28
src/views/home/cpns/PanelSgzy.vue

@@ -6,14 +6,14 @@
     <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.heightMin" :max="form.heightMax" type="number" class="flex-1"></el-input>
+        <el-input v-model="form.minZ" :max="form.maxZ" type="number" class="flex-1"></el-input>
         <div class="mx-2">--</div>
-        <el-input v-model="form.heightMax" :min="form.heightMin" type="number" class="flex-1"></el-input>
-        <el-button class="btn-secondary ml-3 -mb-1">绘制区域</el-button>
+        <el-input v-model="form.maxZ" :min="form.minZ" type="number" class="flex-1"></el-input>
+        <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>
@@ -32,9 +32,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>
@@ -47,40 +47,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级',
-  heightMin: '0',
-  heightMax: '200'
+  level: '23',
+  minZ: '0',
+  maxZ: '200',
+  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() {
-
+  const { maxZ, minZ } = form.value
+  if (!drawResult) return
+  if (!minZ || !maxZ) return
+  handleClear()
+  setTimeout(() => {
+    QueryCube({
+      ...form.value,
+      show: true,
+      rings: drawResult
+    })
+  }, 0);
 }
 
+onBeforeUnmount(() => {
+  handleClear(true)
+})
+
 </script>
 
 <style lang="scss" scoped>

+ 161 - 38
src/views/home/cpns/PanelSjwg.vue

@@ -24,7 +24,7 @@
     <Transition>
       <div v-if="contentShow.b2" v-collapse="'scroll'" class="flex-1 pr-1">
         <div class="title-shade">
-          <span>限制空域</span>
+          <span>空域</span>
           <i class="btn-edit"></i>
           <i class="drop-down" @click="toggleContentShow('b2r1')" :class="{ 'reverse': contentShow.b2r1 }"></i>
         </div>
@@ -32,15 +32,15 @@
           <ul v-if="contentShow.b2r1" v-collapse>
             <li v-for="item in areaList" class="list-item">
               <img src="../../../assets/images/page/icon-location.png" alt="">
-              <span>{{ item.label }}</span>
-              <i title="查看" @click="handleCheckArea(item)" :class="{'active': item.check}"></i>
-              <i title="网格" :class="{'active': item.mesh}"></i>
+              <span>{{ item.name }}</span>
+              <i title="查看" @click="handleCheck(item, 'area')" :class="{ 'active': item.check }"></i>
+              <i title="网格" @click="handleMesh(item, 'area')" :class="{ 'active': item.mesh }"></i>
             </li>
           </ul>
         </Transition>
 
         <div class="title-shade">
-          <span>航路航线</span>
+          <span>航线</span>
           <i class="btn-edit"></i>
           <i class="drop-down" @click="toggleContentShow('b2r2')" :class="{ 'reverse': contentShow.b2r2 }"></i>
         </div>
@@ -48,9 +48,25 @@
           <ul v-if="contentShow.b2r2" v-collapse>
             <li v-for="item in routeList" class="list-item">
               <img src="../../../assets/images/page/icon-route.png" alt="">
-              <span>{{ item.label }}</span>
-              <i title="查看" :class="{'active': item.check}"></i>
-              <i title="网格" :class="{'active': item.mesh}"></i>
+              <span>{{ item.name }}</span>
+              <i title="查看" @click="handleCheck(item, 'route')" :class="{ 'active': item.check }"></i>
+              <i title="网格" @click="handleMesh(item, 'route')" :class="{ 'active': item.mesh }"></i>
+            </li>
+          </ul>
+        </Transition>
+
+        <div class="title-shade">
+          <span>起降场</span>
+          <i class="btn-edit"></i>
+          <i class="drop-down" @click="toggleContentShow('b2r3')" :class="{ 'reverse': contentShow.b2r3 }"></i>
+        </div>
+        <Transition>
+          <ul v-if="contentShow.b2r3" v-collapse>
+            <li v-for="item in plotList" class="list-item">
+              <img src="../../../assets/images/page/icon-plot.png" alt="">
+              <span>{{ item.name }}</span>
+              <i title="查看" @click="handleCheck(item, 'plot')" :class="{ 'active': item.check }"></i>
+              <i title="网格" @click="handleMesh(item, 'plot')" :class="{ 'active': item.mesh }"></i>
             </li>
           </ul>
         </Transition>
@@ -61,57 +77,163 @@
 
 <script setup>
 import { getAssetsFile, getData } from '@/utils/require';
-import { nextTick, reactive, ref } from 'vue';
-import { showShapes } from '../../../utils/map/addLayer'
+import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue';
+import { showShapes, heatMap, AddSingleLayer, InspectCube } from '@/utils/map/addLayer'
+import { GetAreaList, GetPlotList, GetRouteList } from '@/service/http'
+
+onBeforeMount(() => {
+  getLists()
+})
+
+function showWarning(message) {
+  ElMessage({ offset: 90, type: 'warning', message })
+}
+
+function getLists() {
+  GetAreaList().then(res => {
+    if (!Array.isArray(res.data.data)) {
+      showWarning('空域列表查询失败')
+      return
+    }
+    areaList.value = res.data.data.map(row => ({
+      ...row,
+      check: false,
+      mesh: false
+    }))
+    contentShow.b2r1 = true
+  }).catch(() => {
+    showWarning('空域列表查询失败')
+  })
+  GetPlotList().then(res => {
+    if (!Array.isArray(res.data.data)) {
+      showWarning('起降场列表查询失败')
+      return
+    }
+    plotList.value = res.data.data.map(row => ({
+      ...row,
+      check: false,
+      mesh: false
+    }))
+  }).catch(() => {
+    showWarning('起降场列表查询失败')
+  })
+  GetRouteList().then(res => {
+    if (!Array.isArray(res.data.data)) {
+      showWarning('航线列表查询失败')
+      return
+    }
+    routeList.value = res.data.data.map(row => ({
+      ...row,
+      check: false,
+      mesh: false
+    }))
+  }).catch(() => {
+    showWarning('航线列表查询失败')
+  })
+}
 
 const basicList = ref([
-  { label: '白模', icon: 'icon-layer-bm', active: false },
-  { label: '精模', icon: 'icon-layer-jm', active: false },
-  { label: '道路', icon: 'icon-layer-dl', active: false },
-  { label: '河流', icon: 'icon-layer-hl', active: false },
-  { label: '人口', icon: 'icon-layer-rk', active: false },
+  { label: '白模', alias: '全市白模', icon: 'icon-layer-bm', active: false },
+  { label: '精模', alias: '五角场精模', icon: 'icon-layer-jm', active: false },
+  { label: '道路', alias: ['快速路', '高速公路', '地面道路'], icon: 'icon-layer-dl', active: false },
+  { label: '河流', alias: '全市河流', icon: 'icon-layer-hl', active: false },
+  { label: '人口', alias: '人口', icon: 'icon-layer-rk', active: false },
 ])
 
-const areaList = ref([
-  { label: '临时限制区', check: false, mesh: false },
-])
+async function handleBaseClick(layer) {
+  layer.active = !layer.active
+  const aliasArr = Array.isArray(layer.alias) ? layer.alias : [layer.alias]
+  const resources = await getData('resources.json')
+  const targetServices = resources.filter(r => aliasArr.some(i => i === r.title))
+  if (targetServices.length === 0) return
+  targetServices.forEach(service => {
+    if (service.type == "feature") {
+      heatMap({
+        ...service,
+        visible: layer.active,
+      })
+    } else {
+      AddSingleLayer({
+        ...service,
+        visible: layer.active,
+        opacity: 1
+      })
+    }
+  })
+}
+
+const areaList = ref([])
 
-async function handleCheckArea(item) {
+function handleCheck(item, type) {
   item.check = !item.check
+  const colorMap = {
+    'area': [0, 255, 0, 0.5],
+    'plot': [0, 0, 255, 0.5],
+    'route': [255, 255, 0, 0.5]
+  }
+  const data = [{
+    type: type === 'route' ? item.type : item.geoType,
+    shape: {
+      ...JSON.parse(item.shape),
+      color: colorMap[type]
+    }
+  }]
   showShapes({
-    id: 'drawOne',
-    data: item.check ? await getData('restrictArea.json') : null
+    id: item.id,
+    data: item.check ? data : null
   })
 }
 
-const routeList = ref([
-  { label: '航线1', check: false, mesh: false },
-  { label: '航线2', check: false, mesh: false },
-  { label: '航线3', check: false, mesh: false },
-  { label: '航线4', check: false, mesh: false },
-  { label: '航线5', check: false, mesh: false },
-  { label: '航线6', check: false, mesh: false },
-  { label: '航线7', check: false, mesh: false },
-  { label: '航线8', check: false, mesh: false },
-  { label: '航线9', check: false, mesh: false },
-  { label: '航线10', check: false, mesh: false },
-])
-
-function handleBaseClick(item) {
-  item.active = !item.active
+function handleMesh(item) {
+  item.mesh = !item.mesh
+  InspectCube({
+    id: item.id,
+    show: item.mesh,
+    type: item.geoType || item.type,
+    shape: JSON.parse(item.shape)
+  })
 }
 
+const routeList = ref([])
+
+const plotList = ref([])
+
 const contentShow = reactive({
   b1: true,
   b2: true,
-  b2r1: true,
-  b2r2: true
+  b2r1: false,
+  b2r2: false,
+  b2r3: false,
 })
 
 function toggleContentShow(id) {
   contentShow[id] = !contentShow[id]
+  const subs = ['b2r1', 'b2r2', 'b2r3']
+  subs.forEach(i => {
+    if (contentShow[id] && subs.includes(id) && id !== i) {
+      contentShow[i] = false
+    }
+  })
 }
 
+onBeforeUnmount(() => {
+  [...areaList.value, ...plotList.value, ...routeList.value].forEach(row => {
+    if (row.check) {
+      showShapes({
+        id: row.id,
+        data: null
+      })
+    }
+    if (row.mesh) {
+      InspectCube({
+        id: row.id,
+        show: false,
+        type: row.geoType || row.type,
+      })
+    }
+  })
+})
+
 const vCollapse = {
   beforeMount(el, binding) {
     el.style.height = '0';
@@ -237,6 +359,7 @@ const vCollapse = {
     cursor: pointer;
     background-size: cover !important;
     filter: grayscale(1);
+
     &.active {
       filter: grayscale(0);
     }