From 264880703c677d63b7e35b5eb085e6bc3214e3ed Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期三, 17 七月 2024 18:29:31 +0800
Subject: [PATCH] 2024.7.17

---
 src/composables/fetchData.js               |    2 
 src/utils/map/util.js                      |   87 ++++
 src/views/historymode/HistoryMode.vue      |   39 +
 src/utils/map/dialog.js                    |    3 
 src/components/mission/MIssionCreate.vue   |   37 +
 src/components.d.ts                        |    3 
 src/components/mission/MissionManage.vue   |  182 ++++----
 src/components/CardDialog.vue              |   11 
 src/components/search/OptionTime.vue       |    2 
 src/styles/elementUI.scss                  |    9 
 src/utils/map/marks.js                     |   13 
 src/components/MessageBox.vue              |   64 +++
 src/components/core/CoreMenu.vue           |    8 
 src/api/index.js                           |    2 
 src/main.js                                |    4 
 src/composables/messageBox.js              |   56 ++
 src/utils/map/sector.js                    |   42 +
 src/components/search/OptionMission.vue    |   30 
 src/stores/mission.js                      |   35 +
 src/components/search/OptionLocation2.vue  |  165 ++++++++
 src/utils/map/3dLayer.js                   |   23 -
 src/constant/location.js                   |  257 +++++++++++++
 src/components/chart/ProgressLineChart.vue |   27 
 23 files changed, 917 insertions(+), 184 deletions(-)

diff --git a/src/api/index.js b/src/api/index.js
index f657c25..ed45795 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -1,7 +1,7 @@
 import axios from 'axios';
 import { ElMessage } from 'element-plus';
 
-const debug = true;
+const debug = false;
 
 // let ip1 = 'http://114.215.109.124:8805/';
 let ip1 = 'http://47.100.191.150:9029/';
diff --git a/src/components.d.ts b/src/components.d.ts
index 93c0d11..c720d3b 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -16,6 +16,7 @@
     DataSummary: typeof import('./components/monitor/DataSummary.vue')['default']
     DataTable: typeof import('./components/monitor/DataTable.vue')['default']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCascader: typeof import('element-plus/es')['ElCascader']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
     ElCol: typeof import('element-plus/es')['ElCol']
@@ -51,11 +52,13 @@
     MapLocation: typeof import('./components/map/MapLocation.vue')['default']
     MapScene: typeof import('./components/map/MapScene.vue')['default']
     MapToolbox: typeof import('./components/map/MapToolbox.vue')['default']
+    MessageBox: typeof import('./components/MessageBox.vue')['default']
     MissionCreate: typeof import('./components/mission/MissionCreate.vue')['default']
     MissionImport: typeof import('./components/mission/MissionImport.vue')['default']
     MissionManage: typeof import('./components/mission/MissionManage.vue')['default']
     OptionDevice: typeof import('./components/search/OptionDevice.vue')['default']
     OptionLocation: typeof import('./components/search/OptionLocation.vue')['default']
+    OptionLocation2: typeof import('./components/search/OptionLocation2.vue')['default']
     OptionMission: typeof import('./components/search/OptionMission.vue')['default']
     OptionTime: typeof import('./components/search/OptionTime.vue')['default']
     OptionType: typeof import('./components/search/OptionType.vue')['default']
diff --git a/src/components/CardDialog.vue b/src/components/CardDialog.vue
index 6c04562..4ce1ea9 100644
--- a/src/components/CardDialog.vue
+++ b/src/components/CardDialog.vue
@@ -4,7 +4,9 @@
     @opened="handleChange(true)"
     @closed="handleChange(false)"
     :show-close="false"
+    :destroy-on-close="true"
     align-center
+    :width="width"
   >
     <template #header="{ close, titleId, titleClass }">
       <BaseCard direction="top-left" borderless="t">
@@ -27,6 +29,9 @@
       <template #content>
         <slot></slot>
       </template>
+      <template #footer>
+        <slot name="footer"></slot>
+      </template>
     </BaseCard>
   </el-dialog>
 </template>
@@ -34,7 +39,11 @@
 export default {
   props: {
     title: String,
-    modelValue: Boolean
+    modelValue: Boolean,
+    width: {
+      type: [String, Number],
+      default: '50%'
+    }
   },
   emits: ['update:modelValue'],
   methods: {
diff --git a/src/components/MessageBox.vue b/src/components/MessageBox.vue
new file mode 100644
index 0000000..ce075f9
--- /dev/null
+++ b/src/components/MessageBox.vue
@@ -0,0 +1,64 @@
+<template>
+  <CardDialog
+    :title="title"
+    :model-value="modelValue"
+    :width="400"
+    @handleChange="handleChange"
+  >
+    <el-row justify="center">
+      <div class="m-v-16">{{ msg }}</div>
+    </el-row>
+    <template #footer>
+      <el-row justify="end">
+        <el-button type="primary" class="el-button-custom" @click="cancel">
+          {{ cancelText }}
+        </el-button>
+        <el-button
+          type="danger"
+          class="el-button-custom-light"
+          @click="confirm"
+        >
+          {{ confirmText }}
+        </el-button>
+      </el-row>
+    </template>
+  </CardDialog>
+</template>
+<script>
+export default {
+  props: {
+    title: String,
+    msg: String,
+    modelValue: Boolean,
+    confirmText: {
+      type: String,
+      default: '纭'
+    },
+    cancelText: {
+      type: String,
+      default: '鍙栨秷'
+    },
+    onConfirm: Function,
+    onCancel: Function
+  },
+  data() {},
+  emits: ['update:modelValue'],
+  methods: {
+    handleChange(value) {
+      this.$emit('update:modelValue', value);
+    },
+    confirm() {
+      if (this.onConfirm) {
+        this.onConfirm();
+      }
+      this.$emit('update:modelValue', false);
+    },
+    cancel() {
+      if (this.onCancel) {
+        this.onCancel();
+      }
+      this.$emit('update:modelValue', false);
+    }
+  }
+};
+</script>
diff --git a/src/components/chart/ProgressLineChart.vue b/src/components/chart/ProgressLineChart.vue
index 7a40cc0..8f22e3c 100644
--- a/src/components/chart/ProgressLineChart.vue
+++ b/src/components/chart/ProgressLineChart.vue
@@ -67,13 +67,6 @@
     },
     locateIndex(nV, oV) {
       if (nV == oV) return;
-      // 1. 瀹氫綅鐐瑰簲璇ュ睍绀哄湪瓒嬪娍鍥句腑闂达紝鍥犳瀹氫綅鐧惧垎姣斿線鍓嶅亸绉诲綋鍓峗size鐨勪竴鍗�
-      let i = nV - parseInt(this.pageSize / 2);
-      // 2. 纭繚绱㈠紩涓嶄細瓒呭嚭鑼冨洿
-      i = i < 0 ? 0 : i;
-      // 3. 鑾峰彇绱㈠紩瀵瑰簲鐨勮繘搴︾櫨鍒嗘瘮
-      this.progress = (i / (this.allXAxis.length - this.pageSize)) * 100;
-
       for (const iterator of this.allSeries) {
         // if (iterator.name == factorName || (iterator.name == 'TVOC' || factorName == 'VOC')) {
         iterator.markLine = {
@@ -92,7 +85,21 @@
           ]
         };
       }
-      this.changeChartRange();
+      // 璁$畻瓒呭嚭鍗曢〉鏁版嵁閲忕殑闀垮害
+      let len = this.allXAxis.length - this.pageSize;
+      len = len < 0 ? 0 : len;
+      // 瀹氫綅鐐瑰簲璇ュ睍绀哄湪瓒嬪娍鍥句腑闂达紝鍥犳瀹氫綅鐧惧垎姣斿線鍓嶅亸绉诲綋鍓峗size鐨勪竴鍗�
+      let i = nV - parseInt(this.pageSize / 2);
+      // 纭繚绱㈠紩涓嶄細瓒呭嚭鑼冨洿
+      i = i < 0 ? 0 : i;
+      i = i > len ? len : i;
+      // 鑾峰彇绱㈠紩瀵瑰簲鐨勮繘搴︾櫨鍒嗘瘮
+      const _progress = (i / len) * 100;
+      if (this.progress != _progress) {
+        this.progress = _progress;
+      } else {
+        this.changeChartRange();
+      }
     }
   },
   methods: {
@@ -143,9 +150,7 @@
     },
     getShowSeries(sIndex, eIndex) {
       this.allSeries.forEach((s) => {
-        if (sIndex && eIndex) {
-          s.data = s.allData.slice(sIndex, eIndex);
-        }
+        s.data = s.allData.slice(sIndex, eIndex);
       });
       const res = this.allSeries.filter((s) => {
         return this.selectFactorType.includes(s.key);
diff --git a/src/components/core/CoreMenu.vue b/src/components/core/CoreMenu.vue
index a7aa2bf..b15b6f3 100644
--- a/src/components/core/CoreMenu.vue
+++ b/src/components/core/CoreMenu.vue
@@ -56,12 +56,12 @@
         {
           name: '璧拌埅鐩戞祴',
           path: 'rmode'
-        },
-        {
-          name: '姹℃煋婧簮2',
-          path: 'hmode2'
         }
         // {
+        //   name: '姹℃煋婧簮2',
+        //   path: 'hmode2'
+        // }
+        // {
         //   name: '缃戞牸鍖栫洃娴�',
         //   path: 'gridmonitor'
         // }
diff --git a/src/components/mission/MIssionCreate.vue b/src/components/mission/MIssionCreate.vue
index 58565ab..1966572 100644
--- a/src/components/mission/MIssionCreate.vue
+++ b/src/components/mission/MIssionCreate.vue
@@ -15,6 +15,15 @@
       label-position="right"
       label-width="100px"
     >
+      <el-form-item label="鍖哄幙" prop="location">
+        <OptionLocation2
+          :level="3"
+          :initValue="false"
+          :checkStrictly="false"
+          :allOption="false"
+          v-model="formObj.location"
+        ></OptionLocation2>
+      </el-form-item>
       <el-form-item label="浠诲姟缂栧彿" prop="missionCode">
         <el-input
           size="small"
@@ -24,14 +33,18 @@
         />
       </el-form-item>
       <OptionType v-model="formObj.deviceType"></OptionType>
-      <el-form-item label="璁惧缂栧彿" prop="acountname">
+      <!-- <el-form-item label="璁惧缂栧彿" prop="acountname">
         <el-input
           size="small"
           clearable
           v-model="formObj.deviceCode"
           placeholder="璁惧缂栧彿"
         />
-      </el-form-item>
+      </el-form-item> -->
+      <OptionDevice
+        :type="formObj.deviceType"
+        v-model="formObj.deviceCode"
+      ></OptionDevice>
       <OptionTime v-model="formObj.timeArray"></OptionTime>
       <el-form-item>
         <el-button
@@ -51,34 +64,37 @@
 import missionApi from '@/api/missionApi';
 import { useFormConfirm } from '@/composables/formConfirm';
 import { useFetchData } from '@/composables/fetchData';
+import { useMissionStore } from '@/stores/mission';
 
+const missionStore = useMissionStore();
 const dialogVisible = ref(false);
 const { loading, fetchData } = useFetchData();
-const baseRules = reactive({
-  _usertype: [
+const rules = reactive({
+  location: [
     {
       required: true,
-      message: '鐢ㄦ埛绫诲瀷涓嶈兘涓虹┖',
+      message: '鍖哄幙涓嶈兘涓虹┖',
       trigger: 'change'
     }
   ],
-  _locations: [
+  missionCode: [
     {
       required: true,
-      message: '琛屾斂鍖哄垝涓嶈兘涓虹┖',
-      trigger: 'change'
+      message: '浠诲姟缂栧彿涓嶈兘涓虹┖',
+      trigger: 'blur'
     }
   ],
-  _scenetype: [
+  timeArray: [
     {
       required: true,
-      message: '鍦烘櫙绫诲瀷涓嶈兘涓虹┖',
+      message: '鏃堕棿涓嶈兘涓虹┖',
       trigger: 'change'
     }
   ]
 });
 const param = computed(() => {
   return {
+    districtName: formObj.value.location.dName,
     missionCode: formObj.value.missionCode,
     deviceType: formObj.value.deviceType,
     deviceCode: formObj.value.deviceCode,
@@ -91,6 +107,7 @@
   fetchData((page, pageSize) => {
     return missionApi.putNewMission(param.value).then((res) => {
       dialogVisible.value = false;
+      missionStore.fetchMission();
     });
   });
 }
diff --git a/src/components/mission/MissionManage.vue b/src/components/mission/MissionManage.vue
index d7efdb4..5884383 100644
--- a/src/components/mission/MissionManage.vue
+++ b/src/components/mission/MissionManage.vue
@@ -7,116 +7,110 @@
   >
     浠诲姟绠$悊
   </el-button>
-  <el-dialog v-model="dialogVisible" :show-close="false" align-center>
-    <template #header="{ close, titleId, titleClass }">
-      <BaseCard direction="top-left" borderless="t">
-        <template #content>
-          <el-row justify="space-between" align="middle">
-            <el-row align="middle">
-              <font-awesome-icon icon="fa fa-list" class="m-r-4" />
-              <span :id="titleId" :class="titleClass">璧拌埅浠诲姟绠$悊</span>
-            </el-row>
-            <font-awesome-icon
-              icon="fa fa-times"
-              class="cursor-p m-r-4"
-              @click="close"
-            />
-          </el-row>
-        </template>
-      </BaseCard>
-    </template>
-    <BaseCard size="medium">
-      <template #content>
-        <el-row class="mission-table">
-          <el-col :span="20">
-            <el-table
-              :data="missionList"
-              table-layout="fixed"
-              size="small"
-              :show-overflow-tooltip="true"
-              border
-              row-class-name="t-row"
-              cell-class-name="t-cell"
-              header-row-class-name="t-header-row"
-              header-cell-class-name="t-header-cell"
-            >
-              <el-table-column
-                type="index"
-                label="搴忓彿"
-                align="center"
-                width="50"
-              />
-              <el-table-column
-                prop="missionCode"
-                label="浠诲姟缂栧彿"
-                align="center"
-              />
-              <el-table-column
-                prop="startTime"
-                label="寮�濮嬫椂闂�"
-                align="center"
-                :formatter="timeFormatter"
-              />
-              <el-table-column
-                prop="endTime"
-                label="缁撴潫鏃堕棿"
-                align="center"
-                :formatter="timeFormatter"
-              />
-              <el-table-column label="绠$悊" width="70" align="center">
-                <template #default="{ row }">
-                  <el-button
-                    type="primary"
-                    size="small"
-                    class="el-button-custom"
-                    @click="deleteMission(row)"
-                    >鍒犻櫎</el-button
-                  >
-                </template>
-              </el-table-column>
-            </el-table>
-          </el-col>
-          <el-col :span="4" class="flex-col">
-            <div>
-              <!-- <el-button type="primary" class="el-button-custom">
+  <CardDialog v-model="dialogVisible" title="璧拌埅浠诲姟绠$悊">
+    <el-row class="mission-table">
+      <el-col :span="20">
+        <el-table
+          :data="missionStore.missionList"
+          table-layout="fixed"
+          size="small"
+          :show-overflow-tooltip="true"
+          border
+          height="64vh"
+          row-class-name="t-row"
+          cell-class-name="t-cell"
+          header-row-class-name="t-header-row"
+          header-cell-class-name="t-header-cell"
+        >
+          <el-table-column
+            type="index"
+            label="搴忓彿"
+            align="center"
+            width="50"
+          />
+          <el-table-column prop="missionCode" label="浠诲姟缂栧彿" align="center" />
+          <el-table-column
+            prop="startTime"
+            label="寮�濮嬫椂闂�"
+            align="center"
+            :formatter="timeFormatter"
+          />
+          <el-table-column
+            prop="endTime"
+            label="缁撴潫鏃堕棿"
+            align="center"
+            :formatter="timeFormatter"
+          />
+          <el-table-column label="绠$悊" width="70" align="center">
+            <template #default="{ row }">
+              <el-button
+                type="primary"
+                size="small"
+                class="el-button-custom"
+                @click="deleteMission(row)"
+                >鍒犻櫎</el-button
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-col>
+      <el-col :span="4" class="flex-col">
+        <div>
+          <!-- <el-button type="primary" class="el-button-custom">
                 鏂板缓浠诲姟
               </el-button> -->
-              <MissionCreate></MissionCreate>
-            </div>
-            <div>
-              <el-button type="primary" class="el-button-custom">
-                鏁版嵁瀵煎叆
-              </el-button>
-            </div>
-            <div>
-              <el-button type="primary" class="el-button-custom">
-                涓嬭浇妯℃澘
-              </el-button>
-            </div>
-          </el-col>
-        </el-row>
-      </template>
-    </BaseCard>
-  </el-dialog>
+          <MissionCreate></MissionCreate>
+        </div>
+        <div>
+          <el-button type="primary" class="el-button-custom">
+            鏁版嵁瀵煎叆
+          </el-button>
+        </div>
+        <div>
+          <el-button type="primary" class="el-button-custom">
+            涓嬭浇妯℃澘
+          </el-button>
+        </div>
+      </el-col>
+    </el-row>
+  </CardDialog>
+  <MessageBox
+    v-model="msgBoxVisible"
+    :on-confirm="onConfirm"
+    title="鍒犻櫎璧拌埅浠诲姟"
+    msg="纭鏄惁鍒犻櫎璇ヨ蛋鑸换鍔�"
+    confirmText="鍒犻櫎"
+  ></MessageBox>
 </template>
 <script>
 import moment from 'moment';
-import { mapState } from 'pinia';
+import { mapStores } from 'pinia';
 import { useMissionStore } from '@/stores/mission';
+import { useFetchData } from '@/composables/fetchData';
 
 export default {
+  setup() {
+    const { loading, fetchData } = useFetchData();
+    return { loading, fetchData };
+  },
   props: {},
   data() {
     return {
-      dialogVisible: false
+      dialogVisible: false,
+      msgBoxVisible: false,
+      onConfirm: undefined
     };
   },
   computed: {
-    ...mapState(useMissionStore, ['missionList'])
+    ...mapStores(useMissionStore)
   },
   methods: {
-    createMission() {},
-    deleteMission(row) {},
+    deleteMission(row) {
+      this.onConfirm = () => {
+        this.missionStore.deleteMission(row.missionCode);
+      };
+      this.msgBoxVisible = true;
+    },
     timeFormatter(row, col, cellValue, index) {
       return moment(cellValue).format('YYYY-MM-DD HH:mm:ss');
     }
diff --git a/src/components/search/OptionLocation2.vue b/src/components/search/OptionLocation2.vue
new file mode 100644
index 0000000..4ebcdd2
--- /dev/null
+++ b/src/components/search/OptionLocation2.vue
@@ -0,0 +1,165 @@
+<template>
+  <!-- <el-form-item :label="placeholder" :prop="prop"> -->
+  <el-cascader
+    :model-value="formatedValue"
+    @change="handleChange"
+    :options="locations"
+    :placeholder="placeholder"
+    :props="optionProps"
+    size="small"
+    :style="'width: ' + width + 'px'"
+  />
+  <!-- </el-form-item> -->
+</template>
+
+<script>
+import { enumLocation } from '@/constant/location';
+
+export default {
+  props: {
+    // 鏄惁鍦ㄩ閫夐」澶勬坊鍔犫�滃叏閮ㄢ�濋�夐」
+    allOption: {
+      type: Boolean,
+      default: true
+    },
+    // 鏌ヨ鐨勮鏀跨骇鍒紝鍙栧��1锛�2锛�3锛�4, 5, 6
+    level: {
+      type: Number,
+      default: 4
+    },
+    // 缁撴灉杩斿洖
+    modelValue: Object,
+    // 鏄惁榛樿杩斿洖鍒濆閫夐」
+    initValue: {
+      type: Boolean,
+      default: true
+    },
+    // 鑳藉惁閫夋嫨浠绘剰涓�绾ч�夐」
+    checkStrictly: {
+      type: Boolean,
+      default: true
+    },
+    prop: {
+      type: String,
+      default: '_locations'
+    },
+    width: {
+      type: Number,
+      default: 220
+    }
+  },
+  emits: ['update:modelValue'],
+  data() {
+    return {
+      locations: enumLocation(this.allOption, this.level),
+      optionProps: {
+        checkStrictly: this.checkStrictly
+      }
+    };
+  },
+  computed: {
+    placeholder() {
+      const list = '鐪�/甯�/鍖�/闀�/闆�/鐗�'.split('/');
+      const p = [];
+      for (let i = 0; i < this.level; i++) {
+        p.push(list[i]);
+      }
+      return p.join('/');
+    },
+    formatedValue() {
+      return this.optionFormatReverse(this.modelValue);
+    }
+  },
+  methods: {
+    handleChange(value) {
+      this.$emit('update:modelValue', this.optionFormat(value));
+    },
+    /**
+     * 鍦板尯閫夐」缁撴灉鏍煎紡鍖�
+     */
+    optionFormat(val) {
+      const res = {
+        pCode: null,
+        pName: null,
+        cCode: null,
+        cName: null,
+        dCode: null,
+        dName: null,
+        tCode: null,
+        tName: null,
+        aCode: null,
+        aName: null,
+        mCode: null,
+        mName: null
+      };
+      if (val.length > 0) {
+        res.pCode = val[0][0];
+        res.pName = val[0][1];
+      }
+      if (val.length > 1) {
+        res.cCode = val[1][0];
+        res.cName = val[1][1];
+      }
+      if (val.length > 2) {
+        res.dCode = val[2][0];
+        res.dName = val[2][1];
+      }
+      if (val.length > 3) {
+        res.tCode = val[3][0];
+        res.tName = val[3][1];
+      }
+      if (val.length > 4) {
+        res.aCode = val[4][0];
+        res.aName = val[4][1];
+      }
+      if (val.length > 5) {
+        res.mCode = val[5][0];
+        res.mName = val[5][1];
+      }
+      return res;
+    },
+    optionFormatReverse(val) {
+      const res = [];
+      if (val) {
+        if (val.pName) {
+          res.push([val.pCode, val.pName]);
+        }
+        if (val.cName) {
+          res.push([val.cCode, val.cName]);
+        }
+        if (val.dName) {
+          res.push([val.dCode, val.dName]);
+        }
+        if (val.tName) {
+          res.push([val.tCode, val.tName]);
+        }
+        if (val.aName) {
+          res.push([val.aCode, val.aName]);
+        }
+        if (val.mName) {
+          res.push([val.mCode, val.mName]);
+        }
+      }
+      return res;
+    }
+  },
+  mounted() {
+    if (this.initValue) {
+      if (this.checkStrictly) {
+        this.handleChange([this.locations[0].value]);
+      } else {
+        const f = (location) => {
+          if (location.children && location.children.length > 0) {
+            const r = f(location.children[0]);
+            r.unshift(location.value);
+            return r;
+          } else {
+            return [location.value];
+          }
+        };
+        this.handleChange(f(this.locations[0]));
+      }
+    }
+  }
+};
+</script>
diff --git a/src/components/search/OptionMission.vue b/src/components/search/OptionMission.vue
index 5ac3d51..7ee4d9b 100644
--- a/src/components/search/OptionMission.vue
+++ b/src/components/search/OptionMission.vue
@@ -8,7 +8,7 @@
       class="w-150"
     >
       <el-option
-        v-for="(s, i) in missionList"
+        v-for="(s, i) in missionStore.missionList"
         :key="i"
         :label="s.missionCode"
         :value="i"
@@ -35,7 +35,6 @@
   emits: ['update:modelValue', 'change'],
   data() {
     return {
-      missionList: [],
       index: undefined
     };
   },
@@ -44,21 +43,22 @@
   },
   methods: {
     fetchMission() {
-      this.fetchData((page, pageSize) => {
-        return missionApi
-          .fethchMission({ type: this.type, page, pageSize })
-          .then((res) => {
-            this.missionList = res.data;
-            this.missionStore.missionList = res.data;
-            // if (this.missionList.length > 0) {
-            //   this.handleChange(0);
-            // }
-            return res.head;
-          });
-      });
+      // this.fetchData((page, pageSize) => {
+      //   return missionApi
+      //     .fethchMission({ type: this.type, page, pageSize })
+      //     .then((res) => {
+      //       this.missionList = res.data;
+      //       this.missionStore.missionList = res.data;
+      //       // if (this.missionList.length > 0) {
+      //       //   this.handleChange(0);
+      //       // }
+      //       return res.head;
+      //     });
+      // });
+      this.missionStore.fetchMission(this.type);
     },
     handleChange(value) {
-      this.$emit('update:modelValue', this.missionList[value]);
+      this.$emit('update:modelValue', this.missionStore.missionList[value]);
       // this.$emit('change', this.missionList[value]);
     }
   },
diff --git a/src/components/search/OptionTime.vue b/src/components/search/OptionTime.vue
index 4c504a8..29ccf19 100644
--- a/src/components/search/OptionTime.vue
+++ b/src/components/search/OptionTime.vue
@@ -1,5 +1,5 @@
 <template>
-  <el-form-item label="鏃堕棿">
+  <el-form-item label="鏃堕棿" prop="timeArray">
     <el-date-picker
       :model-value="modelValue"
       @update:model-value="handleChange"
diff --git a/src/composables/fetchData.js b/src/composables/fetchData.js
index fb8cff0..c1b4937 100644
--- a/src/composables/fetchData.js
+++ b/src/composables/fetchData.js
@@ -28,7 +28,7 @@
   // 鏁版嵁鑾峰彇
   function fetchData(fetch) {
     loadStatus.value = 1;
-    fetch(page.value, pageSize.value)
+    return fetch(page.value, pageSize.value)
       .then((pageInfo) => {
         if (pageInfo) {
           page.value = pageInfo.page ? pageInfo.page : 1;
diff --git a/src/composables/messageBox.js b/src/composables/messageBox.js
new file mode 100644
index 0000000..8606bd6
--- /dev/null
+++ b/src/composables/messageBox.js
@@ -0,0 +1,56 @@
+import { ElMessageBox, ElNotification, ElMessage } from 'element-plus';
+
+function useMessageBoxTip({
+  confirmMsg,
+  confirmTitle = '鎻愪氦',
+  doneMsg = confirmTitle,
+  onConfirm,
+}) {
+  ElMessageBox.confirm(confirmMsg, `${confirmTitle}纭`, {
+    confirmButtonText: '纭',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning',
+  })
+    .then(async () => {
+      let msg = `宸�${doneMsg}`
+      if (typeof onConfirm === 'function') {
+        const str = await onConfirm();
+        if (typeof str === 'string' && str != '') {
+          msg = `宸�${doneMsg}, ${str}`
+        }
+      }
+      ElNotification({
+        title: `${confirmTitle}鎴愬姛`,
+        message: msg,
+        type: 'success',
+        // offset: 170,
+        position: 'bottom-left',
+      });
+    })
+    .catch((err) => {
+      let errStr = `${confirmTitle}鍙栨秷`;
+      if (err != 'cancel') {
+        errStr = `${confirmTitle}澶辫触, ${err}`;
+      }
+      ElMessage({
+        message: errStr,
+        type: 'warning',
+      });
+    });
+}
+
+function useMessageBox({ confirmMsg, confirmTitle, onConfirm }) {
+  ElMessageBox.confirm(confirmMsg, confirmTitle, {
+    confirmButtonText: '纭',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning',
+  })
+    .then(async () => {
+      if (typeof onConfirm === 'function') {
+        onConfirm();
+      }
+    })
+    .catch(() => {});
+}
+
+export { useMessageBoxTip, useMessageBox };
diff --git a/src/constant/location.js b/src/constant/location.js
new file mode 100644
index 0000000..cf4054c
--- /dev/null
+++ b/src/constant/location.js
@@ -0,0 +1,257 @@
+/**
+ * 鑾峰彇琛屾斂鍖哄垝
+ * @param {Boolean} allOption 鏄惁鍦ㄥご閮ㄦ坊鍔犫�滃叏閮ㄢ�濋�夐」
+ * @param {Number} level 鑾峰彇鐨勫垎绫绘繁搴︼紝鑼冨洿 1 - 4
+ * @returns
+ */
+function enumLocation(allOption = true, level = 4) {
+  const l = _enumLocation();
+  if (!allOption) {
+    l.shift();
+  }
+  _deleteByLevel(l, level, 1);
+
+  return l;
+}
+
+function _enumLocation() {
+  return [
+    {
+      label: '鍏ㄥ競',
+      value: [null, '鍏ㄥ競']
+    },
+    {
+      label: '涓婃捣甯�',
+      value: ['31', '涓婃捣甯�'],
+      children: [
+        {
+          label: '涓婃捣甯�',
+          value: ['3100', '涓婃捣甯�'],
+          children: [
+            {
+              label: '閲戝北鍖�',
+              value: ['310116', '閲戝北鍖�'],
+              children: [
+                { label: '寮犲牥闀�', value: ['310116103', '寮犲牥闀�'] },
+                { label: '浜灄闀�', value: ['310116104', '浜灄闀�'] },
+                { label: '鍚曞贩闀�', value: ['310116105', '鍚曞贩闀�'] },
+                { label: '寤婁笅闀�', value: ['310116107', '寤婁笅闀�'] },
+                { label: '楂樻柊鍖�', value: ['310116503', '楂樻柊鍖�'] },
+                { label: '閲戝北鍗晣', value: ['310116109', '閲戝北鍗晣'] },
+                { label: '婕曟尘闀�', value: ['310116112', '婕曟尘闀�'] },
+                {
+                  label: '灞遍槼闀�',
+                  value: ['310116113', '灞遍槼闀�'],
+                  children: [
+                    {
+                      label: '涓囪揪骞垮満',
+                      value: ['31011611301', '涓囪揪骞垮満']
+                    }
+                  ]
+                },
+                { label: '鐭冲寲琛楅亾', value: ['310116001', '鐭冲寲琛楅亾'] },
+                { label: '鏈辨尘闀�', value: ['310116101', '鏈辨尘闀�'] },
+                { label: '鏋尘闀�', value: ['310116102', '鏋尘闀�'] },
+                { label: '纰宠胺缁挎咕', value: ['9000', '纰宠胺缁挎咕'] }
+              ]
+            },
+            {
+              label: '寰愭眹鍖�',
+              value: ['310104', '寰愭眹鍖�'],
+              children: [
+                {
+                  label: '婕曟渤娉炬柊鍏存妧鏈紑鍙戝尯',
+                  value: ['310104501', '婕曟渤娉炬柊鍏存妧鏈紑鍙戝尯']
+                },
+                { label: '婀栧崡璺閬�', value: ['310104004', '婀栧崡璺閬�'] },
+                { label: '澶╁钩璺閬�', value: ['310104003', '澶╁钩璺閬�'] },
+                { label: '铏规璺閬�', value: ['310104012', '铏规璺閬�'] },
+                { label: '鏋灄璺閬�', value: ['310104008', '鏋灄璺閬�'] },
+                { label: '鏂滃湡璺閬�', value: ['310104007', '鏂滃湡璺閬�'] },
+                { label: '闀挎ˉ琛楅亾', value: ['310104010', '闀挎ˉ琛楅亾'] },
+                {
+                  label: '鐢版灄琛楅亾',
+                  value: ['310104011', '鐢版灄琛楅亾'],
+                  children: [
+                    {
+                      label: '鐢板皻鍧�',
+                      value: ['31010401101', '鐢板皻鍧�']
+                    }
+                  ]
+                },
+                { label: '搴峰仴鏂版潙琛楅亾', value: ['310104013', '搴峰仴鏂版潙琛楅亾'] },
+                {
+                  label: '寰愬姹囪閬�',
+                  value: ['310104014', '寰愬姹囪閬�'],
+                  children: [
+                    {
+                      label: '澶╅挜妗�',
+                      value: ['31010401401', '澶╅挜妗�']
+                    }
+                  ]
+                },
+                { label: '鍑屼簯璺閬�', value: ['310104015', '鍑屼簯璺閬�'] },
+                { label: '榫欏崕琛楅亾', value: ['310104016', '榫欏崕琛楅亾'] },
+                { label: '婕曟渤娉捐閬�', value: ['310104017', '婕曟渤娉捐閬�'] },
+                { label: '鍗庢尘闀�', value: ['310104103', '鍗庢尘闀�'] }
+              ]
+            },
+            {
+              label: '闈欏畨鍖�',
+              value: ['310106', '闈欏畨鍖�'],
+              children: [
+                {
+                  label: '澶у畞璺閬�',
+                  value: ['310106019', '澶у畞璺閬�'],
+                  children: [
+                    {
+                      label: '涔呭厜涓績',
+                      value: ['31010601901', '涔呭厜涓績']
+                    }
+                  ]
+                },
+                { label: '褰郸鏂版潙琛楅亾', value: ['310106020', '褰郸鏂版潙琛楅亾'] },
+                { label: '涓存本璺閬�', value: ['310106021', '涓存本璺閬�'] },
+                { label: '鑺锋睙瑗胯矾琛楅亾', value: ['310106022', '鑺锋睙瑗胯矾琛楅亾'] },
+                {
+                  label: '褰郸闀�',
+                  value: ['310106101', '褰郸闀�'],
+                  children: [
+                    {
+                      label: '澶ц瀺鍩�',
+                      value: ['31010610101', '澶ц瀺鍩�']
+                    }
+                  ]
+                },
+                { label: '姹熷畞璺閬�', value: ['310106006', '姹熷畞璺閬�'] },
+                { label: '鐭抽棬浜岃矾琛楅亾', value: ['310106011', '鐭抽棬浜岃矾琛楅亾'] },
+                {
+                  label: '鍗椾含瑗胯矾琛楅亾',
+                  value: ['310106012', '鍗椾含瑗胯矾琛楅亾'],
+                  children: [
+                    {
+                      label: 'X88',
+                      value: ['31010601201', 'X88']
+                    }
+                  ]
+                },
+                { label: '闈欏畨瀵鸿閬�', value: ['310106013', '闈欏畨瀵鸿閬�'] },
+                {
+                  label: '鏇瑰娓¤閬�',
+                  value: ['310106014', '鏇瑰娓¤閬�'],
+                  children: [
+                    {
+                      label: '889',
+                      value: ['31010601401', '889']
+                    }
+                  ]
+                },
+                { label: '澶╃洰瑗胯矾琛楅亾', value: ['310106015', '澶╃洰瑗胯矾琛楅亾'] },
+                {
+                  label: '鍖楃珯琛楅亾',
+                  value: ['310106016', '鍖楃珯琛楅亾'],
+                  children: [
+                    {
+                      label: '澶ф偊鍩�',
+                      value: ['31010601601', '澶ф偊鍩�']
+                    }
+                  ]
+                },
+                { label: '瀹濆北璺閬�', value: ['310106017', '瀹濆北璺閬�'] },
+                { label: '鍏卞拰鏂拌矾琛楅亾', value: ['310106018', '鍏卞拰鏂拌矾琛楅亾'] }
+              ]
+            },
+            {
+              label: '鏅檧鍖�',
+              value: ['310107', '鏅檧鍖�'],
+              children: [
+                { label: '鏇规潹鏂版潙琛楅亾', value: ['310107005', '鏇规潹鏂版潙琛楅亾'] },
+                { label: '涓囬噷琛楅亾', value: ['310107021', '涓囬噷琛楅亾'] },
+                { label: '鐪熷闀囪閬�', value: ['310107022', '鐪熷闀囪閬�'] },
+                { label: '闀垮緛闀�', value: ['310107102', '闀垮緛闀�'] },
+                { label: '妗冩郸闀�', value: ['310107103', '妗冩郸闀�'] },
+                { label: '鐭虫硥璺閬�', value: ['310107017', '鐭虫硥璺閬�'] },
+                { label: '鐢樻硥璺閬�', value: ['310107016', '鐢樻硥璺閬�'] },
+                { label: '闀垮璺閬�', value: ['310107015', '闀垮璺閬�'] },
+                { label: '闀块鏂版潙琛楅亾', value: ['310107014', '闀块鏂版潙琛楅亾'] },
+                { label: '瀹滃窛璺閬�', value: ['310107020', '瀹滃窛璺閬�'] }
+              ]
+            },
+            {
+              label: '闂佃鍖�',
+              value: ['310112', '闂佃鍖�'],
+              children: [
+                { label: '姹熷窛璺閬�', value: ['310112001', '姹熷窛璺閬�'] },
+                { label: '鍙ょ編琛楅亾', value: ['310112006', '鍙ょ編琛楅亾'] },
+                { label: '鏂拌櫣琛楅亾', value: ['310112008', '鏂拌櫣琛楅亾'] },
+                { label: '娴﹂敠琛楅亾', value: ['310112009', '娴﹂敠琛楅亾'] },
+                { label: '鑾樺簞闀�', value: ['310112101', '鑾樺簞闀�'] },
+                { label: '涓冨疂闀�', value: ['310112102', '涓冨疂闀�'] },
+                { label: '棰涙ˉ闀�', value: ['310112103', '棰涙ˉ闀�'] },
+                { label: '鍗庢紩闀�', value: ['310112106', '鍗庢紩闀�'] },
+                { label: '铏规ˉ闀�', value: ['310112107', '铏规ˉ闀�'] },
+                { label: '姊呴檱闀�', value: ['310112108', '姊呴檱闀�'] },
+                { label: '鍚存尘闀�', value: ['310112110', '鍚存尘闀�'] },
+                { label: '椹ˉ闀�', value: ['310112112', '椹ˉ闀�'] },
+                { label: '娴︽睙闀�', value: ['310112114', '娴︽睙闀�'] },
+                { label: '鑾樺簞宸ヤ笟鍖�', value: ['310112501', '鑾樺簞宸ヤ笟鍖�'] }
+              ]
+            },
+            {
+              label: '闀垮畞鍖�',
+              value: ['310105', '闀垮畞鍖�'],
+              children: [
+                { label: '鍗庨槼璺閬�', value: ['310105001', '鍗庨槼璺閬�'] },
+                { label: '姹熻嫃璺閬�', value: ['310105002', '姹熻嫃璺閬�'] },
+                { label: '鏂板崕璺閬�', value: ['310105004', '鏂板崕璺閬�'] },
+                { label: '鍛ㄥ妗ヨ閬�', value: ['310105005', '鍛ㄥ妗ヨ閬�'] },
+                { label: '澶╁北璺閬�', value: ['310105006', '澶╁北璺閬�'] },
+                { label: '浠欓湠鏂版潙琛楅亾', value: ['310105008', '浠欓湠鏂版潙琛楅亾'] },
+                { label: '铏规ˉ琛楅亾', value: ['310105009', '铏规ˉ琛楅亾'] },
+                { label: '绋嬪妗ヨ閬�', value: ['310105010', '绋嬪妗ヨ閬�'] },
+                { label: '鍖楁柊娉捐閬�', value: ['310105011', '鍖楁柊娉捐閬�'] },
+                { label: '鏂版尘闀�', value: ['310105102', '鏂版尘闀�'] }
+              ]
+            },
+            {
+              label: '瀹濆北鍖�',
+              value: ['310113', '瀹濆北鍖�'],
+              children: []
+            },
+            {
+              label: '鍢夊畾鍖�',
+              value: ['310114', '鍢夊畾鍖�'],
+              children: []
+            },
+            {
+              label: '娴︿笢鏂板尯',
+              value: ['310115', '娴︿笢鏂板尯'],
+              children: []
+            }
+          ]
+        }
+      ]
+    }
+  ];
+}
+
+// 鎸夌収闇�姹傜殑瀹氫綅绮惧害杩斿洖瀵瑰簲鏁版嵁
+function _deleteByLevel(locations, level, step) {
+  if (step == level) {
+    locations.forEach((l) => {
+      if (l.children) {
+        l.children = undefined;
+      }
+    });
+    return;
+  } else {
+    step++;
+    locations.forEach((l) => {
+      if (l.children) {
+        _deleteByLevel(l.children, level, step);
+      }
+    });
+  }
+}
+
+export { enumLocation };
diff --git a/src/main.js b/src/main.js
index 06f7e7e..625b331 100644
--- a/src/main.js
+++ b/src/main.js
@@ -3,6 +3,10 @@
 import { createApp } from 'vue';
 import { createPinia } from 'pinia';
 import * as ElementPlusIconsVue from '@element-plus/icons-vue';
+import 'element-plus/theme-chalk/src/overlay.scss';
+import 'element-plus/theme-chalk/src/message.scss';
+import 'element-plus/theme-chalk/src/message-box.scss';
+import 'element-plus/theme-chalk/src/notification.scss';
 
 import App from './App.vue';
 import router from './router';
diff --git a/src/stores/mission.js b/src/stores/mission.js
index cb79aa8..37c2871 100644
--- a/src/stores/mission.js
+++ b/src/stores/mission.js
@@ -1,9 +1,42 @@
 import { ref } from 'vue';
 import { defineStore } from 'pinia';
+import missionApi from '@/api/missionApi';
+import { useFetchData } from '@/composables/fetchData';
 
 // 璧拌埅浠诲姟
 export const useMissionStore = defineStore('mission', () => {
   const missionList = ref([]);
+  const { loading, fetchData } = useFetchData();
 
-  return { missionList };
+  function fetchMission(type) {
+    return fetchData((page, pageSize) => {
+      return missionApi
+        .fethchMission({ type: type, page, pageSize })
+        .then((res) => {
+          missionList.value = res.data;
+          return res;
+        });
+    });
+  }
+
+  function deleteMission(missionCode) {
+    return fetchData(() => {
+      return missionApi.deleteMission(missionCode).then((res) => {
+        let index = -1;
+        for (let i = 0; i < missionList.value.length; i++) {
+          const e = missionList.value[i];
+          if (e.missionCode == missionCode) {
+            index = i;
+            break;
+          }
+        }
+        if (index != -1) {
+          missionList.value.splice(index, 1);
+        }
+        return res;
+      });
+    });
+  }
+
+  return { missionList, loading, fetchMission, deleteMission };
 });
diff --git a/src/styles/elementUI.scss b/src/styles/elementUI.scss
index fa8428e..b3203b6 100644
--- a/src/styles/elementUI.scss
+++ b/src/styles/elementUI.scss
@@ -23,6 +23,15 @@
   --el-button-active-border-color: transparent;
 }
 
+.el-button-custom-light {
+  --el-button-bg-color: var(--font-color);
+  --el-button-text-color: var(--bg-color);
+  --el-button-hover-text-color: var(--bg-color);
+  --el-button-hover-bg-color: var(--font-color);
+  --el-button-border-color: var(--bg-color);
+  --el-button-active-border-color: transparent;
+}
+
 .el-button-custom:focus-visible {
   outline: 0px solid var(--el-button-outline-color);
 }
diff --git a/src/utils/map/3dLayer.js b/src/utils/map/3dLayer.js
index af6ff34..72d0e14 100644
--- a/src/utils/map/3dLayer.js
+++ b/src/utils/map/3dLayer.js
@@ -30,6 +30,7 @@
   const fDatas = _factorDatas;
   const factor = _factor;
   drawMesh(fDatas, factor);
+  // console.log(map.getZoom());
 }
 
 var _maxHeight = 1000,
@@ -90,15 +91,12 @@
 /**
  * 缁樺浘
  */
-function drawMesh(fDatas, factor, center, merge) {
+function drawMesh(fDatas, factor, merge) {
   const lnglats_GD = fDatas.lnglats_GD;
   const coors = fDatas.coors_GD;
   const heights = factor.heights;
   const colors = factor.colors;
   const bColor = factor.bottomColor;
-  if (center) {
-    map.setZoomAndCenter(16, center);
-  }
 
   // eslint-disable-next-line no-undef
   var cylinder = new AMap.Object3D.Mesh();
@@ -198,23 +196,8 @@
       _maxH = maxH;
     }
 
-    // 3.纭畾瀹氫綅鍧愭爣鐐�
-    var center;
-    if (setCenter && lnglats_GD.length > 0) {
-      var p = lnglats_GD[0];
-      for (let i = 0; i < lnglats_GD.length; i++) {
-        const e = lnglats_GD[i];
-        if (e[0] != 0) {
-          p = e;
-          break;
-        }
-      }
-      // eslint-disable-next-line no-undef
-      center = new AMap.LngLat(...p);
-    }
-
     // 5.缁樺埗3D鍥惧舰
-    this.drawMesh(fDatas, factor, center, merge);
+    this.drawMesh(fDatas, factor, merge);
 
     // 缂╂斁鍦板浘鍒板悎閫傜殑瑙嗛噹绾у埆
     // map.setFitView()
diff --git a/src/utils/map/dialog.js b/src/utils/map/dialog.js
index e041443..900ac0c 100644
--- a/src/utils/map/dialog.js
+++ b/src/utils/map/dialog.js
@@ -33,7 +33,8 @@
       isCustom: true, //浣跨敤鑷畾涔夌獥浣�
       content: this.createWindowContent(m),
       // eslint-disable-next-line no-undef
-      offset: new AMap.Pixel(16, -45)
+      offset: new AMap.Pixel(16, -45),
+      autoMove: false
     });
     return m.window;
   },
diff --git a/src/utils/map/marks.js b/src/utils/map/marks.js
index c15f267..ba31891 100644
--- a/src/utils/map/marks.js
+++ b/src/utils/map/marks.js
@@ -3,8 +3,6 @@
  */
 
 import { map } from './index_old';
-import sector from './sector';
-import { DialogUtil } from './dialog';
 import { useToolboxStore } from '@/stores/toolbox';
 
 const toolboxStore = useToolboxStore();
@@ -21,10 +19,7 @@
     if (!toolboxStore.dataMarkerStatus) {
       return;
     }
-    if (_massMarks) {
-      map.remove(_massMarks);
-      _massMarks = undefined;
-    }
+    this.clearMassMarks();
     const lnglats = fDatas.lnglats_GD;
     var data = [];
     for (let i = 0; i < lnglats.length; i++) {
@@ -77,6 +72,12 @@
     _massMarks = massMarks;
     map.add(massMarks);
   },
+  clearMassMarks() {
+    if (_massMarks) {
+      map.remove(_massMarks);
+      _massMarks = undefined;
+    }
+  },
 
   createLabelMarks(img, dataList) {
     // eslint-disable-next-line no-undef
diff --git a/src/utils/map/sector.js b/src/utils/map/sector.js
index 0e3ced6..de4a8b5 100644
--- a/src/utils/map/sector.js
+++ b/src/utils/map/sector.js
@@ -1,6 +1,7 @@
 import { map, object3Dlayer } from './index_old';
 import calculate from './calculate';
 import imgLocation from '@/assets/mipmap/location.png';
+import { FactorDatas } from '@/model/FactorDatas';
 
 var _defaultDeg = 30,
   _sector = undefined,
@@ -76,7 +77,7 @@
           content: content,
           offset: [-35, 0],
           position: 'BM',
-          minZoom: 15
+          minZoom: 10
         }
       }
     ],
@@ -107,6 +108,9 @@
 }
 
 function drawSectorMesh(sDeg, eDeg, lnglat, distance, distance2) {
+  if (distance == 0 || distance2 == 0) {
+    return;
+  }
   // eslint-disable-next-line no-undef
   var sector = new AMap.Object3D.Mesh();
   sector.transparent = true;
@@ -124,16 +128,16 @@
     var angle1 = sDeg + unitDeg * i;
     var angle2 = sDeg + unitDeg * (i + 1);
 
-    var l1 = calculate.getLatLon(lnglat, distance, angle1);
-    var l2 = calculate.getLatLon(lnglat, distance, angle2);
-    var l3 = calculate.getLatLon(lnglat, distance2, angle1);
-    var l4 = calculate.getLatLon(lnglat, distance2, angle2);
+    var p1 = calculate.getLatLon(lnglat, distance, angle1);
+    var p2 = calculate.getLatLon(lnglat, distance, angle2);
+    var p3 = calculate.getLatLon(lnglat, distance2, angle1);
+    var p4 = calculate.getLatLon(lnglat, distance2, angle2);
 
-    var coors = calculate.lngLatToGeodeticCoord([l1, l2, l3, l4]);
-    l1 = coors[0];
-    l2 = coors[1];
-    l3 = coors[2];
-    l4 = coors[3];
+    var coors = calculate.lngLatToGeodeticCoord([p1, p2, p3, p4]);
+    const l1 = coors[0];
+    const l2 = coors[1];
+    const l3 = coors[2];
+    const l4 = coors[3];
 
     // 鍐呮祴鎵囧舰
     geometry.vertices.push(p0.x, p0.y, 0);
@@ -211,6 +215,9 @@
 }
 
 export default {
+  /**
+   * 娓呯┖鎵囧舰鍜屾枃鏈爣璁�
+   */
   clearSector() {
     var list = [];
     for (const iterator of _sectorViews) {
@@ -225,11 +232,20 @@
     }
     this.clearSectorMesh();
   },
+  /**
+   * 鍙竻绌烘墖褰�
+   */
   clearSectorMesh() {
     if (_sector) {
       object3Dlayer.remove(_sector);
     }
   },
+  /**
+   * 缁樺埗鎵囧舰
+   * @param {FactorDatas} fDatas
+   * @param {number} i
+   * @returns 鏁版嵁鍧愭爣鐐瑰拰鎵囧舰鏈�澶у崐寰�
+   */
   drawSector(fDatas, i) {
     if (_sector != undefined) {
       this.clearSector();
@@ -238,8 +254,14 @@
       sectorParams(fDatas, i);
     drawSectorMesh(sDeg, eDeg, lnglat, distance, distance2);
     drawElasticMarker(list, list2, distance, distance2);
+    return { p: lnglat, r: distance };
   },
 
+  /**
+   * 缁樺埗杞ㄨ抗鍔ㄧ敾涓殑鎵囧舰
+   * @param {FactorDatas} fDatas
+   * @param {number} i
+   */
   drawSectorAna(fDatas, i) {
     this.clearSectorMesh();
     const { sDeg, eDeg, lnglat, distance, distance2, list, list2 } =
diff --git a/src/utils/map/util.js b/src/utils/map/util.js
index 27871e9..ee73357 100644
--- a/src/utils/map/util.js
+++ b/src/utils/map/util.js
@@ -1,4 +1,65 @@
 import { map, isDragging } from '@/utils/map/index_old';
+import marks from '@/utils/map/marks';
+
+/**
+ * 鍧愭爣闆嗗悎鐨勬渶瑗垮崡瑙掑拰鏈�涓滃寳瑙�
+ * @param {*} list
+ *  list 鏄帴鍙h幏鍙栫殑鐐� 鐨勬暟缁�
+ */
+const getBound = (list) => {
+  const offset = 0.005;
+  let south = null;
+  let west = null;
+  let north = null;
+  let east = null;
+  for (let item of list) {
+    // 鎺掗櫎鏃犳晥缁忕含搴�
+    if (item[0] == 0 && item[1] == 0) {
+      continue;
+    }
+    if ((west && item[0] < west) || !west) {
+      west = item[0] - offset;
+    }
+    if ((south && item[1] < south) || !south) {
+      south = item[1] - offset;
+    }
+    if ((east && item[0] > east) || !east) {
+      east = item[0] + offset;
+    }
+    if ((north && item[1] > north) || !north) {
+      north = item[1] + offset;
+    }
+  }
+  if (!south || !west || !north || !east) {
+    return { sw: null, ne: null };
+  } else {
+    return { sw: [west, south], ne: [east, north] };
+  }
+};
+
+/**
+ * 鏍规嵁涓績鐐瑰嚭鍙戠殑鍗婂緞锛屽緱鍒板悎閫傜殑鍦板浘缂╂斁绯绘暟
+ * 楂樺痉鍦板浘缂╂斁绯绘暟姣忓噺灏�1锛屽垯鍦板浘灞曠ず鐨勫疄闄呰窛绂绘斁澶�1鍊�
+ * 楂樺痉鍦板浘缂╂斁绯绘暟鑼冨洿[3, 18]
+ * @param {*} d
+ */
+const distanceToZoom = (d) => {
+  let baseDis = 250,
+    z = 0;
+  while (baseDis < d) {
+    baseDis *= 2;
+    z++;
+  }
+
+  // 澶氫綑鐨勫湴鍥剧缉鏀剧郴鏁�
+  const x = (baseDis - d) / (baseDis / 2);
+  z -= x;
+  z = z < 0 ? 0 : z;
+
+  z = 18 - z;
+  z = z < 3 ? 3 : z;
+  return z;
+};
 
 export default {
   setCenter(lnglat) {
@@ -20,7 +81,29 @@
   removeViews(view) {
     map.remove(view);
   },
-  setFitView() {
-    map.setFitView();
+  clearMap() {
+    marks.clearMassMarks();
+    map.clearMap();
+  },
+  setFitView(views) {
+    if (views) {
+      map.setFitView(views);
+    } else {
+      map.setFitView();
+    }
+  },
+  setFitSector({ p, r }) {
+    this.setCenter(p);
+    const z = distanceToZoom(r);
+    map.setZoom(z);
+  },
+  setBound(lnglats_GD) {
+    const { sw, ne } = getBound(lnglats_GD);
+    if (!sw || !ne) {
+      return;
+    }
+    // eslint-disable-next-line no-undef
+    var mybounds = new AMap.Bounds(sw, ne); // sw, ne > [xxx,xxx], [xxx,xxx]
+    map.setBounds(mybounds);
   }
 };
diff --git a/src/views/historymode/HistoryMode.vue b/src/views/historymode/HistoryMode.vue
index 1b21f51..9421a94 100644
--- a/src/views/historymode/HistoryMode.vue
+++ b/src/views/historymode/HistoryMode.vue
@@ -50,6 +50,7 @@
 import Layer from '@/utils/map/3dLayer';
 import marks from '@/utils/map/marks';
 import sector from '@/utils/map/sector';
+import mapUtil from '@/utils/map/util';
 import { DialogUtil } from '@/utils/map/dialog';
 import monitorDataApi from '@/api/monitorDataApi';
 import { useFetchData } from '@/composables/fetchData';
@@ -58,6 +59,7 @@
 import { FactorDatas } from '@/model/FactorDatas';
 import TrendAnalysis from './component/TrendAnalysis.vue';
 import DataSheet from './component/DataSheet.vue';
+import { ElMessageBox, ElNotification, ElMessage } from 'element-plus';
 
 export default {
   components: { TrendAnalysis, DataSheet },
@@ -94,14 +96,31 @@
     }
   },
   methods: {
+    // 妫�鏌ユ暟鎹粡绾害鏄惁鍚堟硶
+    checkDataIsValid(index) {
+      const lnglats_GD = this.factorDatas.lnglats_GD[index];
+      const time = this.factorDatas.times[index];
+      if (lnglats_GD[0] == 0 && lnglats_GD[1] == 0) {
+        ElMessage({
+          message: `${time}鐨勬暟鎹粡绾害鏃犳晥`,
+          type: 'warning'
+        });
+        return false;
+      } else {
+        this.locateIndex = index;
+        return true;
+      }
+    },
     // 鐩戝惉鎶樼嚎鍥惧拰琛ㄦ牸鐨勭偣鍑讳簨浠�
     handelIndexChange(index) {
-      this.locateIndex = index;
-      this.drawSector(index);
+      if (this.checkDataIsValid(index)) {
+        this.drawSector(index);
+      }
     },
     draw() {
-      // todo 鍒锋柊鍥句緥
+      // 鍒锋柊鍥句緥
       const factor = this.factorDatas.factor[this.factorType];
+      sector.clearSector();
       this.drawRoadMap(factor);
       this.drawMassMarks(factor);
     },
@@ -116,13 +135,18 @@
       marks.drawMassMarks(this.factorDatas, e, (index) => {
         // 鏌ヨ鑼冨洿鍐呯殑鐩戞祴绔欑偣
         // SceneUtil.searchByCoordinate(lnglat[0], lnglat[1], distance);
-        this.drawSector(index);
-        this.locateIndex = index;
+        if (this.checkDataIsValid(index)) {
+          this.drawSector(index);
+        }
       });
+      // 璋冩暣鍦板浘瑙嗚
+      mapUtil.setBound(this.factorDatas.lnglats_GD);
     },
     drawSector(index) {
       // 1. 缁樺埗鏂版墖褰㈠尯鍩�
-      sector.drawSector(this.factorDatas, index);
+      const pr = sector.drawSector(this.factorDatas, index);
+      // 璋冩暣瑙嗚灞呬腑鏄剧ず
+      mapUtil.setFitSector(pr);
       // 2. 缁樺埗瀵硅瘽妗�
       DialogUtil.openNewWindow(this.factorDatas, index, () => {
         // 绉婚櫎鎵囧舰鍖哄煙
@@ -181,6 +205,9 @@
   },
   mounted() {
     this.fetchRealTimeData();
+  },
+  unmounted() {
+    mapUtil.clearMap();
   }
 };
 </script>

--
Gitblit v1.9.3