From 723be8e0896fbf7e9456a5defb44911a3d0cbc27 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期四, 12 三月 2026 17:34:55 +0800
Subject: [PATCH] 2026.3.12

---
 src/views/monitor/DataException_old.vue                               | 1690 ++++++++++++++
 src/views/inspection/scenenew/components/CompUserInfo.vue             |  250 ++
 src/views/inspection/scenenew/components/CompHazardousWasteFile.vue   |    1 
 src/views/inspection/scenenew/components/CompUserInfoAddDrawer.vue    |   54 
 src/constants/menu.js                                                 |   82 
 src/style/base.scss                                                   |   99 
 src/sfc/TimeSelect.vue                                                |  177 +
 src/views/monitor/DataHistory.vue                                     |   56 
 src/views/inspection/scenenew/components/CompSceneInfo.vue            |  132 +
 index.html                                                            |    5 
 src/utils/map/index.js                                                |   98 
 src/views/inspection/scenenew/components/CompCompanyInfo.vue          |  205 +
 src/views/monitor/DataDashboard_old3.vue                              |  730 ++++++
 components.d.ts                                                       |   20 
 src/views/inspection/scenenew/UserEdit.vue                            |  191 +
 src/views/monitor/DataDashboard_old2.vue                              |  313 ++
 src/sfc/ExceptionTypeLineChart.vue                                    |   74 
 src/router/index.js                                                   |    8 
 src/components/layout/FormCol.vue                                     |   18 
 src/views/inspection/scenenew/components/CompHazardousWasteRecord.vue |    1 
 src/views/monitor/DataDashboard.vue                                   | 1064 +++++++--
 src/views/inspection/scenenew/UserInfo.vue                            |  226 +
 src/style/layout.js                                                   |   70 
 src/views/inspection/scenenew/components/CompDeviceInfo.vue           |  159 +
 src/views/monitor/DataException.vue                                   | 1058 +++++---
 src/utils/map/districtsearch.js                                       |   80 
 26 files changed, 5,938 insertions(+), 923 deletions(-)

diff --git a/components.d.ts b/components.d.ts
index dac87af..3884445 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -27,10 +27,12 @@
     ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
     ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
     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']
+    ElCheckboxButton: typeof import('element-plus/es')['ElCheckboxButton']
     ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElCollapse: typeof import('element-plus/es')['ElCollapse']
@@ -43,6 +45,9 @@
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
+    ElDropdown: typeof import('element-plus/es')['ElDropdown']
+    ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
+    ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
     ElEmpty: typeof import('element-plus/es')['ElEmpty']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
@@ -58,6 +63,7 @@
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
     ElOption: typeof import('element-plus/es')['ElOption']
+    ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
     ElPagination: typeof import('element-plus/es')['ElPagination']
     ElPopover: typeof import('element-plus/es')['ElPopover']
     ElRadio: typeof import('element-plus/es')['ElRadio']
@@ -81,6 +87,7 @@
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
     ElUpload: typeof import('element-plus/es')['ElUpload']
+    FormCol: typeof import('./src/components/layout/FormCol.vue')['default']
     FYDownloadTableButton: typeof import('./src/components/button/FYDownloadTableButton.vue')['default']
     FYForm: typeof import('./src/components/form/FYForm.vue')['default']
     FYImageSelectDialog: typeof import('./src/components/FYImageSelectDialog.vue')['default']
@@ -103,8 +110,11 @@
     FYReconfrimButton: typeof import('./src/components/button/FYReconfrimButton.vue')['default']
     FYSearchBar: typeof import('./src/components/search-option/FYSearchBar.vue')['default']
     FYTable: typeof import('./src/components/table/FYTable.vue')['default']
+    IEpDataLine: typeof import('~icons/ep/data-line')['default']
     IEpDownload: typeof import('~icons/ep/download')['default']
+    IEpGrid: typeof import('~icons/ep/grid')['default']
     IEpInfoFilled: typeof import('~icons/ep/info-filled')['default']
+    IEpWarning: typeof import('~icons/ep/warning')['default']
     ItemDevice: typeof import('./src/components/list-item/ItemDevice.vue')['default']
     ItemMonitorObj: typeof import('./src/components/list-item/ItemMonitorObj.vue')['default']
     ItemScene: typeof import('./src/components/list-item/ItemScene.vue')['default']
@@ -142,10 +152,12 @@
   const ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
   const ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
   const ElButton: typeof import('element-plus/es')['ElButton']
+  const ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
   const ElCalendar: typeof import('element-plus/es')['ElCalendar']
   const ElCard: typeof import('element-plus/es')['ElCard']
   const ElCascader: typeof import('element-plus/es')['ElCascader']
   const ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
+  const ElCheckboxButton: typeof import('element-plus/es')['ElCheckboxButton']
   const ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
   const ElCol: typeof import('element-plus/es')['ElCol']
   const ElCollapse: typeof import('element-plus/es')['ElCollapse']
@@ -158,6 +170,9 @@
   const ElDialog: typeof import('element-plus/es')['ElDialog']
   const ElDivider: typeof import('element-plus/es')['ElDivider']
   const ElDrawer: typeof import('element-plus/es')['ElDrawer']
+  const ElDropdown: typeof import('element-plus/es')['ElDropdown']
+  const ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
+  const ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
   const ElEmpty: typeof import('element-plus/es')['ElEmpty']
   const ElForm: typeof import('element-plus/es')['ElForm']
   const ElFormItem: typeof import('element-plus/es')['ElFormItem']
@@ -173,6 +188,7 @@
   const ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
   const ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
   const ElOption: typeof import('element-plus/es')['ElOption']
+  const ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
   const ElPagination: typeof import('element-plus/es')['ElPagination']
   const ElPopover: typeof import('element-plus/es')['ElPopover']
   const ElRadio: typeof import('element-plus/es')['ElRadio']
@@ -196,6 +212,7 @@
   const ElTooltip: typeof import('element-plus/es')['ElTooltip']
   const ElTree: typeof import('element-plus/es')['ElTree']
   const ElUpload: typeof import('element-plus/es')['ElUpload']
+  const FormCol: typeof import('./src/components/layout/FormCol.vue')['default']
   const FYDownloadTableButton: typeof import('./src/components/button/FYDownloadTableButton.vue')['default']
   const FYForm: typeof import('./src/components/form/FYForm.vue')['default']
   const FYImageSelectDialog: typeof import('./src/components/FYImageSelectDialog.vue')['default']
@@ -218,8 +235,11 @@
   const FYReconfrimButton: typeof import('./src/components/button/FYReconfrimButton.vue')['default']
   const FYSearchBar: typeof import('./src/components/search-option/FYSearchBar.vue')['default']
   const FYTable: typeof import('./src/components/table/FYTable.vue')['default']
+  const IEpDataLine: typeof import('~icons/ep/data-line')['default']
   const IEpDownload: typeof import('~icons/ep/download')['default']
+  const IEpGrid: typeof import('~icons/ep/grid')['default']
   const IEpInfoFilled: typeof import('~icons/ep/info-filled')['default']
+  const IEpWarning: typeof import('~icons/ep/warning')['default']
   const ItemDevice: typeof import('./src/components/list-item/ItemDevice.vue')['default']
   const ItemMonitorObj: typeof import('./src/components/list-item/ItemMonitorObj.vue')['default']
   const ItemScene: typeof import('./src/components/list-item/ItemScene.vue')['default']
diff --git a/index.html b/index.html
index 5022eff..3799af3 100644
--- a/index.html
+++ b/index.html
@@ -8,6 +8,11 @@
   </head>
   <body>
     <div id="app"></div>
+    <script type="text/javascript">
+      window._AMapSecurityConfig = {
+        serviceHost: 'https://fyami.com.cn:449/_AMapService',
+      }
+    </script>
     <script type="module" src="/src/main.js"></script>
   </body>
 </html>
diff --git a/src/components/layout/FormCol.vue b/src/components/layout/FormCol.vue
new file mode 100644
index 0000000..b17f57d
--- /dev/null
+++ b/src/components/layout/FormCol.vue
@@ -0,0 +1,18 @@
+<template>
+  <el-col :xs="cols.xs" :sm="cols.sm" :md="cols.md" :lg="cols.lg" :xl="cols.xl">
+    <slot></slot>
+  </el-col>
+</template>
+
+<script>
+import { formResponsiveCols } from '@/style/layout'
+
+export default {
+  data() {
+    return {
+      cols: formResponsiveCols(),
+    }
+  },
+}
+</script>
+<style scoped></style>
diff --git a/src/constants/menu.js b/src/constants/menu.js
index b244501..ce7a257 100644
--- a/src/constants/menu.js
+++ b/src/constants/menu.js
@@ -6,49 +6,59 @@
       {
         path: '/index/monitor/data-dashboard',
         icon: 'solar:window-frame-line-duotone',
-        name: '鏁版嵁鐪嬫澘',
+        name: '姹℃煋鎬佸娍',
       },
       {
         path: '/index/monitor/data-exception',
         icon: 'solar:siren-line-duotone',
-        name: '寮傚父鍒嗘瀽',
+        name: '鐩戞祴棰勮',
       },
       {
+        path: '/index/monitor/data-analysis-all',
         icon: 'solar:presentation-graph-line-duotone',
-        name: '瑕佺礌鍒嗘瀽',
-        children: [
-          {
-            path: '/index/monitor/data-analysis-all',
-            icon: 'solar:structure-line-duotone',
-            name: '鍏ㄨ绱犲垎鏋�',
-          },
-          {
-            icon: 'solar:round-graph-line-duotone',
-            name: '鍒嗚绱犲垎鏋�',
-            children: [
-              {
-                path: '/index/monitor/data-analysis-concentration',
-                icon: 'solar:graph-new-line-duotone',
-                name: '娌圭儫娴撳害',
-              },
-              {
-                path: '/index/monitor/data-analysis-online-rate',
-                icon: 'solar:graph-new-line-duotone',
-                name: '鍦ㄧ嚎鐜�',
-              },
-              {
-                path: '/index/monitor/data-analysis-open-rate',
-                icon: 'solar:graph-new-line-duotone',
-                name: '寮�鍚巼',
-              },
-              {
-                path: '/index/monitor/data-analysis-over-standard-rate',
-                icon: 'solar:graph-new-line-duotone',
-                name: '瓒呮爣鐜�',
-              },
-            ],
-          },
-        ],
+        name: '鏁版嵁鍒嗘瀽',
+      },
+      // {
+      //   icon: 'solar:presentation-graph-line-duotone',
+      //   name: '鏁版嵁鍒嗘瀽',
+      //   children: [
+      //     {
+      //       path: '/index/monitor/data-analysis-all',
+      //       icon: 'solar:structure-line-duotone',
+      //       name: '鍏ㄨ绱犲垎鏋�',
+      //     },
+      //     {
+      //       icon: 'solar:round-graph-line-duotone',
+      //       name: '鍒嗚绱犲垎鏋�',
+      //       children: [
+      //         {
+      //           path: '/index/monitor/data-analysis-concentration',
+      //           icon: 'solar:graph-new-line-duotone',
+      //           name: '娌圭儫娴撳害',
+      //         },
+      //         {
+      //           path: '/index/monitor/data-analysis-online-rate',
+      //           icon: 'solar:graph-new-line-duotone',
+      //           name: '鍦ㄧ嚎鐜�',
+      //         },
+      //         {
+      //           path: '/index/monitor/data-analysis-open-rate',
+      //           icon: 'solar:graph-new-line-duotone',
+      //           name: '寮�鍚巼',
+      //         },
+      //         {
+      //           path: '/index/monitor/data-analysis-over-standard-rate',
+      //           icon: 'solar:graph-new-line-duotone',
+      //           name: '瓒呮爣鐜�',
+      //         },
+      //       ],
+      //     },
+      //   ],
+      // },
+      {
+        path: '/index/monitor/data-history',
+        icon: 'solar:graph-new-line-duotone',
+        name: '鍘嗗彶鏁版嵁',
       },
     ],
   },
diff --git a/src/router/index.js b/src/router/index.js
index 4f042be..058233e 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -77,7 +77,13 @@
             {
               name: 'scene-info',
               path: 'scene-info',
-              component: () => import('@/views/inspection/scene/SceneInfo.vue'),
+              component: () => import('@/views/inspection/scenenew/UserInfo.vue'),
+            },
+            {
+              //璐︽埛缂栬緫
+              name: 'scene-info-edit',
+              path: 'scene-info-edit/:userId',
+              component: () => import('@/views/inspection/scenenew/UserEdit.vue'),
             },
             {
               name: 'pro-check',
diff --git a/src/sfc/ExceptionTypeLineChart.vue b/src/sfc/ExceptionTypeLineChart.vue
index 75576f2..ae457c4 100644
--- a/src/sfc/ExceptionTypeLineChart.vue
+++ b/src/sfc/ExceptionTypeLineChart.vue
@@ -1,5 +1,5 @@
 <!-- 寮傚父鎯呭喌鐨� 鎶樼嚎鍥剧粍浠�
-瀛愮粍浠舵湁鍩烘湰鐨勬牱寮� 
+瀛愮粍浠舵湁鍩烘湰鐨勬牱寮�
 浣跨敤鍚屼竴涓浘褰㈠疄渚嬶紝鎺ュ彈鐖剁粍浠朵紶鍏ョ殑鎶樼嚎鍥緊ption
 **鐖剁粍浠�
  <ExceptionTypeLineChart
@@ -9,66 +9,65 @@
       ></ExceptionTypeLineChart>
  -->
 <template>
-  <div  id="main" class="line-chart"></div>
+  <div id="main" class="line-chart"></div>
 </template>
 
 <script>
-import * as echarts from 'echarts';
+import * as echarts from 'echarts'
 
 export default {
   props: {
-    option:{
-      type:Object,
-      default(){
+    option: {
+      type: Object,
+      default() {
         return {}
-      }
+      },
     },
-    isOpenDialog:{
-      type:Boolean
+    isOpenDialog: {
+      type: Boolean,
     },
-
   },
   data() {
     return {
-      chart: null
-    };
+      chart: null,
+    }
   },
   mounted() {
-     // 鑾峰彇椤甸潰瀹藉害鐨勪竴鍗�
-     
-    this.initChart();
+    // 鑾峰彇椤甸潰瀹藉害鐨勪竴鍗�
+
+    this.initChart()
     this.chart.clear
-    this.chart.setOption(this.option,true)
-    window.addEventListener('resize', this.resizeChart);
+    this.chart.setOption(this.option, true)
+    window.addEventListener('resize', this.resizeChart)
   },
   watch: {
-    option(){
+    option() {
       // this.chart.dispose;
       // this.initChart();
       // this.chart.clear
       // 涓嶄笌涔嬪墠鐨刼ption杩涜鍚堝苟
-      this.chart.setOption(this.option,true)
+      this.chart.setOption(this.option, true)
     },
-    isOpenDialog(){
-      window.addEventListener('resize', this.resizeChart);
+    isOpenDialog() {
+      window.addEventListener('resize', this.resizeChart)
     },
   },
   beforeUnmount() {
     if (this.chart) {
-      this.chart.dispose;
+      this.chart.dispose
     }
   },
   methods: {
     initChart() {
       // 鍒涘缓echarts瀹炰緥
-      this.chart = echarts.init(document.getElementById('main'));
+      this.chart = echarts.init(document.getElementById('main'))
       // 瀹氫箟鍥捐〃鐨勯厤缃」鍜屾暟鎹�
       const option = {
         grid: {
           left: '3%',
           right: '4%',
           bottom: '3%',
-          containLabel: true
+          containLabel: true,
         },
         tooltip: {},
         toolbox: {
@@ -79,8 +78,8 @@
             //   yAxisIndex: 'none'
             // },
             // 淇濆瓨涓哄浘鐗�
-            saveAsImage: {}
-          }
+            saveAsImage: {},
+          },
         },
         xAxis: {
           type: 'time',
@@ -93,31 +92,30 @@
           {
             name: '娌圭儫娴撳害',
             type: 'line',
-            data: []
-          }
-        ]
-      };
+            data: [],
+          },
+        ],
+      }
       // 浣跨敤鍒氭寚瀹氱殑閰嶇疆椤瑰拰鏁版嵁鏄剧ず鍥捐〃
-      this.chart.setOption(option, true);
+      this.chart.setOption(option, true)
     },
 
     // 璺熼〉闈㈠搷搴斿紡鍙樺寲
     resizeChart() {
       this.$nextTick(() => {
         if (this.chart) {
-          this.chart.resize();
+          this.chart.resize()
         }
-      });
+      })
       // this.chart.resize();
-    }
-  }
-};
+    },
+  },
+}
 </script>
-
 
 <style>
 .line-chart {
-  width:920px;
+  width: 100%;
   height: 300px;
   margin-bottom: 20px;
   /* margin-left: 10px; */
diff --git a/src/sfc/TimeSelect.vue b/src/sfc/TimeSelect.vue
index c2834ac..c6783a8 100644
--- a/src/sfc/TimeSelect.vue
+++ b/src/sfc/TimeSelect.vue
@@ -1,8 +1,8 @@
-<!-- 鏃ユ湡鏃堕棿閫夋嫨鍣ㄧ粍浠�  
+<!-- 鏃ユ湡鏃堕棿閫夋嫨鍣ㄧ粍浠�
   浼氬皢鍒濆榛樿鏃堕棿锛堜竴鍛ㄥ墠锛夊拰鏀瑰彉鐨勬椂闂撮�氳繃浜嬩欢鈥榮ubmitTime鈥欎紶閫掔粰鐖剁粍浠�
-  
+
   鍒濆娓叉煋鏃跺氨灏嗘椂闂翠紶閫掔粰鐖剁粍浠讹細
-  ** 
+  **
   鍦ㄧ埗缁勪欢涓缃�
   <TimeSelect @submit-time="giveTime"></TimeSelect>
    giveTime(val) {
@@ -16,63 +16,192 @@
 import dayjs from 'dayjs'
 export default {
   emits: ['submitTime'],
+  props: {
+    // 鎺у埗鏄惁鍚敤鏂扮殑鏁堟灉锛堝揩鎹锋寜閽� + 璇︽儏鎸夐挳锛�
+    useNewStyle: {
+      type: Boolean,
+      default: false,
+    },
+  },
 
   data() {
     return {
       //淇濆瓨寮�濮嬪拰缁撴潫鏃堕棿
       // 闅忎究璁剧疆鍒濆鍊� 锛宮ounted鏃跺啀璁炬纭殑锛岀洰鐨勬槸鏀瑰彉鏃堕棿浜嗚Е鍙慶hange
-      time: ['2023-06-01 12:00:00', '2023-06-20 16:00:00']
-    };
+      time: ['2023-06-01 12:00:00', '2023-06-20 16:00:00'],
+      // 鎺у埗鏃堕棿閫夋嫨鍣ㄧ殑鏄剧ず/闅愯棌锛堜粎鍦ㄦ柊鏍峰紡涓嬩娇鐢級
+      showTimePicker: false,
+      // 鏃堕棿鑼冨洿閫夐」
+      timeRanges: [
+        { value: 'today', label: '浠婃棩' },
+        { value: 'yesterday', label: '鏄ㄦ棩' },
+        { value: 'thisWeek', label: '鏈懆' },
+        { value: 'lastWeek', label: '涓婂懆' },
+        { value: 'thisMonth', label: '鏈湀' },
+        { value: 'lastMonth', label: '涓婃湀' },
+      ],
+      // 閫変腑鐨勬椂闂磋寖鍥�
+      selectedRange: '',
+    }
   },
 
   // 灏嗗垵濮嬮粯璁ゅ紑濮嬪拰缁撴潫鏃堕棿浼犻�掔粰鐖剁粍浠�
   mounted() {
-    this,this.initOneWeekAgoTime()
-    this.$emit('submitTime', this.time);
+    if (this.useNewStyle) {
+      // 鏂版牱寮忎笅榛樿閫変腑浠婃棩
+      this.selectedRange = 'today'
+      this.selectTimeRange('today')
+    } else {
+      // 鍘熸湁鏍峰紡涓嬩娇鐢ㄤ竴鍛ㄥ墠鐨勯粯璁ゆ椂闂�
+      this.initOneWeekAgoTime()
+      this.$emit('submitTime', this.time)
+    }
   },
 
-  methods:{
-    initOneWeekAgoTime(){
+  methods: {
+    initOneWeekAgoTime() {
       // 缁欐椂闂撮�夋嫨鍣ㄨ缃粯璁ゆ椂闂翠负涓�鍛ㄥ墠
-    this.time[0] = dayjs().subtract(4, 'week').format('YYYY-MM-DD HH:mm:ss');
-    this.time[1] = dayjs().format('YYYY-MM-DD HH:mm:ss');
-    }
-  }
-};
+      this.time[0] = dayjs().subtract(4, 'week').format('YYYY-MM-DD HH:mm:ss')
+      this.time[1] = dayjs().format('YYYY-MM-DD HH:mm:ss')
+    },
+
+    // 蹇嵎鏃舵閫夋嫨
+    selectTimeRange(range) {
+      let now = dayjs()
+      let start, end
+
+      switch (range) {
+        case 'today':
+          start = now.startOf('day').format('YYYY-MM-DD HH:mm:ss')
+          end = now.endOf('day').format('YYYY-MM-DD HH:mm:ss')
+          break
+        case 'yesterday':
+          start = now.subtract(1, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss')
+          end = now.subtract(1, 'day').endOf('day').format('YYYY-MM-DD HH:mm:ss')
+          break
+        case 'thisWeek':
+          start = now.startOf('week').format('YYYY-MM-DD HH:mm:ss')
+          end = now.endOf('week').format('YYYY-MM-DD HH:mm:ss')
+          break
+        case 'lastWeek':
+          start = now.subtract(1, 'week').startOf('week').format('YYYY-MM-DD HH:mm:ss')
+          end = now.subtract(1, 'week').endOf('week').format('YYYY-MM-DD HH:mm:ss')
+          break
+        case 'thisMonth':
+          start = now.startOf('month').format('YYYY-MM-DD HH:mm:ss')
+          end = now.endOf('month').format('YYYY-MM-DD HH:mm:ss')
+          break
+        case 'lastMonth':
+          start = now.subtract(1, 'month').startOf('month').format('YYYY-MM-DD HH:mm:ss')
+          end = now.subtract(1, 'month').endOf('month').format('YYYY-MM-DD HH:mm:ss')
+          break
+      }
+
+      this.time = [start, end]
+      this.$emit('submitTime', this.time)
+    },
+
+    // 澶勭悊鏃堕棿鑼冨洿閫夋嫨鍙樺寲
+    handleRangeChange(val) {
+      if (val) {
+        this.selectTimeRange(val)
+      }
+    },
+
+    // 鍒囨崲鏃堕棿閫夋嫨鍣ㄧ殑鏄剧ず/闅愯棌
+    toggleTimePicker() {
+      this.showTimePicker = !this.showTimePicker
+    },
+  },
+}
 </script>
 
 <template>
-  <!-- 鏃ユ湡鏃堕棿閫夋嫨鍣� -->
-  <div class="block">
-    <span class="demonstration">璧锋鏃堕棿锛�</span>
+  <!-- 鏃堕棿閫夋嫨缁勪欢 -->
+  <div v-if="useNewStyle" class="time-select-container">
+    <el-row align="middle" class="m-b-8">
+      <span class="demonstration">鏃堕棿锛�</span>
+      <!-- 蹇嵎鏃舵閫夋嫨鎸夐挳 -->
+      <div class="quick-time-buttons">
+        <el-radio-group v-model="selectedRange" @change="handleRangeChange">
+          <el-radio-button v-for="range in timeRanges" :key="range.value" :label="range.value">
+            {{ range.label }}
+          </el-radio-button>
+        </el-radio-group>
+        <el-button size="small" type="primary" @click="toggleTimePicker">鏃堕棿璇︽儏</el-button>
+      </div>
+    </el-row>
+
+    <!-- 鏃堕棿閫夋嫨鍣紙榛樿闅愯棌锛� -->
+    <div v-show="showTimePicker" class="time-picker-container">
+      <el-date-picker
+        v-model="time"
+        type="daterange"
+        range-separator="~"
+        start-placeholder="寮�濮嬫椂闂�"
+        end-placeholder="缁撴潫鏃堕棿"
+        @change="$emit('submitTime', time)"
+        class="pick-date"
+      />
+    </div>
+  </div>
+
+  <!-- 鍘熸湁鏍峰紡 -->
+  <div v-else class="block">
+    <span class="demonstration">鏃堕棿锛�</span>
     <el-date-picker
       v-model="time"
-      type="datetimerange"
+      type="daterange"
       range-separator="~"
       start-placeholder="Start date"
       end-placeholder="End date"
       @change="$emit('submitTime', time)"
       class="pick-date"
-
     />
   </div>
 </template>
 
 <style>
+.time-select-container {
+  /* width: 100%; */
+}
+
+.time-label {
+  margin-bottom: 8px;
+}
+
+.quick-time-buttons {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+  align-items: center;
+}
+
+.time-picker-container {
+  display: flex;
+  align-items: center;
+  white-space: nowrap;
+}
+
 .demonstration {
-  margin-left: 30px;
-  margin-top: 5px;
+  margin-right: 10px;
   font-weight: bold;
   white-space: nowrap;
 }
+
+.pick-date {
+  width: 100%;
+}
+
 .block {
   display: flex;
   justify-content: center;
   /* width: 50%; */
   white-space: nowrap;
 }
-.pick-date {
-  width: 100%;
 
-} 
+.block .demonstration {
+  margin-left: 30px;
+  margin-top: 5px;
+}
 </style>
diff --git a/src/style/base.scss b/src/style/base.scss
index 93f05ed..b151ce8 100644
--- a/src/style/base.scss
+++ b/src/style/base.scss
@@ -5,3 +5,102 @@
 body {
   margin: 0;
 }
+
+/************************************** font size **************************************/
+$fontsize: (
+  s: var(--el-font-size-small),
+  b: var(--el-font-size-base),
+  m: var(--el-font-size-medium),
+  l: var(--el-font-size-large),
+);
+
+@each $dName, $dValue in $fontsize {
+  .f-#{$dName} {
+    font-size: #{$dValue};
+  }
+}
+
+/************************************** color **************************************/
+$colors: (
+  p: var(--el-color-primary),
+  s: var(--el-color-success),
+  w: var(--el-color-warning),
+  d: var(--el-color-danger),
+  e: var(--el-color-error),
+  i: var(--el-color-info),
+);
+
+@each $dName, $dValue in $colors {
+  .color-#{$dName} {
+    color: #{$dValue};
+  }
+  .b-color-#{$dName} {
+    background-color: #{$dValue};
+  }
+}
+
+/************************************** 鍐呭杈硅窛 **************************************/
+$direction: (
+  l: 'left',
+  t: 'top',
+  r: 'right',
+  b: 'bottom',
+);
+$size: (4, 8, 10, 16);
+@each $dName, $dValue in $direction {
+  @each $i in $size {
+    .p-#{$dName}-#{$i} {
+      padding-#{$dValue}: #{$i}px;
+    }
+    .m-#{$dName}-#{$i} {
+      margin-#{$dValue}: #{$i}px;
+    }
+  }
+}
+
+@each $i in $size {
+  .p-#{$i} {
+    padding: #{$i}px;
+  }
+  .p-v-#{$i} {
+    padding: #{$i}px 0;
+  }
+  .p-h-#{$i} {
+    padding: 0 #{$i}px;
+  }
+  .m-v-#{$i} {
+    margin: #{$i}px 0;
+  }
+  .m-h-#{$i} {
+    margin: 0 #{$i}px;
+  }
+}
+
+/************************************** 瀹介珮 **************************************/
+$csize: (
+  small: var(--el-component-size-small),
+  default: var(--el-component-size-default),
+  large: var(--el-component-size-large),
+);
+$ws: (20px, 40px, 60px, 100px, 150px, 250px, 300px);
+@each $name, $value in $csize {
+  .w-#{$name} {
+    width: #{$value};
+  }
+  .h-#{$name} {
+    height: #{$value};
+  }
+}
+@each $i in $ws {
+  .w-#{$i} {
+    width: #{$i};
+  }
+  .h-#{$i} {
+    height: #{$i};
+  }
+}
+
+//
+.cursor-p {
+  cursor: pointer;
+}
diff --git a/src/style/layout.js b/src/style/layout.js
new file mode 100644
index 0000000..f315ca1
--- /dev/null
+++ b/src/style/layout.js
@@ -0,0 +1,70 @@
+// 琛ㄥ崟鐨勫搷搴斿紡鏍呮牸甯冨眬
+function formResponsiveCols() {
+  return {
+    xs: {
+      span: 24,
+      offset: 0,
+      push: 0,
+      pull: 0
+    },
+    sm: {
+      span: 24,
+      offset: 0,
+      push: 0,
+      pull: 0
+    },
+    md: {
+      span: 20,
+      offset: 2,
+      push: 0,
+      pull: 0
+    },
+    lg: {
+      span: 18,
+      offset: 3,
+      push: 0,
+      pull: 0
+    },
+    xl: {
+      span: 14,
+      offset: 5,
+      push: 0,
+      pull: 0
+    }
+  };
+}
+
+const cardResponsiveCols = {
+  xs: {
+    span: 24,
+    offset: 0,
+    push: 0,
+    pull: 0
+  },
+  sm: {
+    span: 24,
+    offset: 0,
+    push: 0,
+    pull: 0
+  },
+  md: {
+    span: 24,
+    offset: 0,
+    push: 0,
+    pull: 0
+  },
+  lg: {
+    span: 12,
+    offset: 0,
+    push: 0,
+    pull: 0
+  },
+  xl: {
+    span: 8,
+    offset: 0,
+    push: 0,
+    pull: 0
+  }
+};
+
+export { formResponsiveCols, cardResponsiveCols };
diff --git a/src/utils/map/districtsearch.js b/src/utils/map/districtsearch.js
index dcba0a1..a145b87 100644
--- a/src/utils/map/districtsearch.js
+++ b/src/utils/map/districtsearch.js
@@ -1,53 +1,83 @@
-import { map, AMap, onMapMounted } from './index';
+import { map, AMap, onMapMounted } from './index'
 
 // 琛屾斂鍖哄垝缂撳瓨
-var districtPolygonMap = new Map();
+var districtPolygonMap = new Map()
 // 褰撳墠鏄剧ず鐨勫尯鍘�
-var activeDistrict = undefined;
+var activeDistrict = undefined
 export default {
   // 缁樺埗鍖哄幙杈圭晫
   drawDistrict(districtName, isNew) {
-    if(!districtName) return;
+    if (!districtName) return
     onMapMounted(() => {
       if (!isNew && districtPolygonMap.has(districtName)) {
-        const districtPolygon = districtPolygonMap.get(districtName);
-        map.add(districtPolygon);
-        map.setFitView(districtPolygon);
-        activeDistrict = districtPolygon;
+        const { polygon, mask } = districtPolygonMap.get(districtName)
+        map.add(polygon)
+        map.setFitView(polygon)
+        map.setMask(mask)
+        activeDistrict = polygon
       } else {
         var district = new AMap.DistrictSearch({
           extensions: 'all', //杩斿洖琛屾斂鍖鸿竟鐣屽潗鏍囩瓑鍏蜂綋淇℃伅
-          level: 'district' //璁剧疆鏌ヨ琛屾斂鍖虹骇鍒负鍖�
-        });
+          level: 'district', //璁剧疆鏌ヨ琛屾斂鍖虹骇鍒负鍖�
+        })
         district.search(districtName, function (status, result) {
-          var bounds = result.districtList[0].boundaries; //鑾峰彇杈圭晫淇℃伅
-          if (bounds) {
+          if (status === 'complete') {
+            var bounds = result.districtList[0].boundaries //鑾峰彇杈圭晫淇℃伅
+            var mask = []
+            var polygon = []
             for (var i = 0; i < bounds.length; i++) {
+              mask.push([bounds[i]])
+
               //鐢熸垚琛屾斂鍖哄垝 polygon
               const districtPolygon = new AMap.Polygon({
                 map: map, //鏄剧ず璇ヨ鐩栫墿鐨勫湴鍥惧璞�
-                strokeWeight: 1, //杞粨绾垮搴�
+                strokeWeight: 2, //杞粨绾垮搴�
                 path: bounds[i], //澶氳竟褰㈣疆寤撶嚎鐨勮妭鐐瑰潗鏍囨暟缁�
-                fillOpacity: 0.4, //澶氳竟褰㈠~鍏呴�忔槑搴�
+                fillOpacity: 0, //澶氳竟褰㈠~鍏呴�忔槑搴�
                 fillColor: '#0077ff',
-                strokeColor: '#CC66CC' //绾挎潯棰滆壊
-              });
+                strokeColor: '#99ffff', //绾挎潯棰滆壊
+              })
 
-              districtPolygonMap.set(districtName, districtPolygon);
-              activeDistrict = districtPolygon;
-              map.setFitView(districtPolygon, true);
+              polygon.push(districtPolygon)
             }
+            activeDistrict = polygon
+            districtPolygonMap.set(districtName, { polygon, mask })
+            map.setFitView(polygon, true)
+            map.setMask(mask)
           }
-        });
+        })
       }
-    });
+    })
   },
   removeDistrict() {
     onMapMounted(() => {
       if (activeDistrict) {
-        map.remove(activeDistrict);
-        activeDistrict = undefined;
+        map.remove(activeDistrict)
+        activeDistrict = undefined
       }
     })
-  }
-};
+  },
+  districtLayer(districtName) {
+    onMapMounted(() => {
+      //2銆佸垱寤虹渷甯傜畝鏄撹鏀垮尯鍥惧眰
+      var distProvince = new AMap.DistrictLayer.Province({
+        zIndex: 10, //璁剧疆鍥惧眰灞傜骇
+        zooms: [2, 15], //璁剧疆鍥惧眰鏄剧ず鑼冨洿
+        adcode: districtName, //璁剧疆琛屾斂鍖� adcode
+        depth: 2, //璁剧疆鏁版嵁鏄剧ず灞傜骇锛�0锛氭樉绀哄浗瀹堕潰锛�1锛氭樉绀虹渷绾э紝褰撳浗瀹朵负涓浗鏃惰缃甦epth涓�2鐨勫彲浠ユ樉绀哄競涓�绾�
+      })
+      // 3銆佽缃鏀垮尯鍥惧眰鏍峰紡
+      distProvince.setStyles({
+        'stroke-width': 2, //鎻忚竟绾垮
+        fill: function (data) {
+          //璁剧疆鍖哄煙濉厖棰滆壊锛屽彲鏍规嵁鍥炶皟淇℃伅杩斿洖鍖哄煙淇℃伅璁剧疆涓嶅悓濉厖鑹�
+          //鍥炶皟杩斿洖鍖哄煙淇℃伅鏁版嵁锛屽瓧娈靛寘鎷� SOC(鍥藉浠g爜)銆丯AME_ENG(鑻辨枃鍚嶇О)銆丯AME_CHN(涓枃鍚嶇О)绛�
+          //鍥藉浠g爜鍚嶇О璇存槑鍙傝�� https://a.amap.com/jsapi_demos/static/demo-center/js/soc-list.json
+          return '#ffffffe7'
+        },
+      })
+      //4銆佸皢绠�鏄撹鏀垮尯鍥惧眰娣诲姞鍒板湴鍥�
+      map.add(distProvince)
+    })
+  },
+}
diff --git a/src/utils/map/index.js b/src/utils/map/index.js
index 76a1e7b..80a18f1 100644
--- a/src/utils/map/index.js
+++ b/src/utils/map/index.js
@@ -1,28 +1,28 @@
-import AMapLoader from '@amap/amap-jsapi-loader';
+import AMapLoader from '@amap/amap-jsapi-loader'
 
-var mapInitDone = false;
-var onMapMountedEvents = [];
+var mapInitDone = false
+var onMapMountedEvents = []
 
-var AMap;
+var AMap
 // 鍦板浘瀵硅薄
-var map;
+var map
 // 鍗槦鍥惧眰
-var satellite;
+var satellite
 // 榧犳爣缁樺浘
-var mouseTool;
+var mouseTool
 // 3D鍥惧眰
-var object3Dlayer;
+var object3Dlayer
 // 鍦板浘鎷栧姩鐘舵��
-var isDragging = false;
+var isDragging = false
 
 // 鍦板浘鍔犺浇瀹屾垚瑙﹀彂
 function onMapMounted(...events) {
   if (mapInitDone) {
     events.forEach((e) => {
-      e();
-    });
+      e()
+    })
   } else {
-    onMapMountedEvents = onMapMountedEvents.concat(events);
+    onMapMountedEvents = onMapMountedEvents.concat(events)
   }
 }
 
@@ -36,50 +36,51 @@
       'AMap.ControlBar',
       'AMap.ToolBar',
       'AMap.Scale',
-      'AMap.DistrictSearch'
+      'AMap.DistrictSearch',
       // 'AMap.DragRoute',
       // 'AMap.MouseTool',
       // 'AMap.PolygonEditor'
-    ]
+    ],
   })
     .then((_AMap) => {
-      AMap = _AMap;
-      _initMap(id);
-      mapInitDone = true;
+      AMap = _AMap
+      _initMap(id)
+      mapInitDone = true
       onMapMountedEvents.forEach((e) => {
-        e();
-      });
-      onMapMountedEvents = [];
-      console.log('-------------------map init done');
+        e()
+      })
+      onMapMountedEvents = []
+      console.log('-------------------map init done')
     })
     .catch((e) => {
-      console.log(e);
-    });
+      console.log(e)
+    })
 }
 
 function destroyMap() {
-  map?.destroy();
-  map = null;
-  mapInitDone = false;
+  map?.destroy()
+  map = null
+  mapInitDone = false
 }
 
 function _initMap(elementId) {
   map = new AMap.Map(elementId, {
     // mapStyle: 'amap://styles/e1e78509de64ddcd2efb4cb34c6fae2a',
     features: ['bg', 'road'],
-    pitch: 45, // 鍦板浘淇话瑙掑害锛屾湁鏁堣寖鍥� 0 搴�- 83 搴�
-    viewMode: '2D', // 鍦板浘妯″紡
+    pitch: 30, // 鍦板浘淇话瑙掑害锛屾湁鏁堣寖鍥� 0 搴�- 83 搴�
+    viewMode: '3D', // 鍦板浘妯″紡
     resizeEnable: true,
     center: [121.6039283, 31.25295567],
     zooms: [2, 26],
-    zoom: 14
-  });
+    zoom: 14,
+  })
   // map = new AMap.Map(elementId);
 
   // 娣诲姞鍗槦鍦板浘
-  satellite = new AMap.TileLayer.Satellite();
-  satellite.hide();
-  map.add([satellite]);
+  satellite = new AMap.TileLayer.Satellite()
+  const roadNet = new AMap.TileLayer.RoadNet()
+  // satellite.hide()
+  map.add([satellite, roadNet])
 
   // _initMouseTool();
   // _init3DLayer();
@@ -88,36 +89,27 @@
 
 // 榧犳爣缁樺浘鍒濆鍖�
 function _initMouseTool() {
-  mouseTool = new AMap.MouseTool(map);
+  mouseTool = new AMap.MouseTool(map)
 }
 
 // 3D鍥惧眰鍒濆鍖�
 function _init3DLayer() {
-  object3Dlayer = new AMap.Object3DLayer();
-  map.add(object3Dlayer);
+  object3Dlayer = new AMap.Object3DLayer()
+  map.add(object3Dlayer)
 }
 
 // 璁剧疆鍦板浘鎷栨嫿鐩戝惉浜嬩欢
 function _initDragEvent() {
-  let dragEndEvent;
+  let dragEndEvent
   map.on('dragstart', () => {
-    clearTimeout(dragEndEvent);
-    isDragging = true;
-  });
+    clearTimeout(dragEndEvent)
+    isDragging = true
+  })
   map.on('dragend', function () {
     dragEndEvent = setTimeout(() => {
-      isDragging = false;
-    }, 8000);
-  });
+      isDragging = false
+    }, 8000)
+  })
 }
 
-export {
-  createMap,
-  destroyMap,
-  onMapMounted,
-  map,
-  AMap,
-  mouseTool,
-  object3Dlayer,
-  isDragging
-};
+export { createMap, destroyMap, onMapMounted, map, AMap, mouseTool, object3Dlayer, isDragging }
diff --git a/src/views/inspection/scenenew/UserEdit.vue b/src/views/inspection/scenenew/UserEdit.vue
new file mode 100644
index 0000000..1db19c5
--- /dev/null
+++ b/src/views/inspection/scenenew/UserEdit.vue
@@ -0,0 +1,191 @@
+<template>
+  <el-page-header @back="onBack">
+    <template #content>
+      <span> 璐︽埛淇℃伅缂栬緫 </span>
+    </template>
+  </el-page-header>
+  <el-divider />
+  <el-tabs v-model="activeName" class="p-h-8" @tab-click="handleClick">
+    <el-tab-pane label="鍩烘湰淇℃伅" name="first">
+      <FormCol>
+        <div class="sub-title">璐︽埛淇℃伅</div>
+        <CompUserInfo :model="formUser" />
+      </FormCol>
+      <el-divider />
+      <FormCol>
+        <div class="sub-title">搴楅摵淇℃伅</div>
+        <CompSceneInfo :form-info="formSceneInfo" />
+      </FormCol>
+      <el-divider />
+      <FormCol>
+        <div class="sub-title">浼佷笟淇℃伅</div>
+        <CompCompanyInfo :form-info="formCompanyInfo" />
+      </FormCol>
+    </el-tab-pane>
+    <el-tab-pane label="璁惧绠$悊" name="second">
+      <FormCol>
+        <el-row class="sub-title" justify="space-between">
+          <div>鐩戞祴璁惧淇℃伅</div>
+          <el-button type="success" @click="addDevice">鏂板璁惧</el-button>
+        </el-row>
+        <!-- 鏂板璁惧琛ㄥ崟 -->
+        <CompDeviceInfo
+          v-if="showAddDevice"
+          :form-info="newDeviceForm"
+          :create="true"
+          @onSubmit="handleDeviceSubmit"
+          @onCancel="handleDeviceCancel"
+        />
+        <!-- 璁惧鍒楄〃 -->
+        <div v-if="formDeviceList.length === 0 && !showAddDevice" class="empty-device">
+          <el-empty description="鏆傛棤璁惧淇℃伅" />
+        </div>
+        <CompDeviceInfo
+          v-else-if="formDeviceList.length > 0"
+          v-for="(item, index) in formDeviceList"
+          :key="index"
+          :form-info="item"
+        />
+      </FormCol>
+    </el-tab-pane>
+
+    <el-tab-pane label="鍗卞簾鎺掓薄" name="third">
+      <FormCol>
+        <div class="sub-title">鍗卞簾鎺掓薄娓呭崟</div>
+        <CompHazardousWasteFile :form-info="formHazardousWasteFile" />
+      </FormCol>
+      <FormCol>
+        <div class="sub-title">鍗卞簾鎺掓薄璁板綍</div>
+        <CompHazardousWasteRecord :form-info="formHazardousWasteRecord" />
+      </FormCol>
+    </el-tab-pane>
+
+    <el-tab-pane label="琛屾斂澶勭綒" name="fourth">
+      <FormCol>
+        <div class="sub-title">琛屾斂澶勭綒琛�</div>
+        <!-- <CompPunishment :form-info="formProblem" /> -->
+      </FormCol>
+    </el-tab-pane>
+
+    <el-tab-pane label="淇¤鎶曡瘔" name="fifth">
+      <FormCol>
+        <div class="sub-title">淇¤鎶曡瘔</div>
+        <!-- <CompLaint :form-info="formLaint" /> -->
+      </FormCol>
+    </el-tab-pane>
+
+    <el-tab-pane label="宸℃煡闂琛�" name="sixth">
+      <FormCol>
+        <div class="sub-title">宸℃煡闂琛�</div>
+        <!-- <CompProblem :form-info="formProblem" /> -->
+      </FormCol>
+    </el-tab-pane>
+  </el-tabs>
+
+  <!-- <ComBaseInformation v-model="drawer"></ComBaseInformation> -->
+</template>
+
+<script>
+import userApi from '@/api/fytz/userApi'
+import CompUserInfo from './components/CompUserInfo.vue'
+import CompSceneInfo from './components/CompSceneInfo.vue'
+import CompCompanyInfo from './components/CompCompanyInfo.vue'
+import CompDeviceInfo from './components/CompDeviceInfo.vue'
+import CompHazardousWasteFile from './components/CompHazardousWasteFile.vue'
+import CompHazardousWasteRecord from './components/CompHazardousWasteRecord.vue'
+
+export default {
+  components: {
+    // ComBaseInformation,
+    // CompLaint,
+    CompUserInfo,
+    CompSceneInfo,
+    CompCompanyInfo,
+    CompDeviceInfo,
+    CompHazardousWasteFile,
+    CompHazardousWasteRecord,
+    // CompPanyInfo,
+    // CompFumePurifyDevice,
+    // CompHazardousWasteFile,
+    // CompHazardousWasteRecord,
+    // CompProblem,
+    // CompPunishment,
+    // CompRestaurantBaseInfo,
+    // CompVehicleBaseInfo,
+    // CompUserInfos,
+  },
+  data() {
+    return {
+      drawer: false,
+      formUser: {},
+      formSceneInfo: {},
+      formCompanyInfo: {},
+      // formSubScene: {},
+      formLaint: {},
+      formDeviceList: [],
+      formPanyInfo: {},
+      formFumePurifyDevice: {},
+      formHazardousWasteFile: {},
+      formHazardousWasteRecord: {},
+      formProblem: {},
+      formPunishment: {},
+      formRestaurantBaseInfo: {},
+      activeName: 'first',
+      scroll: '',
+      showAddDevice: false,
+      newDeviceForm: {},
+    }
+  },
+  beforeRouteEnter(to, from, next) {
+    userApi.fetchUserBaseInfo(to.params.userId).then((res) => {
+      next((vm) => {
+        if (res.userInfo) {
+          vm.formUser = res.userInfo
+        } else {
+          vm.formUser = {
+            guid: to.params.userId,
+          }
+        }
+      })
+    })
+  },
+  methods: {
+    handleClick(tab) {
+      console.log('tab', tab)
+    },
+    // 鍥為��椤甸潰
+    onBack() {
+      this.$router.back()
+    },
+    // 鏂板璁惧
+    addDevice() {
+      this.showAddDevice = true
+      this.newDeviceForm = {}
+    },
+    // 璁惧鎻愪氦
+    handleDeviceSubmit(formData) {
+      // 杩欓噷鍙互娣诲姞瀹為檯鐨凙PI璋冪敤
+      this.formDeviceList.push(formData.value)
+      this.showAddDevice = false
+      this.newDeviceForm = {}
+    },
+    // 璁惧鍙栨秷
+    handleDeviceCancel() {
+      this.showAddDevice = false
+      this.newDeviceForm = {}
+    },
+  },
+}
+</script>
+<style scoped>
+.sub-title {
+  font-size: var(--el--font--size--large);
+  margin-bottom: 30px;
+  margin-top: 30px;
+  margin-left: 20px;
+}
+.empty-device {
+  padding: 40px 0;
+  text-align: center;
+}
+</style>
diff --git a/src/views/inspection/scenenew/UserInfo.vue b/src/views/inspection/scenenew/UserInfo.vue
new file mode 100644
index 0000000..73dbfb2
--- /dev/null
+++ b/src/views/inspection/scenenew/UserInfo.vue
@@ -0,0 +1,226 @@
+<template>
+  <FYTable @search="onSearch" :row-class-name="tableRowClassName">
+    <template #options>
+      <FYOptionLocation
+        :allOption="true"
+        :level="5"
+        v-model:value="formSearch._locations"
+      ></FYOptionLocation>
+      <FYOptionText
+        label="鍦烘櫙鍚嶇О"
+        placeholder="杈撳叆鍚嶇О鍏抽敭瀛�"
+        v-model:value="formSearch.searchText"
+      ></FYOptionText>
+      <FYOptionScene
+        :allOption="true"
+        :type="1"
+        :initValue="false"
+        v-model:value="formSearch.scensetype"
+      ></FYOptionScene>
+      <FYOptionOnlineStatus
+        :allOption="true"
+        v-model:value="formSearch.online"
+      ></FYOptionOnlineStatus>
+    </template>
+
+    <template #table-column>
+      <el-table-column
+        fixed="left"
+        prop="userInfo.realname"
+        label="鍚嶇О"
+        :show-overflow-tooltip="true"
+        width="400"
+      >
+      </el-table-column>
+      <el-table-column prop="userInfo.acountname" label="璐﹀彿" width="110" />
+      <el-table-column prop="sceneTypeName" label="绫诲瀷" width="100" />
+      <el-table-column prop="biProvinceName" label="鐪�" width="80" />
+      <el-table-column prop="biCityName" label="甯�" width="80" />
+      <!-- <el-table-column prop="districtname" label="鍖哄幙" width="90" /> -->
+      <el-table-column prop="userInfo.extension1" label="鍖哄幙" width="80" />
+      <el-table-column prop="biTownName" label="琛楅亾" width="110" />
+      <el-table-column prop="biArea" label="闆嗕腑鍖�" width="110" />
+      <el-table-column prop="biManagementCompany" label="鐗╀笟" min-width="110" />
+      <el-table-column prop="userInfo.isenable" label="鐘舵��" width="90">
+        <template #default="{ row }">
+          {{ row.userInfo.isenable ? '涓婄嚎涓�' : '宸蹭笅绾�' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="userInfo.usertype" label="鐢ㄦ埛绫诲瀷" width="90" />
+      <el-table-column fixed="right" align="right" label="鎿嶄綔" width="190">
+        <template #header>
+          <el-button icon="DocumentAdd" size="default" type="success" @click="drawer = true"
+            >鏂板鐢ㄦ埛</el-button
+          >
+        </template>
+        <template #default="{ row }">
+          <el-space>
+            <el-button
+              :loading="row.loading2"
+              :type="row.userInfo.isenable != '0' ? 'danger' : 'primary'"
+              size="small"
+              @click="itemActive(row)"
+              >{{ row.userInfo.isenable != '0' ? '涓嬬嚎' : '涓婄嚎' }}</el-button
+            >
+            <el-button-group>
+              <el-button type="primary" :loading="row.loading1" size="small" @click="editRow(row)"
+                >鏌ョ湅</el-button
+              >
+              <el-dropdown @command="handleCommand" trigger="click">
+                <el-button
+                  type="primary"
+                  :loading="row.downloadLoading"
+                  size="small"
+                  :icon="row.downloadLoading ? '' : 'ArrowDown'"
+                ></el-button>
+                <template #dropdown>
+                  <el-dropdown-menu>
+                    <el-dropdown-item icon="Download" :command="{ c: 1, p: row }"
+                      >涓嬭浇鐜俊鐮�</el-dropdown-item
+                    >
+                  </el-dropdown-menu>
+                </template>
+              </el-dropdown>
+            </el-button-group>
+            <!-- <el-dropdown
+              split-button
+              :loading="row.loading1"
+              size="small"
+              type="primary"
+              @click="editRow(row)"
+              @command="handleCommand"
+              trigger="click"
+            >
+              鏌ョ湅
+              <template #dropdown>
+                <el-dropdown-menu>
+                  <el-dropdown-item icon="Download" :command="{ c: 1, p: row }"
+                    >涓嬭浇鐜俊鐮�</el-dropdown-item
+                  >
+                </el-dropdown-menu>
+              </template>
+            </el-dropdown> -->
+          </el-space>
+        </template>
+      </el-table-column>
+    </template>
+  </FYTable>
+  <CompUserInfoAddDrawer v-model="drawer"></CompUserInfoAddDrawer>
+</template>
+
+<script>
+import userApi from '@/api/fytz/userApi'
+import creditApi from '@/api/fytz/creditApi'
+import { useLoadingStore } from '@/stores/loadingStore'
+import { mapStores } from 'pinia'
+import { useMessageBoxTip } from '@/composables/messageBox'
+import CompUserInfoAddDrawer from './components/CompUserInfoAddDrawer.vue'
+
+export default {
+  components: {
+    CompUserInfoAddDrawer,
+  },
+  data() {
+    return {
+      // 鏌ヨ鏉′欢
+      formSearch: {
+        _locations: {},
+        searchText: '',
+        scensetype: {
+          label: '椁愰ギ',
+          value: '1',
+        },
+        online: {},
+      },
+      // 鏂板鐢ㄦ埛寮瑰嚭妗�
+      drawer: false,
+    }
+  },
+  computed: {
+    ...mapStores(useLoadingStore),
+  },
+  methods: {
+    onSearch(page, func) {
+      const f = this.formSearch
+      const area = {}
+      // 琛屾斂鍖哄垝
+      area.provinceCode = f._locations.pCode
+      area.provinceName = f._locations.pName
+      if (area.provinceCode == null) {
+        area.provinceCode = null
+        area.provinceName = null
+      }
+      area.cityCode = f._locations.cCode
+      area.cityName = f._locations.cName
+      area.districtCode = f._locations.dCode
+      area.districtName = f._locations.dName
+      area.townCode = f._locations.tCode
+      area.townName = f._locations.tName
+      // 鍦烘櫙绫诲瀷
+      area.sceneTypes = []
+      f.scensetype.value == null ? (area.sceneTypes = []) : (area.sceneTypes = [f.scensetype.value])
+      // 涓婁笅绾跨姸鎬�
+      area.online = f.online.value
+      // 鍏抽敭瀛�
+      area.searchText = f.searchText
+
+      userApi.fetchUser(page.currentPage, page.pageSize, area).then((res) => {
+        if (res) {
+          func({
+            data: res.data,
+            total: res.head.totalCount,
+          })
+        }
+      })
+    },
+    editRow(row) {
+      row.loading1 = true
+      this.loadingStore.pushLoading(() => (row.loading1 = false))
+      this.$router.push(`scene-info-edit/${row.userInfo.guid}`)
+    },
+    itemActive(row) {
+      const param = {
+        guid: row.userInfo.guid,
+        isenable: !row.userInfo.isenable,
+      }
+      const msg = row.userInfo.isenable ? '涓嬬嚎' : '涓婄嚎'
+      useMessageBoxTip({
+        confirmMsg: `纭${msg}璇ュ満鏅紵`,
+        confirmTitle: msg,
+        onConfirm: async () => {
+          row.loading2 = true
+          return userApi
+            .updateUserInfo(param)
+            .then((res) => {
+              if (res.success) {
+                row.userInfo.isenable = param.isenable
+              }
+            })
+            .finally(() => {
+              row.loading2 = false
+            })
+        },
+      })
+    },
+    tableRowClassName({ row }) {
+      return row.userInfo.isenable ? 'online-row' : 'offline-row'
+    },
+    handleCommand(e) {
+      const userId = e.p.userInfo.guid
+      switch (e.c) {
+        // 涓嬭浇鐜俊鐮�
+        case 1:
+          e.p.downloadLoading = true
+          creditApi.downloadCode(userId).finally(() => {
+            e.p.downloadLoading = false
+          })
+          break
+
+        default:
+          break
+      }
+    },
+  },
+}
+</script>
+<style></style>
diff --git a/src/views/inspection/scenenew/components/CompCompanyInfo.vue b/src/views/inspection/scenenew/components/CompCompanyInfo.vue
new file mode 100644
index 0000000..dc440f1
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompCompanyInfo.vue
@@ -0,0 +1,205 @@
+<template>
+  <el-form
+    :inline="false"
+    :model="formObj"
+    ref="formRef"
+    :rules="rules"
+    label-position="right"
+    label-width="150px"
+  >
+    <el-form-item label="鍗曚綅鍚嶇О" prop="companyName">
+      <el-input clearable v-model="formObj.companyName" placeholder="鍗曚綅鍚嶇О" />
+    </el-form-item>
+    <el-form-item label="涓昏浠庝簨涓氬姟" prop="businessScope">
+      <el-input
+        clearable
+        v-model="formObj.businessScope"
+        placeholder="涓昏浠庝簨涓氬姟"
+        type="textarea"
+        rows="2"
+      />
+    </el-form-item>
+    <el-form-item label="鎵�灞為泦鍥�" prop="group">
+      <el-input clearable v-model="formObj.group" placeholder="鎵�灞為泦鍥�" />
+    </el-form-item>
+    <el-form-item label="鐪佷唤鍚嶇О" prop="province">
+      <el-input clearable v-model="formObj.province" placeholder="鐪佷唤鍚嶇О" />
+    </el-form-item>
+    <el-form-item label="鍦板競鍚嶇О" prop="city">
+      <el-input clearable v-model="formObj.city" placeholder="鍦板競鍚嶇О" />
+    </el-form-item>
+    <el-form-item label="鍖哄幙鍚嶇О" prop="district">
+      <el-input clearable v-model="formObj.district" placeholder="鍖哄幙鍚嶇О" />
+    </el-form-item>
+    <el-form-item label="琛楅晣鍚嶇О" prop="town">
+      <el-input clearable v-model="formObj.town" placeholder="琛楅晣鍚嶇О" />
+    </el-form-item>
+    <el-form-item label="鎵�鍦ㄥ伐涓氬尯" prop="industrialZone">
+      <el-input clearable v-model="formObj.industrialZone" placeholder="鎵�鍦ㄥ伐涓氬尯" />
+    </el-form-item>
+    <el-form-item label="鍗曚綅鍦板潃" prop="address">
+      <el-input
+        clearable
+        v-model="formObj.address"
+        placeholder="鍗曚綅鍦板潃"
+        type="textarea"
+        rows="2"
+      />
+    </el-form-item>
+    <el-form-item label="缁勭粐鏈烘瀯浠g爜" prop="orgCode">
+      <el-input clearable v-model="formObj.orgCode" placeholder="缁勭粐鏈烘瀯浠g爜" />
+    </el-form-item>
+    <el-form-item label="娉曚汉" prop="legalPerson">
+      <el-input clearable v-model="formObj.legalPerson" placeholder="娉曚汉" />
+    </el-form-item>
+    <el-form-item label="琛屼笟绫诲埆" prop="industryCategory">
+      <el-input clearable v-model="formObj.industryCategory" placeholder="琛屼笟绫诲埆" />
+    </el-form-item>
+    <el-form-item label="琛屼笟浠g爜" prop="industryCode">
+      <el-input clearable v-model="formObj.industryCode" placeholder="琛屼笟浠g爜" />
+    </el-form-item>
+    <el-form-item label="鐧昏娉ㄥ唽绫诲瀷" prop="registrationType">
+      <el-input clearable v-model="formObj.registrationType" placeholder="鐧昏娉ㄥ唽绫诲瀷" />
+    </el-form-item>
+    <el-form-item label="娉ㄥ唽璧勬湰锛堜竾鍏冿級" prop="registeredCapital">
+      <el-input
+        clearable
+        type="number"
+        v-model="formObj.registeredCapital"
+        placeholder="娉ㄥ唽璧勬湰锛堜竾鍏冿級"
+      />
+    </el-form-item>
+    <el-form-item label="寤哄巶骞存湀" prop="establishmentDate">
+      <el-input clearable v-model="formObj.establishmentDate" placeholder="寤哄巶骞存湀" />
+    </el-form-item>
+    <el-form-item label="鏈�鏂版敼鎵╁缓骞存湀" prop="latestExpansionDate">
+      <el-input clearable v-model="formObj.latestExpansionDate" placeholder="鏈�鏂版敼鎵╁缓骞存湀" />
+    </el-form-item>
+    <el-form-item label="鑱屽伐浜烘暟" prop="employeeCount">
+      <el-input clearable type="number" v-model="formObj.employeeCount" placeholder="鑱屽伐浜烘暟" />
+    </el-form-item>
+    <el-form-item label="浼佷笟瑙勬ā" prop="companyScale">
+      <el-input clearable v-model="formObj.companyScale" placeholder="浼佷笟瑙勬ā" />
+    </el-form-item>
+    <el-form-item label="鍘嗘鐜瘎瀹℃壒骞存湀" prop="鐜瘎ApprovalDate">
+      <el-input clearable v-model="formObj.鐜瘎ApprovalDate" placeholder="鍘嗘鐜瘎瀹℃壒骞存湀" />
+    </el-form-item>
+    <el-form-item label="鎺掓薄璁稿彲璇佺紪鍙�" prop="pollutantLicenseNumber">
+      <el-input clearable v-model="formObj.pollutantLicenseNumber" placeholder="鎺掓薄璁稿彲璇佺紪鍙�" />
+    </el-form-item>
+    <el-form-item label="鎺掓薄鏉冧氦鏄撴枃浠�" prop="emissionRightFile">
+      <el-input clearable v-model="formObj.emissionRightFile" placeholder="鎺掓薄鏉冧氦鏄撴枃浠�" />
+    </el-form-item>
+    <el-form-item label="閭斂缂栫爜" prop="postalCode">
+      <el-input clearable v-model="formObj.postalCode" placeholder="閭斂缂栫爜" />
+    </el-form-item>
+    <el-form-item label="鑱旂郴浜哄鍚�" prop="contactName">
+      <el-input clearable v-model="formObj.contactName" placeholder="鑱旂郴浜哄鍚�" />
+    </el-form-item>
+    <el-form-item label="鑱旂郴鐢佃瘽" prop="telephone">
+      <el-input clearable type="tel" v-model="formObj.telephone" placeholder="鑱旂郴鐢佃瘽">
+        <template #prepend>
+          <el-icon><Iphone /></el-icon>
+        </template>
+      </el-input>
+    </el-form-item>
+    <el-form-item label="鑱旂郴寰俊鍙�" prop="wechat">
+      <el-input clearable v-model="formObj.wechat" placeholder="鑱旂郴寰俊鍙�" />
+    </el-form-item>
+    <el-form-item label="浼犵湡" prop="fax">
+      <el-input clearable v-model="formObj.fax" placeholder="浼犵湡" />
+    </el-form-item>
+    <el-form-item label="鐢靛瓙閭" prop="email">
+      <el-input clearable type="email" v-model="formObj.email" placeholder="鐢靛瓙閭" />
+    </el-form-item>
+
+    <el-form-item>
+      <el-button :disabled="!edit" type="primary" @click="onSubmit" :loading="updateLoading"
+        >鎻愪氦</el-button
+      >
+      <el-button :disabled="!edit" @click="onReset">閲嶇疆</el-button>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, reactive, ref, watch } from 'vue'
+import { Iphone } from '@element-plus/icons-vue'
+import { useFormConfirm } from '@/composables/formConfirm'
+
+const props = defineProps({
+  //浼佷笟淇℃伅
+  formInfo: Object,
+  //鏄垱寤烘垨鑰呮洿鏂�
+  create: Boolean,
+})
+const emit = defineEmits(['onSubmit', 'onCancel'])
+
+const { formObj, formRef, edit, onSubmit, onReset } = useFormConfirm({
+  submit: {
+    do: submit,
+  },
+  cancel: {
+    do: cancel,
+  },
+})
+const updateLoading = ref(false)
+const rules = reactive({
+  companyName: [
+    {
+      required: true,
+      message: '鍗曚綅鍚嶇О涓嶈兘涓虹┖',
+      trigger: 'blur',
+    },
+  ],
+  address: [
+    {
+      required: true,
+      message: '鍗曚綅鍦板潃涓嶈兘涓虹┖',
+      trigger: 'blur',
+    },
+  ],
+  contactName: [
+    {
+      required: true,
+      message: '鑱旂郴浜哄鍚嶄笉鑳戒负绌�',
+      trigger: 'blur',
+    },
+  ],
+  telephone: [
+    {
+      required: true,
+      message: '鑱旂郴鐢佃瘽涓嶈兘涓虹┖',
+      trigger: 'blur',
+    },
+  ],
+})
+
+// 浼佷笟淇℃伅鏍煎紡鍖�
+function parseCompanyInfo(s) {
+  return s
+}
+
+function updateCompany() {
+  updateLoading.value = true
+  // 杩欓噷鍙互娣诲姞瀹為檯鐨凙PI璋冪敤
+  setTimeout(() => {
+    updateLoading.value = false
+  }, 1000)
+}
+
+watch(
+  () => props.formInfo,
+  (nValue) => {
+    formObj.value = parseCompanyInfo(nValue)
+  },
+)
+
+function submit() {
+  emit('onSubmit', formObj)
+  return updateCompany()
+}
+function cancel() {
+  emit('onCancel')
+}
+</script>
diff --git a/src/views/inspection/scenenew/components/CompDeviceInfo.vue b/src/views/inspection/scenenew/components/CompDeviceInfo.vue
new file mode 100644
index 0000000..385f1e2
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompDeviceInfo.vue
@@ -0,0 +1,159 @@
+<template>
+  <el-form
+    :inline="false"
+    :model="formObj"
+    ref="formRef"
+    :rules="rules"
+    label-position="right"
+    label-width="150px"
+  >
+    <el-form-item label="璁惧鍚嶇О" prop="deviceName">
+      <el-input clearable v-model="formObj.deviceName" placeholder="璁惧鍚嶇О" />
+    </el-form-item>
+    <el-form-item label="璁惧鍨嬪彿" prop="deviceModel">
+      <el-input clearable v-model="formObj.deviceModel" placeholder="璁惧鍨嬪彿" />
+    </el-form-item>
+    <el-form-item label="璁惧缂栧彿" prop="deviceCode">
+      <el-input clearable v-model="formObj.deviceCode" placeholder="璁惧缂栧彿" />
+    </el-form-item>
+    <el-form-item label="鐢熶骇鍘傚" prop="manufacturer">
+      <el-input clearable v-model="formObj.manufacturer" placeholder="鐢熶骇鍘傚" />
+    </el-form-item>
+    <el-form-item label="瀹夎鏃ユ湡" prop="installationDate">
+      <el-input clearable v-model="formObj.installationDate" placeholder="瀹夎鏃ユ湡" />
+    </el-form-item>
+    <el-form-item label="璁惧鐘舵��" prop="status">
+      <el-select v-model="formObj.status" placeholder="璁惧鐘舵��">
+        <el-option label="姝e父" value="normal" />
+        <el-option label="寮傚父" value="abnormal" />
+        <el-option label="缁存姢涓�" value="maintenance" />
+        <el-option label="鍋滅敤" value="disabled" />
+      </el-select>
+    </el-form-item>
+    <el-form-item label="璁惧浣嶇疆" prop="location">
+      <el-input clearable v-model="formObj.location" placeholder="璁惧浣嶇疆" />
+    </el-form-item>
+    <el-form-item label="缁存姢鍛ㄦ湡" prop="maintenanceCycle">
+      <el-input clearable v-model="formObj.maintenanceCycle" placeholder="缁存姢鍛ㄦ湡" />
+    </el-form-item>
+    <el-form-item label="涓婃缁存姢鏃ユ湡" prop="lastMaintenanceDate">
+      <el-input clearable v-model="formObj.lastMaintenanceDate" placeholder="涓婃缁存姢鏃ユ湡" />
+    </el-form-item>
+    <el-form-item label="璐熻矗浜�" prop="responsiblePerson">
+      <el-input clearable v-model="formObj.responsiblePerson" placeholder="璐熻矗浜�" />
+    </el-form-item>
+    <el-form-item label="鑱旂郴鐢佃瘽" prop="contactPhone">
+      <el-input clearable type="tel" v-model="formObj.contactPhone" placeholder="鑱旂郴鐢佃瘽">
+        <template #prepend>
+          <el-icon><Iphone /></el-icon>
+        </template>
+      </el-input>
+    </el-form-item>
+    <el-form-item label="璁惧鎻忚堪" prop="description">
+      <el-input
+        clearable
+        v-model="formObj.description"
+        placeholder="璁惧鎻忚堪"
+        type="textarea"
+        rows="2"
+      />
+    </el-form-item>
+
+    <el-form-item>
+      <el-button :disabled="!edit" type="primary" @click="onSubmit" :loading="updateLoading"
+        >鎻愪氦</el-button
+      >
+      <el-button :disabled="!edit" @click="onReset">閲嶇疆</el-button>
+      <el-button v-if="create" @click="cancel">鍙栨秷</el-button>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, reactive, ref, watch } from 'vue'
+import { Iphone } from '@element-plus/icons-vue'
+import { useFormConfirm } from '@/composables/formConfirm'
+
+const props = defineProps({
+  //璁惧淇℃伅
+  formInfo: Object,
+  //鏄垱寤烘垨鑰呮洿鏂�
+  create: Boolean,
+})
+const emit = defineEmits(['onSubmit', 'onCancel'])
+
+const { formObj, formRef, edit, onSubmit, onReset } = useFormConfirm({
+  submit: {
+    do: submit,
+  },
+  cancel: {
+    do: cancel,
+  },
+})
+const updateLoading = ref(false)
+const rules = reactive({
+  deviceName: [
+    {
+      required: true,
+      message: '璁惧鍚嶇О涓嶈兘涓虹┖',
+      trigger: 'blur',
+    },
+  ],
+  deviceModel: [
+    {
+      required: true,
+      message: '璁惧鍨嬪彿涓嶈兘涓虹┖',
+      trigger: 'blur',
+    },
+  ],
+  deviceCode: [
+    {
+      required: true,
+      message: '璁惧缂栧彿涓嶈兘涓虹┖',
+      trigger: 'blur',
+    },
+  ],
+  manufacturer: [
+    {
+      required: true,
+      message: '鐢熶骇鍘傚涓嶈兘涓虹┖',
+      trigger: 'blur',
+    },
+  ],
+  status: [
+    {
+      required: true,
+      message: '璁惧鐘舵�佷笉鑳戒负绌�',
+      trigger: 'change',
+    },
+  ],
+})
+
+// 璁惧淇℃伅鏍煎紡鍖�
+function parseDeviceInfo(s) {
+  return s
+}
+
+function updateDevice() {
+  updateLoading.value = true
+  // 杩欓噷鍙互娣诲姞瀹為檯鐨凙PI璋冪敤
+  setTimeout(() => {
+    updateLoading.value = false
+  }, 1000)
+}
+
+watch(
+  () => props.formInfo,
+  (nValue) => {
+    formObj.value = parseDeviceInfo(nValue)
+  },
+)
+
+function submit() {
+  emit('onSubmit', formObj)
+  return updateDevice()
+}
+function cancel() {
+  emit('onCancel')
+}
+</script>
diff --git a/src/views/inspection/scenenew/components/CompHazardousWasteFile.vue b/src/views/inspection/scenenew/components/CompHazardousWasteFile.vue
new file mode 100644
index 0000000..50ede86
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompHazardousWasteFile.vue
@@ -0,0 +1 @@
+<template>s</template>
diff --git a/src/views/inspection/scenenew/components/CompHazardousWasteRecord.vue b/src/views/inspection/scenenew/components/CompHazardousWasteRecord.vue
new file mode 100644
index 0000000..50ede86
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompHazardousWasteRecord.vue
@@ -0,0 +1 @@
+<template>s</template>
diff --git a/src/views/inspection/scenenew/components/CompSceneInfo.vue b/src/views/inspection/scenenew/components/CompSceneInfo.vue
new file mode 100644
index 0000000..874818e
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompSceneInfo.vue
@@ -0,0 +1,132 @@
+<template>
+  <el-form
+    :inline="false"
+    :model="formObj"
+    ref="formRef"
+    :rules="rules"
+    label-position="right"
+    label-width="150px"
+  >
+    <el-form-item label="搴楅摵鍚嶇О" prop="shopName">
+      <el-input clearable v-model="formObj.shopName" placeholder="搴楅摵鍚嶇О" />
+    </el-form-item>
+    <el-form-item label="鎵�灞炲叕鍙�" prop="company">
+      <el-input clearable v-model="formObj.company" placeholder="鎵�灞炲叕鍙�" />
+    </el-form-item>
+    <el-form-item label="闆嗕腑鍖�" prop="centralArea">
+      <el-input clearable v-model="formObj.centralArea" placeholder="闆嗕腑鍖�" />
+    </el-form-item>
+    <el-form-item label="鐗╀笟鍏徃" prop="propertyCompany">
+      <el-input clearable v-model="formObj.propertyCompany" placeholder="鐗╀笟鍏徃" />
+    </el-form-item>
+    <el-form-item label="鑱旂郴浜�" prop="contactName">
+      <el-input clearable v-model="formObj.contactName" placeholder="鑱旂郴浜�" />
+    </el-form-item>
+    <el-form-item label="鑱旂郴鐢佃瘽" prop="telephone">
+      <el-input clearable type="tel" v-model="formObj.telephone" placeholder="鑱旂郴鐢佃瘽">
+        <template #prepend>
+          <el-icon><Iphone /></el-icon>
+        </template>
+      </el-input>
+    </el-form-item>
+    <el-form-item label="鍦板潃" prop="address">
+      <el-input clearable v-model="formObj.address" placeholder="鍦板潃" type="textarea" rows="2" />
+    </el-form-item>
+
+    <el-form-item>
+      <el-button :disabled="!edit" type="primary" @click="onSubmit" :loading="updateLoading"
+        >鎻愪氦</el-button
+      >
+      <el-button :disabled="!edit" @click="onReset">閲嶇疆</el-button>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, reactive, ref, watch } from 'vue'
+import { Iphone } from '@element-plus/icons-vue'
+import { useFormConfirm } from '@/composables/formConfirm'
+
+const props = defineProps({
+  //鍩烘湰淇℃伅
+  formInfo: Object,
+  //鏄垱寤烘垨鑰呮洿鏂�
+  create: Boolean,
+})
+const emit = defineEmits(['onSubmit', 'onCancel'])
+
+const { formObj, formRef, edit, onSubmit, onReset } = useFormConfirm({
+  submit: {
+    do: submit,
+  },
+  cancel: {
+    do: cancel,
+  },
+})
+const updateLoading = ref(false)
+const rules = reactive({
+  shopName: [
+    {
+      required: true,
+      message: '搴楅摵鍚嶇О涓嶈兘涓虹┖',
+      trigger: 'blur',
+    },
+  ],
+  company: [
+    {
+      required: true,
+      message: '鎵�灞炲叕鍙镐笉鑳戒负绌�',
+      trigger: 'blur',
+    },
+  ],
+  contactName: [
+    {
+      required: true,
+      message: '鑱旂郴浜轰笉鑳戒负绌�',
+      trigger: 'blur',
+    },
+  ],
+  telephone: [
+    {
+      required: true,
+      message: '鑱旂郴鐢佃瘽涓嶈兘涓虹┖',
+      trigger: 'blur',
+    },
+  ],
+  address: [
+    {
+      required: true,
+      message: '鍦板潃涓嶈兘涓虹┖',
+      trigger: 'blur',
+    },
+  ],
+})
+
+// 鍦烘櫙鍩烘湰淇℃伅鏍煎紡鍖�
+function parseSceneBaseInfo(s) {
+  return s
+}
+
+function updateScene() {
+  updateLoading.value = true
+  // 杩欓噷鍙互娣诲姞瀹為檯鐨凙PI璋冪敤
+  setTimeout(() => {
+    updateLoading.value = false
+  }, 1000)
+}
+
+watch(
+  () => props.formInfo,
+  (nValue) => {
+    formObj.value = parseSceneBaseInfo(nValue)
+  },
+)
+
+function submit() {
+  emit('onSubmit', formObj)
+  return updateScene()
+}
+function cancel() {
+  emit('onCancel')
+}
+</script>
diff --git a/src/views/inspection/scenenew/components/CompUserInfo.vue b/src/views/inspection/scenenew/components/CompUserInfo.vue
new file mode 100644
index 0000000..aece522
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompUserInfo.vue
@@ -0,0 +1,250 @@
+<template>
+  <FYForm
+    :form-info="formInfo"
+    :rules="rules"
+    :doClear="active"
+    :useCancel="create"
+    :useReset="!create"
+    @update:isEdit="(v) => $emit('updateEdit', v)"
+    @submit="submit"
+    @cancel="$emit('onCancel')"
+  >
+    <template #form-item="{ formObj }">
+      <!-- <el-form-item label="澶村儚url" prop="HeadIconUrl">
+        <el-input
+          clearable
+          v-model="formObj.HeadIconUrl"
+          placeholder="澶村儚url"
+        />
+      </el-form-item> -->
+      <el-form-item label="璐︽埛鍚�" prop="acountname">
+        <el-input clearable v-model="formObj.acountname" placeholder="璐︽埛鍚�" />
+      </el-form-item>
+      <el-form-item label="鐢ㄦ埛鏄电О" prop="realname">
+        <el-input clearable v-model="formObj.realname" placeholder="鐢ㄦ埛鏄电О" />
+      </el-form-item>
+      <el-form-item label="瀵嗙爜" prop="password">
+        <el-col :span="18">
+          <el-input
+            :disabled="true"
+            clearable
+            type="password"
+            v-model="formObj.password"
+            placeholder="榛樿瀵嗙爜123456"
+          />
+        </el-col>
+        <el-col :span="6" v-if="!create">
+          <el-row justify="end">
+            <el-button type="danger" @click="onResetPw" :loading="pwLoading">閲嶇疆瀵嗙爜</el-button>
+          </el-row>
+        </el-col>
+      </el-form-item>
+      <FYOptionUserType
+        prop="_usertype"
+        :allOption="false"
+        :initValue="false"
+        v-model:value="formObj._usertype"
+      ></FYOptionUserType>
+      <!-- <el-form-item label="鎵�灞炰紒涓�" prop="departmentname">
+        <el-input
+          clearable
+          v-model="formObj.departmentname"
+          placeholder="鎵�灞炰紒涓�"
+          disabled
+        />
+      </el-form-item> -->
+      <el-form-item label="鏄惁鍙敤" prop="isenable">
+        <el-switch v-model="formObj.isenable" />
+        <span style="margin-left: 16px">{{ formObj.isenable ? '鍙敤' : '涓嶅彲鐢�' }}</span>
+      </el-form-item>
+      <el-form-item label="宸ュ彿" prop="workno">
+        <el-input clearable v-model="formObj.workno" placeholder="宸ュ彿" />
+      </el-form-item>
+      <el-form-item label="鎵嬫満" prop="telephone">
+        <el-input clearable type="tel" v-model="formObj.telephone" placeholder="鎵嬫満" />
+      </el-form-item>
+      <FYOptionLocation
+        v-if="create"
+        prop="_locations"
+        :allOption="false"
+        :level="5"
+        :checkStrictly="true"
+        :initValue="false"
+        v-model:value="formObj._locations"
+      ></FYOptionLocation>
+      <FYOptionScene
+        prop="_scenetype"
+        :allOption="false"
+        :type="1"
+        :initValue="false"
+        v-model:value="formObj._scenetype"
+      ></FYOptionScene>
+    </template>
+  </FYForm>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, reactive, ref, watch, computed } from 'vue';
+import { getSceneName } from '@/enum/scene';
+import userApi from '@/api/fytz/userApi';
+import { useMessageBoxTip } from '@/composables/messageBox';
+
+const props = defineProps({
+  //鍩烘湰淇℃伅
+  model: {
+    type: Object
+    // default: () => {
+    //   return { isenable: true };
+    // }
+  },
+  create: {
+    type: Boolean,
+    default: false
+  },
+  active: {
+    type: Boolean,
+    default: false
+  }
+});
+
+const formInfo = ref({ isenable: true });
+
+watch(
+  () => props.model,
+  (nValue) => {
+    formInfo.value = parseUserInfo(nValue);
+  }
+);
+
+const emit = defineEmits(['onSubmit', 'onCancel', 'updateEdit']);
+
+const rules = reactive({
+  acountname: [
+    {
+      required: true,
+      message: '璐︽埛鍚嶄笉鑳戒负绌�',
+      trigger: 'blur'
+    }
+  ],
+  realname: [
+    {
+      required: true,
+      message: '鐢ㄦ埛鏄电О涓嶈兘涓虹┖',
+      trigger: 'blur'
+    }
+  ]
+  // password: [
+  //   {
+  //     required: props.create,
+  //     message: '瀵嗙爜涓嶈兘涓虹┖',
+  //     trigger: 'blur',
+  //   },
+  // ],
+});
+
+// 鐢ㄦ埛鍩烘湰淇℃伅鏍煎紡鍖�
+function parseUserInfo(s) {
+  if (s.usertype && s.usertypeid) {
+    s._usertype = {
+      label: s.usertype,
+      value: s.usertypeid + ''
+    };
+  }
+
+  if (s.extension2) {
+    s._scenetype = getSceneName(s.extension2, 1);
+  }
+
+  s._locations = {};
+
+  return s;
+}
+
+function parseUserInfoReverse(v) {
+  // 琛屾斂鍖哄垝淇℃伅濉厖
+  const a = v._locations;
+  v.extension1 = a.dName;
+  // 鐢ㄦ埛绫诲瀷淇℃伅濉厖
+  const b = v._usertype;
+  v.usertypeid = b.value;
+  v.usertype = b.label;
+
+  // 鍦烘櫙绫诲瀷淇℃伅濉厖
+  const c = v._scenetype;
+  v.extension2 = c.value;
+
+  return v;
+}
+
+function createUser(v, success, fail) {
+  const l = v._locations;
+  const params = {
+    userInfo: v,
+    baseInfo: {
+      biProvinceCode: l.pCode,
+      biProvinceName: l.pName,
+      biCityCode: l.cCode,
+      biCityName: l.cName,
+      biDistrictCode: l.dCode,
+      biDistrictName: l.dName,
+      biTownCode: l.tCode,
+      biTownName: l.tName,
+      biAreaCode: l.aCode,
+      biArea: l.aName
+      // biManagementCompanyId:
+      // biManagementCompany:
+      // biContact
+      // biTelephone
+      // biAddress
+    }
+  };
+  return userApi
+    .createUser(params)
+    .then(() => {
+      emit('onSubmit', params);
+      success();
+    })
+    .catch((err) => {
+      fail(err);
+    });
+}
+
+function updateUser(v, success, fail) {
+  return userApi
+    .updateUserInfo(v)
+    .then(() => {
+      emit('onSubmit', v);
+      if (success) success();
+    })
+    .catch((err) => {
+      if (fail) fail(err);
+    });
+}
+
+function submit(v, success, fail) {
+  parseUserInfoReverse(v.value);
+
+  return props.create ? createUser(v.value, success, fail) : updateUser(v.value, success, fail);
+  // parseUserInfoReverse(props.formInfo);
+
+  // return props.create
+  //   ? createUser(props.formInfo, success, fail)
+  //   : updateUser(props.formInfo, success, fail);
+}
+
+// 閲嶇疆瀵嗙爜
+const pwLoading = ref(false);
+
+function onResetPw() {
+  useMessageBoxTip({
+    confirmMsg: '鏄惁閲嶇疆璇ュ満鏅瘑鐮侊紵',
+    confirmTitle: '閲嶇疆瀵嗙爜',
+    onConfirm: async () => {
+      pwLoading.value = true;
+      return userApi.resetPassword(formInfo.value.guid).finally(() => {
+        pwLoading.value = false;
+      });
+    }
+  });
+}
+</script>
diff --git a/src/views/inspection/scenenew/components/CompUserInfoAddDrawer.vue b/src/views/inspection/scenenew/components/CompUserInfoAddDrawer.vue
new file mode 100644
index 0000000..720a1a5
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompUserInfoAddDrawer.vue
@@ -0,0 +1,54 @@
+<template>
+  <el-drawer
+    title="鏂板鐢ㄦ埛"
+    direction="rtl"
+    :model-value="modelValue"
+    @open="updateDrawer(true)"
+    @close="updateDrawer(false)"
+    :before-close="onDrawerClose"
+  >
+    <CompUserInfo
+      :create="true"
+      :active="modelValue"
+      @updateEdit="(v) => (drawerEdit = v)"
+      @on-submit="updateDrawer(false)"
+      @on-cancel="updateDrawer(false)"
+    ></CompUserInfo>
+  </el-drawer>
+</template>
+
+<script>
+import CompUserInfo from './CompUserInfo.vue';
+import { useMessageBox } from '@/composables/messageBox';
+
+export default {
+  components: { CompUserInfo },
+  props: ['modelValue'],
+  emits: ['update:modelValue'],
+  data() {
+    return {
+      drawerEdit: false
+    };
+  },
+  methods: {
+    updateDrawer(status) {
+      this.$emit('update:modelValue', status);
+    },
+    onDrawerClose(done) {
+      if (this.drawerEdit) {
+        // 寮瑰嚭纭妗�
+        useMessageBox({
+          confirmMsg: '鏄惁鏀惧純宸茬紪杈戠殑鍐呭锛�',
+          confirmTitle: '鍏抽棴寮瑰嚭妗�',
+          onConfirm: () => {
+            done();
+          }
+        });
+      } else {
+        // 鐩存帴鍏抽棴
+        done();
+      }
+    },
+  }
+};
+</script>
diff --git a/src/views/monitor/DataDashboard.vue b/src/views/monitor/DataDashboard.vue
index 3292858..4d366dd 100644
--- a/src/views/monitor/DataDashboard.vue
+++ b/src/views/monitor/DataDashboard.vue
@@ -1,313 +1,865 @@
 <template>
-  <el-container class="data-dashboard">
-    <el-main>
-      <div class="grid-container">
-        <div class="left-section">
-          <!-- 璁惧鍦ㄧ嚎鎯呭喌鍖哄煙 -->
-          <DeviceStatus
-            :online-count="onlineCount"
-            :offline-count="offlineCount"
-            :normal-count="normalCount"
-            :fault-count="faultCount"
-          />
-          <!-- 鍒嗗尯鏁版嵁鎺掑悕鍖哄煙 -->
-          <DistrictRanking
-            style="flex: 1"
-            :selected-month="selectedMonth"
-            :ranking-type="rankingType"
-            :ranking-data="rankingData"
-            :sorted-ranking-data="sortedRankingData"
-            @month-change="handleMonthChange"
-            @type-change="handleTypeChange"
-          />
+  <div class="data-dashboard">
+    <!-- 椤堕儴鎸囨爣鍗$墖鍖� -->
+    <div class="top-cards">
+      <div class="cards-container">
+        <!-- 鏃堕棿鍛ㄦ湡閫夐」鍗$墖 -->
+        <div class="time-period-card">
+          <div class="card-title">鏃堕棿鍛ㄦ湡</div>
+          <div class="time-tab-container">
+            <div
+              v-for="tab in timeTabs"
+              :key="tab.value"
+              class="time-tab"
+              :class="{ active: activeTime === tab.value }"
+              @click="handleTimeChange(tab)"
+            >
+              {{ tab.label }}
+            </div>
+          </div>
         </div>
-        <div class="right-section">
-          <!-- 璁惧瀹炴椂鏁版嵁鍖哄煙 -->
-          <RealTimeData style="flex: 1" :devices="devices" />
+
+        <!-- 瓒呮爣鏁� -->
+        <div class="metric-card">
+          <div class="card-header">
+            <div class="card-title">{{ getPeriodLabel() }}瓒呮爣鏁�</div>
+            <div class="card-icon warning-icon">
+              <svg
+                width="20"
+                height="20"
+                viewBox="0 0 24 24"
+                fill="none"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path d="M12 9V13" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
+                <path
+                  d="M12 17.5V17"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                />
+                <path
+                  d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
+              </svg>
+            </div>
+          </div>
+          <div class="card-value">{{ metrics.overStandardCount }}</div>
+          <div class="card-trend">
+            <span
+              class="trend-arrow"
+              :class="{ up: metrics.overStandardTrend > 0, down: metrics.overStandardTrend < 0 }"
+            >
+              {{ metrics.overStandardTrend > 0 ? '鈫�' : '鈫�' }}
+            </span>
+            <span class="trend-text">{{ Math.abs(metrics.overStandardTrend) }}%</span>
+            <span class="trend-label">{{ getCompareLabel() }}</span>
+          </div>
+        </div>
+
+        <!-- 鍦ㄧ嚎鐜� -->
+        <div class="metric-card">
+          <div class="card-header">
+            <div class="card-title">鍦ㄧ嚎鐜�</div>
+            <div class="card-icon online-icon">
+              <svg
+                width="20"
+                height="20"
+                viewBox="0 0 24 24"
+                fill="none"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="M9 12L11 14L15 10"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
+                <path
+                  d="M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
+              </svg>
+            </div>
+          </div>
+          <div class="card-value">{{ metrics.onlineRate }}%</div>
+          <div class="card-trend">
+            <span
+              class="trend-arrow"
+              :class="{ up: metrics.onlineRateTrend > 0, down: metrics.onlineRateTrend < 0 }"
+            >
+              {{ metrics.onlineRateTrend > 0 ? '鈫�' : '鈫�' }}
+            </span>
+            <span class="trend-text">{{ Math.abs(metrics.onlineRateTrend) }}%</span>
+            <span class="trend-label">{{ getCompareLabel() }}</span>
+          </div>
+        </div>
+
+        <!-- 鍑�鍖栧櫒杩愯鏁堢巼 -->
+        <div class="metric-card">
+          <div class="card-header">
+            <div class="card-title">鍑�鍖栧櫒杩愯鏁堢巼</div>
+            <div class="card-icon efficiency-icon">
+              <svg
+                width="20"
+                height="20"
+                viewBox="0 0 24 24"
+                fill="none"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2Z"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
+                <path
+                  d="M12 6V12L16 14"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
+              </svg>
+            </div>
+          </div>
+          <div class="card-value">{{ metrics.purifierEfficiency }}%</div>
+          <div class="card-trend">
+            <span
+              class="trend-arrow"
+              :class="{
+                up: metrics.purifierEfficiencyTrend > 0,
+                down: metrics.purifierEfficiencyTrend < 0,
+              }"
+            >
+              {{ metrics.purifierEfficiencyTrend > 0 ? '鈫�' : '鈫�' }}
+            </span>
+            <span class="trend-text">{{ Math.abs(metrics.purifierEfficiencyTrend) }}%</span>
+            <span class="trend-label">{{ getCompareLabel() }}</span>
+          </div>
+        </div>
+
+        <!-- 浠诲姟瀹屾垚鐜� -->
+        <div class="metric-card">
+          <div class="card-header">
+            <div class="card-title">浠诲姟瀹屾垚鐜�</div>
+            <div class="card-icon task-icon">
+              <svg
+                width="20"
+                height="20"
+                viewBox="0 0 24 24"
+                fill="none"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="M22 11.08V12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C15.7376 2 19.0503 4.16113 20.7748 7.33007"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
+                <path
+                  d="M22 4L12 14.01L9 11.01"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
+              </svg>
+            </div>
+          </div>
+          <div class="card-value">{{ metrics.taskCompletionRate }}%</div>
+          <div class="card-trend">
+            <span
+              class="trend-arrow"
+              :class="{
+                up: metrics.taskCompletionRateTrend > 0,
+                down: metrics.taskCompletionRateTrend < 0,
+              }"
+            >
+              {{ metrics.taskCompletionRateTrend > 0 ? '鈫�' : '鈫�' }}
+            </span>
+            <span class="trend-text">{{ Math.abs(metrics.taskCompletionRateTrend) }}%</span>
+            <span class="trend-label">{{ getCompareLabel() }}</span>
+          </div>
         </div>
       </div>
+    </div>
 
-      <!-- 鍦ㄧ嚎璁惧鍜屽簵閾烘竻鍗曞尯鍩� -->
-      <ShopList
-        :shops="shops"
-        :shop-types="shopTypes"
-        :districts="districts"
-        :filter="filter"
-        @filter-change="handleFilterChange"
-      />
-    </el-main>
-  </el-container>
+    <!-- 涓昏鍐呭鍖� -->
+    <div class="main-content">
+      <!-- 涓儴GIS鍦板浘鍖� -->
+      <div class="map-section">
+        <div id="map" class="map-container">
+          <BaseMap></BaseMap>
+        </div>
+
+        <!-- 鍦板浘鐐逛綅寮圭獥 -->
+        <el-dialog v-model="dialogVisible" title="浼佷笟瀹炴椂鏁版嵁" width="400px">
+          <div class="dialog-content">
+            <el-descriptions :column="1" border>
+              <el-descriptions-item label="浼佷笟鍚嶇О">{{
+                selectedPoint.enterpriseName
+              }}</el-descriptions-item>
+              <el-descriptions-item label="璁惧缂栧彿">{{
+                selectedPoint.deviceId
+              }}</el-descriptions-item>
+              <el-descriptions-item label="娌圭儫娴撳害"
+                >{{ selectedPoint.oilSmokeConcentration }} mg/m鲁</el-descriptions-item
+              >
+              <el-descriptions-item label="棰楃矑鐗�"
+                >{{ selectedPoint.particulateMatter }} mg/m鲁</el-descriptions-item
+              >
+              <el-descriptions-item label="闈炵敳鐑锋�荤儍"
+                >{{ selectedPoint.nonMethaneHydrocarbon }} mg/m鲁</el-descriptions-item
+              >
+              <el-descriptions-item label="鐩戞祴鏃堕棿">{{
+                selectedPoint.monitoringTime
+              }}</el-descriptions-item>
+              <el-descriptions-item label="瓒呮爣鎯呭喌">
+                <el-tag :type="selectedPoint.isOverStandard ? 'danger' : 'success'">
+                  {{ selectedPoint.isOverStandard ? '瓒呮爣' : '姝e父' }}
+                </el-tag>
+              </el-descriptions-item>
+            </el-descriptions>
+          </div>
+          <template #footer>
+            <span class="dialog-footer">
+              <el-button @click="dialogVisible = false">鍏抽棴</el-button>
+              <el-button type="primary" @click="viewDetails">鏌ョ湅璇︽儏</el-button>
+            </span>
+          </template>
+        </el-dialog>
+      </div>
+
+      <!-- 鍙充晶瀹炴椂鐩戞祴鎬昏鍖� -->
+      <div class="overview-section">
+        <div class="section-header">
+          <h3>瀹炴椂鐩戞祴鎬昏</h3>
+          <span class="view-more">鏌ョ湅鏇村</span>
+        </div>
+
+        <div class="overview-items-container">
+          <div class="overview-item">
+            <div class="overview-label">椁愰ギ搴楅摵鎬绘暟</div>
+            <div class="overview-value">{{ overview.totalShops }}</div>
+          </div>
+
+          <div class="overview-item">
+            <div class="overview-label">鍦ㄧ嚎璁惧鏁�</div>
+            <div class="overview-value">{{ overview.onlineDevices }}</div>
+          </div>
+
+          <div class="overview-item">
+            <div class="overview-label">绂荤嚎璁惧鏁�</div>
+            <div class="overview-value">{{ overview.offlineDevices }}</div>
+          </div>
+        </div>
+
+        <!-- 璁惧鐘舵�侀ゼ鍥� -->
+        <div class="device-status-chart">
+          <canvas id="deviceStatusChart"></canvas>
+        </div>
+      </div>
+    </div>
+  </div>
 </template>
 
 <script>
-import DeviceStatus from '@/components/monitor/DeviceStatus.vue'
-import RealTimeData from '@/components/monitor/RealTimeData.vue'
-import DistrictRanking from '@/components/monitor/DistrictRanking.vue'
-import ShopList from '@/components/monitor/ShopList.vue'
+import * as echarts from 'echarts'
+import { onMapMounted, map, AMap } from '@/utils/map/index'
+import districtSearch from '@/utils/map/districtsearch.js'
 
 export default {
   name: 'DataDashboard',
-  components: {
-    DeviceStatus,
-    RealTimeData,
-    DistrictRanking,
-    ShopList,
-  },
   data() {
     return {
-      // 璁惧鍦ㄧ嚎鎯呭喌鏁版嵁
-      onlineCount: 0,
-      offlineCount: 0,
-      normalCount: 0,
-      faultCount: 0,
-
-      // 璁惧瀹炴椂鏁版嵁
-      devices: [],
-
-      // 鍒嗗尯鏁版嵁鎺掑悕
-      selectedMonth: '2023-12',
-      rankingType: 'hourly',
-      rankingData: [],
-      sortedRankingData: [],
-
-      // 绛涢�夋潯浠�
-      filter: {
-        district: '',
-        shopType: '',
-        status: '',
-      },
-      shopTypes: ['涓', '瑗块', '蹇', '鐏攨', '鐑х儰'],
-      districts: ['涓滃煄鍖�', '瑗垮煄鍖�', '鏈濋槼鍖�', '娴锋穩鍖�', '涓板彴鍖�'],
-
-      // 搴楅摵鏁版嵁
-      shops: [
-        {
-          id: 1,
-          name: '寮犱笁椁愬巺',
-          deviceCount: 2,
-          status: '鍦ㄧ嚎',
-          district: '涓滃煄鍖�',
-          type: '涓',
-        },
-        {
-          id: 2,
-          name: '鏉庡洓楗簵',
-          deviceCount: 1,
-          status: '绂荤嚎',
-          district: '瑗垮煄鍖�',
-          type: '瑗块',
-        },
-        {
-          id: 3,
-          name: '鐜嬩簲灏忓悆',
-          deviceCount: 3,
-          status: '鍦ㄧ嚎',
-          district: '鏈濋槼鍖�',
-          type: '蹇',
-        },
-        {
-          id: 4,
-          name: '璧靛叚鐏攨',
-          deviceCount: 2,
-          status: '鍦ㄧ嚎',
-          district: '娴锋穩鍖�',
-          type: '鐏攨',
-        },
-        {
-          id: 5,
-          name: '閽变竷鐑х儰',
-          deviceCount: 1,
-          status: '绂荤嚎',
-          district: '涓板彴鍖�',
-          type: '鐑х儰',
-        },
+      activeTime: 'day',
+      timeTabs: [
+        { label: '鏃�', value: 'day' },
+        { label: '鍛�', value: 'week' },
+        { label: '鏈�', value: 'month' },
       ],
+      dialogVisible: false,
+      selectedPoint: {
+        enterpriseName: '',
+        deviceId: '',
+        oilSmokeConcentration: 0,
+        particulateMatter: 0,
+        nonMethaneHydrocarbon: 0,
+        monitoringTime: '',
+        isOverStandard: false,
+      },
+      metrics: {
+        overStandardCount: 12,
+        overStandardTrend: 5,
+        onlineRate: 92,
+        onlineRateTrend: 2,
+        purifierEfficiency: 85,
+        purifierEfficiencyTrend: -3,
+        taskCompletionRate: 78,
+        taskCompletionRateTrend: 10,
+      },
+      overview: {
+        totalShops: 245,
+        onlineDevices: 220,
+        offlineDevices: 25,
+      },
+      map: null,
+      refreshTimer: null,
     }
   },
   mounted() {
-    this.initData()
-    this.startRealTimeUpdate()
+    this.initMap()
+    this.initDeviceStatusChart()
+    this.startAutoRefresh()
+  },
+  beforeUnmount() {
+    if (this.refreshTimer) {
+      clearInterval(this.refreshTimer)
+    }
   },
   methods: {
-    initData() {
-      // 鍒濆鍖栬澶囧湪绾挎儏鍐垫暟鎹�
-      this.updateDeviceStatus()
-
-      // 鍒濆鍖栧疄鏃舵暟鎹�
-      this.updateRealTimeData()
-
-      // 鍒濆鍖栧垎鍖烘暟鎹帓鍚�
-      this.updateRankingData()
+    handleTimeChange(tab) {
+      this.activeTime = tab.value
+      // 妯℃嫙鍒囨崲鏃堕棿鍛ㄦ湡鍚庣殑鏁版嵁鏇存柊
+      this.updateMetrics()
     },
-
-    updateDeviceStatus() {
-      // 妯℃嫙鏁版嵁 - 瀹為檯搴斾粠API鑾峰彇
-      this.onlineCount = Math.floor(Math.random() * 50) + 50
-      this.offlineCount = Math.floor(Math.random() * 20)
-      this.normalCount = this.onlineCount
-      this.faultCount = this.offlineCount
+    getPeriodLabel() {
+      switch (this.activeTime) {
+        case 'day':
+          return '浠婃棩'
+        case 'week':
+          return '鏈懆'
+        case 'month':
+          return '鏈湀'
+        default:
+          return '浠婃棩'
+      }
     },
-
-    updateRealTimeData() {
-      // 妯℃嫙鏁版嵁 - 瀹為檯搴斾粠API鑾峰彇
-      this.devices = [
-        {
-          deviceId: 'DEV-001',
-          supplier: '渚涘簲鍟咥',
-          status: '姝e父',
-          monitorTime: new Date().toLocaleString(),
-          smokeDensity: (Math.random() * 2).toFixed(2),
-          fanCurrent: (Math.random() * 5 + 1).toFixed(2),
-          purifierCurrent: (Math.random() * 3 + 0.5).toFixed(2),
-          hourlyData: this.generateHourlyData(),
-        },
-        {
-          deviceId: 'DEV-002',
-          supplier: '渚涘簲鍟咮',
-          status: '姝e父',
-          monitorTime: new Date().toLocaleString(),
-          smokeDensity: (Math.random() * 2).toFixed(2),
-          fanCurrent: (Math.random() * 5 + 1).toFixed(2),
-          purifierCurrent: (Math.random() * 3 + 0.5).toFixed(2),
-          hourlyData: this.generateHourlyData(),
-        },
-        {
-          deviceId: 'DEV-003',
-          supplier: '渚涘簲鍟咰',
-          status: '寮傚父',
-          monitorTime: new Date().toLocaleString(),
-          smokeDensity: (Math.random() * 15 + 5).toFixed(2),
-          fanCurrent: (Math.random() * 3 + 4).toFixed(2),
-          purifierCurrent: (Math.random() * 2 + 2).toFixed(2),
-          hourlyData: this.generateHourlyData(),
-        },
-        {
-          deviceId: 'DEV-004',
-          supplier: '渚涘簲鍟咲',
-          status: '寮傚父',
-          monitorTime: new Date().toLocaleString(),
-          smokeDensity: (Math.random() * 15 + 5).toFixed(2),
-          fanCurrent: (Math.random() * 3 + 4).toFixed(2),
-          purifierCurrent: (Math.random() * 2 + 2).toFixed(2),
-          hourlyData: this.generateHourlyData(),
-        },
-      ]
+    getCompareLabel() {
+      switch (this.activeTime) {
+        case 'day':
+          return '杈冩槰鏃�'
+        case 'week':
+          return '杈冧笂鍛�'
+        case 'month':
+          return '杈冧笂鏈�'
+        default:
+          return '杈冩槰鏃�'
+      }
     },
+    updateMetrics() {
+      // 杩欓噷搴旇鏍规嵁閫夋嫨鐨勬椂闂村懆鏈熶粠鎺ュ彛鑾峰彇鏁版嵁
+      // 妯℃嫙鏁版嵁鏇存柊
+      setTimeout(() => {
+        this.metrics = {
+          overStandardCount: Math.floor(Math.random() * 30),
+          overStandardTrend: Math.floor(Math.random() * 20) - 10,
+          onlineRate: Math.floor(Math.random() * 20) + 80,
+          onlineRateTrend: Math.floor(Math.random() * 10) - 5,
+          purifierEfficiency: Math.floor(Math.random() * 30) + 70,
+          purifierEfficiencyTrend: Math.floor(Math.random() * 10) - 5,
+          taskCompletionRate: Math.floor(Math.random() * 40) + 60,
+          taskCompletionRateTrend: Math.floor(Math.random() * 15) - 7,
+        }
+      }, 300)
+    },
+    initMap() {
+      // setTimeout(() => {
+      districtSearch.removeDistrict()
+      districtSearch.drawDistrict('涓婃捣甯�')
+      // districtSearch.districtLayer('310106')
+      // }, 2000)
+    },
+    initDeviceStatusChart() {
+      const chartDom = document.getElementById('deviceStatusChart')
+      if (chartDom) {
+        const chart = echarts.init(chartDom)
+        const option = {
+          tooltip: {
+            trigger: 'item',
+            formatter: '{b}: {c} ({d}%)',
+            backgroundColor: 'rgba(255, 255, 255, 0.95)',
+            borderColor: '#e8e8e8',
+            borderWidth: 1,
+            textStyle: {
+              color: '#333',
+            },
+          },
+          legend: {
+            bottom: '0%',
+            left: 'center',
+            textStyle: {
+              color: '#86909c',
+              fontSize: 12,
+            },
+          },
+          series: [
+            {
+              name: '璁惧鐘舵��',
+              type: 'pie',
+              radius: ['50%', '75%'],
+              center: ['50%', '45%'],
+              avoidLabelOverlap: false,
+              itemStyle: {
+                borderRadius: 8,
+                borderColor: '#ffffff',
+                borderWidth: 2,
+                shadowBlur: 5,
+                shadowOffsetX: 0,
+                shadowColor: 'rgba(0, 0, 0, 0.1)',
+              },
+              label: {
+                show: true,
+                position: 'center',
+                formatter: '{d}%',
+                fontSize: 18,
+                fontWeight: 'bold',
+                color: '#262626',
+              },
+              labelLine: {
+                show: false,
+              },
+              data: [
+                {
+                  value: this.overview.onlineDevices,
+                  name: '鍦ㄧ嚎',
+                  itemStyle: {
+                    color: '#1890ff',
+                  },
+                },
+                {
+                  value: this.overview.offlineDevices,
+                  name: '绂荤嚎',
+                  itemStyle: {
+                    color: '#f5222d',
+                  },
+                },
+              ],
+            },
+          ],
+        }
+        chart.setOption(option)
 
-    generateHourlyData() {
-      // 鐢熸垚妯℃嫙鐨勮繎涓�灏忔椂鏁版嵁
-      const hourlyData = []
-      for (let i = 59; i >= 0; i--) {
-        const time = new Date()
-        time.setMinutes(time.getMinutes() - i)
-        hourlyData.push({
-          time: time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
-          smokeDensity: (Math.random() * 2).toFixed(2),
-          fanCurrent: (Math.random() * 5 + 1).toFixed(2),
-          purifierCurrent: (Math.random() * 3 + 0.5).toFixed(2),
+        // 鍝嶅簲寮忚皟鏁�
+        window.addEventListener('resize', () => {
+          chart.resize()
         })
       }
-      return hourlyData
     },
-
-    updateRankingData() {
-      // 妯℃嫙鏁版嵁 - 瀹為檯搴斾粠API鑾峰彇
-      this.rankingData = [
-        { name: '鐜勬鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 },
-        { name: '绉︽樊鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -1 },
-        { name: '寤洪偤鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 },
-        { name: '榧撴ゼ鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 },
-        { name: '娴﹀彛鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -2 },
-        { name: '鏍栭湠鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 2 },
-        { name: '闆ㄨ姳鍙板尯', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 },
-        { name: '姹熷畞鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 },
-        { name: '鍏悎鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -1 },
-        { name: '婧ф按鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 },
-        { name: '楂樻烦鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 },
-      ]
-
-      // 鎺掑簭
-      this.sortedRankingData = [...this.rankingData].sort(
-        (a, b) => parseFloat(b.value) - parseFloat(a.value),
-      )
-    },
-
-    startRealTimeUpdate() {
-      // 姣�30绉掓洿鏂颁竴娆℃暟鎹�
-      this.realTimeInterval = setInterval(() => {
-        this.updateDeviceStatus()
-        this.updateRealTimeData()
+    startAutoRefresh() {
+      // 姣�30绉掕嚜鍔ㄥ埛鏂版暟鎹�
+      this.refreshTimer = setInterval(() => {
+        this.updateMetrics()
+        // 杩欓噷搴旇鍚屾椂鏇存柊鍦板浘鐐逛綅鏁版嵁
       }, 30000)
     },
-
-    handleMonthChange(val) {
-      this.selectedMonth = val
-      this.updateRankingData()
-    },
-
-    handleTypeChange(val) {
-      this.rankingType = val
-      this.updateRankingData()
-    },
-
-    handleFilterChange(val) {
-      this.filter = { ...val }
+    viewDetails() {
+      // 璺宠浆鍒颁紒涓氱洃鎺ц鎯呴〉
+      this.$router.push('/monitor/enterprise-detail')
     },
   },
 }
 </script>
 
 <style scoped>
+/* 鍏ㄥ眬鏍峰紡 */
 .data-dashboard {
-  min-height: 100vh;
+  width: 100%;
+  height: calc(100vh - 60px);
   background-color: #f5f7fa;
+  color: #333;
+  box-sizing: border-box;
+  font-family:
+    -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+  position: relative;
 }
 
-.el-header {
+/* 椤堕儴鎸囨爣鍗$墖鍖� */
+.top-cards {
+  position: absolute;
+  top: 24px;
+  left: 24px;
+  z-index: 10;
+  margin-bottom: 24px;
+}
+
+.cards-container {
+  display: grid;
+  grid-template-columns: 280px;
+  grid-template-rows: auto repeat(4, auto);
+  gap: 16px;
+  background-color: rgba(255, 255, 255, 0.9);
+  padding: 16px;
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+/* 鏃堕棿鍛ㄦ湡鍗$墖 */
+.time-period-card {
+  background-color: #ffffff;
+  border-radius: 8px;
   padding: 20px;
-  background-color: #f5f7fa;
+  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
 }
 
-.el-header h1 {
-  font-size: 24px;
+.time-period-card .card-title {
+  font-size: 14px;
+  color: #86909c;
+  font-weight: 500;
+  margin-bottom: 16px;
+  text-align: center;
+}
+
+.time-tab-container {
+  display: flex;
+  flex-direction: row;
+  gap: 8px;
+  width: 100%;
+  justify-content: center;
+}
+
+.time-tab {
+  padding: 2px 4px;
+  border-radius: 4px;
+  cursor: pointer;
+  font-size: 14px;
+  font-weight: 500;
+  transition: all 0.3s ease;
+  color: #4e5969;
+  text-align: center;
+  border: 1px solid #e8e8e8;
+  background-color: #fafafa;
+}
+
+.time-tab.active {
+  background-color: #1890ff;
+  color: #ffffff;
+  border-color: #1890ff;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.2);
+}
+
+.time-tab:hover:not(.active) {
+  color: #1890ff;
+  border-color: #e6f7ff;
+  background-color: #e6f7ff;
+}
+
+/* 鎸囨爣鍗$墖 */
+.metric-card {
+  background-color: #ffffff;
+  border-radius: 8px;
+  padding: 20px;
+  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
+  transition: all 0.3s ease;
+  position: relative;
+  overflow: hidden;
+}
+
+.metric-card:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 12px;
+}
+
+.card-title {
+  font-size: 14px;
+  color: #86909c;
+  font-weight: 500;
+}
+
+.card-icon {
+  color: #1890ff;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.warning-icon {
+  color: #fa8c16;
+}
+
+.online-icon {
+  color: #52c41a;
+}
+
+.efficiency-icon {
+  color: #722ed1;
+}
+
+.task-icon {
+  color: #1890ff;
+}
+
+.card-value {
+  font-size: 32px;
+  font-weight: bold;
+  margin: 12px 0;
+  color: #262626;
+  line-height: 1.2;
+}
+
+.card-trend {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  font-size: 12px;
+  padding-top: 12px;
+  border-top: 1px solid #f0f0f0;
+}
+
+.trend-arrow {
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.trend-arrow.up {
+  color: #52c41a;
+}
+
+.trend-arrow.down {
+  color: #f5222d;
+}
+
+.trend-text {
+  color: #262626;
+  font-weight: 500;
+}
+
+.trend-label {
+  color: #86909c;
+  font-size: 12px;
+}
+
+/* 涓昏鍐呭鍖� */
+.main-content {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+
+/* 涓儴GIS鍦板浘鍖� */
+.map-section {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+}
+
+.section-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 16px;
+  color: #262626;
+}
+
+.section-header h3 {
+  font-size: 16px;
+  font-weight: 600;
+  color: #262626;
   margin: 0;
+}
+
+.view-more {
+  font-size: 12px;
+  color: #1890ff;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+}
+
+.view-more:hover {
+  text-decoration: underline;
+}
+
+.map-container {
+  flex: 1;
+  position: relative;
+  overflow: hidden;
+  background-color: #fafafa;
+}
+
+.map-placeholder {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #86909c;
+  font-size: 16px;
+}
+
+/* 鍙充晶瀹炴椂鐩戞祴鎬昏鍖� */
+.overview-section {
+  position: absolute;
+  top: 200px;
+  right: 24px;
+  width: 320px;
+  background-color: rgba(255, 255, 255, 0.9);
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  padding: 20px;
+  display: flex;
+  flex-direction: column;
+  z-index: 10;
+  max-height: calc(100vh - 220px);
+}
+
+.overview-items-container {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 24px;
+  padding-bottom: 16px;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.overview-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  flex: 1;
+  text-align: center;
+}
+
+.overview-label {
+  font-size: 12px;
+  color: #86909c;
+  font-weight: 500;
+  margin-bottom: 8px;
+}
+
+.overview-value {
+  font-size: 24px;
+  font-weight: bold;
+  color: #262626;
+}
+
+.device-status-chart {
+  flex: 1;
+  margin-top: 16px;
+  min-height: 200px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+/* 寮圭獥鏍峰紡 */
+.dialog-content {
   color: #333;
 }
 
-.el-main {
-  padding: 20px;
+.dialog-footer {
+  text-align: right;
 }
 
-.grid-container {
-  display: flex;
-  /* display: grid;
-  grid-template-columns: 1fr 1fr;
-  grid-template-rows: min-content; */
-  gap: 20px;
+/* 闂儊鏁堟灉 */
+@keyframes blink {
+  0%,
+  100% {
+    opacity: 1;
+  }
+  50% {
+    opacity: 0.5;
+  }
 }
 
-.left-section {
-  flex: 2;
-  display: flex;
-  flex-direction: column;
-  gap: 20px;
-}
-
-.right-section {
-  width: 670px;
-  display: flex;
-  flex-direction: column;
+.blink {
+  animation: blink 1s infinite;
 }
 
 /* 鍝嶅簲寮忚璁� */
-@media (max-width: 768px) {
-  .grid-container {
-    grid-template-columns: 1fr;
+@media (max-width: 1200px) {
+  .top-cards {
+    position: relative;
+    margin-bottom: 24px;
   }
 
-  .left-section,
-  .right-section {
-    margin-bottom: 10px;
+  .cards-container {
+    grid-template-columns: repeat(2, 1fr);
+    grid-template-rows: auto auto;
+    background-color: #ffffff;
+  }
+
+  .main-content {
+    height: calc(100vh - 300px);
+  }
+
+  .overview-section {
+    position: relative;
+    top: 0;
+    right: 0;
+    width: 100%;
+    max-height: none;
+    height: 300px;
+    margin-top: 16px;
+    background-color: #ffffff;
+  }
+}
+
+@media (max-width: 768px) {
+  .data-dashboard {
+    padding: 16px;
+  }
+
+  .top-cards {
+    left: 16px;
+  }
+
+  .cards-container {
+    grid-template-columns: 1fr;
+    grid-template-rows: auto repeat(4, auto);
+  }
+
+  .time-period-card {
+    order: -1;
+  }
+
+  .time-tab-container {
+    flex-direction: row;
+  }
+
+  .time-tab {
+    flex: 1;
+    padding: 8px 0;
+  }
+
+  .overview-section {
+    right: 16px;
+  }
+
+  .overview-items-container {
+    flex-direction: column;
+    gap: 16px;
+  }
+
+  .overview-item {
+    flex-direction: row;
+    justify-content: space-between;
+    width: 100%;
+    text-align: left;
   }
 }
 </style>
diff --git a/src/views/monitor/DataDashboard_old2.vue b/src/views/monitor/DataDashboard_old2.vue
new file mode 100644
index 0000000..3292858
--- /dev/null
+++ b/src/views/monitor/DataDashboard_old2.vue
@@ -0,0 +1,313 @@
+<template>
+  <el-container class="data-dashboard">
+    <el-main>
+      <div class="grid-container">
+        <div class="left-section">
+          <!-- 璁惧鍦ㄧ嚎鎯呭喌鍖哄煙 -->
+          <DeviceStatus
+            :online-count="onlineCount"
+            :offline-count="offlineCount"
+            :normal-count="normalCount"
+            :fault-count="faultCount"
+          />
+          <!-- 鍒嗗尯鏁版嵁鎺掑悕鍖哄煙 -->
+          <DistrictRanking
+            style="flex: 1"
+            :selected-month="selectedMonth"
+            :ranking-type="rankingType"
+            :ranking-data="rankingData"
+            :sorted-ranking-data="sortedRankingData"
+            @month-change="handleMonthChange"
+            @type-change="handleTypeChange"
+          />
+        </div>
+        <div class="right-section">
+          <!-- 璁惧瀹炴椂鏁版嵁鍖哄煙 -->
+          <RealTimeData style="flex: 1" :devices="devices" />
+        </div>
+      </div>
+
+      <!-- 鍦ㄧ嚎璁惧鍜屽簵閾烘竻鍗曞尯鍩� -->
+      <ShopList
+        :shops="shops"
+        :shop-types="shopTypes"
+        :districts="districts"
+        :filter="filter"
+        @filter-change="handleFilterChange"
+      />
+    </el-main>
+  </el-container>
+</template>
+
+<script>
+import DeviceStatus from '@/components/monitor/DeviceStatus.vue'
+import RealTimeData from '@/components/monitor/RealTimeData.vue'
+import DistrictRanking from '@/components/monitor/DistrictRanking.vue'
+import ShopList from '@/components/monitor/ShopList.vue'
+
+export default {
+  name: 'DataDashboard',
+  components: {
+    DeviceStatus,
+    RealTimeData,
+    DistrictRanking,
+    ShopList,
+  },
+  data() {
+    return {
+      // 璁惧鍦ㄧ嚎鎯呭喌鏁版嵁
+      onlineCount: 0,
+      offlineCount: 0,
+      normalCount: 0,
+      faultCount: 0,
+
+      // 璁惧瀹炴椂鏁版嵁
+      devices: [],
+
+      // 鍒嗗尯鏁版嵁鎺掑悕
+      selectedMonth: '2023-12',
+      rankingType: 'hourly',
+      rankingData: [],
+      sortedRankingData: [],
+
+      // 绛涢�夋潯浠�
+      filter: {
+        district: '',
+        shopType: '',
+        status: '',
+      },
+      shopTypes: ['涓', '瑗块', '蹇', '鐏攨', '鐑х儰'],
+      districts: ['涓滃煄鍖�', '瑗垮煄鍖�', '鏈濋槼鍖�', '娴锋穩鍖�', '涓板彴鍖�'],
+
+      // 搴楅摵鏁版嵁
+      shops: [
+        {
+          id: 1,
+          name: '寮犱笁椁愬巺',
+          deviceCount: 2,
+          status: '鍦ㄧ嚎',
+          district: '涓滃煄鍖�',
+          type: '涓',
+        },
+        {
+          id: 2,
+          name: '鏉庡洓楗簵',
+          deviceCount: 1,
+          status: '绂荤嚎',
+          district: '瑗垮煄鍖�',
+          type: '瑗块',
+        },
+        {
+          id: 3,
+          name: '鐜嬩簲灏忓悆',
+          deviceCount: 3,
+          status: '鍦ㄧ嚎',
+          district: '鏈濋槼鍖�',
+          type: '蹇',
+        },
+        {
+          id: 4,
+          name: '璧靛叚鐏攨',
+          deviceCount: 2,
+          status: '鍦ㄧ嚎',
+          district: '娴锋穩鍖�',
+          type: '鐏攨',
+        },
+        {
+          id: 5,
+          name: '閽变竷鐑х儰',
+          deviceCount: 1,
+          status: '绂荤嚎',
+          district: '涓板彴鍖�',
+          type: '鐑х儰',
+        },
+      ],
+    }
+  },
+  mounted() {
+    this.initData()
+    this.startRealTimeUpdate()
+  },
+  methods: {
+    initData() {
+      // 鍒濆鍖栬澶囧湪绾挎儏鍐垫暟鎹�
+      this.updateDeviceStatus()
+
+      // 鍒濆鍖栧疄鏃舵暟鎹�
+      this.updateRealTimeData()
+
+      // 鍒濆鍖栧垎鍖烘暟鎹帓鍚�
+      this.updateRankingData()
+    },
+
+    updateDeviceStatus() {
+      // 妯℃嫙鏁版嵁 - 瀹為檯搴斾粠API鑾峰彇
+      this.onlineCount = Math.floor(Math.random() * 50) + 50
+      this.offlineCount = Math.floor(Math.random() * 20)
+      this.normalCount = this.onlineCount
+      this.faultCount = this.offlineCount
+    },
+
+    updateRealTimeData() {
+      // 妯℃嫙鏁版嵁 - 瀹為檯搴斾粠API鑾峰彇
+      this.devices = [
+        {
+          deviceId: 'DEV-001',
+          supplier: '渚涘簲鍟咥',
+          status: '姝e父',
+          monitorTime: new Date().toLocaleString(),
+          smokeDensity: (Math.random() * 2).toFixed(2),
+          fanCurrent: (Math.random() * 5 + 1).toFixed(2),
+          purifierCurrent: (Math.random() * 3 + 0.5).toFixed(2),
+          hourlyData: this.generateHourlyData(),
+        },
+        {
+          deviceId: 'DEV-002',
+          supplier: '渚涘簲鍟咮',
+          status: '姝e父',
+          monitorTime: new Date().toLocaleString(),
+          smokeDensity: (Math.random() * 2).toFixed(2),
+          fanCurrent: (Math.random() * 5 + 1).toFixed(2),
+          purifierCurrent: (Math.random() * 3 + 0.5).toFixed(2),
+          hourlyData: this.generateHourlyData(),
+        },
+        {
+          deviceId: 'DEV-003',
+          supplier: '渚涘簲鍟咰',
+          status: '寮傚父',
+          monitorTime: new Date().toLocaleString(),
+          smokeDensity: (Math.random() * 15 + 5).toFixed(2),
+          fanCurrent: (Math.random() * 3 + 4).toFixed(2),
+          purifierCurrent: (Math.random() * 2 + 2).toFixed(2),
+          hourlyData: this.generateHourlyData(),
+        },
+        {
+          deviceId: 'DEV-004',
+          supplier: '渚涘簲鍟咲',
+          status: '寮傚父',
+          monitorTime: new Date().toLocaleString(),
+          smokeDensity: (Math.random() * 15 + 5).toFixed(2),
+          fanCurrent: (Math.random() * 3 + 4).toFixed(2),
+          purifierCurrent: (Math.random() * 2 + 2).toFixed(2),
+          hourlyData: this.generateHourlyData(),
+        },
+      ]
+    },
+
+    generateHourlyData() {
+      // 鐢熸垚妯℃嫙鐨勮繎涓�灏忔椂鏁版嵁
+      const hourlyData = []
+      for (let i = 59; i >= 0; i--) {
+        const time = new Date()
+        time.setMinutes(time.getMinutes() - i)
+        hourlyData.push({
+          time: time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
+          smokeDensity: (Math.random() * 2).toFixed(2),
+          fanCurrent: (Math.random() * 5 + 1).toFixed(2),
+          purifierCurrent: (Math.random() * 3 + 0.5).toFixed(2),
+        })
+      }
+      return hourlyData
+    },
+
+    updateRankingData() {
+      // 妯℃嫙鏁版嵁 - 瀹為檯搴斾粠API鑾峰彇
+      this.rankingData = [
+        { name: '鐜勬鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 },
+        { name: '绉︽樊鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -1 },
+        { name: '寤洪偤鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 },
+        { name: '榧撴ゼ鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 },
+        { name: '娴﹀彛鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -2 },
+        { name: '鏍栭湠鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 2 },
+        { name: '闆ㄨ姳鍙板尯', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 },
+        { name: '姹熷畞鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 },
+        { name: '鍏悎鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -1 },
+        { name: '婧ф按鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 },
+        { name: '楂樻烦鍖�', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 },
+      ]
+
+      // 鎺掑簭
+      this.sortedRankingData = [...this.rankingData].sort(
+        (a, b) => parseFloat(b.value) - parseFloat(a.value),
+      )
+    },
+
+    startRealTimeUpdate() {
+      // 姣�30绉掓洿鏂颁竴娆℃暟鎹�
+      this.realTimeInterval = setInterval(() => {
+        this.updateDeviceStatus()
+        this.updateRealTimeData()
+      }, 30000)
+    },
+
+    handleMonthChange(val) {
+      this.selectedMonth = val
+      this.updateRankingData()
+    },
+
+    handleTypeChange(val) {
+      this.rankingType = val
+      this.updateRankingData()
+    },
+
+    handleFilterChange(val) {
+      this.filter = { ...val }
+    },
+  },
+}
+</script>
+
+<style scoped>
+.data-dashboard {
+  min-height: 100vh;
+  background-color: #f5f7fa;
+}
+
+.el-header {
+  padding: 20px;
+  background-color: #f5f7fa;
+}
+
+.el-header h1 {
+  font-size: 24px;
+  margin: 0;
+  color: #333;
+}
+
+.el-main {
+  padding: 20px;
+}
+
+.grid-container {
+  display: flex;
+  /* display: grid;
+  grid-template-columns: 1fr 1fr;
+  grid-template-rows: min-content; */
+  gap: 20px;
+}
+
+.left-section {
+  flex: 2;
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+.right-section {
+  width: 670px;
+  display: flex;
+  flex-direction: column;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 768px) {
+  .grid-container {
+    grid-template-columns: 1fr;
+  }
+
+  .left-section,
+  .right-section {
+    margin-bottom: 10px;
+  }
+}
+</style>
diff --git a/src/views/monitor/DataDashboard_old3.vue b/src/views/monitor/DataDashboard_old3.vue
new file mode 100644
index 0000000..2a70319
--- /dev/null
+++ b/src/views/monitor/DataDashboard_old3.vue
@@ -0,0 +1,730 @@
+<template>
+  <div class="data-dashboard">
+    <!-- 椤堕儴鎸囨爣鍗$墖鍖� -->
+    <div class="top-cards">
+      <div class="cards-container">
+        <!-- 鏃堕棿鍛ㄦ湡閫夐」鍗$墖 -->
+        <div class="time-period-card">
+          <div class="card-title">鏃堕棿鍛ㄦ湡</div>
+          <div class="time-tab-container">
+            <div
+              v-for="tab in timeTabs"
+              :key="tab.value"
+              class="time-tab"
+              :class="{ active: activeTime === tab.value }"
+              @click="handleTimeChange(tab)"
+            >
+              {{ tab.label }}
+            </div>
+          </div>
+        </div>
+
+        <!-- 瓒呮爣鏁� -->
+        <div class="metric-card">
+          <div class="card-header">
+            <div class="card-title">{{ getPeriodLabel() }}瓒呮爣鏁�</div>
+            <div class="card-icon warning-icon">鈿�</div>
+          </div>
+          <div class="card-value">{{ metrics.overStandardCount }}</div>
+          <div class="card-trend">
+            <span
+              class="trend-arrow"
+              :class="{ up: metrics.overStandardTrend > 0, down: metrics.overStandardTrend < 0 }"
+            >
+              {{ metrics.overStandardTrend > 0 ? '鈫�' : '鈫�' }}
+            </span>
+            <span class="trend-text">{{ Math.abs(metrics.overStandardTrend) }}%</span>
+            <span class="trend-label">{{ getCompareLabel() }}</span>
+          </div>
+        </div>
+
+        <!-- 鍦ㄧ嚎鐜� -->
+        <div class="metric-card">
+          <div class="card-header">
+            <div class="card-title">{{ getPeriodLabel() }}鍦ㄧ嚎鐜�</div>
+            <div class="card-icon online-icon">馃煝</div>
+          </div>
+          <div class="card-value">{{ metrics.onlineRate }}%</div>
+          <div class="card-trend">
+            <span
+              class="trend-arrow"
+              :class="{ up: metrics.onlineRateTrend > 0, down: metrics.onlineRateTrend < 0 }"
+            >
+              {{ metrics.onlineRateTrend > 0 ? '鈫�' : '鈫�' }}
+            </span>
+            <span class="trend-text">{{ Math.abs(metrics.onlineRateTrend) }}%</span>
+            <span class="trend-label">{{ getCompareLabel() }}</span>
+          </div>
+        </div>
+
+        <!-- 鍑�鍖栧櫒杩愯鏁堢巼 -->
+        <div class="metric-card">
+          <div class="card-header">
+            <div class="card-title">{{ getPeriodLabel() }}鍑�鍖栧櫒杩愯鏁堢巼</div>
+            <div class="card-icon efficiency-icon">鈿�</div>
+          </div>
+          <div class="card-value">{{ metrics.purifierEfficiency }}%</div>
+          <div class="card-trend">
+            <span
+              class="trend-arrow"
+              :class="{
+                up: metrics.purifierEfficiencyTrend > 0,
+                down: metrics.purifierEfficiencyTrend < 0,
+              }"
+            >
+              {{ metrics.purifierEfficiencyTrend > 0 ? '鈫�' : '鈫�' }}
+            </span>
+            <span class="trend-text">{{ Math.abs(metrics.purifierEfficiencyTrend) }}%</span>
+            <span class="trend-label">{{ getCompareLabel() }}</span>
+          </div>
+        </div>
+
+        <!-- 浠诲姟瀹屾垚鐜� -->
+        <div class="metric-card">
+          <div class="card-header">
+            <div class="card-title">{{ getPeriodLabel() }}浠诲姟瀹屾垚鐜�</div>
+            <div class="card-icon task-icon">鉁�</div>
+          </div>
+          <div class="card-value">{{ metrics.taskCompletionRate }}%</div>
+          <div class="card-trend">
+            <span
+              class="trend-arrow"
+              :class="{
+                up: metrics.taskCompletionRateTrend > 0,
+                down: metrics.taskCompletionRateTrend < 0,
+              }"
+            >
+              {{ metrics.taskCompletionRateTrend > 0 ? '鈫�' : '鈫�' }}
+            </span>
+            <span class="trend-text">{{ Math.abs(metrics.taskCompletionRateTrend) }}%</span>
+            <span class="trend-label">{{ getCompareLabel() }}</span>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 涓儴GIS鍦板浘鍖� -->
+    <div class="map-section">
+      <div id="map" class="map-container"></div>
+
+      <!-- 鍦板浘鐐逛綅寮圭獥 -->
+      <el-dialog v-model="dialogVisible" title="浼佷笟瀹炴椂鏁版嵁" width="400px">
+        <div class="dialog-content">
+          <el-descriptions :column="1" border>
+            <el-descriptions-item label="浼佷笟鍚嶇О">{{
+              selectedPoint.enterpriseName
+            }}</el-descriptions-item>
+            <el-descriptions-item label="璁惧缂栧彿">{{
+              selectedPoint.deviceId
+            }}</el-descriptions-item>
+            <el-descriptions-item label="娌圭儫娴撳害"
+              >{{ selectedPoint.oilSmokeConcentration }} mg/m鲁</el-descriptions-item
+            >
+            <el-descriptions-item label="棰楃矑鐗�"
+              >{{ selectedPoint.particulateMatter }} mg/m鲁</el-descriptions-item
+            >
+            <el-descriptions-item label="闈炵敳鐑锋�荤儍"
+              >{{ selectedPoint.nonMethaneHydrocarbon }} mg/m鲁</el-descriptions-item
+            >
+            <el-descriptions-item label="鐩戞祴鏃堕棿">{{
+              selectedPoint.monitoringTime
+            }}</el-descriptions-item>
+            <el-descriptions-item label="瓒呮爣鎯呭喌">
+              <el-tag :type="selectedPoint.isOverStandard ? 'danger' : 'success'">
+                {{ selectedPoint.isOverStandard ? '瓒呮爣' : '姝e父' }}
+              </el-tag>
+            </el-descriptions-item>
+          </el-descriptions>
+        </div>
+        <template #footer>
+          <span class="dialog-footer">
+            <el-button @click="dialogVisible = false">鍏抽棴</el-button>
+            <el-button type="primary" @click="viewDetails">鏌ョ湅璇︽儏</el-button>
+          </span>
+        </template>
+      </el-dialog>
+    </div>
+
+    <!-- 鍙充晶瀹炴椂鐩戞祴鎬昏鍖� -->
+    <div class="overview-section">
+      <div class="overview-card">
+        <div class="overview-title">瀹炴椂鐩戞祴鎬昏</div>
+
+        <div class="overview-items-container">
+          <div class="overview-item">
+            <div class="overview-label">椁愰ギ搴楅摵鎬绘暟</div>
+            <div class="overview-value">{{ overview.totalShops }}</div>
+          </div>
+
+          <div class="overview-item">
+            <div class="overview-label">鍦ㄧ嚎璁惧鏁�</div>
+            <div class="overview-value">{{ overview.onlineDevices }}</div>
+          </div>
+
+          <div class="overview-item">
+            <div class="overview-label">绂荤嚎璁惧鏁�</div>
+            <div class="overview-value">{{ overview.offlineDevices }}</div>
+          </div>
+        </div>
+
+        <!-- 璁惧鐘舵�侀ゼ鍥� -->
+        <div class="device-status-chart">
+          <canvas id="deviceStatusChart"></canvas>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+
+export default {
+  name: 'DataDashboard',
+  data() {
+    return {
+      activeTime: 'day',
+      timeTabs: [
+        { label: '鏃�', value: 'day' },
+        { label: '鍛�', value: 'week' },
+        { label: '鏈�', value: 'month' },
+      ],
+      dialogVisible: false,
+      selectedPoint: {
+        enterpriseName: '',
+        deviceId: '',
+        oilSmokeConcentration: 0,
+        particulateMatter: 0,
+        nonMethaneHydrocarbon: 0,
+        monitoringTime: '',
+        isOverStandard: false,
+      },
+      metrics: {
+        overStandardCount: 12,
+        overStandardTrend: 5,
+        onlineRate: 92,
+        onlineRateTrend: 2,
+        purifierEfficiency: 85,
+        purifierEfficiencyTrend: -3,
+        taskCompletionRate: 78,
+        taskCompletionRateTrend: 10,
+      },
+      overview: {
+        totalShops: 245,
+        onlineDevices: 220,
+        offlineDevices: 25,
+      },
+      map: null,
+      refreshTimer: null,
+    }
+  },
+  mounted() {
+    this.initMap()
+    this.initDeviceStatusChart()
+    this.startAutoRefresh()
+  },
+  beforeUnmount() {
+    if (this.refreshTimer) {
+      clearInterval(this.refreshTimer)
+    }
+  },
+  methods: {
+    handleTimeChange(tab) {
+      this.activeTime = tab.value
+      // 妯℃嫙鍒囨崲鏃堕棿鍛ㄦ湡鍚庣殑鏁版嵁鏇存柊
+      this.updateMetrics()
+    },
+    getPeriodLabel() {
+      switch (this.activeTime) {
+        case 'day':
+          return '浠婃棩'
+        case 'week':
+          return '鏈懆'
+        case 'month':
+          return '鏈湀'
+        default:
+          return '浠婃棩'
+      }
+    },
+    getCompareLabel() {
+      switch (this.activeTime) {
+        case 'day':
+          return '杈冩槰鏃�'
+        case 'week':
+          return '杈冧笂鍛�'
+        case 'month':
+          return '杈冧笂鏈�'
+        default:
+          return '杈冩槰鏃�'
+      }
+    },
+    updateMetrics() {
+      // 杩欓噷搴旇鏍规嵁閫夋嫨鐨勬椂闂村懆鏈熶粠鎺ュ彛鑾峰彇鏁版嵁
+      // 妯℃嫙鏁版嵁鏇存柊
+      setTimeout(() => {
+        this.metrics = {
+          overStandardCount: Math.floor(Math.random() * 30),
+          overStandardTrend: Math.floor(Math.random() * 20) - 10,
+          onlineRate: Math.floor(Math.random() * 20) + 80,
+          onlineRateTrend: Math.floor(Math.random() * 10) - 5,
+          purifierEfficiency: Math.floor(Math.random() * 30) + 70,
+          purifierEfficiencyTrend: Math.floor(Math.random() * 10) - 5,
+          taskCompletionRate: Math.floor(Math.random() * 40) + 60,
+          taskCompletionRateTrend: Math.floor(Math.random() * 15) - 7,
+        }
+      }, 300)
+    },
+    initMap() {
+      // 杩欓噷搴旇鍒濆鍖栫湡瀹炵殑GIS鍦板浘
+      // 妯℃嫙鍦板浘鍒濆鍖�
+      const mapElement = document.getElementById('map')
+      if (mapElement) {
+        mapElement.innerHTML = '<div class="map-placeholder">GIS鍦板浘鍔犺浇涓�...</div>'
+        // 瀹為檯椤圭洰涓繖閲屽簲璇ヤ娇鐢ㄧ湡瀹炵殑鍦板浘API锛屽楂樺痉鍦板浘銆佺櫨搴﹀湴鍥剧瓑
+      }
+    },
+    initDeviceStatusChart() {
+      const chartDom = document.getElementById('deviceStatusChart')
+      if (chartDom) {
+        const chart = echarts.init(chartDom)
+        const option = {
+          tooltip: {
+            trigger: 'item',
+            formatter: '{b}: {c} ({d}%)',
+            backgroundColor: 'rgba(255, 255, 255, 0.95)',
+            borderColor: '#ebeef5',
+            borderWidth: 1,
+            textStyle: {
+              color: '#303133',
+            },
+          },
+          legend: {
+            bottom: '0%',
+            left: 'center',
+            textStyle: {
+              color: '#606266',
+              fontSize: 12,
+            },
+          },
+          series: [
+            {
+              name: '璁惧鐘舵��',
+              type: 'pie',
+              radius: ['40%', '65%'],
+              center: ['50%', '45%'],
+              avoidLabelOverlap: false,
+              itemStyle: {
+                borderRadius: 8,
+                borderColor: '#ffffff',
+                borderWidth: 2,
+                shadowBlur: 10,
+                shadowOffsetX: 0,
+                shadowColor: 'rgba(0, 0, 0, 0.1)',
+              },
+              label: {
+                show: true,
+                position: 'outside',
+                formatter: '{b}: {d}%',
+                fontSize: 12,
+                color: '#606266',
+              },
+              labelLine: {
+                show: true,
+                length: 10,
+                length2: 20,
+                lineStyle: {
+                  color: '#606266',
+                  width: 1,
+                },
+              },
+              data: [
+                {
+                  value: this.overview.onlineDevices,
+                  name: '鍦ㄧ嚎',
+                  itemStyle: {
+                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                      { offset: 0, color: '#67c23a' },
+                      { offset: 1, color: '#409eff' },
+                    ]),
+                  },
+                },
+                {
+                  value: this.overview.offlineDevices,
+                  name: '绂荤嚎',
+                  itemStyle: {
+                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                      { offset: 0, color: '#f56c6c' },
+                      { offset: 1, color: '#e6a23c' },
+                    ]),
+                  },
+                },
+              ],
+            },
+          ],
+        }
+        chart.setOption(option)
+
+        // 鍝嶅簲寮忚皟鏁�
+        window.addEventListener('resize', () => {
+          chart.resize()
+        })
+      }
+    },
+    startAutoRefresh() {
+      // 姣�30绉掕嚜鍔ㄥ埛鏂版暟鎹�
+      this.refreshTimer = setInterval(() => {
+        this.updateMetrics()
+        // 杩欓噷搴旇鍚屾椂鏇存柊鍦板浘鐐逛綅鏁版嵁
+      }, 30000)
+    },
+    viewDetails() {
+      // 璺宠浆鍒颁紒涓氱洃鎺ц鎯呴〉
+      this.$router.push('/monitor/enterprise-detail')
+    },
+  },
+}
+</script>
+
+<style scoped>
+.data-dashboard {
+  width: 100%;
+  height: 100vh;
+  background-color: #f5f7fa;
+  color: #303133;
+  padding: 20px;
+  box-sizing: border-box;
+  display: grid;
+  grid-template-rows: auto 1fr;
+  grid-template-columns: 1fr 300px;
+  grid-template-areas:
+    'top overview'
+    'map overview';
+  gap: 20px;
+}
+
+.top-cards {
+  grid-area: top;
+}
+
+.time-period-card {
+  background-color: #ffffff;
+  border: 1px solid #ebeef5;
+  border-radius: 12px;
+  padding: 24px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+
+.time-period-card .card-title {
+  font-size: 14px;
+  color: #909399;
+  font-weight: 500;
+  margin-bottom: 16px;
+  text-align: center;
+}
+
+.time-tab-container {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+  width: 100%;
+}
+
+.time-tab {
+  padding: 2px 4px;
+  border-radius: 8px;
+  cursor: pointer;
+  font-size: 14px;
+  font-weight: 500;
+  transition: all 0.3s ease;
+  color: #606266;
+  text-align: center;
+  border: 1px solid #ebeef5;
+  background-color: #f9f9f9;
+}
+
+.time-tab.active {
+  background-color: #409eff;
+  color: #ffffff;
+  border-color: #409eff;
+  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
+}
+
+.time-tab:hover:not(.active) {
+  color: #409eff;
+  border-color: #c6e2ff;
+  background-color: #ecf5ff;
+}
+
+.time-tab.active {
+  background-color: #409eff;
+  color: #ffffff;
+  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
+}
+
+.time-tab:hover:not(.active) {
+  color: #409eff;
+  background-color: rgba(64, 158, 255, 0.1);
+}
+
+.cards-container {
+  display: grid;
+  grid-template-columns: 120px repeat(4, 1fr);
+  gap: 20px;
+}
+
+.metric-card {
+  background-color: #ffffff;
+  border: 1px solid #ebeef5;
+  border-radius: 12px;
+  padding: 24px;
+  transition: all 0.3s ease;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
+  position: relative;
+  overflow: hidden;
+}
+
+.metric-card::before {
+  content: '';
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 4px;
+  height: 100%;
+  background-color: #409eff;
+}
+
+.metric-card:nth-child(1)::before {
+  background-color: #f56c6c;
+}
+
+.metric-card:nth-child(2)::before {
+  background-color: #67c23a;
+}
+
+.metric-card:nth-child(3)::before {
+  background-color: #e6a23c;
+}
+
+.metric-card:nth-child(4)::before {
+  background-color: #909399;
+}
+
+.metric-card:hover {
+  transform: translateY(-5px);
+  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12);
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 16px;
+}
+
+.card-title {
+  font-size: 14px;
+  color: #909399;
+  font-weight: 500;
+}
+
+.card-icon {
+  font-size: 20px;
+}
+
+.card-value {
+  font-size: 36px;
+  font-weight: bold;
+  margin: 16px 0;
+  color: #303133;
+  line-height: 1.2;
+}
+
+.card-trend {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  font-size: 13px;
+  padding-top: 12px;
+  border-top: 1px solid #f0f2f5;
+}
+
+.trend-arrow {
+  font-size: 16px;
+  font-weight: bold;
+}
+
+.trend-arrow.up {
+  color: #67c23a;
+}
+
+.trend-arrow.down {
+  color: #f56c6c;
+}
+
+.trend-text {
+  color: #606266;
+  font-weight: 500;
+}
+
+.trend-label {
+  color: #909399;
+  font-size: 12px;
+}
+
+.map-section {
+  grid-area: map;
+  background-color: #ffffff;
+  border: 1px solid #ebeef5;
+  border-radius: 8px;
+  position: relative;
+  overflow: hidden;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.map-container {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+
+.map-placeholder {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #909399;
+  font-size: 18px;
+}
+
+.overview-section {
+  grid-area: overview;
+}
+
+.overview-card {
+  background-color: #ffffff;
+  border: 1px solid #ebeef5;
+  border-radius: 8px;
+  padding: 20px 0px;
+  display: flex;
+  flex-direction: column;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.overview-title {
+  font-size: 16px;
+  font-weight: bold;
+  margin-bottom: 20px;
+  text-align: center;
+  color: #303133;
+}
+
+.overview-items-container {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  width: 100%;
+}
+
+.overview-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  flex: 1;
+  text-align: center;
+  padding: 12px 0;
+}
+
+.overview-item:last-child {
+  border-right: none;
+}
+
+.overview-label {
+  font-size: 14px;
+  color: #606266;
+  font-weight: 500;
+  margin-bottom: 8px;
+}
+
+.overview-value {
+  font-size: 24px;
+  font-weight: bold;
+  color: #303133;
+}
+
+.device-status-chart {
+  flex: 1;
+  margin-top: 20px;
+  min-height: 200px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  /* background-color: #c6e2ff; */
+}
+
+.dialog-content {
+  color: #333;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+/* 闂儊鏁堟灉 */
+@keyframes blink {
+  0%,
+  100% {
+    opacity: 1;
+  }
+  50% {
+    opacity: 0.5;
+  }
+}
+
+.blink {
+  animation: blink 1s infinite;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 1200px) {
+  .data-dashboard {
+    grid-template-columns: 1fr;
+    grid-template-areas:
+      'top'
+      'map'
+      'overview';
+    height: auto;
+  }
+
+  .cards-container {
+    grid-template-columns: 160px repeat(2, 1fr);
+  }
+
+  .overview-section {
+    height: 300px;
+  }
+}
+
+@media (max-width: 768px) {
+  .cards-container {
+    grid-template-columns: 1fr;
+    grid-template-rows: auto repeat(4, auto);
+  }
+
+  .time-period-card {
+    order: -1;
+  }
+
+  .time-tab-container {
+    flex-direction: row;
+  }
+
+  .time-tab {
+    flex: 1;
+    padding: 8px 0;
+  }
+}
+</style>
diff --git a/src/views/monitor/DataException.vue b/src/views/monitor/DataException.vue
index 159f6c5..b678d8a 100644
--- a/src/views/monitor/DataException.vue
+++ b/src/views/monitor/DataException.vue
@@ -1,92 +1,84 @@
 <template>
-  <el-row ref="h1">
-    <el-col>
-      <!-- 鑿滃崟璇绘爣棰� -->
-      <div ref="h1" class="header-container">
-        <span class="describe-info">搴楅摵鍚嶉�夋嫨锛�</span>
-        <!-- 搴楅摵鍚�  绾ц仈 -->
-        <ShopNameAndID @submit-id="(n) => (deviceId[1] = n)"></ShopNameAndID>
-
-        <!-- 寮傚父绫诲瀷閫夋嫨 -->
-        <ExceptionType @submitExceptionType="(val) => (exceptionValue = val)"> </ExceptionType>
-
-        <TimeSelect @submit-time="giveTime"></TimeSelect>
+  <div class="data-exception-container">
+    <!-- 鎼滅储鍖哄煙 -->
+    <div ref="h1" class="search-container">
+      <!-- <div class="search-header">
+        <h3>鏌ヨ琛ㄦ牸</h3>
+      </div> -->
+      <el-row>
+        <div class="search-form">
+          <div class="form-row">
+            <div class="form-item">
+              <span class="form-label">搴楅摵璁惧锛�</span>
+              <ShopNameAndID @submit-id="(n) => (deviceId[1] = n)"></ShopNameAndID>
+            </div>
+            <div class="form-item">
+              <ExceptionType @submitExceptionType="(val) => (exceptionValue = val)">
+              </ExceptionType>
+            </div>
+          </div>
+          <div class="form-row">
+            <div class="form-item full-width">
+              <TimeSelect @submit-time="giveTime" :useNewStyle="true"></TimeSelect>
+            </div>
+          </div>
+        </div>
+        <div class="form-actions">
+          <el-button type="primary" :loading="button.queryButton" @click="showTable"
+            >鏌ヨ</el-button
+          >
+          <el-tooltip
+            class="box-item"
+            effect="dark"
+            content="鐐瑰嚮鍙鍑篍xcel鏂囦欢"
+            placement="top-start"
+          >
+            <el-icon class="iconExcel clickable" title="瀵煎嚭Excel鏂囦欢" @click="exportDom">
+              <i-ep-Download />
+            </el-icon>
+          </el-tooltip>
+        </div>
+      </el-row>
+      <div class="summary-info">
+        <span>{{ beginTime }} 鈥斺�� {{ endTime }} 娌圭儫鐩戞祴寮傚父淇℃伅姹囨��</span>
       </div>
-      <div ref="h2" style="display: flex; margin-top: 2px; justify-content: right">
-        <el-button
-          type="primary"
-          plain
-          style="margin-left: 20px"
-          :loading="button.queryButton"
-          @click="showTable"
-          >鏌ヨ</el-button
-        >
+    </div>
 
-        <el-tooltip
-          class="box-item"
-          effect="dark"
-          content="鐐瑰嚮鍙鍑篍xcel鏂囦欢"
-          placement="top-start"
-        >
-          <!-- 鍋氭垚鍑芥暟js鏂囦欢 -->
-          <el-icon class="iconExcel clickable" title="瀵煎嚭Excel鏂囦欢" @click="exportDom">
-            <i-ep-Download />
-            <!-- 瀵煎嚭涓篍xcel -->
-          </el-icon>
-        </el-tooltip>
-      </div>
-      <div style="display: flex; justify-content: right; margin-right: 40px">
-        <span class="collapse-header-text">
-          闈欏畨鍖� {{ beginTime }} 鈥斺�� {{ endTime }} 娌圭儫鐩戞祴寮傚父淇℃伅姹囨��</span
-        >
-      </div>
-      <br />
-
-      <el-collapse ref="h3" v-model="activeNames">
+    <!-- 寮傚父鍒嗘瀽 -->
+    <div class="analysis-container">
+      <el-collapse v-model="activeNames">
         <el-collapse-item name="1">
           <template #title>
-            <el-tooltip class="box-item" effect="dark" content="鐐瑰嚮鍙姌鍙�" placement="right-start">
+            <div class="collapse-title">
               <h4 class="collapse-header">寮傚父鍒嗘瀽</h4>
               <el-icon class="header-icon">
                 <i-ep-info-filled />
               </el-icon>
-            </el-tooltip>
-
-            <el-tooltip class="box-item" effect="dark" content="鐐瑰嚮鍙姌鍙�" placement="right-start">
-            </el-tooltip>
+            </div>
           </template>
-          <el-card class="box-card">
-            <el-row :gutter="25">
+          <el-card class="analysis-card">
+            <el-row :gutter="24">
               <el-col :span="8">
-                <div style="display: flex">
-                  <img
-                    src="@/assets/exceed.jpg"
-                    style="width: 25px; height: 25px; margin-top: 5px"
-                  />
-                  <span
-                    style="font-size: 16px; font-weight: bold; margin-top: 4px; margin-left: 4px"
-                    >娌圭儫娴撳害瓒呮爣</span
-                  >
-                </div>
-
-                <div class="box-card-label">
-                  <el-scrollbar>
-                    <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
-                    <span style="font-size: 20px">{{ exception0.length }} /{{ shopsTotal }} </span>
-                    <span style="font-size: 17px">
-                      ({{ ((exception0.length / shopsTotal) * 100).toFixed(1) }}%)</span
-                    >
-                    {{ shopsTotal }}
-                    <span class="right-text">
+                <div class="analysis-item">
+                  <div class="item-header">
+                    <img src="@/assets/exceed.jpg" class="item-icon" />
+                    <span class="item-title">娌圭儫娴撳害瓒呮爣</span>
+                  </div>
+                  <div class="item-content">
+                    <div class="item-stats">
+                      <span class="stats-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+                      <span class="stats-value">{{ exception0.length }} /{{ shopsTotal }}</span>
+                      <span class="stats-percent"
+                        >({{ ((exception0.length / shopsTotal) * 100).toFixed(1) }}%)</span
+                      >
+                    </div>
+                    <div class="item-percent">
                       寮傚父鏁板崰姣旓細{{ ((exception0Num / exceptionAllNum) * 100).toFixed(1) }}%
-                    </span>
-                  </el-scrollbar>
-                </div>
-
-                <hr />
-                <div class="box-card-butcontainer">
-                  <el-card class="sub-box-card">
-                    <el-scrollbar max-height="70px">
+                    </div>
+                  </div>
+                  <hr class="item-divider" />
+                  <div class="item-shops">
+                    <el-scrollbar max-height="80px">
                       <ExceptionText
                         v-for="(item, index) in exception0"
                         :key="item"
@@ -100,39 +92,30 @@
                         <span v-if="index < exception0.length - 1" class="text-blank">,</span>
                       </ExceptionText>
                     </el-scrollbar>
-                  </el-card>
+                  </div>
                 </div>
               </el-col>
-
               <el-col :span="8">
-                <div style="display: flex">
-                  <img
-                    src="@/assets/exception.jpg"
-                    style="width: 25px; height: 25px; margin-top: 5px"
-                  />
-                  <span
-                    style="font-size: 16px; font-weight: bold; margin-top: 5px; margin-left: 4px"
-                    >渚涚數寮傚父</span
-                  >
-                </div>
-                <div class="box-card-label">
-                  <el-scrollbar>
-                    <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
-                    <span style="font-size: 20px">{{ exception1.length }} /{{ shopsTotal }}</span>
-                    <span style="font-size: 17px">
-                      ({{ ((exception1.length / shopsTotal) * 100).toFixed(1) }}%)</span
-                    >
-                    <span class="right-text">
+                <div class="analysis-item">
+                  <div class="item-header">
+                    <img src="@/assets/exception.jpg" class="item-icon" />
+                    <span class="item-title">渚涚數寮傚父</span>
+                  </div>
+                  <div class="item-content">
+                    <div class="item-stats">
+                      <span class="stats-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+                      <span class="stats-value">{{ exception1.length }} /{{ shopsTotal }}</span>
+                      <span class="stats-percent"
+                        >({{ ((exception1.length / shopsTotal) * 100).toFixed(1) }}%)</span
+                      >
+                    </div>
+                    <div class="item-percent">
                       寮傚父鏁板崰姣旓細{{ ((exception1Num / exceptionAllNum) * 100).toFixed(1) }}%
-                    </span>
-                  </el-scrollbar>
-                </div>
-
-                <hr />
-
-                <div>
-                  <el-card class="sub-box-card">
-                    <el-scrollbar max-height="70px">
+                    </div>
+                  </div>
+                  <hr class="item-divider" />
+                  <div class="item-shops">
+                    <el-scrollbar max-height="80px">
                       <ExceptionText
                         v-for="(item, index) in exception1"
                         :key="item"
@@ -146,35 +129,28 @@
                         <span v-if="index < exception1.length - 1" class="text-blank">,</span>
                       </ExceptionText>
                     </el-scrollbar>
-                  </el-card>
+                  </div>
                 </div>
               </el-col>
-
               <el-col :span="8">
-                <div style="display: flex">
-                  <img
-                    src="@/assets/offline.jpg"
-                    style="width: 25px; height: 25px; margin-top: 5px"
-                  />
-                  <span
-                    style="font-size: 16px; font-weight: bold; margin-top: 5px; margin-left: 4px"
-                    >璁惧鎴栫綉缁滃紓甯�</span
-                  >
-                </div>
-                <div class="box-card-label">
-                  <el-scrollbar>
-                    <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
-                    <span style="font-size: 20px">{{ exception2.length }} /{{ shopsTotal }}</span>
-                    <span style="font-size: 17px">
-                      ({{ ((exception2.length / shopsTotal) * 100).toFixed(1) }}%)</span
-                    >
-                    <span class="right-text"> 寮傚父鏁板崰姣旓細{{ connectException }}% </span>
-                  </el-scrollbar>
-                </div>
-                <hr />
-                <div>
-                  <el-card class="sub-box-card">
-                    <el-scrollbar max-height="70px">
+                <div class="analysis-item">
+                  <div class="item-header">
+                    <img src="@/assets/offline.jpg" class="item-icon" />
+                    <span class="item-title">璁惧鎴栫綉缁滃紓甯�</span>
+                  </div>
+                  <div class="item-content">
+                    <div class="item-stats">
+                      <span class="stats-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+                      <span class="stats-value">{{ exception2.length }} /{{ shopsTotal }}</span>
+                      <span class="stats-percent"
+                        >({{ ((exception2.length / shopsTotal) * 100).toFixed(1) }}%)</span
+                      >
+                    </div>
+                    <div class="item-percent">寮傚父鏁板崰姣旓細{{ connectException }}%</div>
+                  </div>
+                  <hr class="item-divider" />
+                  <div class="item-shops">
+                    <el-scrollbar max-height="80px">
                       <ExceptionText
                         v-for="(item, index) in exception2"
                         :key="item"
@@ -188,212 +164,198 @@
                         <span v-if="index < exception2.length - 1" class="text-blank">,</span>
                       </ExceptionText>
                     </el-scrollbar>
-                  </el-card>
+                  </div>
                 </div>
               </el-col>
             </el-row>
           </el-card>
         </el-collapse-item>
       </el-collapse>
+    </div>
 
-      <h4 class="table-text">寮傚父鏁版嵁</h4>
-    </el-col>
-  </el-row>
-  <el-card class="table-page" v-show="!isNoData">
-    <el-table
-      ref="tableH"
-      size="small"
-      v-loading="loading"
-      :data="displayData"
-      style="width: 100%"
-      border
-      :height="tableHeight"
-      :cell-class-name="tableCellClassName"
-    >
-      <el-table-column prop="diName" label="搴楅摵鍚嶇О" align="center">
-        <template #default="{ row }">
-          <el-tooltip effect="dark" :content="row.diName">
-            <div class="cell ellipsis">{{ row.diName }}</div>
-          </el-tooltip>
-        </template>
-      </el-table-column>
-
-      <el-table-column prop="devId" label="璁惧缂栧彿" align="center">
-        <template #default="{ row }">
-          <el-tooltip effect="dark" :content="row.devId">
-            <div class="cell ellipsis">{{ row.devId }}</div>
-          </el-tooltip>
-        </template>
-      </el-table-column>
-
-      <el-table-column prop="diSupplier" label="渚涘簲鍟�" align="center">
-        <template #default="{ row }">
-          <el-tooltip effect="dark" :content="row.diSupplier">
-            <div class="cell ellipsis">{{ row.diSupplier }}</div>
-          </el-tooltip>
-        </template>
-      </el-table-column>
-
-      <el-table-column prop="exception" label="寮傚父鍒嗙被" align="center">
-        <template #default="{ row }">
-          <el-tooltip effect="dark" :content="row.exception">
-            <div class="cell ellipsis">{{ row.exception }}</div>
-          </el-tooltip>
-        </template>
-      </el-table-column>
-      <el-table-column label="寮傚父绫诲瀷" align="center">
-        <template #default="{ row }">
-          <span v-if="row.exceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
-          <span v-else-if="row.exceptionType == '1'">鐤戜技渚涚數寮傚父</span>
-          <span v-else-if="row.exceptionType == '2'">鎺夌嚎</span>
-        </template>
-      </el-table-column>
-      <el-table-column prop="region" label="鍦板尯" align="center">
-        <template #default="{ row }">
-          <el-tooltip effect="dark" :content="row.region">
-            <div class="cell ellipsis">{{ row.region }}</div>
-          </el-tooltip>
-        </template>
-      </el-table-column>
-
-      <el-table-column prop="beginTime" label="寮�濮嬫椂闂�" align="center">
-        <template #default="{ row }">
-          <el-tooltip effect="dark" :content="row.beginTime">
-            <div class="cell ellipsis">{{ row.beginTime }}</div>
-          </el-tooltip>
-        </template>
-      </el-table-column>
-      <el-table-column prop="endTime" label="缁撴潫鏃堕棿" align="center">
-        <template #default="{ row }">
-          <el-tooltip effect="dark" :content="row.endTime">
-            <div class="cell ellipsis">{{ row.endTime }}</div>
-          </el-tooltip>
-        </template>
-      </el-table-column>
-      <el-table-column label="鎿嶄綔" align="center">
-        <template #default="{ row }">
-          <el-button type="primary" class="table-button" @click="showDrawer(row)"
-            >鏌ョ湅璇︽儏</el-button
-          >
-        </template>
-      </el-table-column>
-    </el-table>
-
-    <el-pagination
-      ref="h4"
-      background
-      @size-change="handleSizeChange"
-      @current-change="handleCurrentChange"
-      :total="total"
-      :page-size="pageSize"
-      layout="total,prev, pager, next, jumper"
-    />
-  </el-card>
-  <el-empty v-show="isNoData" :image-size="200" />
-  <!-- 瀵硅瘽妗� -->
-  <div>
-    <el-dialog v-model="centerDialogVisible" draggable align-center>
-      <template #header>
-        <div style="font-size: 17px">
-          搴楅摵鍚嶏細{{ rowShopName }}
-          <span style="margin-left: 40px">寮傚父绫诲瀷锛�</span>
-          <span v-if="rowExceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
-          <span v-else-if="rowExceptionType == '1'">渚涚數寮傚父</span>
-          <span v-else-if="rowExceptionType == '2'">鎺夌嚎</span>
-          <div style="margin-top: 10px">
-            寮傚父鏃堕棿娈碉細{{ rowBeginTime }} ~
-            {{ rowEndTime }}
-          </div>
-        </div>
-
-        <div class="dialog-button-position">
-          <el-button
-            type="danger"
-            :loading="button.preButton"
-            :disabled="isPreCantouch || banTouch"
-            @click="getPreviousRowData"
-            >涓婃潯寮傚父</el-button
-          >
-          <el-button
-            type="danger"
-            :loading="button.afterButton"
-            :disabled="isNextCantouch || banTouch"
-            @click="getNextRowData"
-            >涓嬫潯寮傚父</el-button
-          >
-        </div>
-      </template>
-
-      <!-- 瓒呮爣鏁版嵁鏃� -->
-      <!-- 鎶樼嚎鍥� -->
-
-      <!-- 鎺夌嚎 -->
-      <!-- <div
-          ref="ref"
-          v-show="isOfflineShow"
-          style="
-            width: 100%;
-            height: 300px;
-            /* min-width: 100px; */
-            margin-bottom: 20px;
-            margin-left: 10px;
-            min-width: 350px;
-          "
-        ></div> -->
-
-      <ExceptionTypeLineChart
-        :option="option"
-        :is-open-dialog="centerDialogVisible"
-        v-loading="chartLoading"
-      ></ExceptionTypeLineChart>
-
-      <!--  -->
-      <div style="margin-top: 40px; margin-bottom: 5px; border: 1px">
-        <el-table :data="exceedingData" height="360" border style="margin-top: 25px">
-          <el-table-column
-            type="index"
-            label="搴忓彿"
-            width="60px"
-            align="center"
-            fixed
-            :index="indexMethod"
-          ></el-table-column>
-          <el-table-column fixed prop="diName" label="搴楅摵鍚嶇О" show-overflow-tooltip />
-          <el-table-column
-            prop="mvStatCode"
-            label="璁惧缂栧彿"
-            align="center"
-            show-overflow-tooltip
-          />
-          <el-table-column prop="diSupplier" label="渚涘簲鍟�" align="center" show-overflow-tooltip />
-          <el-table-column
-            prop="mvDataTime"
-            label="閲囬泦鏃堕棿"
-            align="center"
-            show-overflow-tooltip
-          />
-
-          <el-table-column
-            prop="mvFumeConcentration2"
-            label="娌圭儫娴撳害(mg/m鲁)"
-            align="center"
-            show-overflow-tooltip
-          />
+    <!-- 寮傚父鏁版嵁琛ㄦ牸 -->
+    <div class="table-container">
+      <h4 class="table-title">寮傚父鏁版嵁</h4>
+      <el-card v-show="!isNoData">
+        <el-table
+          ref="tableH"
+          v-loading="loading"
+          :data="displayData"
+          style="width: 100%"
+          border
+          :height="tableHeight"
+          :cell-class-name="tableCellClassName"
+        >
+          <el-table-column prop="diName" label="搴楅摵鍚嶇О" align="center">
+            <template #default="{ row }">
+              <el-tooltip effect="dark" :content="row.diName">
+                <div class="cell ellipsis">{{ row.diName }}</div>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column prop="devId" label="璁惧缂栧彿" align="center">
+            <template #default="{ row }">
+              <el-tooltip effect="dark" :content="row.devId">
+                <div class="cell ellipsis">{{ row.devId }}</div>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column prop="diSupplier" label="渚涘簲鍟�" align="center">
+            <template #default="{ row }">
+              <el-tooltip effect="dark" :content="row.diSupplier">
+                <div class="cell ellipsis">{{ row.diSupplier }}</div>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column prop="exception" label="寮傚父鍒嗙被" align="center">
+            <template #default="{ row }">
+              <el-tooltip effect="dark" :content="row.exception">
+                <div class="cell ellipsis">{{ row.exception }}</div>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column label="寮傚父绫诲瀷" align="center">
+            <template #default="{ row }">
+              <span v-if="row.exceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
+              <span v-else-if="row.exceptionType == '1'">鐤戜技渚涚數寮傚父</span>
+              <span v-else-if="row.exceptionType == '2'">鎺夌嚎</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="region" label="鍦板尯" align="center">
+            <template #default="{ row }">
+              <el-tooltip effect="dark" :content="row.region">
+                <div class="cell ellipsis">{{ row.region }}</div>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column prop="beginTime" label="寮�濮嬫椂闂�" align="center">
+            <template #default="{ row }">
+              <el-tooltip effect="dark" :content="row.beginTime">
+                <div class="cell ellipsis">{{ row.beginTime }}</div>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column prop="endTime" label="缁撴潫鏃堕棿" align="center">
+            <template #default="{ row }">
+              <el-tooltip effect="dark" :content="row.endTime">
+                <div class="cell ellipsis">{{ row.endTime }}</div>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column label="鎿嶄綔" align="center" width="120">
+            <template #default="{ row }">
+              <el-button type="primary" size="small" @click="showDrawer(row)">鏌ョ湅</el-button>
+            </template>
+          </el-table-column>
         </el-table>
-      </div>
+        <div class="pagination-container">
+          <el-pagination
+            ref="h4"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+            :total="total"
+            :page-size="pageSize"
+            layout="total, prev, pager, next, jumper"
+          />
+        </div>
+      </el-card>
+      <el-empty v-show="isNoData" :image-size="200" />
+    </div>
 
-      <el-tag type="success" class="mx-1" effect="dark" round
-        ><span class="table-line-lable" v-show="rowExceptionType == '0'">寮傚父璁板綍锛� </span>
-        <span v-show="rowExceptionType == '1' || rowExceptionType == '2'">缂哄け鏁版嵁锛�</span>
-        <span class="table-line-num">{{ exceptionTotal }}鏉�</span>
-        <span v-show="rowExceptionType === '1' || rowExceptionType === '2'"> (閫昏緫璁$畻)</span>
-      </el-tag>
-    </el-dialog>
+    <!-- 瀵硅瘽妗� -->
+    <div>
+      <el-dialog v-model="centerDialogVisible" draggable align-center class="detail-dialog">
+        <template #header>
+          <div class="dialog-header">
+            <div class="dialog-title">
+              <span>搴楅摵鍚嶏細{{ rowShopName }}</span>
+              <span class="dialog-info"
+                >寮傚父绫诲瀷锛�
+                <span v-if="rowExceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
+                <span v-else-if="rowExceptionType == '1'">渚涚數寮傚父</span>
+                <span v-else-if="rowExceptionType == '2'">鎺夌嚎</span>
+              </span>
+              <div class="dialog-time">寮傚父鏃堕棿娈碉細{{ rowBeginTime }} ~ {{ rowEndTime }}</div>
+            </div>
+            <div class="dialog-actions">
+              <el-button
+                type="primary"
+                :loading="button.preButton"
+                :disabled="isPreCantouch || banTouch"
+                @click="getPreviousRowData"
+                >涓婃潯寮傚父</el-button
+              >
+              <el-button
+                type="primary"
+                :loading="button.afterButton"
+                :disabled="isNextCantouch || banTouch"
+                @click="getNextRowData"
+                >涓嬫潯寮傚父</el-button
+              >
+            </div>
+          </div>
+        </template>
+
+        <ExceptionTypeLineChart
+          :option="option"
+          :is-open-dialog="centerDialogVisible"
+          v-loading="chartLoading"
+        ></ExceptionTypeLineChart>
+
+        <div class="dialog-table-container">
+          <el-table :data="exceedingData" height="360" border style="margin-top: 20px">
+            <el-table-column
+              type="index"
+              label="搴忓彿"
+              width="60px"
+              align="center"
+              fixed
+              :index="indexMethod"
+            ></el-table-column>
+            <el-table-column fixed prop="diName" label="搴楅摵鍚嶇О" show-overflow-tooltip />
+            <el-table-column
+              prop="mvStatCode"
+              label="璁惧缂栧彿"
+              align="center"
+              show-overflow-tooltip
+            />
+            <el-table-column
+              prop="diSupplier"
+              label="渚涘簲鍟�"
+              align="center"
+              show-overflow-tooltip
+            />
+            <el-table-column
+              prop="mvDataTime"
+              label="閲囬泦鏃堕棿"
+              align="center"
+              show-overflow-tooltip
+            />
+            <el-table-column
+              prop="mvFumeConcentration2"
+              label="娌圭儫娴撳害(mg/m鲁)"
+              align="center"
+              show-overflow-tooltip
+            />
+          </el-table>
+        </div>
+
+        <div class="dialog-footer">
+          <el-tag type="success" effect="dark" round
+            ><span v-show="rowExceptionType == '0'">寮傚父璁板綍锛�</span>
+            <span v-show="rowExceptionType == '1' || rowExceptionType == '2'">缂哄け鏁版嵁锛�</span>
+            <span class="table-line-num">{{ exceptionTotal }}鏉�</span>
+            <span v-show="rowExceptionType === '1' || rowExceptionType === '2'"> (閫昏緫璁$畻)</span>
+          </el-tag>
+        </div>
+      </el-dialog>
+    </div>
   </div>
 </template>
 
 <script>
 import { defineAsyncComponent } from 'vue'
+import { ElMessage } from 'element-plus'
 import ExceptionType from '@/sfc/ExceptionType.vue'
 import TimeSelect from '@/sfc/TimeSelect.vue'
 import ExceptionText from '@/sfc/ExceptionText.vue'
@@ -632,7 +594,7 @@
 
     //鍔熻兘锛� 鍔ㄦ�佽绠楄〃鏍奸珮搴�
     calcTableHeight() {
-      const h1 = this.$refs.h1.$el.offsetHeight
+      const h1 = this.$refs.h1.offsetHeight
       const h2 = this.$refs.h4.$el.offsetHeight
       this.tableHeight = `calc(100vh - ${h1}px - ${h2}px - 45px - var(--el-main-padding) * 2 - var(--el-card-padding))`
     },
@@ -1530,12 +1492,241 @@
 </script>
 
 <style scoped>
-.header-container {
-  display: flex;
-  margin-left: 20px;
-  /* flex-wrap: wrap;
-    align-items: center; */
+/* 鍏ㄥ眬瀹瑰櫒 */
+.data-exception-container {
+  padding: 20px;
+  background-color: #f5f7fa;
+  min-height: 100vh;
 }
+
+/* 鎼滅储鍖哄煙 */
+.search-container {
+  background-color: white;
+  border-radius: 8px;
+  padding: 20px;
+  margin-bottom: 20px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+}
+
+.search-header {
+  margin-bottom: 20px;
+}
+
+.search-header h3 {
+  margin: 0;
+  font-size: 16px;
+  font-weight: 600;
+  color: #333;
+}
+
+.search-form {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+  flex: 1;
+}
+
+.form-row {
+  display: flex;
+  align-items: flex-start;
+  gap: 16px;
+  flex-wrap: wrap;
+}
+
+.form-item {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  flex: 1;
+  min-width: 200px;
+}
+
+.form-item.full-width {
+  flex: 100%;
+}
+
+.form-label {
+  font-weight: bolder;
+  white-space: nowrap;
+}
+
+.form-actions {
+  margin-left: auto;
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+
+.summary-info {
+  text-align: right;
+  font-size: 14px;
+  color: #999;
+  margin-top: 8px;
+}
+
+/* 寮傚父鍒嗘瀽 */
+.analysis-container {
+  background-color: white;
+  border-radius: 8px;
+  padding: 20px;
+  margin-bottom: 20px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+}
+
+.collapse-title {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.collapse-header {
+  margin: 0;
+  font-size: 16px;
+  font-weight: 600;
+  color: #333;
+}
+
+.header-icon {
+  color: #1890ff;
+}
+
+.analysis-card {
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+.analysis-item {
+  height: 180px;
+  display: flex;
+  flex-direction: column;
+}
+
+.item-header {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-bottom: 12px;
+}
+
+.item-icon {
+  width: 24px;
+  height: 24px;
+}
+
+.item-title {
+  font-size: 14px;
+  font-weight: 600;
+  color: #333;
+}
+
+.item-content {
+  flex: 1;
+  margin-bottom: 12px;
+}
+
+.item-stats {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-bottom: 4px;
+}
+
+.stats-label {
+  font-size: 13px;
+  color: #666;
+}
+
+.stats-value {
+  font-size: 18px;
+  font-weight: 600;
+  color: #333;
+}
+
+.stats-percent {
+  font-size: 13px;
+  color: #999;
+}
+
+.item-percent {
+  font-size: 13px;
+  color: #666;
+  margin-top: 4px;
+}
+
+.item-divider {
+  margin: 10px 0;
+  border: 0.5px solid #f0f0f0;
+}
+
+.item-shops {
+  flex: 1;
+}
+
+/* 琛ㄦ牸鍖哄煙 */
+.table-container {
+  background-color: white;
+  border-radius: 8px;
+  padding: 20px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+}
+
+.table-title {
+  margin: 0 0 16px 0;
+  font-size: 16px;
+  font-weight: 600;
+  color: #333;
+}
+
+.pagination-container {
+  margin-top: 16px;
+  display: flex;
+  justify-content: flex-end;
+}
+
+/* 瀵硅瘽妗� */
+.detail-dialog {
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+.dialog-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  width: 100%;
+}
+
+.dialog-title {
+  font-size: 16px;
+  color: #333;
+}
+
+.dialog-info {
+  margin-left: 24px;
+  color: #666;
+}
+
+.dialog-time {
+  margin-top: 8px;
+  font-size: 14px;
+  color: #666;
+}
+
+.dialog-actions {
+  display: flex;
+  gap: 8px;
+}
+
+.dialog-table-container {
+  margin-top: 20px;
+}
+
+.dialog-footer {
+  margin-top: 20px;
+  text-align: right;
+}
+
+/* 閫氱敤鏍峰紡 */
 .ellipsis {
   white-space: nowrap;
   overflow: hidden;
@@ -1543,148 +1734,127 @@
 }
 
 .iconExcel {
-  font-size: 25px;
-  margin-left: 20px;
-  bottom: -6px;
+  font-size: 20px;
+  cursor: pointer;
+  color: #1890ff;
 }
 
-/* 鍙紶鏍囩澶村彉涓哄彲鐐瑰嚮鐘舵�� */
 .clickable {
   cursor: pointer;
 }
-.card-header {
-  margin: 0;
-}
 
-body {
-  margin: 0;
-}
-.exception-divider-rowline {
-  margin: 10px 0px;
-}
-/* 寮傚父鍒嗘瀽鏁版嵁涓庢寜閽� */
-.exception-container {
-  display: flex;
-}
-.example-showcase .el-loading-mask {
-  z-index: 9;
-}
-
-.scrollbar-demo-item {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  height: 20px;
-  margin: 10px;
-  text-align: center;
-  border-radius: 4px;
-  background: var(--el-color-primary-light-9);
-  color: var(--el-color-primary);
-}
-.collapse-header {
-  margin-left: 5px;
-  font-size: 18px;
-}
-.collapse-header-text {
-  margin-top: 5px;
-  font-size: 14px;
-  color: gray;
-}
-
-.box-card-label {
-  font-size: 14px;
-  white-space: nowrap;
-}
-
-.right-text {
-  /* float :right; */
-  /* text-align: right; */
-  margin-left: 80px;
-}
-:deep().el-card {
-  border-radius: 9px;
-}
-
-/* 鈥樻煡鐪嬭鎯呪�� 鐨勫脊鍑烘楂樺害璋冩暣 */
-:deep().el-dialog {
-  height: 98%;
-  /* 涓嶅嚭鐜版粴鍔ㄦ潯 */
-  overflow-y: hidden;
-  border-radius: 9px;
-}
-.table-page {
-  margin-left: 20px;
-}
-
-.table-text {
-  font-size: 18px;
-  margin: 5px 0px 10px 20px;
-}
 .text-blank {
   margin-right: 10px;
   color: #000000;
 }
-/* 搴楅摵鍚嶉�夋嫨鏂囨湰 */
-.describe-info {
-  margin-top: 5px;
-  font-weight: bold;
-  white-space: nowrap;
-}
-/* 鏃堕棿閫夋嫨鏂囨湰 */
-.describe-time-text {
-  margin-left: 30px;
-  margin-top: 5px;
-  font-weight: bold;
-}
 
-/* 寮傚父琛ㄦ牸涓嬫爣绛句腑鐨勬暟缁� */
 .table-line-num {
   font-weight: bold;
   color: black;
 }
-.button_info.el-button_inner {
-  text-align: left;
+
+/* 琛ㄦ牸琛屾牱寮� */
+:deep().el-table__row .exceeding-row {
+  background-color: #fff1f0;
+  color: #cf1322;
 }
+
+:deep().el-table__row .abnormal-power-supply {
+  background-color: #fffbe6;
+  color: #d48806;
+}
+
+:deep().el-table__row .disconnect {
+  background-color: #e6f7ff;
+  color: #1890ff;
+}
+
+/* 琛ㄦ牸鏍峰紡 */
+:deep().el-table {
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+:deep().el-table th {
+  background-color: #fafafa;
+  font-weight: 600;
+}
+
+/* 鎸夐挳鏍峰紡 */
+:deep().el-button--primary {
+  background-color: #1890ff;
+  border-color: #1890ff;
+}
+
+:deep().el-button--primary:hover {
+  background-color: #40a9ff;
+  border-color: #40a9ff;
+}
+
+/* 鍗$墖鏍峰紡 */
+:deep().el-card {
+  border-radius: 8px;
+  border: 1px solid #f0f0f0;
+}
+
+/* 鍝嶅簲寮忚皟鏁� */
+@media (max-width: 1200px) {
+  .search-form {
+    flex-direction: column;
+    align-items: flex-start;
+  }
+
+  .form-actions {
+    margin-left: 0;
+    margin-top: 12px;
+  }
+}
+
+/* 鍘熸湁鏍峰紡鍏煎 */
+.header-container {
+  display: flex;
+  margin-left: 0;
+  flex-wrap: wrap;
+  align-items: center;
+  gap: 16px;
+}
+
+.describe-info {
+  margin-top: 0;
+  font-weight: 500;
+  white-space: nowrap;
+  color: #666;
+}
+
+.table-page {
+  margin-left: 0;
+}
+
+.table-text {
+  font-size: 16px;
+  margin: 0 0 16px 0;
+  font-weight: 600;
+  color: #333;
+}
+
 .el-collapse {
-  margin-left: 20px;
+  margin-left: 0;
 }
-:deep().el-collapse .el-collapse-item__content {
-  padding-bottom: 0px;
-}
+
 .box-card {
-  height: 190px;
+  height: auto;
+  min-height: 190px;
 }
 
 .sub-box-card {
-  height: 100px;
+  height: auto;
+  min-height: 100px;
   border: 0px;
 }
 
-.mx-1 {
-  margin-bottom: 0px;
-}
 .dialog-button-position {
   display: flex;
   justify-content: right;
   margin-bottom: 10px;
-}
-
-:deep().el-table__row .exceeding-row {
-  background-color: #f53f3f;
-}
-:deep().el-table__row .abnormal-power-supply {
-  background-color: #fdf4bf;
-}
-:deep().el-table__row .disconnect {
-  background-color: #f7ba1e;
-}
-
-.el-table {
-  color: #000000;
-}
-
-/* 琛ㄦ牸涓殑鎸夐挳瀹藉害閾烘弧 */
-.table-button {
-  width: 100%;
 }
 </style>
diff --git a/src/views/monitor/DataException_old.vue b/src/views/monitor/DataException_old.vue
new file mode 100644
index 0000000..159f6c5
--- /dev/null
+++ b/src/views/monitor/DataException_old.vue
@@ -0,0 +1,1690 @@
+<template>
+  <el-row ref="h1">
+    <el-col>
+      <!-- 鑿滃崟璇绘爣棰� -->
+      <div ref="h1" class="header-container">
+        <span class="describe-info">搴楅摵鍚嶉�夋嫨锛�</span>
+        <!-- 搴楅摵鍚�  绾ц仈 -->
+        <ShopNameAndID @submit-id="(n) => (deviceId[1] = n)"></ShopNameAndID>
+
+        <!-- 寮傚父绫诲瀷閫夋嫨 -->
+        <ExceptionType @submitExceptionType="(val) => (exceptionValue = val)"> </ExceptionType>
+
+        <TimeSelect @submit-time="giveTime"></TimeSelect>
+      </div>
+      <div ref="h2" style="display: flex; margin-top: 2px; justify-content: right">
+        <el-button
+          type="primary"
+          plain
+          style="margin-left: 20px"
+          :loading="button.queryButton"
+          @click="showTable"
+          >鏌ヨ</el-button
+        >
+
+        <el-tooltip
+          class="box-item"
+          effect="dark"
+          content="鐐瑰嚮鍙鍑篍xcel鏂囦欢"
+          placement="top-start"
+        >
+          <!-- 鍋氭垚鍑芥暟js鏂囦欢 -->
+          <el-icon class="iconExcel clickable" title="瀵煎嚭Excel鏂囦欢" @click="exportDom">
+            <i-ep-Download />
+            <!-- 瀵煎嚭涓篍xcel -->
+          </el-icon>
+        </el-tooltip>
+      </div>
+      <div style="display: flex; justify-content: right; margin-right: 40px">
+        <span class="collapse-header-text">
+          闈欏畨鍖� {{ beginTime }} 鈥斺�� {{ endTime }} 娌圭儫鐩戞祴寮傚父淇℃伅姹囨��</span
+        >
+      </div>
+      <br />
+
+      <el-collapse ref="h3" v-model="activeNames">
+        <el-collapse-item name="1">
+          <template #title>
+            <el-tooltip class="box-item" effect="dark" content="鐐瑰嚮鍙姌鍙�" placement="right-start">
+              <h4 class="collapse-header">寮傚父鍒嗘瀽</h4>
+              <el-icon class="header-icon">
+                <i-ep-info-filled />
+              </el-icon>
+            </el-tooltip>
+
+            <el-tooltip class="box-item" effect="dark" content="鐐瑰嚮鍙姌鍙�" placement="right-start">
+            </el-tooltip>
+          </template>
+          <el-card class="box-card">
+            <el-row :gutter="25">
+              <el-col :span="8">
+                <div style="display: flex">
+                  <img
+                    src="@/assets/exceed.jpg"
+                    style="width: 25px; height: 25px; margin-top: 5px"
+                  />
+                  <span
+                    style="font-size: 16px; font-weight: bold; margin-top: 4px; margin-left: 4px"
+                    >娌圭儫娴撳害瓒呮爣</span
+                  >
+                </div>
+
+                <div class="box-card-label">
+                  <el-scrollbar>
+                    <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+                    <span style="font-size: 20px">{{ exception0.length }} /{{ shopsTotal }} </span>
+                    <span style="font-size: 17px">
+                      ({{ ((exception0.length / shopsTotal) * 100).toFixed(1) }}%)</span
+                    >
+                    {{ shopsTotal }}
+                    <span class="right-text">
+                      寮傚父鏁板崰姣旓細{{ ((exception0Num / exceptionAllNum) * 100).toFixed(1) }}%
+                    </span>
+                  </el-scrollbar>
+                </div>
+
+                <hr />
+                <div class="box-card-butcontainer">
+                  <el-card class="sub-box-card">
+                    <el-scrollbar max-height="70px">
+                      <ExceptionText
+                        v-for="(item, index) in exception0"
+                        :key="item"
+                        :devId="item.devId"
+                        exception-value="0"
+                        :begin-time="beginTime"
+                        :end-time="endTime"
+                        @submit-exception-data="getAbnormalDataByClick"
+                      >
+                        {{ item.diName }}
+                        <span v-if="index < exception0.length - 1" class="text-blank">,</span>
+                      </ExceptionText>
+                    </el-scrollbar>
+                  </el-card>
+                </div>
+              </el-col>
+
+              <el-col :span="8">
+                <div style="display: flex">
+                  <img
+                    src="@/assets/exception.jpg"
+                    style="width: 25px; height: 25px; margin-top: 5px"
+                  />
+                  <span
+                    style="font-size: 16px; font-weight: bold; margin-top: 5px; margin-left: 4px"
+                    >渚涚數寮傚父</span
+                  >
+                </div>
+                <div class="box-card-label">
+                  <el-scrollbar>
+                    <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+                    <span style="font-size: 20px">{{ exception1.length }} /{{ shopsTotal }}</span>
+                    <span style="font-size: 17px">
+                      ({{ ((exception1.length / shopsTotal) * 100).toFixed(1) }}%)</span
+                    >
+                    <span class="right-text">
+                      寮傚父鏁板崰姣旓細{{ ((exception1Num / exceptionAllNum) * 100).toFixed(1) }}%
+                    </span>
+                  </el-scrollbar>
+                </div>
+
+                <hr />
+
+                <div>
+                  <el-card class="sub-box-card">
+                    <el-scrollbar max-height="70px">
+                      <ExceptionText
+                        v-for="(item, index) in exception1"
+                        :key="item"
+                        :devId="item.devId"
+                        exception-value="1"
+                        :begin-time="beginTime"
+                        :end-time="endTime"
+                        @submit-exception-data="getAbnormalDataByClick"
+                      >
+                        {{ item.diName }}
+                        <span v-if="index < exception1.length - 1" class="text-blank">,</span>
+                      </ExceptionText>
+                    </el-scrollbar>
+                  </el-card>
+                </div>
+              </el-col>
+
+              <el-col :span="8">
+                <div style="display: flex">
+                  <img
+                    src="@/assets/offline.jpg"
+                    style="width: 25px; height: 25px; margin-top: 5px"
+                  />
+                  <span
+                    style="font-size: 16px; font-weight: bold; margin-top: 5px; margin-left: 4px"
+                    >璁惧鎴栫綉缁滃紓甯�</span
+                  >
+                </div>
+                <div class="box-card-label">
+                  <el-scrollbar>
+                    <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+                    <span style="font-size: 20px">{{ exception2.length }} /{{ shopsTotal }}</span>
+                    <span style="font-size: 17px">
+                      ({{ ((exception2.length / shopsTotal) * 100).toFixed(1) }}%)</span
+                    >
+                    <span class="right-text"> 寮傚父鏁板崰姣旓細{{ connectException }}% </span>
+                  </el-scrollbar>
+                </div>
+                <hr />
+                <div>
+                  <el-card class="sub-box-card">
+                    <el-scrollbar max-height="70px">
+                      <ExceptionText
+                        v-for="(item, index) in exception2"
+                        :key="item"
+                        :devId="item.devId"
+                        exception-value="2"
+                        :begin-time="beginTime"
+                        :end-time="endTime"
+                        @submit-exception-data="getAbnormalDataByClick"
+                      >
+                        {{ item.diName }}
+                        <span v-if="index < exception2.length - 1" class="text-blank">,</span>
+                      </ExceptionText>
+                    </el-scrollbar>
+                  </el-card>
+                </div>
+              </el-col>
+            </el-row>
+          </el-card>
+        </el-collapse-item>
+      </el-collapse>
+
+      <h4 class="table-text">寮傚父鏁版嵁</h4>
+    </el-col>
+  </el-row>
+  <el-card class="table-page" v-show="!isNoData">
+    <el-table
+      ref="tableH"
+      size="small"
+      v-loading="loading"
+      :data="displayData"
+      style="width: 100%"
+      border
+      :height="tableHeight"
+      :cell-class-name="tableCellClassName"
+    >
+      <el-table-column prop="diName" label="搴楅摵鍚嶇О" align="center">
+        <template #default="{ row }">
+          <el-tooltip effect="dark" :content="row.diName">
+            <div class="cell ellipsis">{{ row.diName }}</div>
+          </el-tooltip>
+        </template>
+      </el-table-column>
+
+      <el-table-column prop="devId" label="璁惧缂栧彿" align="center">
+        <template #default="{ row }">
+          <el-tooltip effect="dark" :content="row.devId">
+            <div class="cell ellipsis">{{ row.devId }}</div>
+          </el-tooltip>
+        </template>
+      </el-table-column>
+
+      <el-table-column prop="diSupplier" label="渚涘簲鍟�" align="center">
+        <template #default="{ row }">
+          <el-tooltip effect="dark" :content="row.diSupplier">
+            <div class="cell ellipsis">{{ row.diSupplier }}</div>
+          </el-tooltip>
+        </template>
+      </el-table-column>
+
+      <el-table-column prop="exception" label="寮傚父鍒嗙被" align="center">
+        <template #default="{ row }">
+          <el-tooltip effect="dark" :content="row.exception">
+            <div class="cell ellipsis">{{ row.exception }}</div>
+          </el-tooltip>
+        </template>
+      </el-table-column>
+      <el-table-column label="寮傚父绫诲瀷" align="center">
+        <template #default="{ row }">
+          <span v-if="row.exceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
+          <span v-else-if="row.exceptionType == '1'">鐤戜技渚涚數寮傚父</span>
+          <span v-else-if="row.exceptionType == '2'">鎺夌嚎</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="region" label="鍦板尯" align="center">
+        <template #default="{ row }">
+          <el-tooltip effect="dark" :content="row.region">
+            <div class="cell ellipsis">{{ row.region }}</div>
+          </el-tooltip>
+        </template>
+      </el-table-column>
+
+      <el-table-column prop="beginTime" label="寮�濮嬫椂闂�" align="center">
+        <template #default="{ row }">
+          <el-tooltip effect="dark" :content="row.beginTime">
+            <div class="cell ellipsis">{{ row.beginTime }}</div>
+          </el-tooltip>
+        </template>
+      </el-table-column>
+      <el-table-column prop="endTime" label="缁撴潫鏃堕棿" align="center">
+        <template #default="{ row }">
+          <el-tooltip effect="dark" :content="row.endTime">
+            <div class="cell ellipsis">{{ row.endTime }}</div>
+          </el-tooltip>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center">
+        <template #default="{ row }">
+          <el-button type="primary" class="table-button" @click="showDrawer(row)"
+            >鏌ョ湅璇︽儏</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <el-pagination
+      ref="h4"
+      background
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      :total="total"
+      :page-size="pageSize"
+      layout="total,prev, pager, next, jumper"
+    />
+  </el-card>
+  <el-empty v-show="isNoData" :image-size="200" />
+  <!-- 瀵硅瘽妗� -->
+  <div>
+    <el-dialog v-model="centerDialogVisible" draggable align-center>
+      <template #header>
+        <div style="font-size: 17px">
+          搴楅摵鍚嶏細{{ rowShopName }}
+          <span style="margin-left: 40px">寮傚父绫诲瀷锛�</span>
+          <span v-if="rowExceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
+          <span v-else-if="rowExceptionType == '1'">渚涚數寮傚父</span>
+          <span v-else-if="rowExceptionType == '2'">鎺夌嚎</span>
+          <div style="margin-top: 10px">
+            寮傚父鏃堕棿娈碉細{{ rowBeginTime }} ~
+            {{ rowEndTime }}
+          </div>
+        </div>
+
+        <div class="dialog-button-position">
+          <el-button
+            type="danger"
+            :loading="button.preButton"
+            :disabled="isPreCantouch || banTouch"
+            @click="getPreviousRowData"
+            >涓婃潯寮傚父</el-button
+          >
+          <el-button
+            type="danger"
+            :loading="button.afterButton"
+            :disabled="isNextCantouch || banTouch"
+            @click="getNextRowData"
+            >涓嬫潯寮傚父</el-button
+          >
+        </div>
+      </template>
+
+      <!-- 瓒呮爣鏁版嵁鏃� -->
+      <!-- 鎶樼嚎鍥� -->
+
+      <!-- 鎺夌嚎 -->
+      <!-- <div
+          ref="ref"
+          v-show="isOfflineShow"
+          style="
+            width: 100%;
+            height: 300px;
+            /* min-width: 100px; */
+            margin-bottom: 20px;
+            margin-left: 10px;
+            min-width: 350px;
+          "
+        ></div> -->
+
+      <ExceptionTypeLineChart
+        :option="option"
+        :is-open-dialog="centerDialogVisible"
+        v-loading="chartLoading"
+      ></ExceptionTypeLineChart>
+
+      <!--  -->
+      <div style="margin-top: 40px; margin-bottom: 5px; border: 1px">
+        <el-table :data="exceedingData" height="360" border style="margin-top: 25px">
+          <el-table-column
+            type="index"
+            label="搴忓彿"
+            width="60px"
+            align="center"
+            fixed
+            :index="indexMethod"
+          ></el-table-column>
+          <el-table-column fixed prop="diName" label="搴楅摵鍚嶇О" show-overflow-tooltip />
+          <el-table-column
+            prop="mvStatCode"
+            label="璁惧缂栧彿"
+            align="center"
+            show-overflow-tooltip
+          />
+          <el-table-column prop="diSupplier" label="渚涘簲鍟�" align="center" show-overflow-tooltip />
+          <el-table-column
+            prop="mvDataTime"
+            label="閲囬泦鏃堕棿"
+            align="center"
+            show-overflow-tooltip
+          />
+
+          <el-table-column
+            prop="mvFumeConcentration2"
+            label="娌圭儫娴撳害(mg/m鲁)"
+            align="center"
+            show-overflow-tooltip
+          />
+        </el-table>
+      </div>
+
+      <el-tag type="success" class="mx-1" effect="dark" round
+        ><span class="table-line-lable" v-show="rowExceptionType == '0'">寮傚父璁板綍锛� </span>
+        <span v-show="rowExceptionType == '1' || rowExceptionType == '2'">缂哄け鏁版嵁锛�</span>
+        <span class="table-line-num">{{ exceptionTotal }}鏉�</span>
+        <span v-show="rowExceptionType === '1' || rowExceptionType === '2'"> (閫昏緫璁$畻)</span>
+      </el-tag>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { defineAsyncComponent } from 'vue'
+import ExceptionType from '@/sfc/ExceptionType.vue'
+import TimeSelect from '@/sfc/TimeSelect.vue'
+import ExceptionText from '@/sfc/ExceptionText.vue'
+
+import * as XLSX from 'xlsx/xlsx.mjs'
+import dayjs from 'dayjs'
+import axiosInstanceInstance from '@/utils/request.js'
+
+const ShopNameAndID = defineAsyncComponent(() => import('@/sfc/ShopNameAndID.vue'))
+
+//  寮傚父鍥惧舰寮傛缁勪欢
+const ExceptionTypeLineChart = defineAsyncComponent(
+  () => import('@/sfc/ExceptionTypeLineChart.vue'),
+)
+export default {
+  name: 'TablePage',
+  components: {
+    ExceptionType,
+    TimeSelect,
+    ShopNameAndID,
+    ExceptionText,
+    ExceptionTypeLineChart,
+  },
+  data() {
+    return {
+      exception0Num: 0,
+      exception1Num: 0,
+      exception2Num: 0,
+      // 鎶樼嚎鍥惧姞杞戒腑
+      chartLoading: false,
+      button: {
+        // 鏌ヨ鎸夐挳
+        queryButton: false,
+        // 涓婁竴鏉℃寜閽�
+        preButton: false,
+        // 涓嬩竴鏉℃寜閽�
+        afterButton: false,
+        //
+        banTouch: 0,
+      },
+      // 寮傚父鎶樼嚎鍥剧殑閰嶇疆
+      option: {},
+      // 鎶樼嚎鍥惧睍绀�
+      isChartShow: false,
+      // table鍏冪礌
+      tableRef: null,
+      // 寮傚父琛ㄦ牸鏁版嵁
+      tableHeight: 300,
+      // 绌烘暟鎹姸鎬�
+      isNoData: false,
+      // 寮瑰嚭妗嗕腑琛ㄦ牸鏉℃暟
+      exceptionTotal: 0,
+      // 鏃犳暟鎹椂鐨勬椂闂存暟缁勶紝鍏冪礌鐩稿樊10鍒嗛挓
+      // abnormalTimeTenMinute: [],
+      // 搴楅摵鎬绘暟
+      shopsTotal: 0,
+
+      // 鈥欎笂涓�鏉♀�樻寜閽槸鍚﹀彲浠ヨ鐐瑰嚮鐘舵��
+      isPreCantouch: false,
+      // 鈥欎笅涓�鏉♀�樻寜閽槸鍚﹀彲浠ヨ鐐瑰嚮鐘舵��
+      isNextCantouch: false,
+
+      // 瀵硅瘽妗嗘槸鍚﹀睍绀�
+      centerDialogVisible: false,
+
+      // 鎶藉眽澶撮儴淇℃伅
+      // 鎶樼嚎鍥惧搴旂殑褰撳墠琛ㄦ牸琛屾暟鎹�
+      // 搴楅摵鍚�
+      rowShopName: '',
+      // 寮傚父绫诲瀷
+      rowExceptionType: '',
+      // 寮傚父寮�濮嬫椂闂�
+      rowBeginTime: '',
+      // 寮傚父缁撴潫鏃堕棿
+      rowEndTime: '',
+      // 寮傚父鐨勮澶囩紪鍙�
+      rowMvStatCode: '',
+      // 渚涘簲鍟�
+      rowDiSupplier: '',
+      // 琛ㄦ牸鐨勪竴琛屾暟鎹�
+      rowTable: [],
+      //鎷兼帴鐨勬墍鏈夋暟鎹�
+      allExceptionTimeData: [],
+      // 鏃犳暟鎹椂澧炲姞鐨勫墠30鍒嗛挓鏁版嵁
+      beforeData: [],
+      // 鏃犳暟鎹椂澧炲姞鐨勫悗40鍒嗛挓鏁版嵁
+      afterData: [],
+
+      // -1琛ㄧず鏈�夋嫨琛ㄦ牸鐨勮
+      selectedRowIndex: -1,
+
+      // 榛樿閫夋嫨鐨勬姌鍙犻潰鏉跨紪鍙�
+      activeNames: ['1'],
+      // 寮傚父鏃剁殑琛ㄦ牸
+      abnormalTb: [],
+      // 寮傚父鐨勮捣姝㈡椂闂�
+      abnormalBt: '',
+      abnormalEt: '',
+      // 鏄惁灞曠ず鏃堕棿杞�  鍚�
+      isAbnormal: false,
+      // 淇濆瓨鐫�寮傚父绫诲瀷0瀵瑰簲鐨勫簵閾哄悕绉板拰璁惧缂栧彿
+      exception0: [],
+      // 淇濆瓨鐫�寮傚父绫诲瀷1瀵瑰簲鐨勫簵閾哄悕绉板拰璁惧缂栧彿
+      exception1: [],
+      // 淇濆瓨鐫�寮傚父绫诲瀷2瀵瑰簲鐨勫簵閾哄悕绉板拰璁惧缂栧彿
+      exception2: [],
+      // 鍔犺浇鍔ㄧ敾
+      loading: false,
+      // 鎶藉眽鍔犺浇鍔ㄧ敾
+      loadingDrawer: true,
+      // 鍒嗛〉灞曠ず鏁版嵁
+
+      // 寮傚父琛ㄧ殑鏁版嵁
+      displayData: [],
+      // 瀛樻斁鍚庣杩斿洖鐨刯son鏁版嵁
+      jsonData: [],
+      // 鍒嗛〉鐨勮捣濮嬬储寮�
+      startIndex: 0,
+      // 褰撳墠椤�
+      currentPage: 1,
+      // 姣忛〉鏉℃暟
+      pageSize: 10,
+      total: 0,
+      // 閫夋嫨搴楅摵鍚�
+      deviceId: [],
+      deviceInfo: [],
+      // 鏃堕棿閫夋嫨鍣ㄥ紑濮嬫椂闂�
+      beginTime: '',
+      // 鏃堕棿閫夋嫨鍣ㄧ粨鏉熸椂闂�
+      endTime: '',
+      // 寮傚父琛ㄦ暟鎹�
+      abnormalData: [],
+      // 寮瑰嚭鐨勫璇濇涓殑寮傚父琛ㄦ牸鏁版嵁
+      exceedingData: [],
+      drawerVisible: false,
+      // 琛ㄦ牸鐨勪竴琛屾暟鎹�
+      drawerData: {},
+      // 鎶藉眽鏂瑰悜锛屼粠鍙冲悜宸︽墦寮�
+      drawerDirection: 'rtl',
+      optionsTime: [
+        // 鏃堕棿棰楃矑搴�
+        {
+          value: '10',
+          label: '10鍒嗛挓鏁版嵁',
+          disabled: true,
+        },
+      ],
+      // 搴楅摵鍚� 绾ц仈閫夋嫨鍣�
+      optionsShop: [],
+      // 寮傚父绫诲瀷閫夋嫨鍣�
+      exceptionValue: [],
+    }
+  },
+  // 鐩戝惉  鍒ゆ柇鎸夐挳鏄惁鍙偣鍑�
+  watch: {
+    selectedRowIndex(newVaue) {
+      // 澶勪簬琛ㄦ牸鐨勬渶鍚庝竴鏉℃暟鎹� 璁剧疆鈥樹笂涓�鏉♀�欐寜閽笉鍙偣
+      if (newVaue === this.displayData.length - 1) {
+        this.isPreCantouch = true
+        //鐢ㄦ埛鍏堢偣浜嗙涓�鏉★紝pre涓簍rue,鐒跺悗鐐瑰嚮鏈�鍚庝竴鏉�,next涓簍rue銆傛鏃朵袱涓寜閽兘琚皝閿�
+        if (this.isNextCantouch == true) {
+          this.isNextCantouch = false
+        }
+      }
+      // 澶勪簬琛ㄦ牸绗竴鏉℃暟鎹� 璁剧疆鈥樹笅涓�鏉♀�欐寜閽笉鍙偣
+      else if (newVaue === 0) {
+        this.isNextCantouch = true
+        //鐢ㄦ埛鍏堢偣浜嗚〃鏍兼渶鍚庝竴鏉�,next涓簍rue,鐒跺悗鐐瑰嚮绗竴鏉★紝pre涓簍rue銆傛鏃朵袱涓寜閽兘琚皝閿�
+        if (this.isPreCantouch == true) {
+          this.isPreCantouch = false
+        }
+      }
+      // 澶勪簬琛ㄦ牸鐨勪腑闂磋 灏嗘寜閽缃负鍙偣鍑荤姸鎬�
+      else {
+        this.isPreCantouch = false
+        this.isNextCantouch = false
+      }
+    },
+
+    // 褰撻�夋嫨鐨勬椂闂村彂鐢熷彉鍖栨椂锛屽紓甯稿垎鏋愰儴鍒嗙殑寮傚父搴楅摵鏁伴噺鍚屾鍙樺寲
+    beginTime() {
+      this.getShopNames()
+    },
+    endTime() {
+      this.getShopNames()
+    },
+    centerDialogVisible() {
+      window.addEventListener('resize', this.updateChart)
+    },
+  },
+  computed: {
+    exceptionAllNum() {
+      let sum = this.exception0Num + this.exception1Num + this.exception2Num
+      return sum == 0 ? 1 : sum
+    },
+    connectException() {
+      let sum = this.exception0Num + this.exception1Num + this.exception2Num
+      if (sum == 0) {
+        return 0
+      } else {
+        return (100 - (this.exception0Num / sum) * 100 - (this.exception1Num / sum) * 100).toFixed(
+          1,
+        )
+      }
+    },
+  },
+  mounted() {
+    // 浠庢帴鍙h幏鍙栧簵閾哄悕绉� 缁欑骇鑱斾笅鎷夋
+    this.getDeviceInfo()
+    // 灞曠ず鏈�杩�7澶╂暟鎹�
+    this.getRecentSevenDays()
+    // 鏍规嵁寮傚父绫诲瀷杩斿洖搴楅摵鍚嶇О鍜岃澶囩紪鍙� 娓叉煋寮傚父鍒嗘瀽閮ㄥ垎瀵瑰簲鐨勫簵閾哄悕
+    this.getShopNames()
+    this.calcTableHeight()
+    window.addEventListener('resize', this.updateChart)
+  },
+  methods: {
+    // 鍔熻兘锛氬璇濇琛ㄦ牸搴忓彿閫掑
+    // 鏃堕棿锛�2023-8-17
+    indexMethod(index) {
+      return index + 1
+    },
+
+    // 鍔熻兘锛氭敼鍙樿〃鏍兼煇涓崟鍏冩牸鐨勯鑹�
+    tableCellClassName({ row, column, rowIndex, columnIndex }) {
+      if (columnIndex == 4) {
+        if (row.exceptionType == '0') {
+          return 'exceeding-row'
+        } else if (row.exceptionType == '1') {
+          return 'abnormal-power-supply'
+        } else if (row.exceptionType == '2') {
+          return 'disconnect'
+        }
+      }
+    },
+
+    //鍔熻兘锛� 鍔ㄦ�佽绠楄〃鏍奸珮搴�
+    calcTableHeight() {
+      const h1 = this.$refs.h1.$el.offsetHeight
+      const h2 = this.$refs.h4.$el.offsetHeight
+      this.tableHeight = `calc(100vh - ${h1}px - ${h2}px - 45px - var(--el-main-padding) * 2 - var(--el-card-padding))`
+    },
+
+    //鍔熻兘锛� 鏃堕棿鏄惁瓒呰繃10鍒嗛挓
+    isTimeDifferenceGreaterThan10Minutes(dateString1, dateString2) {
+      const date1 = new Date(dateString1)
+      const date2 = new Date(dateString2)
+
+      // 璁$畻涓や釜鏃ユ湡鐨勬椂闂村樊锛堟绉掞級
+      const timeDifferenceMs = Math.abs(date1 - date2)
+
+      // 杞崲涓哄垎閽�
+      const timeDifferenceMinutes = Math.floor(timeDifferenceMs / (1000 * 60))
+
+      // 鍒ゆ柇鏃堕棿宸槸鍚﹀ぇ浜�10鍒嗛挓
+      return timeDifferenceMinutes > 10
+    },
+
+    // 浠�10鍒嗛挓涓洪棿闅旇繑鍥炴椂闂村瓧绗︿覆鏁扮粍
+    generateTimePoints(timePoints, yAxisData) {
+      let updatedTimePoints = []
+      let yAxisDataAdressed = []
+      for (let i = 0; i < timePoints.length; i++) {
+        updatedTimePoints.push(timePoints[i])
+        yAxisDataAdressed.push(yAxisData[i])
+        if (i < timePoints.length - 1) {
+          let current = timePoints[i]
+          let next = timePoints[i + 1]
+          while (this.isTimeDifferenceGreaterThan10Minutes(current, next)) {
+            current = dayjs(current).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+            updatedTimePoints.push(current)
+            yAxisDataAdressed.push(null)
+          }
+        }
+      }
+      let obj = {}
+      obj['time'] = updatedTimePoints
+      obj['data'] = yAxisDataAdressed
+      return obj
+    },
+
+    isExceedOneMonth(dateStr1, dateStr2) {
+      // 瓒呰繃涓�涓湀锛岃繑鍥濼rue锛屽惁鍒欒繑鍥濬alse
+      // 灏嗘棩鏈熷瓧绗︿覆杞负鏃ユ湡瀵硅薄
+      const date1 = new Date(dateStr1)
+      const date2 = new Date(dateStr2)
+
+      // 鑾峰彇涓や釜鏃ユ湡鐨勫勾銆佹湀銆佹棩
+      const year1 = date1.getFullYear()
+      const month1 = date1.getMonth()
+      const day1 = date1.getDate()
+
+      const year2 = date2.getFullYear()
+      const month2 = date2.getMonth()
+      const day2 = date2.getDate()
+
+      // 鍒ゆ柇涓や釜鏃ユ湡鏄惁鐩稿樊涓�涓湀
+      if (year1 === year2) {
+        // 骞翠唤鐩哥瓑锛屾瘮杈冩湀浠藉樊鍊�
+        if (Math.abs(month1 - month2) === 1) {
+          // 鏈堜唤宸�间负1锛岃繕闇�瑕佸垽鏂叿浣撴棩鏈�
+          if ((month1 < month2 && day1 < day2) || (month1 > month2 && day1 > day2)) {
+            return true
+          }
+        }
+      } else if (Math.abs(year1 - year2) === 1) {
+        // 骞翠唤宸�间负1锛屾瘮杈冩湀浠藉拰鏃ユ湡
+        if (
+          (year1 < year2 && month1 === 11 && month2 === 0 && day1 < day2) ||
+          (year1 > year2 && month1 === 0 && month2 === 11 && day1 > day2)
+        ) {
+          return true
+        }
+      }
+
+      // 榛樿杩斿洖false锛岃〃绀轰袱涓棩鏈熷瓧绗︿覆涓嶇浉宸竴涓湀
+      return false
+    },
+
+    // 鍒氭墦寮�鍗$墖鏃剁涓�涓浘褰笉浼氳嚜鍔ㄤ几缂� 褰撶偣鍑讳笂/涓嬩竴鏉℃椂浼氳嚜鍔ㄤ几缂�
+    // 鍥惧舰鍝嶅簲寮忓彉鍖�
+    // updateChart() {
+    //   this.$nextTick(() => {
+    //     if (this.chart1) {
+    //       this.chart1.resize();
+    //     }
+    //     if (this.chart2) {
+    //       this.chart2.resize();
+    //     }
+    //   });
+    // },
+
+    // 浠庢椂闂撮�夋嫨鍣ㄧ粍浠舵嬁鍒板紑濮嬪拰缁撴潫鏃堕棿
+    giveTime(val) {
+      //灏嗕腑鍥芥爣鍑嗘椂闂磋浆涓烘寚瀹氭牸寮�(璇ョ粍浠惰繑鍥炵殑鏍囧噯鏃堕棿鐨勬牸寮忥紝鎵�浠ュ繀椤荤殑鍔犺繖涓嚱鏁�)
+      this.beginTime = dayjs(val[0]).format('YYYY-MM-DD HH:mm:ss')
+      this.endTime = dayjs(val[1]).format('YYYY-MM-DD HH:mm:ss')
+    },
+
+    // 鍙傛暟锛氬紓甯哥殑寮�濮嬪拰缁撴潫鏃堕棿銆傝繑鍥炴椂闂存暟缁勶紝浠庡紑濮嬫椂闂寸殑鍚�10鍒嗛挓鍒扮粨鏉熸椂闂翠负姝€��
+    // 姣斿12:00:00-13:00:00 鎵�浠ヨ繑鍥炵殑鏁扮粍鍏冪礌鏄� 12:10:00 ,12:20:00,12:30:00....13:00:00
+    descTenTime(begin, end) {
+      let time = []
+      if (begin == end) {
+        time.push(begin)
+        return time
+      }
+      // 淇濈暀缁撴灉 00 10 20 30
+      let temp = dayjs(begin).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+      while (temp != end) {
+        time.push(temp)
+        temp = dayjs(temp).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+      }
+      // 鍔犱笂寮傚父鐨勭粨鏉熸椂闂�
+      time.push(temp)
+      return time
+    },
+
+    // 淇濆瓨褰撳墠閫夋嫨鐨勮鎵�鏈変俊鎭�
+    setinfo(index) {
+      this.rowShopName = this.displayData[index].diName
+      this.rowExceptionType = this.displayData[index].exceptionType
+      this.rowBeginTime = this.displayData[index].beginTime
+      this.rowEndTime = this.displayData[index].endTime
+      this.rowMvStatCode = this.displayData[index].devId
+      this.rowDiSupplier = this.displayData[index].diSupplier
+    },
+
+    //鍔熻兘锛� 渚涚數寮傚父鍜屾帀绾挎椂鐨勮〃鏍兼暟鎹�
+    setExceptionData() {
+      // 鏃犳暟鎹椂鐨勬椂闂存暟缁� 鏃堕棿鐩稿樊10鍒嗛挓
+      const abnormalTimeTenMinute = this.descTenTime(this.rowBeginTime, this.rowEndTime)
+      // 鍘婚櫎渚涚數寮傚父鍜屾帀绾垮尯闂寸殑绗竴涓湁鍏冪礌鐨勫��
+      this.exceedingData = []
+
+      for (let i = 0; i < abnormalTimeTenMinute.length; i++) {
+        this.exceedingData.push({
+          mvStatCode: this.rowMvStatCode,
+          diName: this.rowShopName,
+          diSupplier: this.rowDiSupplier,
+          mvDataTime: abnormalTimeTenMinute[i],
+          mvFumeConcentration2: '',
+        })
+      }
+
+      // 淇濆瓨鏃犳暟鎹椂琛ㄦ牸鏉℃暟
+      this.exceptionTotal = abnormalTimeTenMinute.length
+    },
+    // 鐐瑰嚮琛ㄦ牸鐨勮鏃�
+    selectTableRow(row) {
+      // 鑾峰彇褰撳墠琛岀殑绱㈠紩
+      this.selectedRowIndex = this.displayData.indexOf(row)
+      // 杩涘叆鎶藉眽椤甸潰鏇存柊澶撮儴鏁版嵁
+      this.setinfo(this.selectedRowIndex)
+    },
+
+    // 鑾峰彇鑾峰彇琛ㄦ牸涓嬩竴琛屾暟鎹�
+    getNextRowData() {
+      // 涓嶆槸琛ㄦ牸鐨勭涓�琛�
+      if (this.selectedRowIndex !== 0) {
+        // 鐐瑰嚮杩囩▼涓� 閿佷綇涓婁笅鏉℃寜閽�  鍦ㄨ缃畬鍥惧舰閰嶇疆椤瑰悗瑙i攣
+        this.banTouch = 1
+
+        //寰楀埌涓婁竴琛屾暟鎹储寮�
+        this.selectedRowIndex = this.selectedRowIndex - 1
+        //璇锋眰鏁版嵁 鏀瑰彉exceedingData
+        this.setinfo(this.selectedRowIndex)
+        let params = {}
+        if (this.drawerData.devId) {
+          params['devId'] = this.displayData[this.selectedRowIndex].devId
+        }
+        if (this.drawerData.beginTime) {
+          params['beginTime'] = this.displayData[this.selectedRowIndex].beginTime
+        }
+        if (this.drawerData.endTime) {
+          params['endTime'] = this.displayData[this.selectedRowIndex].endTime
+        }
+        this.button.afterButton = true
+        axiosInstanceInstance.get('/fume/exceed', { params: params }).then((response) => {
+          // 淇濆瓨杩斿洖鐨勮秴鏍囨暟鎹�
+          this.exceedingData = response.data.data
+          this.drawChartTest()
+          this.exceptionTotal = this.exceedingData.length
+          this.button.afterButton = false
+        })
+      }
+    },
+
+    // 鑾峰彇鑾峰彇琛ㄦ牸涓嬩竴琛屾暟鎹�
+    getPreviousRowData() {
+      // 涓嶆槸琛ㄦ牸鐨勭涓�琛�
+      if (this.selectedRowIndex < this.displayData.length - 1) {
+        // 鐐瑰嚮杩囩▼涓� 閿佷綇涓婁笅鏉℃寜閽�  鍦ㄨ缃畬鍥惧舰閰嶇疆椤瑰悗瑙i攣
+        this.banTouch = 1
+
+        //寰楀埌涓婁竴琛屾暟鎹储寮�
+        this.selectedRowIndex = this.selectedRowIndex + 1
+
+        //璇锋眰鏁版嵁 鏀瑰彉exceedingData
+        this.setinfo(this.selectedRowIndex)
+        let params = {}
+        if (this.drawerData.devId) {
+          params['devId'] = this.displayData[this.selectedRowIndex].devId
+        }
+        if (this.drawerData.beginTime) {
+          params['beginTime'] = this.displayData[this.selectedRowIndex].beginTime
+        }
+        if (this.drawerData.endTime) {
+          params['endTime'] = this.displayData[this.selectedRowIndex].endTime
+        }
+        this.button.preButton = true
+        axiosInstanceInstance.get('/fume/exceed', { params: params }).then((response) => {
+          // 淇濆瓨杩斿洖鐨勮秴鏍囨暟鎹�
+          this.exceedingData = response.data.data
+          this.drawChartTest()
+          this.exceptionTotal = this.exceedingData.length
+          this.button.preButton = false
+        })
+      }
+    },
+
+    // 鈥樻煡鐪嬭鎯呪�� 寮瑰嚭妗嗛儴鍒�
+    showDrawer(row) {
+      // 璁$畻褰撳墠琛岀殑绱㈠紩
+      this.selectTableRow(row)
+
+      this.rowTable = row
+
+      // 琛ㄦ牸鐨勮鏁版嵁浠ュ璞″舰寮忕粰drawerData
+      this.drawerData = row
+
+      this.centerDialogVisible = true
+
+      // 鏍规嵁琛屾暟鎹姹傝缁嗚秴鏍囨暟鎹覆鏌撴姌绾垮浘
+      let params = {}
+      if (this.drawerData.devId) {
+        params['devId'] = this.drawerData.devId
+      }
+      if (this.drawerData.beginTime) {
+        params['beginTime'] = this.drawerData.beginTime
+      }
+      if (this.drawerData.endTime) {
+        params['endTime'] = this.drawerData.endTime
+      }
+
+      axiosInstanceInstance.get('/fume/exceed', { params: params }).then((response) => {
+        // 淇濆瓨杩斿洖鐨勮秴鏍囨暟鎹�
+        this.exceedingData = response.data.data
+        this.drawChartTest()
+        this.exceptionTotal = this.exceedingData.length
+      })
+    },
+
+    // 鐢ㄦ埛鏍规嵁杈撳叆鐨勬潯浠舵煡璇�
+    showTable() {
+      if (this.isExceedOneMonth(this.beginTime, this.endTime)) {
+        alert('鏃堕棿璺ㄥ害涓嶈兘瓒呰繃涓�涓湀')
+        return
+      }
+      let params = {}
+
+      if (this.deviceId[1]) {
+        params['devId'] = this.deviceId[1]
+      }
+      if (this.exceptionValue.length != 0) {
+        params['exceptionValue'] = this.exceptionValue.join()
+      }
+
+      if (this.beginTime) {
+        params['beginTime'] = this.beginTime
+      }
+      if (this.endTime) {
+        params['endTime'] = this.endTime
+      }
+      this.loading = true
+      this.button.queryButton = true
+
+      axiosInstanceInstance.get('/fume/abnormalthree', { params: params }).then((response) => {
+        this.abnormalData = response.data.data
+        this.total = this.abnormalData.length
+        this.loading = false
+        this.button.queryButton = false
+        if (response.data.data.length == 0) {
+          ElMessage('璇ユ椂娈垫棤鏁版嵁')
+          this.isNoData = true
+          return
+        }
+        // 绉婚櫎绌烘暟鎹姸鎬�
+        this.isNoData = false
+        this.handleCurrentChange(1)
+      })
+    },
+    handleSizeChange(val) {
+      this.pageSize = val
+      // 鏀瑰彉姣忛〉鏄剧ず鏁扮洰鏃惰烦鍒扮涓�椤�
+      this.handleCurrentChange(1)
+    },
+    handleCurrentChange(val) {
+      const startIndex = (val - 1) * this.pageSize
+      const endIndex = startIndex + this.pageSize
+
+      this.displayData = this.abnormalData.slice(startIndex, endIndex)
+    },
+
+    //鐩稿樊澶氬皯涓崄鍒嗛挓  璁$畻涓苟涓嶅寘鎷紑濮嬫椂闂达紝浣嗗寘鎷粨鏉熸椂闂淬��
+    diffTenMinutesNum(beginNormal, endNormal) {
+      // 灏嗗紑濮嬫椂闂村拰缁撴潫鏃堕棿杞崲涓篸ayjs瀵硅薄
+      const start = dayjs(beginNormal)
+      const end = dayjs(endNormal)
+
+      // 璁$畻缁撴潫鏃堕棿鍑忓幓寮�濮嬫椂闂翠腑闂寸浉宸灏戜釜鍗佸垎閽�
+      const diffInMinutes = end.diff(start, 'minute')
+      const diffInTenMinutes = Math.floor(diffInMinutes / 10)
+      return diffInTenMinutes
+    },
+
+    // 鍙傛暟锛氬紓甯哥殑寮�濮嬫椂闂达紝寮傚父鐨勭粨鏉熸椂闂淬��
+    // 鍔熻兘锛氳繑鍥炲紑濮嬫椂闂寸殑鍓�30鍒嗛挓鐨勬椂闂寸偣锛岀粨鏉熸椂闂村悗40鍒嗛挓鐨勬椂闂寸偣
+    before30AndAfter40(begin, end) {
+      let time = []
+      const before30MinBegin = dayjs(begin).subtract(30, 'minute').format('YYYY-MM-DD HH:mm:ss')
+      // 鍚庝竴娈电殑寮�濮嬫椂闂�
+      const after10MinBegin = dayjs(end).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+      // 寰�鍚�40鍒嗛挓
+      const after40MinEnd = dayjs(end).add(40, 'minute').format('YYYY-MM-DD HH:mm:ss')
+      time.push(before30MinBegin)
+      time.push(after10MinBegin)
+      time.push(after40MinEnd)
+      return time
+    },
+
+    // 鍙傛暟锛氳澶囩紪鍙凤紝 寮�濮嬫椂闂达紝 缁撴潫鏃堕棿
+    // 鍔熻兘锛氳繑鍥炴煇璁惧鍦ㄨ鏃舵鍘嗗彶鏁版嵁鐨刧et璇锋眰鍙傛暟銆�
+    requestGetParms(devnum, begin, end) {
+      return {
+        devId: devnum,
+        beginTime: begin,
+        endTime: end,
+      }
+    },
+    // 鍙傛暟锛氬璞℃暟缁�(璇ュ璞′腑鐨勫睘鎬т笉鑳芥槸寮曠敤绫诲瀷锛屽惁鍒欐嫹璐濈殑鍊艰繕鏄細鐩镐簰褰卞搷)
+    // 鍔熻兘锛氭嫹璐濊瀵硅薄鏁扮粍銆�
+    shallowCopyList(itemIsObjOfList) {
+      let tempList = []
+      itemIsObjOfList.forEach((item) => {
+        tempList.push({ ...item })
+      })
+      return tempList
+    },
+
+    // 鍙傛暟锛氭坊鍔犻灏炬椂闂存暟鎹殑寮傚父鏁版嵁鏁扮粍(鍏冪礌涓哄璞�)
+    // 鍔熻兘锛氬涓棿寮傚父鍖洪棿鏃堕棿鍜屽�艰繘琛岃ˉ鍏咃紝杩斿洖澶勭悊鍚庣殑缁撴灉
+    // 璇︾粏鎻忚堪锛氶亶鍘嗘暟缁勶紝褰撳彂鐜版暟缁勫厓绱犱负绌烘椂锛岃缃鍏冪礌鐨勬椂闂翠负涓婁竴涓厓绱犳椂闂寸殑鍚�10鍒嗛挓锛屽苟鎶婃祿搴﹀�艰缃负null(涓婁釜鍏冪礌鐨勬椂闂翠竴瀹氫笉涓虹┖锛屾棤闇�鍐嶅幓鍒ゆ柇涓婁釜鍏冪礌涓虹┖鐨勬儏鍐�)銆�
+    addTenMinutes(exceptionDataArr) {
+      // x杞� 鏃ユ湡鏃堕棿
+      let dateList = []
+      // y杞� 瓒呮爣娌圭儫娴撳害
+      let fumeExceeding = []
+      let obj = {}
+      for (let i = 0; i < exceptionDataArr.length; i++) {
+        if (exceptionDataArr[i] == null) {
+          //x杞存棩鏈熴�傚厓绱犱负null鏃讹紝 璁剧疆璇ュ厓绱犵殑鏃堕棿涓哄墠涓�鍏冪礌鐨勬椂闂村悗10鍒嗛挓
+          dateList.push(
+            dayjs(dateList[dateList.length - 1])
+              .add(10, 'minute')
+              .format('YYYY-MM-DD HH:mm:ss'),
+          )
+          // 瓒呮爣娌圭儫娴撳害
+          fumeExceeding.push(null)
+        } else {
+          //x杞存棩鏈�
+          dateList.push(exceptionDataArr[i].mvDataTime)
+          // 瓒呮爣娌圭儫娴撳害
+          fumeExceeding.push(exceptionDataArr[i].mvFumeConcentration2)
+        }
+      }
+      obj['dateList'] = dateList
+      obj['fumeExceeding'] = fumeExceeding
+      return obj
+    },
+
+    // 鍙傛暟锛氬姞涓婂墠鍚庡尯闂寸殑寮傚父鏁版嵁锛屾椂闂村瓧绗︿覆
+    // 鍔熻兘锛氬垽鏂璬ata涓槸鍚︽湁璇ユ棩鏈熸椂闂达紝瀛樺湪杩斿洖璇ユ椂闂村搴旂殑娴撳害鍊硷紝鍚﹀垯杩斿洖-1
+    findTimeInExceptionData(data, time) {
+      for (let i = 0; i < data.length; i++) {
+        if (data[i] == null) {
+          continue
+        }
+        if (data[i]['mvDataTime'] == time) {
+          return data[i]['mvFumeConcentration2']
+        }
+      }
+      return -1
+    },
+    // 鍙傛暟:鍓嶅尯闂寸殑寮�濮嬫椂闂达紝 鍚庡尯闂寸殑缁撴潫鏃堕棿, 鍔犱笂鍓嶅悗鍖洪棿鐨勬�绘椂闂存鐨勫紓甯告暟鎹殑瀵硅薄鏁扮粍
+    // 鍔熻兘锛氭牴鎹紑濮嬪拰缁撴潫鏃堕棿,杩斿洖浠�10鍒嗛挓涓洪棿闅旂殑鏃堕棿鍜屽搴旂殑鍊�
+    keepContinuousByEachTenMinutes(intervalStarTime, intervalEndTime, headAndTailExceptionData) {
+      let xAxis = []
+      let yAxis = []
+      let obj = {}
+      let current = intervalStarTime
+      let tail = dayjs(intervalEndTime).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+      while (current != tail) {
+        let value = this.findTimeInExceptionData(headAndTailExceptionData, current)
+        if (value != -1) {
+          xAxis.push(current)
+          yAxis.push(value)
+        } else {
+          xAxis.push(current)
+          yAxis.push(null)
+        }
+        current = dayjs(current).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+      }
+      obj['xAxis'] = xAxis
+      obj['yAxis'] = yAxis
+      return obj
+    },
+
+    // 鍙傛暟锛氳秴鏍囨暟鎹墠闈㈠尯闂寸殑鏁版嵁
+    // 鍔熻兘锛氳繑鍥為櫎鍘绘渶鍚庝竴涓厓绱犵殑鏁扮粍
+    removeLastItemOfBeforeData(beforeDataOfExceeding) {
+      let tempList = []
+      if (beforeDataOfExceeding.length == 1) {
+        return tempList
+      } else {
+        for (let i = 0; i < beforeDataOfExceeding.length - 1; i++) {
+          tempList.push({ ...beforeDataOfExceeding[i] })
+        }
+        return tempList
+      }
+    },
+
+    // 璁剧疆option
+    // 鍙傛暟锛歺杞存椂闂达紝 y杞存补鐑熸祿搴︼紝 寮傚父绫诲埆(0浠h〃瓒呮爣锛�1浠h〃渚涚數寮傚父鍜屾帀绾�), 寮傚父寮�濮嬫椂闂达紝寮傚父缁撴潫鏃堕棿锛屽紓甯稿紑濮嬫椂闂村湪鏁翠釜鍖洪棿鐨勭储寮曚笅鏍囷紝寮傚父缁撴潫鏃堕棿鍦ㄦ暣涓尯闂寸殑绱㈠紩涓嬫爣
+    setOption(
+      xData,
+      yData,
+      exceptionCategory,
+      exceptionBeginTime,
+      exceptionEndTime,
+      beginIndex,
+      endIndex,
+    ) {
+      this.option = {}
+      // 瓒呮爣
+      if (exceptionCategory == 0) {
+        this.option = {
+          tooltip: {},
+          toolbox: {
+            // 宸ュ叿鏍�
+            feature: {
+              //     dataZoom: {
+              //   yAxisIndex: 'none'
+              // },
+              // 淇濆瓨涓哄浘鐗�
+              saveAsImage: {},
+            },
+          },
+          xAxis: {
+            type: 'category',
+            data: xData,
+            name: '鏃堕棿',
+            axisLabel: {
+              formatter: function (value) {
+                return value.slice(11, -3)
+              },
+            },
+          },
+          yAxis: {
+            type: 'value',
+            name: 'mg/m鲁',
+          },
+          series: [
+            {
+              name: '娌圭儫娴撳害',
+              type: 'line',
+              data: yData.map((item) => {
+                if (item >= 1) {
+                  return {
+                    value: item,
+                    itemStyle: {
+                      color: 'red',
+                    },
+                  }
+                }
+                return item
+              }),
+              // 鍙樻崲鎸囧畾鏃堕棿鍖洪棿鐨勮儗鏅鑹�
+              markArea: {
+                itemStyle: {
+                  color: 'rgba(255, 173, 177, 0.4)',
+                },
+                data: [
+                  [
+                    {
+                      name: '瓒呮爣鏃堕棿娈�',
+                      xAxis: exceptionBeginTime,
+                    },
+                    {
+                      xAxis: exceptionEndTime,
+                    },
+                  ],
+                ],
+              },
+              markLine: {
+                symbol: 'none',
+                itemStyle: {
+                  // 鍩虹嚎鍏叡鏍峰紡
+                  normal: {
+                    lineStyle: {
+                      type: 'dashed',
+                    },
+                    label: {
+                      show: true,
+                      position: 'end',
+                      formatter: '{b}',
+                    },
+                  },
+                },
+                data: [
+                  {
+                    name: '瓒呮爣',
+                    type: 'average',
+                    yAxis: 1,
+                    lineStyle: {
+                      // color: '#ff0000'
+                      color: 'red',
+                    },
+                  },
+                ],
+              },
+            },
+          ],
+          // 鎸囧畾鏃堕棿鍖洪棿鐨勭嚎娈靛彉棰滆壊
+          visualMap: {
+            show: false,
+            dimension: 0,
+            pieces: [
+              {
+                lte: beginIndex,
+                color: 'green',
+              },
+              {
+                gt: beginIndex,
+                lte: endIndex,
+                color: 'red',
+              },
+              {
+                gt: endIndex,
+                lte: xData.length - 1,
+                color: 'green',
+              },
+            ],
+          },
+        }
+      }
+      // 渚涚數寮傚父鍜屾帀绾�
+      else if (exceptionCategory == 1) {
+        this.option = {
+          tooltip: {},
+          toolbox: {
+            // 宸ュ叿鏍�
+            feature: {
+              // dataZoom: {
+              //   // 鍖哄煙缂╂斁
+              //   yAxisIndex: 'none'
+              // },
+              // 淇濆瓨涓哄浘鐗�
+              saveAsImage: {},
+            },
+          },
+          xAxis: {
+            type: 'category',
+            data: xData,
+            name: '鏃堕棿',
+            axisLabel: {
+              formatter: function (value) {
+                return value.slice(11, -3)
+              },
+            },
+          },
+          yAxis: {
+            type: 'value',
+            name: 'mg/m鲁',
+          },
+          series: [
+            {
+              name: '娌圭儫鏁版嵁',
+              type: 'line',
+              data: yData,
+              markLine: {
+                silent: true,
+                data: [
+                  // 鏍囨敞鏃犳暟鎹椂闂存鐨勬晥鏋滐紝灏嗚繖涓椂闂存鐨勬暟杞撮儴鍒嗗彉涓虹孩鑹�
+                  {
+                    name: '鏃犳暟鎹�',
+                    xAxis: exceptionBeginTime,
+                  },
+                  {
+                    xAxis: exceptionEndTime,
+                  },
+                ],
+                lineStyle: {
+                  color: 'red',
+                },
+              },
+            },
+          ],
+        }
+      }
+      this.banTouch = 0
+    },
+
+    // 鍔熻兘锛氱偣鍑� 鈥樻煡鐪嬭鎯呪�欙紝 鈥樹笅涓�鏉♀�欐寜閽椂浼� 鍏堥�昏緫璁$畻銆傛渶鍚庡睍绀哄浘褰�
+    drawChartTest() {
+      this.beforeData = []
+      this.afterData = []
+      this.allExceptionTimeData = []
+      //寮傚父鐨勫紑濮嬫椂闂� 缁撴潫鏃堕棿
+      let exceptionBeginTime = this.rowBeginTime
+      let exceptionEndTime = this.rowEndTime
+
+      // beforeAndAfterTime[0]:鍓�30鍒嗛挓鐨勬椂闂寸偣
+      // beforeAndAfterTime[1]:鍚�10鍒嗛挓鐨勬椂闂寸偣
+      // beforeAndAfterTime[2]:鍚�40鍒嗛挓鐨勬椂闂寸偣
+      let beforeAndAfterTime = this.before30AndAfter40(exceptionBeginTime, exceptionEndTime)
+
+      // 鏋勯�犲紓甯告椂闂村墠鐨勫尯闂存暟鎹姹傚弬鏁�
+      let paramsBefore = this.requestGetParms(
+        this.displayData[this.selectedRowIndex].devId,
+        beforeAndAfterTime[0],
+        this.displayData[this.selectedRowIndex].beginTime,
+      )
+
+      // 鏋勯�犲紓甯告椂闂村悗鐨勫尯闂存暟鎹姹傚弬鏁�
+      let paramsAfter = this.requestGetParms(
+        this.displayData[this.selectedRowIndex].devId,
+        beforeAndAfterTime[1],
+        beforeAndAfterTime[2],
+      )
+
+      // 鎶樼嚎鍥惧姞杞戒腑鏁堟灉
+      this.chartLoading = true
+      // 璇锋眰鍓嶅崐娈�
+      axiosInstanceInstance.get('/fume/history', { params: paramsBefore }).then((result1) => {
+        this.beforeData = result1.data.data
+        // 璇锋眰鍚庡崐娈�
+        axiosInstanceInstance.get('/fume/history', { params: paramsAfter }).then((result2) => {
+          this.afterData = result2.data.data
+          //淇濆瓨寮傚父鍖洪棿鐨勫��
+          let tempArr = []
+          // 淇濆瓨寮傚父鍖洪棿鍓嶅悗鐨勫��
+          let before = []
+          let after = []
+
+          // 鍒ゆ柇鏄惁鏄緵鐢靛紓甯告垨鎺夌嚎
+          if (this.rowExceptionType === '1' || this.rowExceptionType === '2') {
+            // 閲嶆瀯琛ㄦ牸 缂哄け寮傚父鏁版嵁鑷姩濉厖
+            this.setExceptionData()
+
+            //鐩稿樊鍑犱釜10鍒嗛挓
+            const TenMinuteNum = this.diffTenMinutesNum(exceptionBeginTime, exceptionEndTime)
+            //鐢╪ull濉厖涓紓甯告棤鏁版嵁鐨勬椂闂�
+            for (let i = 0; i < TenMinuteNum; i++) {
+              tempArr.push(null)
+            }
+            before = this.shallowCopyList(this.beforeData)
+
+            after = this.shallowCopyList(this.afterData)
+            // after = this.afterData
+          }
+          // 瓒呮爣
+          else {
+            let beforeTemp = this.removeLastItemOfBeforeData(this.beforeData)
+            // 鍓嶅悗鍖洪棿鍙樉绀鸿窛绂昏秴鏍囧尯闂存椂闂存渶杩戠殑娴撳害灏忎簬1鐨勬椂闂寸偣
+            for (let i = beforeTemp.length - 1; i >= 0; i--) {
+              if (beforeTemp[i].mvFumeConcentration2 >= 1) {
+                break
+              }
+              if (beforeTemp[i].mvFumeConcentration2 < 1) {
+                before.unshift(this.beforeData[i])
+              }
+            }
+
+            for (let i = 0; i < this.afterData.length; i++) {
+              if (this.afterData[i].mvFumeConcentration2 >= 1) {
+                break
+              }
+              if (this.afterData[i].mvFumeConcentration2 < 1) {
+                after.unshift(this.afterData[i])
+              }
+            }
+            tempArr = this.shallowCopyList(this.exceedingData)
+          }
+
+          // 灏嗗墠鍚庡尯闂存暟鎹� 涓� 寮傚父鍖洪棿鏁版嵁 鍚堝苟
+          this.allExceptionTimeData = [...before, ...tempArr, ...after]
+          // x杞存棩鏈熸椂闂�
+          let dateList
+          // y杞� 瓒呮爣娌圭儫娴撳害
+          let fumeExceeding
+          let timeAndValue
+
+          // 浠庢坊鍔犱簡棣栦綅鍖洪棿鐨勫紑濮嬪拰缁撴潫鏃堕棿杩涜閬嶅巻 淇濊瘉鏃堕棿浠�10鍒嗛挓涓洪棿闅�
+          timeAndValue = this.keepContinuousByEachTenMinutes(
+            beforeAndAfterTime[0],
+            beforeAndAfterTime[2],
+            this.allExceptionTimeData,
+          )
+
+          dateList = timeAndValue['xAxis']
+          fumeExceeding = timeAndValue['yAxis']
+
+          // 鎻愬彇寮傚父璧峰鏃堕棿鐐瑰湪鏁翠釜鍖洪棿鍐呯殑鏁版嵁绱㈠紩
+          let startIndex = dateList.findIndex((item) => item === exceptionBeginTime)
+          let endIndex = dateList.findIndex((item) => item === exceptionEndTime)
+
+          // 渚涚數寮傚父鍜屾帀绾挎儏鍐� 瓒呮爣鎯呭喌
+          if (this.rowExceptionType === '1' || this.rowExceptionType === '2') {
+            this.setOption(
+              dateList,
+              fumeExceeding,
+              1,
+              exceptionBeginTime,
+              exceptionEndTime,
+              startIndex,
+              endIndex,
+            )
+          } else {
+            // 瓒呮爣鎯呭喌
+            this.setOption(
+              dateList,
+              fumeExceeding,
+              0,
+              exceptionBeginTime,
+              exceptionEndTime,
+              startIndex,
+              endIndex,
+            )
+          }
+          this.chartLoading = false
+        })
+      })
+    },
+
+    getDeviceInfo() {
+      // 绾ц仈涓嬫媺妗嗘暟鎹� 浠庢帴鍙d腑鍔ㄦ�佽幏鍙�
+      axiosInstanceInstance.get('/fume/device').then((result) => {
+        this.deviceInfo = result.data.data
+        // 鑾峰彇鍒版�荤殑搴楅摵鏁伴噺
+        this.shopsTotal = result.data.data.length
+        this.deviceInfo.forEach((item) => {
+          this.optionsShop[this.optionsShop.length] = {
+            value: item.diName,
+            label: item.diName,
+            children: [
+              {
+                value: item.diCode,
+                label: item.diCode,
+              },
+            ],
+          }
+        })
+      })
+    },
+    exportDom() {
+      // 瀵煎嚭涓篍xcel鏂囦欢
+      const fields = ['devId', 'exceptionType', 'region', 'beginTime', 'endTime']
+      const itemsFormatted = this.abnormalData.map((item) => {
+        const newItem = {}
+        fields.forEach((field) => {
+          newItem[field] = item[field]
+        })
+        return newItem
+      })
+      // 鍒涘缓xlsx瀵硅薄
+      const xls = XLSX.utils.json_to_sheet(itemsFormatted)
+      // 缂栬緫琛ㄥご琛�       淇敼琛ㄥご
+      xls['A1'].v = '璁惧缂栧彿'
+      xls['B1'].v = '寮傚父绫诲瀷'
+      xls['C1'].v = '鍦板尯'
+      xls['D1'].v = '寮�濮嬫椂闂�'
+      xls['E1'].v = '缁撴潫鏃堕棿'
+      // 鍒涘缓workbook锛屽苟鎶妔heet娣诲姞杩涘幓
+      const wb = XLSX.utils.book_new()
+      XLSX.utils.book_append_sheet(wb, xls, 'Sheet1')
+      // 灏唚orkbook杞负浜岃繘鍒秞lsx鏂囦欢骞朵笅杞�
+      XLSX.writeFile(wb, '鍒嗘瀽鏁版嵁.xlsx')
+    },
+
+    getAbnormalDataByClick(val) {
+      this.abnormalData = val
+      this.total = this.abnormalData.length
+      // 榛樿鏄剧ず绗竴椤�
+      this.handleCurrentChange(1)
+    },
+
+    // 鏍规嵁寮傚父绫诲瀷杩斿洖搴楅摵鍚嶇О鍜岃澶囩紪鍙�
+    // 姣斿娌圭儫瓒呮爣瀵瑰簲鐨勬墍鏈夊簵閾哄悕绉板拰璁惧缂栧彿锛堝凡鍘婚櫎閲嶅鐨勫簵閾哄悕锛�
+    getShopNames() {
+      axiosInstanceInstance
+        .get('/fume/shopname', {
+          params: {
+            exceptionType: '0',
+            beginTime: this.beginTime,
+            endTime: this.endTime,
+          },
+        })
+        .then((result) => {
+          this.exception0 = result.data.data
+        })
+      axiosInstanceInstance
+        .get('/fume/shopname', {
+          params: {
+            exceptionType: '1',
+            beginTime: this.beginTime,
+            endTime: this.endTime,
+          },
+        })
+        .then((result) => {
+          this.exception1 = result.data.data
+        })
+      axiosInstanceInstance
+        .get('/fume/shopname', {
+          params: {
+            exceptionType: '2',
+            beginTime: this.beginTime,
+            endTime: this.endTime,
+          },
+        })
+        .then((result) => {
+          this.exception2 = result.data.data
+        })
+
+      /* 寮傚父鏁伴噺 */
+      axiosInstanceInstance
+        .get('/fume/exceptionnum', {
+          params: {
+            exceptionType: '0',
+            beginTime: this.beginTime,
+            endTime: this.endTime,
+          },
+        })
+        .then((result) => {
+          this.exception0Num = result.data.data
+        })
+      axiosInstanceInstance
+        .get('/fume/exceptionnum', {
+          params: {
+            exceptionType: '1',
+            beginTime: this.beginTime,
+            endTime: this.endTime,
+          },
+        })
+        .then((result) => {
+          this.exception1Num = result.data.data
+        })
+      axiosInstanceInstance
+        .get('/fume/exceptionnum', {
+          params: {
+            exceptionType: '2',
+            beginTime: this.beginTime,
+            endTime: this.endTime,
+          },
+        })
+        .then((result) => {
+          this.exception2Num = result.data.data
+        })
+    },
+
+    // 椤甸潰鍔犺浇鏃堕粯璁ゅ睍绀�7澶╁紓甯歌〃鏁版嵁
+    getRecentSevenDays() {
+      // 缁欑骇鑱旈�夋嫨鍣ㄨ缃粯璁ょ殑閫夋嫨椤�
+      this.devId = ['浠樺皬濮愬湪鎴愰兘', 'qinshi_31010320210010']
+      let params = {}
+      params['beginTime'] = this.beginTime
+      params['endTime'] = this.endTime
+      axiosInstanceInstance.get('/fume/abnormalthree', { params: params }).then((response) => {
+        if (response.data.data.length == 0) {
+          ElMessage('璇ユ椂娈垫棤鏁版嵁')
+          return
+        }
+        // 淇濆瓨杩斿洖鐨�
+        this.abnormalData = response.data.data
+        // 鍒嗛〉
+        this.total = this.abnormalData.length
+        // 榛樿鏄剧ず绗竴椤�
+        this.handleCurrentChange(1)
+        this.loading = false
+      })
+    },
+  },
+}
+</script>
+
+<style scoped>
+.header-container {
+  display: flex;
+  margin-left: 20px;
+  /* flex-wrap: wrap;
+    align-items: center; */
+}
+.ellipsis {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.iconExcel {
+  font-size: 25px;
+  margin-left: 20px;
+  bottom: -6px;
+}
+
+/* 鍙紶鏍囩澶村彉涓哄彲鐐瑰嚮鐘舵�� */
+.clickable {
+  cursor: pointer;
+}
+.card-header {
+  margin: 0;
+}
+
+body {
+  margin: 0;
+}
+.exception-divider-rowline {
+  margin: 10px 0px;
+}
+/* 寮傚父鍒嗘瀽鏁版嵁涓庢寜閽� */
+.exception-container {
+  display: flex;
+}
+.example-showcase .el-loading-mask {
+  z-index: 9;
+}
+
+.scrollbar-demo-item {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 20px;
+  margin: 10px;
+  text-align: center;
+  border-radius: 4px;
+  background: var(--el-color-primary-light-9);
+  color: var(--el-color-primary);
+}
+.collapse-header {
+  margin-left: 5px;
+  font-size: 18px;
+}
+.collapse-header-text {
+  margin-top: 5px;
+  font-size: 14px;
+  color: gray;
+}
+
+.box-card-label {
+  font-size: 14px;
+  white-space: nowrap;
+}
+
+.right-text {
+  /* float :right; */
+  /* text-align: right; */
+  margin-left: 80px;
+}
+:deep().el-card {
+  border-radius: 9px;
+}
+
+/* 鈥樻煡鐪嬭鎯呪�� 鐨勫脊鍑烘楂樺害璋冩暣 */
+:deep().el-dialog {
+  height: 98%;
+  /* 涓嶅嚭鐜版粴鍔ㄦ潯 */
+  overflow-y: hidden;
+  border-radius: 9px;
+}
+.table-page {
+  margin-left: 20px;
+}
+
+.table-text {
+  font-size: 18px;
+  margin: 5px 0px 10px 20px;
+}
+.text-blank {
+  margin-right: 10px;
+  color: #000000;
+}
+/* 搴楅摵鍚嶉�夋嫨鏂囨湰 */
+.describe-info {
+  margin-top: 5px;
+  font-weight: bold;
+  white-space: nowrap;
+}
+/* 鏃堕棿閫夋嫨鏂囨湰 */
+.describe-time-text {
+  margin-left: 30px;
+  margin-top: 5px;
+  font-weight: bold;
+}
+
+/* 寮傚父琛ㄦ牸涓嬫爣绛句腑鐨勬暟缁� */
+.table-line-num {
+  font-weight: bold;
+  color: black;
+}
+.button_info.el-button_inner {
+  text-align: left;
+}
+.el-collapse {
+  margin-left: 20px;
+}
+:deep().el-collapse .el-collapse-item__content {
+  padding-bottom: 0px;
+}
+.box-card {
+  height: 190px;
+}
+
+.sub-box-card {
+  height: 100px;
+  border: 0px;
+}
+
+.mx-1 {
+  margin-bottom: 0px;
+}
+.dialog-button-position {
+  display: flex;
+  justify-content: right;
+  margin-bottom: 10px;
+}
+
+:deep().el-table__row .exceeding-row {
+  background-color: #f53f3f;
+}
+:deep().el-table__row .abnormal-power-supply {
+  background-color: #fdf4bf;
+}
+:deep().el-table__row .disconnect {
+  background-color: #f7ba1e;
+}
+
+.el-table {
+  color: #000000;
+}
+
+/* 琛ㄦ牸涓殑鎸夐挳瀹藉害閾烘弧 */
+.table-button {
+  width: 100%;
+}
+</style>
diff --git a/src/views/monitor/DataHistory.vue b/src/views/monitor/DataHistory.vue
index ea6fadc..d1a9eee 100644
--- a/src/views/monitor/DataHistory.vue
+++ b/src/views/monitor/DataHistory.vue
@@ -1,6 +1,7 @@
 <!-- 鍘嗗彶鏁版嵁 -->
 <script>
 import { defineAsyncComponent } from 'vue'
+import { ElMessage } from 'element-plus'
 import * as XLSX from 'xlsx/xlsx.mjs'
 import dayjs from 'dayjs'
 import axiosInstanceInstance from '@/utils/request.js'
@@ -440,9 +441,8 @@
 <template>
   <!-- solid #000000 -->
   <div style="margin: 20px; padding: 10px; border: 1px; height: 620px">
-    <h1 style="margin-bottom: 20px; display: flex; white-space: nowrap">娌圭儫鍘嗗彶鏁版嵁</h1>
     <div style="display: flex">
-      <span class="palce-text"><span class="palce-text-area">鍖哄煙锛�</span>闈欏畨鍖� </span>
+      <!-- <span class="palce-text"><span class="palce-text-area">鍖哄煙锛�</span>闈欏畨鍖� </span> -->
 
       <!-- 搴楅摵鍚�  绾ц仈 -->
       <!-- <el-cascader v-model="devId" :options="optionsShop" :props="{ expandTrigger: 'hover' }" placeholder="璇烽�夋嫨搴楅摵鍚�"
@@ -550,51 +550,15 @@
         :data="displayData"
         style="width: 100%; margin-top: 25px"
         height="500px"
-        table-layout="auto"
+        table-layout="fixed"
+        :show-overflow-tooltip="true"
       >
-        <el-table-column fixed prop="mvStatCode" label="璁惧缂栧彿">
-          <template #default="{ row }">
-            <el-tooltip effect="dark" :content="row.mvStatCode">
-              <div class="cell ellipsis">{{ row.mvStatCode }}</div>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-        <el-table-column prop="diName" label="搴楅摵鍚嶇О">
-          <template #default="{ row }">
-            <el-tooltip effect="dark" :content="row.diName">
-              <div class="cell ellipsis">{{ row.diName }}</div>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-
-        <el-table-column prop="mvDataTime" label="閲囬泦鏃堕棿">
-          <template #default="{ row }">
-            <el-tooltip effect="dark" :content="row.mvDataTime">
-              <div class="cell ellipsis">{{ row.mvDataTime }}</div>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-        <el-table-column prop="mvFanElectricity" label="椋庢満鐢垫祦(A)">
-          <template #default="{ row }">
-            <el-tooltip effect="dark" :content="row.mvFanElectricity">
-              <div class="cell ellipsis">{{ row.mvFanElectricity }}</div>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-        <el-table-column prop="mvPurifierElectricity" label="鍑�鍖栧櫒鐢垫祦(A)">
-          <template #default="{ row }">
-            <el-tooltip effect="dark" :content="row.mvPurifierElectricity">
-              <div class="cell ellipsis">{{ row.mvPurifierElectricity }}</div>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-        <el-table-column prop="mvFumeConcentration2" label="娌圭儫娴撳害(mg/m鲁)">
-          <template #default="{ row }">
-            <el-tooltip effect="dark" :content="row.mvFumeConcentration2">
-              <div class="cell ellipsis">{{ row.mvFumeConcentration2 }}</div>
-            </el-tooltip>
-          </template>
-        </el-table-column>
+        <el-table-column fixed prop="mvStatCode" label="璁惧缂栧彿"> </el-table-column>
+        <el-table-column prop="diName" label="搴楅摵鍚嶇О"> </el-table-column>
+        <el-table-column prop="mvDataTime" label="閲囬泦鏃堕棿"> </el-table-column>
+        <el-table-column prop="mvFanElectricity" label="椋庢満鐢垫祦(A)"> </el-table-column>
+        <el-table-column prop="mvPurifierElectricity" label="鍑�鍖栧櫒鐢垫祦(A)"> </el-table-column>
+        <el-table-column prop="mvFumeConcentration2" label="娌圭儫娴撳害(mg/m鲁)"> </el-table-column>
       </el-table>
       <el-pagination
         background

--
Gitblit v1.9.3