From 971c7c5993ff475157b0c9ed137998fd39f6c548 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期四, 17 十月 2024 17:17:33 +0800
Subject: [PATCH] 1. 完成总任务的管理模块(单日任务的管理未完成)

---
 src/views/fysp/task/MonitorObjEdit copy.vue           |  370 +++++++
 package-lock.json                                     |   11 
 src/api/fysp/domainApi.js                             |   18 
 src/components/search-option/FYOptionTime.vue         |   26 
 src/components.d.ts                                   |   11 
 src/constants/menu.js                                 |   26 
 src/views/fysp/task/components/CompTaskEdit.vue       |  342 +++++++
 src/components/search-option/FYOptionLocation.vue     |    3 
 src/utils/map/index_old.js                            |  117 ++
 src/components/map/BaseMap.vue                        |   43 
 src/api/fysp/sceneApi.js                              |    8 
 index.html                                            |   18 
 src/api/fysp/taskApi.js                               |   18 
 src/components/SearchBar.vue                          |   50 
 src/views/fysp/task/MonitorObjEdit.vue                |  378 -------
 src/components/map/SceneMap.vue                       |   12 
 src/views/fysp/task/components/CompTaskMap.vue        |    8 
 src/views/fysp/task/components/CompSubTaskSelect.vue  |  190 ++++
 src/views/fysp/task/components/CompMonitorObj.vue     |   60 
 src/views/fysp/task/MonitorTaskCreate.vue             |   93 +
 src/api/fysp/userApi.js                               |   21 
 src/components/core/BaseContentLayout.vue             |    6 
 src/components/form/FYForm.vue                        |   45 
 src/router/index.js                                   |    6 
 src/utils/map/marks.js                                |  149 +++
 src/views/fysp/task/TaskProxy.js                      |    8 
 src/views/fysp/task/components/CompMonitorObjEdit.vue |  451 +++++++++
 src/stores/toolbox.js                                 |   29 
 src/views/fysp/check/ProCheck.vue                     |    8 
 src/views/fysp/task/components/CompDayTask.vue        |  116 ++
 package.json                                          |    1 
 src/App.vue                                           |    4 
 src/views/fysp/task/components/CompSubTaskList.vue    |   40 
 src/views/fysp/task/TaskManage.vue                    |  112 +
 34 files changed, 2,350 insertions(+), 448 deletions(-)

diff --git a/index.html b/index.html
index 8cdc486..dc36b7f 100644
--- a/index.html
+++ b/index.html
@@ -1,13 +1,23 @@
-<!DOCTYPE html>
+<!doctype html>
 <html lang="en">
   <head>
-    <meta charset="UTF-8">
-    <link rel="icon" href="/favicon.ico">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta charset="UTF-8" />
+    <link rel="icon" href="/favicon.ico" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>鐢熸�佺幆澧冪嚎涓婄洃绠�</title>
   </head>
   <body>
     <div id="app"></div>
   </body>
+  <script type="text/javascript">
+    window._AMapSecurityConfig = {
+      serviceHost: 'http://47.100.191.150:8083/_AMapService'
+      //渚嬪 锛歴erviceHost:'http://1.1.1.1:80/_AMapService',
+    };
+  </script>
+  <script
+    type="text/javascript"
+    src="https://webapi.amap.com/maps?v=1.4.5&key=520c5e5cf44c7793104e500cbf0ed711&plugin=Map3D,ElasticMarker,AMap.ControlBar,AMap.Geocoder"
+  ></script>
   <script type="module" src="/src/main.js"></script>
 </html>
diff --git a/package-lock.json b/package-lock.json
index d934b3f..508cba5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
       "name": "supervision-vue",
       "version": "0.0.0",
       "dependencies": {
+        "@amap/amap-jsapi-loader": "^1.0.1",
         "@ctrl/tinycolor": "^4.0.2",
         "@element-plus/icons-vue": "^2.0.10",
         "@vueuse/core": "^9.7.0",
@@ -48,6 +49,11 @@
         "vite": "^3.2.5",
         "vitest": "^0.25.3"
       }
+    },
+    "node_modules/@amap/amap-jsapi-loader": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
+      "integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw=="
     },
     "node_modules/@ampproject/remapping": {
       "version": "2.2.0",
@@ -7679,6 +7685,11 @@
     }
   },
   "dependencies": {
+    "@amap/amap-jsapi-loader": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
+      "integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw=="
+    },
     "@ampproject/remapping": {
       "version": "2.2.0",
       "dev": true,
diff --git a/package.json b/package.json
index 2aa6804..0f208cb 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
     "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
   },
   "dependencies": {
+    "@amap/amap-jsapi-loader": "^1.0.1",
     "@ctrl/tinycolor": "^4.0.2",
     "@element-plus/icons-vue": "^2.0.10",
     "@vueuse/core": "^9.7.0",
diff --git a/src/App.vue b/src/App.vue
index 05d5a06..998905c 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -21,9 +21,9 @@
               <Content></Content>
               <!-- <el-backtop
                 target=".el-main .el-scrollbar__wrap"
-                :right="40"
+                :right="10"
                 :bottom="100"
-                style="width: 120px;z-index: 1000;"
+                style="z-index: 1000;"
               >
                 <div class="back-top">
                   <el-icon><ArrowUpBold /></el-icon>
diff --git a/src/api/fysp/domainApi.js b/src/api/fysp/domainApi.js
new file mode 100644
index 0000000..dfd5d1d
--- /dev/null
+++ b/src/api/fysp/domainApi.js
@@ -0,0 +1,18 @@
+import { $fysp } from '../index';
+
+export default {
+  // 鑾峰彇宸℃煡浠诲姟绫诲瀷
+  fetchTaskType() {
+    return $fysp.get(`domainitem/taskType`).then((res) => res.data);
+  },
+
+  // 鑾峰彇宸℃煡浠诲姟鏈熼檺绫诲瀷
+  fetchDeadlineType() {
+    return $fysp.get(`domainitem/deadlineType`).then((res) => res.data);
+  },
+
+  // 鑾峰彇宸℃煡浠诲姟灞傛绫诲瀷
+  fetchLevelType() {
+    return $fysp.get(`domainitem/level`).then((res) => res.data);
+  }
+};
diff --git a/src/api/fysp/sceneApi.js b/src/api/fysp/sceneApi.js
index 88fec3b..a5159c3 100644
--- a/src/api/fysp/sceneApi.js
+++ b/src/api/fysp/sceneApi.js
@@ -67,6 +67,14 @@
   updateScene(scene) {
     return $fysp.post('scense', scene).then((res) => res.data);
   },
+
+  /**
+   * 鎵归噺鏇存柊鍦烘櫙
+   */
+  updateSceneList(sceneList) {
+    return $fysp.post('scense/update/list', sceneList).then((res) => res.data);
+  },
+
   /**
    * 鑾峰彇鎵�鏈夊満鏅被鍨�
    */
diff --git a/src/api/fysp/taskApi.js b/src/api/fysp/taskApi.js
index da5ef7a..d7f918b 100644
--- a/src/api/fysp/taskApi.js
+++ b/src/api/fysp/taskApi.js
@@ -2,12 +2,30 @@
 
 export default {
   /**
+   * 鏂板缓浠诲姟
+   * @param {Object} task 
+   */
+  putTask(task){
+    return $fysp.put(`task/create`, task).then((res) => res.data);
+  },
+  /**
+   * 鏍规嵁涓婚敭鑾峰彇鎬讳换鍔℃垨鏃ヤ换鍔�
+   */
+  fetchTaskById(id){
+    return $fysp.get(`task/${id}`).then((res) => res.data);
+  },
+
+  /**
    * 鑾峰彇椤跺眰浠诲姟
    */
   getTopTask() {
     return $fysp.get('task/alltask/0').then((res) => res.data);
   },
 
+  getLastTopTask(task){
+    return $fysp.post(`task/lastTask`, task).then((res) => res.data);
+  },
+
   /**
    * 鑾峰彇鎬讳换鍔$殑鐩戠鍦烘櫙鐗堟湰淇℃伅
    */
diff --git a/src/api/fysp/userApi.js b/src/api/fysp/userApi.js
index a69250e..022c9be 100644
--- a/src/api/fysp/userApi.js
+++ b/src/api/fysp/userApi.js
@@ -19,7 +19,9 @@
    * 鑾峰彇鍦烘櫙鐨勭敤鎴疯鎯�
    */
   getUserByScene(sId) {
-    return $fysp.get(`userinfo/scene/get?sceneId=${sId}`).then((res) => res.data);
+    return $fysp
+      .get(`userinfo/scene/get?sceneId=${sId}`)
+      .then((res) => res.data);
   },
 
   /**
@@ -28,10 +30,19 @@
   autoCreateAccount(sId) {
     return $fysp.post(`userinfo/create?sceneId=${sId}`).then((res) => res.data);
   },
-   /**
- * 鑾峰彇鍦烘櫙瀵瑰簲鐨勯缇界幆澧冪郴缁熺敤鎴穒d
- */
-   getTzId(sceneId) {
+  /**
+   * 鑾峰彇鍦烘櫙瀵瑰簲鐨勯缇界幆澧冪郴缁熺敤鎴穒d
+   */
+  getTzId(sceneId) {
     return $fysp.get(`usermap?sceneId=${sceneId}`).then((res) => res.data);
+  },
+
+  /**
+   * 鎸夌敤鎴风被鍨嬭幏鍙栫敤鎴蜂俊鎭�
+   */
+  getUserByType(typeId, enable = true) {
+    return $fysp
+      .get(`userinfo/type/get`, { params: { typeId, enable } })
+      .then((res) => res.data);
   }
 };
diff --git a/src/components.d.ts b/src/components.d.ts
index ec0d630..271a7c8 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -8,12 +8,14 @@
 declare module '@vue/runtime-core' {
   export interface GlobalComponents {
     BaseContentLayout: typeof import('./components/core/BaseContentLayout.vue')['default']
+    BaseMap: typeof import('./components/map/BaseMap.vue')['default']
     BasePanelLayout: typeof import('./components/core/BasePanelLayout.vue')['default']
     CompQuickSet: typeof import('./components/search-option/CompQuickSet.vue')['default']
     Content: typeof import('./components/core/Content.vue')['default']
     ElAffix: typeof import('element-plus/es')['ElAffix']
     ElAside: typeof import('element-plus/es')['ElAside']
     ElAvatar: typeof import('element-plus/es')['ElAvatar']
+    ElBacktop: typeof import('element-plus/es')['ElBacktop']
     ElBadge: typeof import('element-plus/es')['ElBadge']
     ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
     ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
@@ -22,11 +24,13 @@
     ElCalendar: typeof import('element-plus/es')['ElCalendar']
     ElCard: typeof import('element-plus/es')['ElCard']
     ElCascader: typeof import('element-plus/es')['ElCascader']
+    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElCollapse: typeof import('element-plus/es')['ElCollapse']
     ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElContainer: typeof import('element-plus/es')['ElContainer']
+    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
     ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
     ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
@@ -39,6 +43,8 @@
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElImage: typeof import('element-plus/es')['ElImage']
     ElInput: typeof import('element-plus/es')['ElInput']
+    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
+    ElLink: typeof import('element-plus/es')['ElLink']
     ElMain: typeof import('element-plus/es')['ElMain']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
@@ -46,10 +52,12 @@
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
     ElPagination: typeof import('element-plus/es')['ElPagination']
+    ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
     ElPopover: typeof import('element-plus/es')['ElPopover']
     ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
+    ElScorllbar: typeof import('element-plus/es')['ElScorllbar']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSegmented: typeof import('element-plus/es')['ElSegmented']
     ElSelect: typeof import('element-plus/es')['ElSelect']
@@ -57,12 +65,14 @@
     ElStep: typeof import('element-plus/es')['ElStep']
     ElSteps: typeof import('element-plus/es')['ElSteps']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
+    ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
+    ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     Footer: typeof import('./components/core/Footer.vue')['default']
@@ -91,6 +101,7 @@
     MenuItems: typeof import('./components/core/MenuItems.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
+    SceneMap: typeof import('./components/map/SceneMap.vue')['default']
     SearchBar: typeof import('./components/SearchBar.vue')['default']
     SideList: typeof import('./components/SideList.vue')['default']
     SiderMenu: typeof import('./components/core/SiderMenu.vue')['default']
diff --git a/src/components/SearchBar.vue b/src/components/SearchBar.vue
index 2cb74e0..b137a36 100644
--- a/src/components/SearchBar.vue
+++ b/src/components/SearchBar.vue
@@ -4,7 +4,11 @@
       <el-form :inline="true" :model="formSearch">
         <el-form-item label="鎬讳换鍔�">
           <!-- <el-input v-model="formSearch.topTaskId" placeholder="鎬讳换鍔�" /> -->
-          <el-select v-model="formSearch.topTaskId" placeholder="鎬讳换鍔�" style="width: 260px">
+          <el-select
+            v-model="formSearch.topTaskId"
+            placeholder="鎬讳换鍔�"
+            style="width: 260px"
+          >
             <el-option
               v-for="s in topTasks"
               :key="s.value"
@@ -14,7 +18,11 @@
           </el-select>
         </el-form-item>
         <el-form-item label="鍦烘櫙绫诲瀷">
-          <el-select v-model="formSearch.sceneTypeId" placeholder="鍦烘櫙绫诲瀷" style="width: 150px">
+          <el-select
+            v-model="formSearch.sceneTypeId"
+            placeholder="鍦烘櫙绫诲瀷"
+            style="width: 150px"
+          >
             <el-option
               v-for="s in sceneTypes"
               :key="s.value"
@@ -38,7 +46,7 @@
 
 <script>
 import taskApi from '@/api/fysp/taskApi';
-import { enumScene } from "@/enum/scene";
+import { enumScene } from '@/enum/scene';
 
 export default {
   emits: ['onSubmit'],
@@ -48,42 +56,44 @@
       sceneTypes: enumScene(2, false),
       formSearch: {
         topTaskId: '',
-        sceneTypeId: '',
-        obj: '',
-      },
+        sceneTypeId: ''
+      }
     };
   },
   methods: {
     //鑾峰彇鏌ヨ鏉′欢
     getOptions() {
       taskApi.getTopTask().then((res) => {
-        const list = [];
-        res.forEach((r) => {
-          list.push({
+        const list = res.map((r) => {
+          return {
             value: r.tguid,
             label: r.name,
-            obj: r,
-            towncode: r.towncode,
-            districtCode: r.districtcode,
-            month: r.starttime.slice(0, 7),
-          });
+            data: r
+          };
         });
         this.topTasks = list;
         this.formSearch.topTaskId = list[0].value;
-        this.formSearch.obj = list[0].obj;
-        this.$emit('onSubmit', this.formSearch);
+        this.onSubmit();
       });
     },
     //鏌ヨ瀛愪换鍔$粺璁′俊鎭�
     onSubmit() {
-      // console.log(this.formSearch.sceneTypeId)
-      this.$emit('onSubmit', this.formSearch);
-    },
+      const task = this.topTasks.find(
+        (t) => t.data.tguid == this.formSearch.topTaskId
+      );
+      const param = {
+        topTask: task ? task.data : {},
+        sceneTypeId: this.formSearch.sceneTypeId
+      };
+      console.log(param);
+
+      this.$emit('onSubmit', param);
+    }
   },
   mounted() {
     this.formSearch.sceneTypeId = this.sceneTypes[0].value;
     this.getOptions();
-  },
+  }
 };
 </script>
 
diff --git a/src/components/core/BaseContentLayout.vue b/src/components/core/BaseContentLayout.vue
index ce92424..46135f0 100644
--- a/src/components/core/BaseContentLayout.vue
+++ b/src/components/core/BaseContentLayout.vue
@@ -30,14 +30,16 @@
       if (this.$refs.headerRef) {
         const h1 = this.$refs.headerRef.$el.offsetHeight;
         const h = h1;
-        return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`;
+        return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2 + 6px)`;
       } else {
         return `calc(100vh - 60px * 2 - var(--el-main-padding) * 2)`;
       }
     }
   },
   mounted() {
-    this.mainHeight = this.calHeight();
+    setTimeout(() => {
+      this.mainHeight = this.calHeight();
+    }, 150);
   }
 };
 </script>
diff --git a/src/components/form/FYForm.vue b/src/components/form/FYForm.vue
index 9c5405e..f8654cc 100644
--- a/src/components/form/FYForm.vue
+++ b/src/components/form/FYForm.vue
@@ -9,10 +9,16 @@
   >
     <slot name="form-item" :formObj="formObj"></slot>
     <el-form-item v-if="showButtons">
-      <el-button :disabled="!edit" type="primary" @click="onSubmit" :loading="loading"
-        >鎻愪氦</el-button
+      <el-button
+        :disabled="!edit"
+        type="primary"
+        @click="onSubmit"
+        :loading="loading"
+        >{{ submitName }}</el-button
       >
-      <el-button v-if="useReset" :disabled="!edit" @click="onReset">閲嶇疆</el-button>
+      <el-button v-if="useReset" :disabled="!edit" @click="onReset"
+        >閲嶇疆</el-button
+      >
       <el-button v-if="useCancel" @click="onCancel">鍙栨秷</el-button>
     </el-form-item>
   </el-form>
@@ -26,7 +32,15 @@
  * 鍙紶鍏ュ垵濮嬭〃鍗曟暟鎹甪ormInfo锛岃〃鍗曟牎楠岃鍒檙ules
  * 瀹炵幇submit鍜宑ancel瑙﹀彂鍑芥暟
  */
-import { defineProps, defineEmits, reactive, ref, watch, computed, defineExpose } from 'vue';
+import {
+  defineProps,
+  defineEmits,
+  reactive,
+  ref,
+  watch,
+  computed,
+  defineExpose
+} from 'vue';
 import { useFormConfirm } from '@/composables/formConfirm';
 
 const props = defineProps({
@@ -42,6 +56,10 @@
   showButtons: {
     type: Boolean,
     default: true
+  },
+  submitName: {
+    type: String,
+    default: '鎻愪氦'
   },
   //鍙栨秷鎸夐挳鏄惁鍙敤
   useCancel: Boolean,
@@ -81,14 +99,15 @@
 });
 
 //琛ㄥ崟鎿嶄綔鍑芥暟
-const { formObj, formRef, edit, onSubmit, onCancel, onReset, clear } = useFormConfirm({
-  submit: {
-    do: submit
-  },
-  cancel: {
-    do: cancel
-  }
-});
+const { formObj, formRef, edit, onSubmit, onCancel, onReset, clear } =
+  useFormConfirm({
+    submit: {
+      do: submit
+    },
+    cancel: {
+      do: cancel
+    }
+  });
 
 //鍔犺浇鐘舵��
 const loading = ref(false);
@@ -106,7 +125,7 @@
       },
       (err) => {
         loading.value = false;
-        reject(err);
+        reject(err ? err : '');
       }
     );
   });
diff --git a/src/components/map/BaseMap.vue b/src/components/map/BaseMap.vue
new file mode 100644
index 0000000..2da91ff
--- /dev/null
+++ b/src/components/map/BaseMap.vue
@@ -0,0 +1,43 @@
+<template>
+  <div id="container"></div>
+</template>
+
+<script setup>
+import { onMounted } from 'vue';
+import { createMap } from '@/utils/map/index_old';
+onMounted(() => {
+  // 楂樺痉鍦板浘鍒濆鍖�
+  createMap('container');
+});
+</script>
+<style>
+#container {
+  position: relative;
+  width: 100%;
+  height: 100vh;
+  min-height: var(--screen-min-height);
+  min-width: var(--screen-min-width);
+  z-index: 0px;
+}
+
+/* 鍘婚櫎楂樺痉鍦板浘鐨勫浐瀹氱増鍙峰浘鏍� */
+.amap-logo {
+  display: none;
+  opacity: 0 !important;
+}
+.amap-copyright {
+  display: none;
+  opacity: 0 !important;
+}
+
+.amap-marker-label {
+  font-size: 13px;
+  text-align: center;
+  color: white;
+  background-color: transparent;
+  text-shadow: black 2px 2px 2px;
+  border-radius: 2px;
+  border: 0px;
+  padding: 4px;
+}
+</style>
diff --git a/src/components/map/SceneMap.vue b/src/components/map/SceneMap.vue
new file mode 100644
index 0000000..60e7038
--- /dev/null
+++ b/src/components/map/SceneMap.vue
@@ -0,0 +1,12 @@
+<template>
+  <div style="width: 70vw; height: 500px; background-color: aliceblue">
+    <BaseMap></BaseMap>
+  </div>
+</template>
+<script setup>
+const props = defineProps({
+  // 鍦烘櫙鐐逛綅淇℃伅
+  data: Array
+});
+</script>
+<style scoped></style>
diff --git a/src/components/search-option/FYOptionLocation.vue b/src/components/search-option/FYOptionLocation.vue
index 6a13c96..821cb2a 100644
--- a/src/components/search-option/FYOptionLocation.vue
+++ b/src/components/search-option/FYOptionLocation.vue
@@ -43,7 +43,7 @@
       default: '_locations'
     }
   },
-  emits: ['update:value'],
+  emits: ['update:value', 'change'],
   data() {
     return {
       locations: enumLocation(this.allOption, this.level),
@@ -68,6 +68,7 @@
   methods: {
     handleChange(value) {
       this.$emit('update:value', this.optionFormat(value));
+      this.$emit('change', this.optionFormat(value));
     },
     /**
      * 鍦板尯閫夐」缁撴灉鏍煎紡鍖�
diff --git a/src/components/search-option/FYOptionTime.vue b/src/components/search-option/FYOptionTime.vue
index ac1292c..82e2a64 100644
--- a/src/components/search-option/FYOptionTime.vue
+++ b/src/components/search-option/FYOptionTime.vue
@@ -1,10 +1,12 @@
 <template>
-  <el-form-item label="鏃堕棿" :prop="prop">
+  <el-form-item :label="label" :prop="prop">
     <el-date-picker
       v-model="date"
       @change="handleChange"
       :type="type"
       placeholder="閫夋嫨鏃堕棿"
+      start-placeholder="閫夋嫨寮�濮嬫椂闂�"
+      end-placeholder="閫夋嫨缁撴潫鏃堕棿"
       style="width: 150px"
     />
   </el-form-item>
@@ -15,6 +17,7 @@
 
 const MONTH = 'month';
 const DATE = 'date';
+const RANGE = 'datetimerange';
 
 export default {
   props: {
@@ -23,30 +26,37 @@
       default: MONTH
     },
     // 杩斿洖缁撴灉
-    value: Date,
+    value: Date || Array,
     // 鏄惁榛樿杩斿洖鍒濆閫夐」
     initValue: {
       type: Boolean,
       default: true
     },
-    prop: String
+    label: {
+      type: String,
+      default: '鏃堕棿'
+    },
+    prop: {
+      type: String,
+      default: 'time'
+    }
   },
-  emits: ['update:value'],
+  emits: ['update:value', 'change'],
   data() {
     return {
       date: this.value
     };
   },
-  computed:{
-  },
+  computed: {},
   methods: {
     handleChange(value) {
       this.$emit('update:value', value);
-    },
+      this.$emit('change', value);
+    }
   },
   mounted() {
     if (this.initValue) {
-      this.date = new Date()
+      this.date = new Date();
       this.handleChange(this.date);
     }
   }
diff --git a/src/constants/menu.js b/src/constants/menu.js
index 6633452..741fa96 100644
--- a/src/constants/menu.js
+++ b/src/constants/menu.js
@@ -15,25 +15,31 @@
   //   ]
   // },
   {
-    path: '/fysp/task/manage',
-    icon: 'CircleCheck',
-    name: '鐩戠浠诲姟'
-  },
-  {
     path: '/fysp/procheck',
     icon: 'CircleCheck',
     name: '闂瀹℃牳'
+  },
+  {
+    icon: 'List',
+    name: '浠诲姟绠$悊',
+    children: [
+      {
+        path: '/fysp/task/manage',
+        icon: 'CircleCheck',
+        name: '鐩戠浠诲姟',
+      },
+      {
+        path: '/fysp/sceneInfo',
+        icon: 'Files',
+        name: '鍦烘櫙淇℃伅',
+      },
+    ],
   },
   // {
   //   path: '/changecheck',
   //   icon: 'Search',
   //   name: '鏁存敼瀹℃牳',
   // },
-  {
-    path: '/fysp/sceneInfo',
-    icon: 'Files',
-    name: '鍦烘櫙淇℃伅'
-  },
   {
     icon: 'DocumentChecked',
     name: '鑷姩璇勪及',
diff --git a/src/router/index.js b/src/router/index.js
index c56817d..f30d22c 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -79,6 +79,12 @@
     component: () => import('@/views/fysp/task/MonitorPlanEdit.vue')
   },
   {
+    //鐩戠浠诲姟璁″垝缂栬緫
+    name: 'monitorTaskCreate',
+    path: '/fysp/task/create',
+    component: () => import('@/views/fysp/task/MonitorTaskCreate.vue')
+  },
+  {
     //闂瀹℃牳
     name: 'procheck',
     path: '/fysp/procheck',
diff --git a/src/stores/toolbox.js b/src/stores/toolbox.js
new file mode 100644
index 0000000..93a5cf3
--- /dev/null
+++ b/src/stores/toolbox.js
@@ -0,0 +1,29 @@
+import { ref } from 'vue';
+import { defineStore } from 'pinia';
+
+export const useToolboxStore = defineStore('toolbox', () => {
+  // 寮�鍏冲湴鐗╂爣娉�
+  const featuresStatus = ref(false);
+  // 寮�鍏冲崼鏄熷湴鍥�
+  const satelliteStatus = ref(false);
+  // 寮�鍏虫帶鍒剁綏鐩�
+  const controlbarStatus = ref(false);
+  // 寮�鍏冲潗鏍囨嬀鍙�
+  const coorPickStatus = ref(false);
+  // 寮�鍏虫暟鎹爣璁�
+  const dataMarkerStatus = ref(true);
+  // 寮�鍏虫暟鎹脊妗�
+  const dataDialogStatus = ref(true);
+  // 寮�鍏虫函婧愭竻鍗�
+  const sceneSearchStatus = ref(true);
+
+  return {
+    featuresStatus,
+    satelliteStatus,
+    controlbarStatus,
+    coorPickStatus,
+    dataMarkerStatus,
+    dataDialogStatus,
+    sceneSearchStatus
+  };
+});
diff --git a/src/utils/map/index_old.js b/src/utils/map/index_old.js
new file mode 100644
index 0000000..3ed5b1b
--- /dev/null
+++ b/src/utils/map/index_old.js
@@ -0,0 +1,117 @@
+/* eslint-disable no-undef */
+// import '@/lib/AMap';
+import { useToolboxStore } from '@/stores/toolbox';
+
+const toolboxStore = useToolboxStore();
+
+var mapInitDone = false;
+var onMapMountedEvents = [];
+
+// 鍦板浘瀵硅薄
+var map;
+// 鍗槦鍥惧眰
+var satellite;
+// 鍦板浘鎷栧姩鎺у埗
+var controlbar;
+// 榧犳爣缁樺浘
+var mouseTool;
+// 3D鍥惧眰
+var object3Dlayer;
+// 鍦板浘鎷栧姩鐘舵��
+var isDragging = false;
+
+// 鍦板浘鍔犺浇瀹屾垚瑙﹀彂
+function onMapMounted(...events) {
+  if (mapInitDone) {
+    events.forEach((e) => {
+      e();
+    });
+  } else {
+    onMapMountedEvents = onMapMountedEvents.concat(events);
+  }
+}
+
+function createMap(id) {
+  _initMap(id);
+  mapInitDone = true;
+  onMapMountedEvents.forEach((e) => {
+    e();
+  });
+  onMapMountedEvents = [];
+}
+
+function _initMap(elementId) {
+  map = new AMap.Map(elementId, {
+    rotateEnable: true,
+    pitchEnable: true,
+    alwaysRender: false,
+    showLabel: true,
+    showBuildingBlock: true,
+    mapStyle: 'amap://styles/e1e78509de64ddcd2efb4cb34c6fae2a',
+    features: ['bg', 'road'],
+    pitch: 45, // 鍦板浘淇话瑙掑害锛屾湁鏁堣寖鍥� 0 搴�- 83 搴�
+    viewMode: '3D', // 鍦板浘妯″紡
+    resizeEnable: true,
+    center: [121.6039283, 31.25295567],
+    zooms: [0, 18],
+    zoom: 14
+  });
+
+  // 娣诲姞鍗槦鍦板浘
+  satellite = new AMap.TileLayer.Satellite();
+  satellite.show();
+  map.add([satellite]);
+  toolboxStore.featuresStatus = true;
+
+  // _initControlbar();
+  // _initMouseTool();
+  _init3DLayer();
+  _initDragEvent();
+}
+
+function _initControlbar() {
+  controlbar = new AMap.ControlBar({
+    position: {
+      right: '300px',
+      top: '260px'
+    }
+  });
+  map.addControl(controlbar);
+  toolboxStore.controlbarStatus = true;
+}
+
+// 榧犳爣缁樺浘鍒濆鍖�
+// function _initMouseTool() {
+//   mouseTool = new AMap.MouseTool(map);
+// }
+
+// 3D鍥惧眰鍒濆鍖�
+function _init3DLayer() {
+  object3Dlayer = new AMap.Object3DLayer();
+  map.add(object3Dlayer);
+}
+
+// 璁剧疆鍦板浘鎷栨嫿鐩戝惉浜嬩欢
+function _initDragEvent() {
+  let dragEndEvent;
+  map.on('dragstart', () => {
+    clearTimeout(dragEndEvent);
+    isDragging = true;
+  });
+  map.on('dragend', function () {
+    dragEndEvent = setTimeout(() => {
+      isDragging = false;
+    }, 8000);
+  });
+}
+
+export {
+  createMap,
+  onMapMounted,
+  map,
+  controlbar,
+  mouseTool,
+  satellite,
+  object3Dlayer,
+  isDragging
+};
diff --git a/src/utils/map/marks.js b/src/utils/map/marks.js
new file mode 100644
index 0000000..a72dcdf
--- /dev/null
+++ b/src/utils/map/marks.js
@@ -0,0 +1,149 @@
+/**
+ * 楂樺痉鍦板浘鐐规爣璁扮粯鍒剁浉鍏�
+ */
+
+import { map } from './index_old';
+import { useToolboxStore } from '@/stores/toolbox';
+
+const toolboxStore = useToolboxStore();
+
+var _massMarks = undefined;
+
+export default {
+  /**
+   * 缁樺埗娴烽噺鐐规爣璁�
+   * @param fDatas 瀹屾暣鐩戞祴鏁版嵁
+   * @param _factor 褰撳墠灞曠ず鐨勭洃娴嬪洜瀛愬璞�
+   */
+  drawMassMarks(fDatas, _factor, onClick) {
+    if (!toolboxStore.dataMarkerStatus) {
+      return;
+    }
+    this.clearMassMarks();
+    const lnglats = fDatas.lnglats_GD;
+    var data = [];
+    for (let i = 0; i < lnglats.length; i++) {
+      data.push({
+        lnglat: lnglats[i], //鐐规爣璁颁綅缃�
+        name: `${fDatas.times[i]}<br/>${_factor.factorName}: ${_factor.datas[i].factorData} mg/m鲁`,
+        id: i
+      });
+    }
+
+    // 鍒涘缓鏍峰紡瀵硅薄
+    var styleObject = {
+      url: 'https://a.amap.com/jsapi_demos/static/images/mass1.png',
+      // url: './asset/mipmap/ic_up_white.png', // 鍥炬爣鍦板潃
+      // eslint-disable-next-line no-undef
+      size: new AMap.Size(11, 11), // 鍥炬爣澶у皬
+      // eslint-disable-next-line no-undef
+      anchor: new AMap.Pixel(5, 5) // 鍥炬爣鏄剧ず浣嶇疆鍋忕Щ閲忥紝鍩哄噯鐐逛负鍥炬爣宸︿笂瑙�
+    };
+    // eslint-disable-next-line no-undef
+    var massMarks = new AMap.MassMarks(data, {
+      zIndex: 5, // 娴烽噺鐐瑰浘灞傚彔鍔犵殑椤哄簭
+      zooms: [15, 18], // 鍦ㄦ寚瀹氬湴鍥剧缉鏀剧骇鍒寖鍥村唴灞曠ず娴烽噺鐐瑰浘灞�
+      style: styleObject // 璁剧疆鏍峰紡瀵硅薄
+    });
+    massMarks.on('click', (event) => {
+      const i = event.data.id;
+      // 3. 鑷畾涔夌偣鍑讳簨浠�
+      onClick(i);
+    });
+    // eslint-disable-next-line no-undef
+    var marker = new AMap.Marker({
+      content: ' ',
+      map: map,
+      // eslint-disable-next-line no-undef
+      offset: new AMap.Pixel(13, 12)
+    });
+    var timeout;
+    massMarks.on('mouseover', (e) => {
+      if (timeout) {
+        clearTimeout(timeout);
+      }
+      marker.setPosition(e.data.lnglat);
+      marker.setLabel({ content: e.data.name });
+      map.add(marker);
+      timeout = setTimeout(() => {
+        map.remove(marker);
+      }, 2000);
+    });
+    _massMarks = massMarks;
+    map.add(massMarks);
+  },
+  clearMassMarks() {
+    if (_massMarks) {
+      map.remove(_massMarks);
+      _massMarks = undefined;
+    }
+  },
+
+  /**
+   * 鍒涘缓鏍囪鐐�
+   * @param {string | Array} img 鍥炬爣鎴栧浘鏍囨暟缁�
+   * @param {Array} dataList 鐩戞祴鏁版嵁
+   * @param {boolean} collision 鏍囨敞閬胯
+   * @returns
+   */
+  createLabelMarks(img, dataList, collision = true) {
+    // eslint-disable-next-line no-undef
+    const layer = new AMap.LabelsLayer({
+      zooms: [3, 20],
+      zIndex: 1000,
+      // 寮�鍚爣娉ㄩ伩璁╋紝榛樿涓哄紑鍚紝v1.4.15 鏂板灞炴��
+      collision: collision,
+      // 寮�鍚爣娉ㄦ贰鍏ュ姩鐢伙紝榛樿涓哄紑鍚紝v1.4.15 鏂板灞炴��
+      animation: true
+    });
+
+    map.add(layer);
+
+    // var markers = [];
+    for (var i = 0; i < dataList.length; i++) {
+      const data = dataList[i];
+      var curData = {
+        name: data.name,
+        position: [data.longitude, data.latitude],
+        zooms: [10, 20],
+        opacity: 1,
+        zIndex: 10,
+        icon: {
+          type: 'image',
+          image: typeof img === 'string' ? img : img[i],
+          // clipOrigin: [14, 92],
+          // clipSize: [50, 68],
+          size: [30, 30],
+          anchor: 'bottom-center',
+          angel: 0,
+          retina: true
+        },
+        text: {
+          content: data.name,
+          direction: 'top',
+          offset: [0, -5],
+          style: {
+            fontSize: 16,
+            fontWeight: 'normal',
+            fillColor: '#fff',
+            strokeColor: '#333',
+            strokeWidth: 0,
+            backgroundColor: '#122b54a9'
+          }
+        }
+      };
+      curData.extData = {
+        index: i
+      };
+
+      // eslint-disable-next-line no-undef
+      var labelMarker = new AMap.LabelMarker(curData);
+
+      // markers.push(labelMarker);
+
+      layer.add(labelMarker);
+    }
+
+    return layer;
+  }
+};
diff --git a/src/views/fysp/check/ProCheck.vue b/src/views/fysp/check/ProCheck.vue
index 1fc2217..0554694 100644
--- a/src/views/fysp/check/ProCheck.vue
+++ b/src/views/fysp/check/ProCheck.vue
@@ -253,12 +253,16 @@
     },
     //鏌ヨ瀛愪换鍔$粺璁′俊鎭�
     search(formSearch) {
-      this.topTask = formSearch.obj;
+      this.topTask = formSearch.topTask;
       this.sideLoading = true;
       this.mainLoading = true;
       this.curProList = [];
       this.curSubtask = {};
-      taskApi.getSubtaskSummary(formSearch).then((res) => {
+      const param = {
+        topTaskId: formSearch.topTask.tguid, 
+        sceneTypeId :formSearch.sceneTypeId
+      }
+      taskApi.getSubtaskSummary(param).then((res) => {
         const list = [];
         res.forEach((s) => {
           const t = this.getSubtaskType(s);
diff --git a/src/views/fysp/task/MonitorObjEdit copy.vue b/src/views/fysp/task/MonitorObjEdit copy.vue
new file mode 100644
index 0000000..820b1e5
--- /dev/null
+++ b/src/views/fysp/task/MonitorObjEdit copy.vue
@@ -0,0 +1,370 @@
+<template>
+  <el-affix :offset="60" target=".el-main">
+    <div class="page-header">
+      <el-page-header @back="goBack">
+        <template #content>
+          <span> {{title}} </span>
+        </template>
+        <template #extra>
+          <div>
+            <el-button type="primary" :disabled="!isEdit" :loading="saveLoading" @click="saveEdit"
+              >淇濆瓨淇敼</el-button
+            >
+          </div>
+        </template>
+      </el-page-header>
+      <!-- <el-divider /> -->
+    </div>
+  </el-affix>
+  <el-row gutter="20">
+    <el-col :span="16">
+      <div>
+        <el-text>宸查�夊満鏅�</el-text>
+      </div>
+      <el-divider />
+      <CompMonitorObj
+        :data="curMonitorObjList"
+        show-btn
+        v-model:tabName="curSceneType"
+        v-model:showData="showMonitorObjList"
+        :tabOptions="sceneTypeOptions"
+        @item-click="deleteMov"
+      >
+      </CompMonitorObj>
+    </el-col>
+    <el-col :span="8">
+      <el-affix :offset="140">
+        <div>
+          <el-text>鍙�夊満鏅�</el-text>
+        </div>
+        <el-divider />
+        <div>
+          <el-segmented v-model="curSceneType" :options="sceneTypeOptions" />
+        </div>
+        <FYInfoSearch
+          placeholder="璇疯緭鍏ュ満鏅悕绉板叧閿瓧"
+          :data="showSceneList"
+          :on-search="searchScene"
+          :total="total"
+          scroll-height="65vh"
+          :page-show="false"
+        >
+          <template #default="{ row }">
+            <ItemScene :item="row">
+              <el-button-group>
+                <el-button size="small" type="primary" @click="openInsertDialog(row)"
+                  >鎻掑叆</el-button
+                >
+                <el-button size="small" type="primary" @click="openAddDialog(row)">鏂板</el-button>
+              </el-button-group>
+            </ItemScene>
+          </template>
+        </FYInfoSearch>
+      </el-affix>
+    </el-col>
+  </el-row>
+
+  <el-dialog v-model="insertDialog" title="鎻掑叆鍦烘櫙鑷崇┖浣欑紪鍙�" width="500">
+    <div v-if="valibleIndex.length > 0">浠ヤ笅涓哄彲閫夌殑绌轰綑缂栧彿</div>
+    <div v-else>鏃犲彲閫夌殑绌轰綑缂栧彿</div>
+    <el-radio-group v-model="selectedIndex" size="default">
+      <el-radio-button v-for="item in valibleIndex" :key="item" :label="item" :value="item" />
+    </el-radio-group>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="insertDialog = false">鍙栨秷</el-button>
+        <el-button :disabled="!selectedIndex" type="primary" @click="insertMov"> 纭 </el-button>
+      </div>
+    </template>
+  </el-dialog>
+  <el-dialog v-model="addDialog" title="鏂板鍦烘櫙缂栧彿椤哄欢" width="500">
+    <div>椤哄欢缂栧彿涓�:{{ lastIndex }}</div>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="addDialog = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="addMov"> 纭 </el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+import CompMonitorObj from './components/CompMonitorObj.vue';
+import svUserApi from '@/api/fysp/userApi';
+import taskApi from '@/api/fysp/taskApi';
+import sceneApi from '@/api/fysp/sceneApi';
+import { ElMessage, ElNotification, ElMessageBox } from 'element-plus';
+
+export default {
+  async beforeRouteLeave(to, from) {
+    // 鍦ㄥ鑸寮�娓叉煋璇ョ粍浠剁殑瀵瑰簲璺敱鏃惰皟鐢�
+    // 涓� `beforeRouteUpdate` 涓�鏍凤紝瀹冨彲浠ヨ闂粍浠跺疄渚� `this`
+    // return this.routerChangeCheck();
+  },
+  components: { CompMonitorObj },
+  props: {
+    title:{
+      type:String,
+      default: '鎬讳换鍔$紪杈�'
+    },
+
+  },
+  data() {
+    return {
+      // 鐩戠鍦烘櫙
+      curMonitorObjList: [],
+      // 褰撳墠绛涢�夌殑鍦烘櫙绫诲瀷
+      curSceneType: undefined,
+      showMonitorObjList: [],
+
+      // 琛屾斂鍖哄垝
+      area: {},
+      // 鎵�鏈夊満鏅�
+      sceneList: [],
+      total: 0,
+
+      // 鎻掑叆寮瑰嚭妗�
+      insertDialog: false,
+      // 鎻掑叆鎴栨柊澧炵殑缂栧彿
+      selectedIndex: undefined,
+      // 鎻掑叆鎴栨柊澧炵殑鍦烘櫙
+      selectedScene: undefined,
+      // 鐩戠娆℃暟
+      monitorTimes: 1,
+      // 鏂板寮瑰嚭妗�
+      addDialog: false,
+      // 鏂板鐨勭洃绠″満鏅�
+      insertObj: [],
+      // 鏇存柊鐨勭洃绠″満鏅�
+      updateObj: [],
+      // 鍒犻櫎鐨勭洃绠″満鏅�
+      deleteObj: []
+    };
+  },
+  computed: {
+    // 褰撳墠鍦烘櫙绫诲瀷涓嬬殑灞曠ず鍦烘櫙
+    showSceneList() {
+      return this.sceneList.filter((v) => {
+        const index = this.curMonitorObjList.findIndex((o) => {
+          return o.sguid == v.guid;
+        });
+        return index == -1 && v.type == this.curSceneType;
+      });
+    },
+    sceneTypeOptions() {
+      const list = [];
+      this.sceneList.forEach((d) => {
+        if (list.indexOf(d.type) == -1) list.push(d.type);
+      });
+      return list;
+    },
+    // 褰撳墠鍦烘櫙绫诲瀷涓嬬殑鍙彃鍏ョ紪鍙�
+    valibleIndex() {
+      // 鍘熷垪琛ㄥ凡缁忔寜鐓х紪鍙烽『搴忔帓鍒�
+      let index = 1;
+      const indexList = [];
+      this.showMonitorObjList.forEach((l) => {
+        while (l.displayid > index) {
+          indexList.push(index);
+          index++;
+        }
+        index++;
+      });
+      if (this.showMonitorObjList.length == 0 && indexList.length == 0) {
+        indexList.push(1);
+      }
+      return indexList;
+    },
+    lastIndex() {
+      const len = this.showMonitorObjList.length;
+      if (len > 0) {
+        return this.showMonitorObjList[len - 1].displayid + 1;
+      } else {
+        return 1;
+      }
+    },
+    isEdit() {
+      return this.insertObj.length > 0 || this.deleteObj.length > 0 || this.updateObj.length > 0;
+    }
+  },
+  methods: {
+    // 鏌ヨ
+    searchScene({ text, page, pageSize }) {
+      this.area.sceneName = text;
+      return sceneApi.searchScene(this.area, 1, 10000).then((res) => {
+        if (res.success) {
+          // 鏌ヨ缁撴灉
+          this.sceneList = res.data;
+          // 鎬绘暟鎹噺
+          this.total = res.head.totalCount;
+        }
+      });
+    },
+    deleteMov(item) {
+      if (item.extension1) {
+        ElMessage({
+          message: '宸茬洃绠″満鏅棤娉曠Щ闄�',
+          type: 'error'
+        });
+        return;
+      }
+      const i = this.curMonitorObjList.indexOf(item);
+      this.curMonitorObjList.splice(i, 1);
+      const i1 = this.insertObj.indexOf(item);
+      this.insertObj.splice(i1, 1);
+      const i2 = this.updateObj.indexOf(item);
+      this.updateObj.splice(i2, 1);
+
+      this.deleteObj.push(item);
+    },
+    openInsertDialog(item) {
+      this.insertDialog = true;
+      this.selectedScene = item;
+      this.monitorTimes = 1;
+    },
+    openAddDialog(item) {
+      this.addDialog = true;
+      this.selectedScene = item;
+      this.monitorTimes = 1;
+    },
+    insertMov() {
+      // 1. 鍒涘缓鏂板満鏅�
+      let mov = this.createMov(this.selectedIndex, this.selectedScene);
+      // 2. 鏌ユ壘绗竴涓紪鍙峰ぇ浜庢彃鍏ョ紪鍙风殑鍊硷紝灏嗘柊鐩戠瀵硅薄鎻掑叆鍏朵箣鍓�
+      const insertAtIndex = this.curMonitorObjList.findIndex((v) => {
+        return v.displayid > this.selectedIndex;
+      });
+      this.curMonitorObjList.splice(insertAtIndex, 0, mov);
+      this.selectedIndex = undefined;
+      this.insertDialog = false;
+    },
+    addMov() {
+      // 1. 鍒涘缓鏂板満鏅�
+      let mov = this.createMov(this.lastIndex, this.selectedScene);
+      // 2. 娣诲姞鑷虫湯灏�
+      this.curMonitorObjList.push(mov);
+      this.addDialog = false;
+    },
+    // 鍒涘缓涓�涓柊鐨勭洃绠″璞�
+    createMov(displayid, scene) {
+      // 1. 鏌ユ壘璇ュ満鏅槸鍚︿箣鍓嶅凡琚垹闄�
+      const index = this.deleteObj.findIndex((v) => {
+        return v.sguid == scene.guid;
+      });
+      let mov;
+      // 2. 鑻ユ槸鍏ㄦ柊鐨勫満鏅紝鍒欐柊鐢熸垚涓�涓洃绠″璞★紝鍚﹀垯鍙洿鏂扮紪鍙�
+      if (index == -1) {
+        mov = {
+          tid: this.task.tguid,
+          sguid: scene.guid,
+          sensename: scene.name,
+          tasktypeid: 1,
+          tasktype: '宸℃煡',
+          monitornum: this.monitorTimes,
+          displayid: displayid,
+          sceneTypeId: scene.typeid,
+          sceneType: scene.type
+        };
+        this.insertObj.push(mov);
+      } else {
+        mov = this.deleteObj[index];
+        mov.displayid = displayid;
+        this.updateObj.push(mov);
+        this.deleteObj.splice(index, 1);
+      }
+      return mov;
+    },
+    // 淇濆瓨淇敼
+    saveEdit() {
+      // this.saveLoading = true;
+      if (this.insertObj.length > 0) {
+        const p1 = taskApi.addMonitorObject(this.insertObj).then((res) => {
+          ElNotification({
+            title: `宸℃煡浠诲姟鏂板瀹屾垚`,
+            message: `鏂板鍦烘櫙${res}涓猔,
+            type: 'success',
+            position: 'bottom-left'
+          });
+          this.insertObj = [];
+        });
+      }
+      if (this.updateObj.length > 0) {
+        const p2 = taskApi.updateMonitorObject(this.updateObj).then((res) => {
+          ElNotification({
+            title: `宸℃煡浠诲姟鏇存柊瀹屾垚`,
+            message: `鏇存柊鍦烘櫙${res}涓猔,
+            type: 'success',
+            position: 'bottom-left'
+          });
+          this.updateObj = [];
+        });
+      }
+      if (this.deleteObj.length > 0) {
+        const p3 = taskApi.deleteMonitorObject(this.deleteObj).then((res) => {
+          ElNotification({
+            title: `宸℃煡浠诲姟鍒犻櫎瀹屾垚`,
+            message: `鍒犻櫎鍦烘櫙${res}涓猔,
+            type: 'success',
+            position: 'bottom-left'
+          });
+          this.deleteObj = [];
+        });
+      }
+      // return Promise.all([p1, p2, p3]).finally(() => {
+      //   this.saveLoading = false;
+      // });
+    },
+    async goBack() {
+      // const answer = await this.routerChangeCheck()
+      // if (answer) {
+      //   this.$router.back();
+      // }
+      this.$router.back();
+    },
+    async routerChangeCheck() {
+      if (this.isEdit) {
+        const answer = await ElMessageBox.confirm('鏄惁鏀惧純宸蹭慨鏀圭殑鎬讳换鍔★紵', '鍙栨秷鎬讳换鍔′慨鏀�', {
+          confirmButtonText: '纭',
+          cancelButtonText: '鍙栨秷',
+          type: 'warning'
+        })
+          .then(() => {
+            return true;
+          })
+          .catch(() => {
+            return false;
+          });
+        return answer;
+      }
+      return true;
+    }
+  },
+  mounted() {
+    // 鐩戠鍦烘櫙淇℃伅
+    this.curMonitorObjList = JSON.parse(decodeURIComponent(this.$route.query.data));
+    // 鏍规嵁鎬讳换鍔¤幏鍙栬鏀垮尯鍒掍俊鎭�
+    const task = JSON.parse(decodeURIComponent(this.$route.query.task));
+    this.task = task;
+    this.area = {
+      provincecode: task.provincecode,
+      provincename: task.provincename,
+      citycode: task.citycode,
+      cityname: task.cityname,
+      districtcode: task.districtcode,
+      districtname: task.districtname,
+      towncode: task.towncode,
+      townname: task.townname,
+      online: true
+    };
+    this.searchScene({ text: '' });
+  }
+};
+</script>
+
+<style scoped>
+.page-header {
+  background-color: white;
+  padding: 10px 0;
+  border-bottom: 1px solid var(--el-color-info-light-7);
+}
+</style>
diff --git a/src/views/fysp/task/MonitorObjEdit.vue b/src/views/fysp/task/MonitorObjEdit.vue
index 636899b..3479166 100644
--- a/src/views/fysp/task/MonitorObjEdit.vue
+++ b/src/views/fysp/task/MonitorObjEdit.vue
@@ -1,5 +1,5 @@
 <template>
-  <el-affix :offset="60">
+  <el-affix :offset="60" target=".el-main">
     <div class="page-header">
       <el-page-header @back="goBack">
         <template #content>
@@ -7,7 +7,11 @@
         </template>
         <template #extra>
           <div>
-            <el-button type="primary" :disabled="!isEdit" :loading="saveLoading" @click="saveEdit"
+            <el-button
+              type="primary"
+              :disabled="!isEdit"
+              :loading="saveLoading"
+              @click="handleSaveClick"
               >淇濆瓨淇敼</el-button
             >
           </div>
@@ -16,346 +20,54 @@
       <el-divider />
     </div>
   </el-affix>
-  <el-row gutter="20">
-    <el-col :span="16">
-      <div>
-        <el-text>宸查�夊満鏅�</el-text>
-      </div>
-      <el-divider />
-      <CompMonitorObj
-        :data="curMonitorObjList"
-        show-btn
-        v-model:tabName="curSceneType"
-        v-model:showData="showMonitorObjList"
-        :tabOptions="sceneTypeOptions"
-        @item-click="deleteMov"
-      >
-      </CompMonitorObj>
-    </el-col>
-    <el-col :span="8">
-      <el-affix :offset="140">
-        <div>
-          <el-text>鍙�夊満鏅�</el-text>
-        </div>
-        <el-divider />
-        <div>
-          <el-segmented v-model="curSceneType" :options="sceneTypeOptions" />
-        </div>
-        <FYInfoSearch
-          placeholder="璇疯緭鍏ュ満鏅悕绉板叧閿瓧"
-          :data="showSceneList"
-          :on-search="searchScene"
-          :total="total"
-          scroll-height="70vh"
-          :page-show="false"
-        >
-          <template #default="{ row }">
-            <ItemScene :item="row">
-              <el-button-group>
-                <el-button size="small" type="primary" @click="openInsertDialog(row)"
-                  >鎻掑叆</el-button
-                >
-                <el-button size="small" type="primary" @click="openAddDialog(row)">鏂板</el-button>
-              </el-button-group>
-            </ItemScene>
-          </template>
-        </FYInfoSearch>
-      </el-affix>
-    </el-col>
-  </el-row>
-
-  <el-dialog v-model="insertDialog" title="鎻掑叆鍦烘櫙鑷崇┖浣欑紪鍙�" width="500">
-    <div>浠ヤ笅涓哄彲閫夌殑绌轰綑缂栧彿</div>
-    <el-radio-group v-model="selectedIndex" size="default">
-      <el-radio-button v-for="item in valibleIndex" :key="item" :label="item" :value="item" />
-    </el-radio-group>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button @click="insertDialog = false">鍙栨秷</el-button>
-        <el-button :disabled="!selectedIndex" type="primary" @click="insertMov"> 纭 </el-button>
-      </div>
-    </template>
-  </el-dialog>
-  <el-dialog v-model="addDialog" title="鏂板鍦烘櫙缂栧彿椤哄欢" width="500">
-    <div>椤哄欢缂栧彿涓�:{{ lastIndex }}</div>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button @click="addDialog = false">鍙栨秷</el-button>
-        <el-button type="primary" @click="addMov"> 纭 </el-button>
-      </div>
-    </template>
-  </el-dialog>
+  <CompMonitorObjEdit
+    ref="objEditRef"
+    :task="task"
+    :objList="curMonitorObjList"
+    @upload-success="goBack"
+  ></CompMonitorObjEdit>
 </template>
 
-<script>
-import CompMonitorObj from './components/CompMonitorObj.vue';
-import svUserApi from '@/api/fysp/userApi';
-import taskApi from '@/api/fysp/taskApi';
-import sceneApi from '@/api/fysp/sceneApi';
-import { ElMessage, ElNotification, ElMessageBox } from 'element-plus';
+<script setup>
+import { ref, computed, onMounted } from 'vue';
+import CompMonitorObjEdit from './components/CompMonitorObjEdit.vue';
+import { useRoute, useRouter } from 'vue-router';
 
-export default {
-  async beforeRouteLeave(to, from) {
-    // 鍦ㄥ鑸寮�娓叉煋璇ョ粍浠剁殑瀵瑰簲璺敱鏃惰皟鐢�
-    // 涓� `beforeRouteUpdate` 涓�鏍凤紝瀹冨彲浠ヨ闂粍浠跺疄渚� `this`
-    // return this.routerChangeCheck();
-  },
-  components: { CompMonitorObj },
-  props: {},
-  data() {
-    return {
-      // 鐩戠鍦烘櫙
-      curMonitorObjList: [],
-      // 褰撳墠绛涢�夌殑鍦烘櫙绫诲瀷
-      curSceneType: undefined,
-      showMonitorObjList: [],
+const route = useRoute();
+const router = useRouter();
 
-      // 琛屾斂鍖哄垝
-      area: {},
-      // 鎵�鏈夊満鏅�
-      sceneList: [],
-      total: 0,
+const objEditRef = ref(null);
+const curMonitorObjList = ref([]);
+const task = ref({});
 
-      // 鎻掑叆寮瑰嚭妗�
-      insertDialog: false,
-      // 鎻掑叆鎴栨柊澧炵殑缂栧彿
-      selectedIndex: undefined,
-      // 鎻掑叆鎴栨柊澧炵殑鍦烘櫙
-      selectedScene: undefined,
-      // 鐩戠娆℃暟
-      monitorTimes: 1,
-      // 鏂板寮瑰嚭妗�
-      addDialog: false,
-      // 鏂板鐨勭洃绠″満鏅�
-      insertObj: [],
-      // 鏇存柊鐨勭洃绠″満鏅�
-      updateObj: [],
-      // 鍒犻櫎鐨勭洃绠″満鏅�
-      deleteObj: []
-    };
-  },
-  computed: {
-    // 褰撳墠鍦烘櫙绫诲瀷涓嬬殑灞曠ず鍦烘櫙
-    showSceneList() {
-      return this.sceneList.filter((v) => {
-        const index = this.curMonitorObjList.findIndex((o) => {
-          return o.sguid == v.guid;
-        });
-        return index == -1 && v.type == this.curSceneType;
-      });
-    },
-    sceneTypeOptions() {
-      const list = [];
-      this.sceneList.forEach((d) => {
-        if (list.indexOf(d.type) == -1) list.push(d.type);
-      });
-      return list;
-    },
-    // 褰撳墠鍦烘櫙绫诲瀷涓嬬殑鍙彃鍏ョ紪鍙�
-    valibleIndex() {
-      // 鍘熷垪琛ㄥ凡缁忔寜鐓х紪鍙烽『搴忔帓鍒�
-      let index = 1;
-      const indexList = [];
-      this.showMonitorObjList.forEach((l) => {
-        while (l.displayid > index) {
-          indexList.push(index);
-          index++;
-        }
-        index++;
-      });
-      if (indexList.length == 0) {
-        indexList.push(1);
-      }
-      return indexList;
-    },
-    lastIndex() {
-      const len = this.showMonitorObjList.length;
-      if (len > 0) {
-        return this.showMonitorObjList[len - 1].displayid + 1;
-      } else {
-        return 1;
-      }
-    },
-    isEdit() {
-      return this.insertObj.length > 0 || this.deleteObj.length > 0 || this.updateObj.length > 0;
-    }
-  },
-  methods: {
-    // 鏌ヨ
-    searchScene({ text, page, pageSize }) {
-      this.area.sceneName = text;
-      return sceneApi.searchScene(this.area, 1, 10000).then((res) => {
-        if (res.success) {
-          // 鏌ヨ缁撴灉
-          this.sceneList = res.data;
-          // 鎬绘暟鎹噺
-          this.total = res.head.totalCount;
-        }
-      });
-    },
-    deleteMov(item) {
-      if (item.extension1) {
-        ElMessage({
-          message: '宸茬洃绠″満鏅棤娉曠Щ闄�',
-          type: 'error'
-        });
-        return;
-      }
-      const i = this.curMonitorObjList.indexOf(item);
-      this.curMonitorObjList.splice(i, 1);
-      const i1 = this.insertObj.indexOf(item);
-      this.insertObj.splice(i1, 1);
-      const i2 = this.updateObj.indexOf(item);
-      this.updateObj.splice(i2, 1);
+const isEdit = computed(() => {
+  return objEditRef.value ? objEditRef.value.isEdit : false;
+});
 
-      this.deleteObj.push(item);
-    },
-    openInsertDialog(item) {
-      this.insertDialog = true;
-      this.selectedScene = item;
-      this.monitorTimes = 1;
-    },
-    openAddDialog(item) {
-      this.addDialog = true;
-      this.selectedScene = item;
-      this.monitorTimes = 1;
-    },
-    insertMov() {
-      // 1. 鍒涘缓鏂板満鏅�
-      let mov = this.createMov(this.selectedIndex, this.selectedScene);
-      // 2. 鏌ユ壘绗竴涓紪鍙峰ぇ浜庢彃鍏ョ紪鍙风殑鍊硷紝灏嗘柊鐩戠瀵硅薄鎻掑叆鍏朵箣鍓�
-      const insertAtIndex = this.curMonitorObjList.findIndex((v) => {
-        return v.displayid > this.selectedIndex;
-      });
-      this.curMonitorObjList.splice(insertAtIndex, 0, mov);
-      this.selectedIndex = undefined;
-      this.insertDialog = false;
-    },
-    addMov() {
-      // 1. 鍒涘缓鏂板満鏅�
-      let mov = this.createMov(this.lastIndex, this.selectedScene);
-      // 2. 娣诲姞鑷虫湯灏�
-      this.curMonitorObjList.push(mov);
-      this.addDialog = false;
-    },
-    // 鍒涘缓涓�涓柊鐨勭洃绠″璞�
-    createMov(displayid, scene) {
-      // 1. 鏌ユ壘璇ュ満鏅槸鍚︿箣鍓嶅凡琚垹闄�
-      const index = this.deleteObj.findIndex((v) => {
-        return v.sguid == scene.guid;
-      });
-      let mov;
-      // 2. 鑻ユ槸鍏ㄦ柊鐨勫満鏅紝鍒欐柊鐢熸垚涓�涓洃绠″璞★紝鍚﹀垯鍙洿鏂扮紪鍙�
-      if (index == -1) {
-        mov = {
-          tid: this.task.tguid,
-          sguid: scene.guid,
-          sensename: scene.name,
-          tasktypeid: 1,
-          tasktype: '宸℃煡',
-          monitornum: this.monitorTimes,
-          displayid: displayid,
-          sceneTypeId: scene.typeid,
-          sceneType: scene.type
-        };
-        this.insertObj.push(mov);
-      } else {
-        mov = this.deleteObj[index];
-        mov.displayid = displayid;
-        this.updateObj.push(mov);
-        this.deleteObj.splice(index, 1);
-      }
-      return mov;
-    },
-    // 淇濆瓨淇敼
-    saveEdit() {
-      // this.saveLoading = true;
-      if (this.insertObj.length > 0) {
-        const p1 = taskApi.addMonitorObject(this.insertObj).then((res) => {
-          ElNotification({
-            title: `宸℃煡浠诲姟淇敼鎴愬姛`,
-            message: `鏂板鍦烘櫙${res}涓猔,
-            type: 'success',
-            position: 'bottom-left'
-          });
-          this.insertObj = [];
-        });
-      }
-      if (this.updateObj.length > 0) {
-        const p2 = taskApi.updateMonitorObject(this.updateObj).then((res) => {
-          ElNotification({
-            title: `宸℃煡浠诲姟淇敼鎴愬姛`,
-            message: `鏇存柊鍦烘櫙${res}涓猔,
-            type: 'success',
-            position: 'bottom-left'
-          });
-          this.updateObj = [];
-        });
-      }
-      if (this.deleteObj.length > 0) {
-        const p3 = taskApi.deleteMonitorObject(this.deleteObj).then((res) => {
-          ElNotification({
-            title: `宸℃煡浠诲姟淇敼鎴愬姛`,
-            message: `鍒犻櫎鍦烘櫙${res}涓猔,
-            type: 'success',
-            position: 'bottom-left'
-          });
-          this.deleteObj = [];
-        });
-      }
-      // return Promise.all([p1, p2, p3]).finally(() => {
-      //   this.saveLoading = false;
-      // });
-    },
-    async goBack() {
-      // const answer = await this.routerChangeCheck()
-      // if (answer) {
-      //   this.$router.back();
-      // }
-      this.$router.back();
-    },
-    async routerChangeCheck() {
-      if (this.isEdit) {
-        const answer = await ElMessageBox.confirm('鏄惁鏀惧純宸蹭慨鏀圭殑鎬讳换鍔★紵', '鍙栨秷鎬讳换鍔′慨鏀�', {
-          confirmButtonText: '纭',
-          cancelButtonText: '鍙栨秷',
-          type: 'warning'
-        })
-          .then(() => {
-            return true;
-          })
-          .catch(() => {
-            return false;
-          });
-        return answer;
-      }
-      return true;
-    }
-  },
-  mounted() {
-    // 鐩戠鍦烘櫙淇℃伅
-    this.curMonitorObjList = JSON.parse(decodeURIComponent(this.$route.query.data));
-    // 鏍规嵁鎬讳换鍔¤幏鍙栬鏀垮尯鍒掍俊鎭�
-    const task = JSON.parse(decodeURIComponent(this.$route.query.task));
-    this.task = task;
-    this.area = {
-      provincecode: task.provincecode,
-      provincename: task.provincename,
-      citycode: task.citycode,
-      cityname: task.cityname,
-      districtcode: task.districtcode,
-      districtname: task.districtname,
-      towncode: task.towncode,
-      townname: task.townname,
-      online: true
-    };
-    this.searchScene({ text: '' });
-  }
-};
+function handleSaveClick() {
+  objEditRef.value.saveEdit();
+}
+
+function goBack() {
+  router.back();
+}
+
+onMounted(() => {
+  // 鐩戠鍦烘櫙淇℃伅
+  // curMonitorObjList.value = JSON.parse(decodeURIComponent(route.query.data));
+  // 鎬讳换鍔�
+  task.value = JSON.parse(decodeURIComponent(route.query.task));
+  // 鐩戠鍦烘櫙淇℃伅
+  curMonitorObjList.value = JSON.parse(
+    decodeURIComponent(route.query.data)
+  );
+});
 </script>
 
 <style scoped>
 .page-header {
-  background-color: #fff;
+  background-color: white;
+  padding: 10px 0;
+  /* border-bottom: 1px solid var(--el-color-info-light-7); */
 }
 </style>
diff --git a/src/views/fysp/task/MonitorTaskCreate.vue b/src/views/fysp/task/MonitorTaskCreate.vue
new file mode 100644
index 0000000..e19d9e3
--- /dev/null
+++ b/src/views/fysp/task/MonitorTaskCreate.vue
@@ -0,0 +1,93 @@
+<template>
+  <el-affix :offset="60" target=".el-main">
+    <div class="page-header">
+      <el-page-header @back="goBack">
+        <template #content>
+          <span> 鏂板缓宸℃煡鎬讳换鍔� </span>
+          <el-text type="info">锛堜换鍔℃ā鏉匡細{{ lastTask.name }}锛�</el-text>
+        </template>
+        <template #extra>
+          <div>
+            <el-button
+              type="primary"
+              :disabled="!isEdit"
+              :loading="saveLoading"
+              @click="handleSaveClick"
+              >鎻愪氦</el-button
+            >
+          </div>
+        </template>
+      </el-page-header>
+      <el-divider />
+    </div>
+  </el-affix>
+  <CompMonitorObjEdit
+    ref="objEditRef"
+    create
+    :task="task"
+    :objList="curMonitorObjList"
+    @upload-success="goBack"
+  ></CompMonitorObjEdit>
+</template>
+<script setup>
+import { ref, computed, onMounted } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+import CompMonitorObjEdit from './components/CompMonitorObjEdit.vue';
+import taskApi from '../../../api/fysp/taskApi';
+
+const route = useRoute();
+const router = useRouter();
+
+const objEditRef = ref(null);
+const curMonitorObjList = ref([]);
+const task = ref({});
+const lastTask = ref({})
+
+const isEdit = computed(()=>{
+  return objEditRef.value ? objEditRef.value.isEdit : false
+})
+
+function handleSaveClick() {
+  objEditRef.value.saveEdit()
+}
+
+function goBack() {
+  router.back();
+}
+
+function getLastTopTask(task) {
+  taskApi.getLastTopTask(task).then(t=>{
+    lastTask.value = t
+    if (t) {
+      taskApi
+        .fetchMonitorObjectVersion(t.tguid)
+        .then((res) => {
+          // 浠ュ巻鍙茬洃绠″満鏅负鍩虹锛屽悓鏃跺垵濮嬪寲閮ㄥ垎灞炴��
+          res.forEach(e => {
+            e.movid = null
+            e.tid = task.tguid
+            e.extension1 = null
+          });
+          curMonitorObjList.value = res;
+        })
+        .finally(() => {
+          // this.mainLoading = false;
+        });
+    }
+  })
+}
+
+onMounted(() => {
+  // 鐩戠鍦烘櫙淇℃伅
+  // curMonitorObjList.value = JSON.parse(decodeURIComponent(route.query.data));
+  // 鎬讳换鍔�
+  task.value = JSON.parse(decodeURIComponent(route.query.task));
+  getLastTopTask(task.value)
+});
+</script>
+<style scoped>
+.page-header {
+  background-color: white;
+  padding-top: 20px;
+}
+</style>
diff --git a/src/views/fysp/task/TaskManage.vue b/src/views/fysp/task/TaskManage.vue
index 7d1c5d4..ae03a36 100644
--- a/src/views/fysp/task/TaskManage.vue
+++ b/src/views/fysp/task/TaskManage.vue
@@ -1,7 +1,7 @@
 <template>
   <BaseContentLayout>
     <template #header>
-      <FYSearchBar @search="search">
+      <!-- <FYSearchBar @search="search">
         <template #options>
           <FYOptionLocation
             :allOption="true"
@@ -10,7 +10,7 @@
             v-model:value="formSearch.locations"
           ></FYOptionLocation>
         </template>
-      </FYSearchBar>
+      </FYSearchBar> -->
     </template>
     <template #aside>
       <SideList
@@ -32,14 +32,28 @@
         v-loading="mainLoading"
       >
         <el-row justify="space-between">
-          <div><el-text>鐩戠璁″垝</el-text></div>
+          <!-- <div><el-text>鐩戠璁″垝</el-text></div>
           <el-button type="warning" size="small" @click="editPlan"
             >璁″垝璋冩暣</el-button
-          >
-          <CompMonitorPlan
-            :task="curTask.data"
-            @date-change="onDateChange"
-          ></CompMonitorPlan>
+          > -->
+          <el-tabs model-value="first">
+            <el-tab-pane label="鐩戠璁″垝" name="first">
+              <el-row>
+                <el-col :span="curSubTaskList.length > 0 ? 16 : 24">
+                  <CompMonitorPlan
+                    :task="curTask.data"
+                    @date-change="onDateChange"
+                  ></CompMonitorPlan>
+                </el-col>
+                <el-col v-if="curSubTaskList.length > 0" :span="8">
+                  <CompSubTaskList :data="curSubTaskList" height="56vh"></CompSubTaskList>
+                </el-col>
+              </el-row>
+            </el-tab-pane>
+            <el-tab-pane label="鐩戠鍦板浘" name="second">
+              <CompTaskMap></CompTaskMap>
+            </el-tab-pane>
+          </el-tabs>
         </el-row>
         <el-divider></el-divider>
         <el-row justify="space-between">
@@ -50,18 +64,45 @@
         </el-row>
         <CompMonitorObj :data="curMonitorObjList"></CompMonitorObj>
       </el-scrollbar>
-      <el-empty v-else description="鏆傛棤璁板綍" v-loading="mainLoading" />
+      <div v-else>
+        <el-empty description="鏆傛棤璁板綍" v-loading="mainLoading" />
+        <el-row v-if="!mainLoading" justify="center">
+          <el-button
+            type="primary"
+            size="default"
+            @click="navToTaskCreate(curTask.data)"
+            >娣诲姞鐩戠鍦烘櫙</el-button
+          >
+        </el-row>
+      </div>
     </template>
   </BaseContentLayout>
   <el-drawer
     v-model="subTaskDrawer"
-    title="鍗曟棩璁″垝"
+    title="鏃ヨ鍒掔鐞�"
     direction="btt"
-    size="80%"
+    size="96%"
     destroy-on-close
   >
-    <CompDayTask :day-task="curDayTask"></CompDayTask>
+    <CompDayTask
+      :day-task="curDayTask"
+      :mObjList="curMonitorObjList"
+    ></CompDayTask>
   </el-drawer>
+  <el-dialog
+    v-model="topTaskAddVisible"
+    width="600"
+    title="涓�閿垱寤烘�讳换鍔�"
+    destroy-on-close
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :show-close="false"
+  >
+    <CompTaskEdit
+      @submit="navToTaskCreate"
+      @cancel="topTaskAddVisible = false"
+    ></CompTaskEdit>
+  </el-dialog>
 </template>
 
 <script>
@@ -69,6 +110,9 @@
 import CompMonitorObj from './components/CompMonitorObj.vue';
 import CompMonitorPlan from './components/CompMonitorPlan.vue';
 import CompDayTask from './components/CompDayTask.vue';
+import CompTaskMap from './components/CompTaskMap.vue';
+import CompTaskEdit from './components/CompTaskEdit.vue';
+import CompSubTaskList from './components/CompSubTaskList.vue';
 export default {
   beforeRouteEnter(to, from, next) {
     // 鍦ㄦ覆鏌撹缁勪欢鐨勫搴旇矾鐢辫楠岃瘉鍓嶈皟鐢�
@@ -77,10 +121,19 @@
     next((vm) => {
       if (from.name == 'monitorObjEdit' && vm.task) {
         vm.chooseTask(vm.task);
+      } else if (from.name == 'monitorTaskCreate') {
+        vm.search();
       }
     });
   },
-  components: { CompMonitorObj, CompMonitorPlan, CompDayTask },
+  components: {
+    CompMonitorObj,
+    CompMonitorPlan,
+    CompDayTask,
+    CompTaskMap,
+    CompTaskEdit,
+    CompSubTaskList
+  },
   data() {
     return {
       formSearch: {
@@ -103,10 +156,13 @@
       curTask: {},
       //鎿嶄綔鎸夐挳
       buttons: [
-        // {
-        //   name: '璁″垝璋冩暣',
-        //   color: 'success'
-        // },
+        {
+          name: '涓�閿垱寤烘�讳换鍔�',
+          color: 'success',
+          click: () => {
+            this.topTaskAddVisible = true;
+          }
+        }
         // {
         //   name: '鍦烘櫙璋冩暣',
         //   color: 'warning'
@@ -115,7 +171,11 @@
       // 瀛愪换鍔$紪杈戝脊鍑烘
       subTaskDrawer: false,
       // 褰撳墠閫夋嫨鐨勬棩浠诲姟
-      curDayTask: {}
+      curDayTask: {},
+      // 褰撳墠閫夋嫨鐨勬棩浠诲姟涓嬬殑瀛愪换鍔�
+      curSubTaskList: [],
+      // 鎬讳换鍔℃柊澧炲脊鍑烘
+      topTaskAddVisible: false
     };
   },
   computed: {
@@ -203,8 +263,20 @@
       });
     },
     onDateChange(dayTask) {
-      this.subTaskDrawer = true;
+      // this.subTaskDrawer = true;
       this.curDayTask = dayTask;
+      taskApi.fetchSubtaskByDayTask(dayTask.guid).then((res) => {
+        this.curSubTaskList = res;
+      });
+    },
+    navToTaskCreate(value) {
+      this.topTaskAddVisible = false;
+      this.$router.push({
+        name: 'monitorTaskCreate',
+        query: {
+          task: encodeURIComponent(JSON.stringify(value))
+        }
+      });
     }
   },
   mounted() {
@@ -221,6 +293,6 @@
 }
 
 .el-scrollbar {
-  height: calc((100vh - 60px * 2 - 20px * 2 - var(--height-toolbar)));
+  height: calc((100vh - 60px - 20px * 2 - var(--height-toolbar)));
 }
 </style>
diff --git a/src/views/fysp/task/TaskProxy.js b/src/views/fysp/task/TaskProxy.js
new file mode 100644
index 0000000..076fcbb
--- /dev/null
+++ b/src/views/fysp/task/TaskProxy.js
@@ -0,0 +1,8 @@
+export default {
+  /**
+   * 鐢熸垚宸℃煡瀛愪换鍔″璞�
+   */
+  ceateSubTask(){
+
+  }
+}
\ No newline at end of file
diff --git a/src/views/fysp/task/components/CompDayTask.vue b/src/views/fysp/task/components/CompDayTask.vue
index 9617c22..db5bab8 100644
--- a/src/views/fysp/task/components/CompDayTask.vue
+++ b/src/views/fysp/task/components/CompDayTask.vue
@@ -1,35 +1,107 @@
 <template>
-  <el-row justify="space-between">
-    <el-text>鍗曟棩璁″垝</el-text>
-    <el-button type="success" size="small" @click="editTask">鏂板</el-button>
+  <el-row gutter="20">
+    <el-col :span="16">
+      <div>
+        <el-text>鐩戠鍦烘櫙</el-text>
+      </div>
+      <el-divider />
+      <CompSubTaskSelect
+        :data="seletedSceneList"
+        :dayTask="dayTask"
+        @delete="deleteScene"
+      ></CompSubTaskSelect>
+      <div>
+        <!-- <el-scrollbar height="50vh"> -->
+          <CompMonitorObj :data="curMonitorObjList" height="50vh">
+            <template #default="{ item }">
+              <el-button
+                v-if="item.select"
+                size="small"
+                type="info"
+                plain
+                disabled
+                icon="select"
+                >閫夋嫨</el-button
+              >
+              <el-button
+                v-else
+                size="small"
+                type="primary"
+                plain
+                @click="selectScene(item)"
+                >閫夋嫨</el-button
+              >
+            </template>
+          </CompMonitorObj>
+        <!-- </el-scrollbar> -->
+      </div>
+    </el-col>
+    <el-col :span="8">
+      <el-row justify="space-between">
+        <el-text>鍗曟棩璁″垝</el-text>
+        <el-button type="success" size="small" @click="editTask"
+          >鏂板</el-button
+        >
+      </el-row>
+      <el-divider />
+      <div>
+        <el-scrollbar :height="height">
+          <ItemSubTask
+            v-for="stask in curSubTaskList"
+            :key="stask.guid"
+            :item="stask"
+          >
+            <template #default="{ item }">
+              <el-button type="danger" size="small" @click="editTask"
+                >绉婚櫎</el-button
+              >
+            </template>
+          </ItemSubTask>
+        </el-scrollbar>
+      </div>
+    </el-col>
   </el-row>
-  <el-divider />
-  <ItemSubTask v-for="stask in curSubTaskList" :key="stask.guid" :item="stask">
-    <template #default="{ item }">
-      <el-button type="danger" size="small" @click="editTask">绉婚櫎</el-button>
-    </template>
-  </ItemSubTask>
 </template>
 <script setup>
 import { ref, watch, onMounted } from 'vue';
+import { useCloned } from '@vueuse/core';
+import { useRoute, useRouter } from 'vue-router';
 import taskApi from '@/api/fysp/taskApi';
+import TaskProxy from '../TaskProxy';
+
+import CompMonitorObj from './CompMonitorObj.vue';
+import CompSubTaskSelect from './CompSubTaskSelect.vue';
+
+const route = useRoute();
 
 const props = defineProps({
   // 鏃ヤ换鍔�
-  dayTask: Object
+  dayTask: Object,
+  mObjList: Array
 });
 
+/*************************** 鏁版嵁鍒濆鍖� ************************************/
 // 宸℃煡瀛愪换鍔¢泦鍚�
+const curMonitorObjList = ref([]);
 const curSubTaskList = ref([]);
+const height = ref('70vh');
 
 // 鐩戝惉鏃ヤ换鍔″彉鍖�
 watch(
   () => props.dayTask,
+  (nV) => {
+    onDayTaskChange(nV);
+  },
+  { immediate: true }
+);
+
+// 鐩戝惉鐩戠鍦烘櫙鍙樺寲
+watch(
+  () => props.mObjList,
   (nV, oV) => {
-    // if (nV != oV) {
-    //   onDayTaskChange(nV)
-    // }
-    onDayTaskChange(nV)
+    if (nV != oV) {
+      curMonitorObjList.value = useCloned(nV).cloned.value;
+    }
   },
   { immediate: true }
 );
@@ -49,5 +121,21 @@
     curSubTaskList.value = res;
   });
 }
+
+/*************************** 娣诲姞瀛愪换鍔� ************************************/
+
+// 鎵�閫夊満鏅�
+const seletedSceneList = ref([]);
+// 閫夋嫨浠诲姟鍦烘櫙
+function selectScene(item) {
+  item.select = true;
+  seletedSceneList.value.push(item);
+}
+// 绉婚櫎浠诲姟鍦烘櫙
+function deleteScene(item) {
+  item.select = false;
+  const index = seletedSceneList.value.indexOf(item);
+  seletedSceneList.value.splice(index, 1);
+}
 </script>
 <style scoped></style>
diff --git a/src/views/fysp/task/components/CompMonitorObj.vue b/src/views/fysp/task/components/CompMonitorObj.vue
index 327787e..0047d9f 100644
--- a/src/views/fysp/task/components/CompMonitorObj.vue
+++ b/src/views/fysp/task/components/CompMonitorObj.vue
@@ -1,17 +1,40 @@
 <template>
-  <div>
-    <el-segmented :model-value="activeName" :options="activeTabs" @change="tabChange" />
+  <div class="monitor-obj-wrapper">
+    <el-affix v-if="affix" :offset="60" target=".monitor-obj-wrapper">
+      <div>
+        <el-segmented
+          :model-value="activeName"
+          :options="activeTabs"
+          @change="tabChange"
+        />
+      </div>
+    </el-affix>
+    <div v-else>
+      <el-segmented
+        :model-value="activeName"
+        :options="activeTabs"
+        @change="tabChange"
+      />
+    </div>
+    <el-scrollbar :height="height">
+      <el-space wrap>
+        <ItemMonitorObj v-for="obj in activeData" :key="obj.movid" :item="obj">
+          <template #default="{ item }">
+            <slot :item="item">
+              <el-button
+                v-if="showBtn"
+                size="small"
+                plain
+                :type="btnType"
+                @click="itemClick(item)"
+                >{{ btnName }}</el-button
+              >
+            </slot>
+          </template>
+        </ItemMonitorObj>
+      </el-space>
+    </el-scrollbar>
   </div>
-  <el-space wrap>
-    <ItemMonitorObj v-for="obj in activeData" :key="obj.movid" :item="obj">
-      <template #default="{ item }">
-        <!-- <slot :item="item"></slot> -->
-        <el-button v-if="showBtn" size="small" type="danger" @click="itemClick(item)">{{
-          btnName
-        }}</el-button>
-      </template>
-    </ItemMonitorObj>
-  </el-space>
 </template>
 
 <script>
@@ -34,7 +57,14 @@
     btnName: {
       type: String,
       default: '绉婚櫎'
-    }
+    },
+    btnType: {
+      type: String,
+      default: 'danger'
+    },
+    // 澶撮儴閫夐」鏄惁鍚搁《
+    affix: Boolean,
+    height: String
   },
   emits: ['update:tabName', 'update:showData', 'itemClick'],
   data() {
@@ -46,7 +76,9 @@
   computed: {
     activeData() {
       const list = this.data.filter((v) => {
-        return this.activeName == defaultTabName || v.sceneType == this.activeName;
+        return (
+          this.activeName == defaultTabName || v.sceneType == this.activeName
+        );
         // return this.tabName == defaultTabName || v.sceneType == this.tabName;
       });
       this.$emit('update:showData', list);
diff --git a/src/views/fysp/task/components/CompMonitorObjEdit.vue b/src/views/fysp/task/components/CompMonitorObjEdit.vue
new file mode 100644
index 0000000..d6c616a
--- /dev/null
+++ b/src/views/fysp/task/components/CompMonitorObjEdit.vue
@@ -0,0 +1,451 @@
+<template>
+  <el-row gutter="20">
+    <el-col
+      :span="16"
+      style="border-right: 1px solid var(--el-color-info-light-7)"
+    >
+      <div>
+        <el-text>宸查�夊満鏅�</el-text>
+        <el-text type="info" size="small">{{ statisticText }}</el-text>
+      </div>
+      <el-divider />
+      <CompMonitorObj
+        height="68vh"
+        :data="curMonitorObjList"
+        show-btn
+        v-model:tabName="curSceneType"
+        v-model:showData="showMonitorObjList"
+        :tabOptions="sceneTypeOptions"
+        @item-click="deleteMov"
+      >
+      </CompMonitorObj>
+    </el-col>
+    <el-col :span="8">
+      <el-affix :offset="140">
+        <div>
+          <el-text>鍙�夊満鏅�</el-text>
+        </div>
+        <el-divider />
+        <div>
+          <el-segmented v-model="curSceneType" :options="sceneTypeOptions" />
+        </div>
+        <FYInfoSearch
+          placeholder="璇疯緭鍏ュ満鏅悕绉板叧閿瓧"
+          :data="showSceneList"
+          :on-search="searchScene"
+          :total="total"
+          scroll-height="60vh"
+          :page-show="false"
+        >
+          <template #default="{ row }">
+            <ItemScene :item="row">
+              <el-button-group>
+                <el-button
+                  size="small"
+                  type="primary"
+                  @click="openInsertDialog(row)"
+                  >鎻掑叆</el-button
+                >
+                <el-button
+                  size="small"
+                  type="primary"
+                  @click="openAddDialog(row)"
+                  >鏂板</el-button
+                >
+              </el-button-group>
+            </ItemScene>
+          </template>
+        </FYInfoSearch>
+      </el-affix>
+    </el-col>
+  </el-row>
+
+  <el-dialog v-model="insertDialog" title="鎻掑叆鍦烘櫙鑷崇┖浣欑紪鍙�" width="500">
+    <div v-if="valibleIndex.length > 0">浠ヤ笅涓哄彲閫夌殑绌轰綑缂栧彿</div>
+    <div v-else>鏃犲彲閫夌殑绌轰綑缂栧彿</div>
+    <el-radio-group v-model="selectedIndex" size="default">
+      <el-radio-button
+        v-for="item in valibleIndex"
+        :key="item"
+        :label="item"
+        :value="item"
+      />
+    </el-radio-group>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="insertDialog = false">鍙栨秷</el-button>
+        <el-button :disabled="!selectedIndex" type="primary" @click="insertMov">
+          纭
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
+  <el-dialog v-model="addDialog" title="鏂板鍦烘櫙缂栧彿椤哄欢" width="500">
+    <div>椤哄欢缂栧彿涓�:{{ lastIndex }}</div>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="addDialog = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="addMov"> 纭 </el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+import { useCloned } from '@vueuse/core';
+import CompMonitorObj from './CompMonitorObj.vue';
+import taskApi from '@/api/fysp/taskApi';
+import sceneApi from '@/api/fysp/sceneApi';
+import { ElMessage, ElNotification, ElMessageBox } from 'element-plus';
+
+const MODE_CREATE = 'create';
+const MODE_UPDATE = 'update';
+
+export default {
+  components: { CompMonitorObj },
+  props: {
+    // 缂栬緫妯″紡锛屾柊澧瀋reate鎴栨洿鏂皍pdate
+    mode: {
+      type: String,
+      default: MODE_CREATE
+    },
+    create: Boolean,
+    // 宸℃煡鎬讳换鍔�
+    task: {
+      type: Object,
+      default: () => {
+        return {};
+      }
+    },
+    // 鐩戠鍦烘櫙闆嗗悎
+    objList: Array
+  },
+  data() {
+    return {
+      // 鐩戠鍦烘櫙
+      curMonitorObjList: [],
+      // 褰撳墠绛涢�夌殑鍦烘櫙绫诲瀷
+      curSceneType: undefined,
+      showMonitorObjList: [],
+
+      // 鎵�鏈夊満鏅�
+      sceneList: [],
+      total: 0,
+
+      // 鎻掑叆寮瑰嚭妗�
+      insertDialog: false,
+      // 鎻掑叆鎴栨柊澧炵殑缂栧彿
+      selectedIndex: undefined,
+      // 鎻掑叆鎴栨柊澧炵殑鍦烘櫙
+      selectedScene: undefined,
+      // 鐩戠娆℃暟
+      monitorTimes: 1,
+      // 鏂板寮瑰嚭妗�
+      addDialog: false,
+      // 鏂板鐨勭洃绠″満鏅�
+      insertObj: [],
+      // 鏇存柊鐨勭洃绠″満鏅�
+      updateObj: [],
+      // 鍒犻櫎鐨勭洃绠″満鏅�
+      deleteObj: [],
+      // 鏇存柊鐨勫満鏅熀鏈俊鎭紙鏇存柊鍦烘櫙鐨勭紪鍙凤級
+      updateScene: []
+    };
+  },
+  emits: ['uploadSuccess', 'uploadFail'],
+  watch: {
+    objList: {
+      handler(nV, oV) {
+        if (nV != oV) {
+          this.curMonitorObjList = useCloned(nV).cloned.value;
+        }
+      },
+      immediate: true
+    }
+    // task: {
+    //   handler(nV, oV) {
+    //     if (nV != oV) {
+    //       this.searchScene({ text: '' });
+    //     }
+    //   },
+    //   immediate: true
+    // }
+  },
+  computed: {
+    // 鏌ヨ鍦烘櫙鑼冨洿鏉′欢
+    area() {
+      return {
+        provincecode: this.task.provincecode,
+        provincename: this.task.provincename,
+        citycode: this.task.citycode,
+        cityname: this.task.cityname,
+        districtcode: this.task.districtcode,
+        districtname: this.task.districtname,
+        towncode: this.task.towncode,
+        townname: this.task.townname,
+        online: true
+      };
+    },
+    // 褰撳墠鍦烘櫙绫诲瀷涓嬬殑灞曠ず鍦烘櫙
+    showSceneList() {
+      return this.sceneList.filter((v) => {
+        const index = this.curMonitorObjList.findIndex((o) => {
+          return o.sguid == v.guid;
+        });
+        return index == -1 && v.type == this.curSceneType;
+      });
+    },
+    sceneTypeOptions() {
+      const list = [];
+      this.sceneList.forEach((d) => {
+        if (list.indexOf(d.type) == -1) list.push(d.type);
+      });
+      return list;
+    },
+    // 褰撳墠鍦烘櫙绫诲瀷涓嬬殑鍙彃鍏ョ紪鍙�
+    valibleIndex() {
+      // 鍘熷垪琛ㄥ凡缁忔寜鐓х紪鍙烽『搴忔帓鍒�
+      let index = 1;
+      const indexList = [];
+      this.showMonitorObjList.forEach((l) => {
+        while (l.displayid > index) {
+          indexList.push(index);
+          index++;
+        }
+        index++;
+      });
+      if (this.showMonitorObjList.length == 0 && indexList.length == 0) {
+        indexList.push(1);
+      }
+      return indexList;
+    },
+    lastIndex() {
+      const len = this.showMonitorObjList.length;
+      if (len > 0) {
+        return this.showMonitorObjList[len - 1].displayid + 1;
+      } else {
+        return 1;
+      }
+    },
+    isEdit() {
+      // 鏂板缓鐩戠鎬讳换鍔℃ā寮�
+      if (this.create) {
+        return this.curMonitorObjList.length > 0;
+      }
+      // 鏇存柊鐩戠鎬讳换鍔℃ā寮�
+      else {
+        return (
+          this.insertObj.length > 0 ||
+          this.deleteObj.length > 0 ||
+          this.updateObj.length > 0
+        );
+      }
+    },
+    statisticText() {
+      const total = this.curMonitorObjList.length;
+      const map = new Map();
+      this.curMonitorObjList.forEach((e) => {
+        const d = e.scene
+        if (!map.has(d.type)) {
+          map.set(d.type, { num: 1 });
+        }
+        map.get(d.type).num++;
+      });
+
+      let res = `锛堟�昏${total}涓猔;
+      for (const [key, value] of map) {
+        res += `锛�${key}${value.num}涓猔;
+      }
+      res += '锛�';
+      return res;
+    }
+  },
+  methods: {
+    // 鏌ヨ
+    searchScene({ text, page, pageSize }) {
+      this.area.sceneName = text;
+      return sceneApi.searchScene(this.area, 1, 10000).then((res) => {
+        if (res.success) {
+          // 鏌ヨ缁撴灉
+          this.sceneList = res.data;
+          // 鎬绘暟鎹噺
+          this.total = res.head.totalCount;
+        }
+      });
+    },
+    deleteMov(item) {
+      if (item.extension1) {
+        ElMessage({
+          message: '宸茬洃绠″満鏅棤娉曠Щ闄�',
+          type: 'error'
+        });
+        return;
+      }
+      const i = this.curMonitorObjList.indexOf(item);
+      this.curMonitorObjList.splice(i, 1);
+      const i1 = this.insertObj.indexOf(item);
+      this.insertObj.splice(i1, 1);
+      const i2 = this.updateObj.indexOf(item);
+      this.updateObj.splice(i2, 1);
+      const i3 = this.updateScene.findIndex((s) => {
+        return s.guid == item.sguid;
+      });
+      this.updateScene.splice(i3, 1);
+
+      this.deleteObj.push(item);
+    },
+    openInsertDialog(item) {
+      this.insertDialog = true;
+      this.selectedScene = item;
+      this.monitorTimes = 1;
+    },
+    openAddDialog(item) {
+      this.addDialog = true;
+      this.selectedScene = item;
+      this.monitorTimes = 1;
+    },
+    insertMov() {
+      // 1. 鍒涘缓鏂板満鏅�
+      let mov = this.createMov(this.selectedIndex, this.selectedScene);
+      // 2. 鏌ユ壘绗竴涓紪鍙峰ぇ浜庢彃鍏ョ紪鍙风殑鍊硷紝灏嗘柊鐩戠瀵硅薄鎻掑叆鍏朵箣鍓�
+      const insertAtIndex = this.curMonitorObjList.findIndex((v) => {
+        return v.displayid > this.selectedIndex;
+      });
+      this.curMonitorObjList.splice(insertAtIndex, 0, mov);
+      this.selectedIndex = undefined;
+      this.insertDialog = false;
+    },
+    addMov() {
+      // 1. 鍒涘缓鏂板満鏅�
+      let mov = this.createMov(this.lastIndex, this.selectedScene);
+      // 2. 娣诲姞鑷虫湯灏�
+      this.curMonitorObjList.push(mov);
+      this.addDialog = false;
+    },
+    // 鍒涘缓涓�涓柊鐨勭洃绠″璞�
+    createMov(displayid, scene) {
+      // 1. 鏌ユ壘璇ュ満鏅槸鍚︿箣鍓嶅凡琚垹闄�
+      const index = this.deleteObj.findIndex((v) => {
+        return v.sguid == scene.guid;
+      });
+      let mov;
+      // 2. 鑻ユ槸鍏ㄦ柊鐨勫満鏅紝鍒欐柊鐢熸垚涓�涓洃绠″璞★紝鍚﹀垯鍙洿鏂扮紪鍙�
+      if (index == -1) {
+        mov = {
+          tid: this.task.tguid,
+          sguid: scene.guid,
+          sensename: scene.name,
+          tasktypeid: 1,
+          tasktype: '宸℃煡',
+          monitornum: this.monitorTimes,
+          displayid: displayid,
+          sceneTypeId: scene.typeid,
+          sceneType: scene.type
+        };
+        this.insertObj.push(mov);
+      } else {
+        mov = this.deleteObj[index];
+        mov.displayid = displayid;
+        this.updateObj.push(mov);
+        this.deleteObj.splice(index, 1);
+      }
+      // 3. 鍚屾鏇存柊鍦烘櫙鍩烘湰淇℃伅涓殑缂栧彿
+      scene._index = displayid;
+      this.updateScene.push(scene);
+
+      return mov;
+    },
+    // 淇濆瓨淇敼
+    saveEdit() {
+      if (this.create) {
+        this.createTask();
+      } else {
+        this.updateTask();
+      }
+    },
+    createTask() {
+      if (this.curMonitorObjList.length > 0) {
+        taskApi
+          .addMonitorObject(this.curMonitorObjList)
+          .then((res) => {
+            ElNotification({
+              title: `宸℃煡鎬讳换鍔″垱寤哄畬鎴恅,
+              message: `鏂板鍦烘櫙${res}涓猔,
+              type: 'success',
+              position: 'bottom-left'
+            });
+            this.$emit('uploadSuccess');
+          })
+          .catch((err) => this.$emit('uploadFail', err));
+      }
+      this.updateSceneList();
+    },
+    updateTask() {
+      // new Promise((resolve, reject)=>{
+
+      // })
+      // this.saveLoading = true;
+      if (this.insertObj.length > 0) {
+        const p1 = taskApi.addMonitorObject(this.insertObj).then((res) => {
+          ElNotification({
+            title: `宸℃煡浠诲姟鏂板瀹屾垚`,
+            message: `鏂板鍦烘櫙${res}涓猔,
+            type: 'success',
+            position: 'bottom-left'
+          });
+          this.insertObj = [];
+        });
+      }
+      if (this.updateObj.length > 0) {
+        const p2 = taskApi.updateMonitorObject(this.updateObj).then((res) => {
+          ElNotification({
+            title: `宸℃煡浠诲姟鏇存柊瀹屾垚`,
+            message: `鏇存柊鍦烘櫙${res}涓猔,
+            type: 'success',
+            position: 'bottom-left'
+          });
+          this.updateObj = [];
+        });
+      }
+      if (this.deleteObj.length > 0) {
+        const p3 = taskApi.deleteMonitorObject(this.deleteObj).then((res) => {
+          ElNotification({
+            title: `宸℃煡浠诲姟鍒犻櫎瀹屾垚`,
+            message: `鍒犻櫎鍦烘櫙${res}涓猔,
+            type: 'success',
+            position: 'bottom-left'
+          });
+          this.deleteObj = [];
+        });
+      }
+      this.updateSceneList();
+      // return Promise.all([p1, p2, p3]).finally(() => {
+      //   this.saveLoading = false;
+      // });
+    },
+    updateSceneList() {
+      if (this.updateScene.length > 0) {
+        this.updateScene.forEach((s) => {
+          s.index = s._index;
+        });
+        sceneApi.updateSceneList(this.updateScene).then((res) => {
+          ElNotification({
+            title: `鍦烘櫙缂栧彿鏇存柊瀹屾垚`,
+            message: `鏇存柊鍦烘櫙${res}涓猔,
+            type: 'success',
+            position: 'bottom-left'
+          });
+          this.updateScene = [];
+        });
+      }
+    }
+  },
+  mounted() {
+    setTimeout(() => {
+      this.searchScene({ text: '' });
+    }, 1000);
+  }
+};
+</script>
+
+<style scoped></style>
diff --git a/src/views/fysp/task/components/CompSubTaskList.vue b/src/views/fysp/task/components/CompSubTaskList.vue
new file mode 100644
index 0000000..70f3f85
--- /dev/null
+++ b/src/views/fysp/task/components/CompSubTaskList.vue
@@ -0,0 +1,40 @@
+<template>
+  <el-row justify="space-between">
+    <el-text>鍗曟棩璁″垝</el-text>
+    <el-button type="success" size="small" @click="add">鏂板</el-button>
+  </el-row>
+  <el-divider />
+  <div>
+    <el-scrollbar :height="height">
+      <ItemSubTask v-for="s in data" :key="s.guid" :item="s">
+        <template #default="{ item }">
+          <el-button type="danger" size="small" @click="remove(item)"
+            >绉婚櫎</el-button
+          >
+        </template>
+      </ItemSubTask>
+    </el-scrollbar>
+  </div>
+</template>
+<script setup>
+import { ref, watch, onMounted } from 'vue';
+
+const props = defineProps({
+  data: Array,
+  height: {
+    type: String,
+    default: '70vh'
+  }
+});
+const curSubTaskList = ref([]);
+
+const emit = defineEmits(['add', 'remove']);
+
+function remove(item) {
+  emit('remove', item);
+}
+
+function add() {
+  emit('add');
+}
+</script>
diff --git a/src/views/fysp/task/components/CompSubTaskSelect.vue b/src/views/fysp/task/components/CompSubTaskSelect.vue
new file mode 100644
index 0000000..cdf66b9
--- /dev/null
+++ b/src/views/fysp/task/components/CompSubTaskSelect.vue
@@ -0,0 +1,190 @@
+<template>
+  <div class="wrapper">
+    <el-row>
+      <FYForm
+        :inline="true"
+        label-width=""
+        :form-info="formInfo"
+        :rules="rules"
+        @submit="submit"
+      >
+        <template #form-item="{ formObj }">
+          <el-form-item label="鎵ц浜�" prop="executor">
+            <el-select
+              v-model="formObj.executor"
+              multiple
+              clearable
+              collapse-tags
+              placeholder="閫夋嫨鎵ц浜�"
+              :max-collapse-tags="1"
+              style="width: 240px"
+            >
+              <template #header>
+                <el-checkbox
+                  v-model="checkAll"
+                  :indeterminate="indeterminate"
+                  @change="handleCheckAll"
+                >
+                  鍏ㄩ��
+                </el-checkbox>
+              </template>
+              <el-option
+                v-for="item in executors"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </template>
+      </FYForm>
+    </el-row>
+    <div>
+      <el-scrollbar :height="scrollHeight" v-if="data.length > 0">
+        <el-space wrap>
+          <ItemMonitorObj v-for="obj in data" :key="obj.movid" :item="obj">
+            <template #default="{ item }">
+              <el-button
+                size="small"
+                type="danger"
+                plain
+                @click="deleteScene(item)"
+                >绉婚櫎</el-button
+              >
+            </template>
+          </ItemMonitorObj>
+        </el-space>
+      </el-scrollbar>
+      <el-empty v-else description=" ">
+        <template #image>
+          <el-row align="middle">
+            <el-icon size="20"><WarningFilled /></el-icon>
+            <el-text size="small" type="info">鏈�夋嫨鍦烘櫙</el-text>
+          </el-row>
+        </template>
+      </el-empty>
+    </div>
+  </div>
+</template>
+<script setup>
+/**
+ * 宸℃煡瀛愪换鍔″垱寤�
+ */
+import { ref, reactive, watch, computed, onMounted } from 'vue';
+import { ElMessageBox, ElNotification, ElMessage } from 'element-plus';
+import taskApi from '@/api/fysp/taskApi';
+
+onMounted(() => {
+  // if (props.height) {
+  //   scrollHeight.value =
+  // }
+});
+
+const props = defineProps({
+  // 瀛愪换鍔¢泦鍚�
+  data: {
+    type: Array,
+    default: () => []
+  },
+  height: String,
+  // 鏃ヤ换鍔�
+  dayTask: Object
+});
+
+const emit = defineEmits(['delete']);
+
+const scrollHeight = ref('14vh');
+
+// 绉婚櫎浠诲姟鍦烘櫙
+function deleteScene(item) {
+  emit('delete', item);
+}
+
+/************************* 浠诲姟鍒涘缓琛ㄥ崟 *******************************/
+const formInfo = ref({});
+const rules = reactive({
+  name: [
+    {
+      required: true,
+      message: '鍦烘櫙鍚嶇О涓嶈兘涓虹┖',
+      trigger: 'blur'
+    }
+  ]
+});
+function submit(v, success, fail) {
+  if (props.data.length == 0) {
+    // ElMessage({
+    //   message: '鏈�夋嫨鐩戠鍦烘櫙',
+    //   type: 'warning'
+    // });
+    fail('鏈�夋嫨鐩戠鍦烘櫙');
+  } else {
+    success();
+  }
+}
+
+/************************* 浠诲姟鎵ц浜轰笅鎷夐�夋 *******************************/
+const executors = ref([]);
+// 鏄惁鍏ㄩ��
+const checkAll = ref(false);
+// 澶氶�夋鏄惁涓棿鐘舵��
+const indeterminate = ref(false);
+// 鍏ㄩ�変簨浠�
+function handleCheckAll(val) {
+  indeterminate.value = false;
+  if (val) {
+    formInfo.value.executor = executors.value.map((_) => _.value);
+  } else {
+    formInfo.value.executor = [];
+  }
+}
+watch(
+  () => props.dayTask,
+  (nV, oV) => {
+    if (nV != oV) {
+      taskApi.fetchTaskById(nV.guid).then((res) => {
+        const ids = res.executorguids.split('#');
+        const userNames = res.executorusernames.split('#');
+        const realNames = res.executorrealnames.split('#');
+        const list = [];
+        ids.forEach((e, i) => {
+          if (i < userNames.length && i < realNames.length) {
+            list.push({
+              label: realNames[i],
+              value: e,
+              data: {
+                id: e,
+                userName: userNames[i],
+                realName: realNames[i]
+              }
+            });
+          }
+        });
+
+        executors.value = list;
+      });
+    }
+  },
+  { immediate: true }
+);
+//
+watch(
+  () => formInfo.value.executor,
+  (val) => {
+    if (val.length === 0) {
+      checkAll.value = false;
+      indeterminate.value = false;
+    } else if (val.length === executors.value.length) {
+      checkAll.value = true;
+      indeterminate.value = false;
+    } else {
+      indeterminate.value = true;
+    }
+  }
+);
+</script>
+<style scoped>
+.wrapper {
+  border-bottom: 1px solid var(--el-color-info-light-7);
+}
+</style>
diff --git a/src/views/fysp/task/components/CompTaskEdit.vue b/src/views/fysp/task/components/CompTaskEdit.vue
new file mode 100644
index 0000000..3058aec
--- /dev/null
+++ b/src/views/fysp/task/components/CompTaskEdit.vue
@@ -0,0 +1,342 @@
+<template>
+  <FYForm
+    ref="formRef"
+    :form-info="formInfo"
+    :rules="rules"
+    :useCancel="true"
+    label-width="120px"
+    submit-name="鍒涘缓"
+    @submit="submit"
+    @cancel="cancel"
+  >
+    <template #form-item="{ formObj }">
+      <!-- 鍖哄幙 -->
+      <FYOptionLocation
+        :allOption="false"
+        :level="3"
+        :initValue="false"
+        :checkStrictly="false"
+        v-model:value="formObj._locations"
+        @change="handleLocationChange"
+      ></FYOptionLocation>
+      <el-form-item label="浠诲姟鍚嶇О" prop="name">
+        <el-input
+          clearable
+          show-word-limit
+          v-model="formObj.name"
+          placeholder="浠诲姟鍚嶇О"
+        />
+      </el-form-item>
+      <FYOptionTime
+        label="璧锋鏃ユ湡"
+        prop="_timeArr"
+        :initValue="false"
+        type="daterange"
+        v-model:value="formObj._timeArr"
+        @change="handleTimeChange"
+      ></FYOptionTime>
+
+      <el-form-item v-show="showMore" label="浠诲姟绫诲瀷" prop="_type">
+        <el-select v-model="formObj._type" style="width: 150px">
+          <el-option
+            v-for="s in taskTypeOptions"
+            :key="s.label"
+            :label="s.label"
+            :value="s.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item v-show="showMore" label="浠诲姟鏈熼檺绫诲埆" prop="_deadlinetype">
+        <el-select v-model="formObj._deadlinetype" style="width: 150px">
+          <el-option
+            v-for="s in deadlineTypeOptions"
+            :key="s.label"
+            :label="s.label"
+            :value="s.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item v-show="showMore" label="浠诲姟灞傛" prop="levelnum">
+        <el-select v-model="formObj.levelnum" style="width: 150px">
+          <el-option
+            v-for="s in levelOptions"
+            :key="s.label"
+            :label="s.label"
+            :value="s.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item v-show="showMore" label="鎵ц浜�" prop="_executors">
+        <el-select
+          v-model="formObj._executors"
+          multiple
+          clearable
+          collapse-tags
+          placeholder="閫夋嫨鎵ц浜�"
+          :max-collapse-tags="3"
+          style="width: 300px"
+        >
+          <el-option
+            v-for="s in executorOptions"
+            :key="s.value"
+            :label="s.label"
+            :value="s.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-row justify="center">
+          <el-link type="primary" @click="showMore = !showMore">
+            {{ showMore ? '鏀惰捣' : '鏌ョ湅鏇村閫夐」' }}
+            <el-icon v-if="showMore"><ArrowUp /></el-icon>
+            <el-icon v-else><ArrowDown /></el-icon>
+          </el-link>
+        </el-row>
+      </el-form-item>
+    </template>
+  </FYForm>
+</template>
+<script setup>
+import { ref, reactive, watch, onMounted } from 'vue';
+import domainApi from '@/api/fysp/domainApi';
+import userApi from '@/api/fysp/userApi';
+import dayjs from 'dayjs';
+import taskApi from '@/api/fysp/taskApi';
+
+const props = defineProps({
+  //鏁版嵁
+  model: {
+    type: Object,
+    default: () => {
+      return {};
+    }
+  },
+  //鏄垱寤烘垨鑰呮洿鏂板満鏅紝榛樿鏇存柊
+  create: Boolean
+});
+
+const emit = defineEmits(['submit', 'cancel']);
+
+const rules = reactive({
+  name: [
+    {
+      required: true,
+      message: '浠诲姟鍚嶇О涓嶈兘涓虹┖',
+      trigger: 'change'
+    }
+  ],
+  _type: [
+    {
+      required: true,
+      message: '浠诲姟绫诲瀷涓嶈兘涓虹┖',
+      trigger: 'change'
+    }
+  ],
+  _deadlinetype: [
+    {
+      required: true,
+      message: '浠诲姟鏈熼檺绫诲瀷涓嶈兘涓虹┖',
+      trigger: 'change'
+    }
+  ],
+  levelnum: [
+    {
+      required: true,
+      message: '浠诲姟灞傛涓嶈兘涓虹┖',
+      trigger: 'change'
+    }
+  ],
+  // starttime: [
+  //   {
+  //     required: true,
+  //     message: '寮�濮嬫棩鏈熶笉鑳戒负绌�',
+  //     trigger: 'change'
+  //   }
+  // ],
+  // endtime: [
+  //   {
+  //     required: true,
+  //     message: '缁撴潫鏃ユ湡涓嶈兘涓虹┖',
+  //     trigger: 'change'
+  //   }
+  // ],
+  _timeArr: [
+    {
+      required: true,
+      message: '璧锋鏃ユ湡涓嶈兘涓虹┖',
+      trigger: 'change'
+    }
+  ],
+  _executors: [
+    {
+      required: true,
+      message: '浠诲姟鎵ц浜轰笉鑳戒负绌�',
+      trigger: 'change'
+    }
+  ]
+});
+
+const formRef = ref(null);
+const formInfo = ref({
+  starttime: dayjs().add(1, 'month').startOf('month').toDate(),
+  endtime: dayjs().add(1, 'month').endOf('month').toDate(),
+  _timeArr: [
+    dayjs().add(1, 'month').startOf('month').toDate(),
+    dayjs().add(1, 'month').endOf('month').set('millisecond', 0).toDate()
+  ]
+});
+// 浠诲姟绫诲瀷閫夐」
+const taskTypeOptions = ref([]);
+// 浠诲姟鏈熼檺绫诲埆閫夐」
+const deadlineTypeOptions = ref([]);
+// 浠诲姟灞傛绫诲埆閫夐」
+const levelOptions = ref([]);
+// 浠诲姟鎵ц浜洪�夐」
+const executorOptions = ref([]);
+const showMore = ref(false);
+
+function locationText(location) {
+  if (location.pName == (undefined | null)) return '';
+  let res = location.pName;
+  if (location.cName && location.cName != location.pName) {
+    res += location.cName;
+  }
+  if (location.dName && location.dName != location.cName) {
+    res += location.dName;
+  }
+  return res;
+}
+
+function handleLocationChange(location) {
+  genTaskName();
+}
+
+function handleTimeChange(timeArr) {
+  genTaskName();
+}
+
+function genTaskName() {
+  let name = dayjs(formRef.value.formObj._timeArr[0]).format('YYYY骞碝M鏈�');
+  name += locationText(formRef.value.formObj._locations);
+  name += formRef.value.formObj._type.text;
+  name += '浠诲姟';
+  formRef.value.formObj.name = name;
+}
+
+/*************************** 鏁版嵁鏇存柊 ************************************/
+
+function getExecutors(data) {
+  const ids = [];
+  const uNames = [];
+  const rNames = [];
+  executorOptions.value.forEach((e) => {
+    const index = data._executors.indexOf(e.value);
+    if (index != -1) {
+      ids.push(e.data.guid);
+      uNames.push(e.data.acountname);
+      rNames.push(e.data.realname);
+    }
+  });
+  return {
+    id: ids.join('#'),
+    uName: uNames.join('#'),
+    rName: rNames.join('#')
+  };
+}
+
+function submit(data, success, fail) {
+  const v = data.value;
+  const executors = getExecutors(v);
+  const task = {
+    levelnum: v.levelnum,
+    name: v.name,
+    typeno: v._type.value,
+    typename: v._type.text,
+    deadlinetype: v._deadlinetype.text,
+    provincecode: v._locations.pCode,
+    provincename: v._locations.pName,
+    citycode: v._locations.cCode,
+    cityname: v._locations.cName,
+    districtcode: v._locations.dCode,
+    districtname: v._locations.dName,
+    starttime: v._timeArr[0],
+    endtime: v._timeArr[1],
+    // fixme 2024.10.16锛� 鍚庣画鍔犲叆鐢ㄦ埛绯荤粺鍚庯紝閲囩敤褰撳墠鐧诲綍鐢ㄦ埛淇℃伅
+    plannerguid: 'rAR0A4gJdlOZEqZs',
+    plannerusername: 'ccheck',
+    plannerrealname: '鏁存敼瀹℃牳',
+    settime: new Date(),
+    executorguids: executors.id,
+    executorusernames: executors.uName,
+    executorrealnames: executors.rName,
+    t1stverifierguid: 'rAR0A4gJdlOZEqZs',
+    t1stverifierusername: 'ccheck',
+    t1stverifierrealname: '鏁存敼瀹℃牳',
+    t1stverifytime: new Date(),
+    t1stisverify: true,
+    runingstatus: '鏈墽琛�',
+    extension1: '3',
+    extension2: '0'
+  };
+  // success();
+  // emit('submit', task);
+  taskApi
+    .putTask(task)
+    .then((res) => {
+      success();
+      emit('submit', res.data);
+    })
+    .catch((err) => fail(err));
+}
+function cancel() {
+  emit('cancel');
+}
+
+/*************************** 鏁版嵁鍒濆鍖� ************************************/
+
+// 鍚勯�夐」鐨勫垵濮嬪寲
+function initOptions() {
+  domainApi.fetchTaskType().then((res) => {
+    taskTypeOptions.value = res.map((v) => {
+      return {
+        label: v.text,
+        value: v
+      };
+    });
+    formInfo.value._type = taskTypeOptions.value[0].value;
+  });
+  domainApi.fetchDeadlineType().then((res) => {
+    deadlineTypeOptions.value = res.map((v) => {
+      return {
+        label: v.text,
+        value: v
+      };
+    });
+    formInfo.value._deadlinetype = deadlineTypeOptions.value[0].value;
+  });
+  domainApi.fetchLevelType().then((res) => {
+    levelOptions.value = res.map((v) => {
+      return {
+        label: v.text,
+        value: v.value
+      };
+    });
+    formInfo.value.levelnum = levelOptions.value[1].value;
+  });
+  userApi.getUserByType(1).then((res) => {
+    executorOptions.value = res.map((v) => {
+      return {
+        label: v.realname,
+        value: v.guid,
+        data: v
+      };
+    });
+    formInfo.value._executors = executorOptions.value.map((v) => v.value);
+  });
+}
+
+onMounted(() => {
+  initOptions();
+});
+</script>
+<style scoped></style>
diff --git a/src/views/fysp/task/components/CompTaskMap.vue b/src/views/fysp/task/components/CompTaskMap.vue
new file mode 100644
index 0000000..fb00bae
--- /dev/null
+++ b/src/views/fysp/task/components/CompTaskMap.vue
@@ -0,0 +1,8 @@
+<template>
+  <SceneMap></SceneMap>
+</template>
+
+<script setup>
+
+
+</script>
\ No newline at end of file

--
Gitblit v1.9.3