From 64d3eae2852d17c3bbade662d3f7a7c47d681ad6 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期四, 19 三月 2026 14:17:04 +0800
Subject: [PATCH] 2026.3.19

---
 src/views/monitor/DataDashboard.vue | 1666 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 1,460 insertions(+), 206 deletions(-)

diff --git a/src/views/monitor/DataDashboard.vue b/src/views/monitor/DataDashboard.vue
index 4e266ec..d039dc4 100644
--- a/src/views/monitor/DataDashboard.vue
+++ b/src/views/monitor/DataDashboard.vue
@@ -1,254 +1,1508 @@
-<!-- e:\VSprojects\fume-supervision-vue\src\views\monitor\DataDashboard.vue -->
 <template>
-  <el-container class="data-dashboard">
-    <el-main>
-      <!-- 璁惧鍦ㄧ嚎鎯呭喌鍖哄煙 -->
-      <DeviceStatus
-        :online-count="onlineCount"
-        :offline-count="offlineCount"
-        :normal-count="normalCount"
-        :fault-count="faultCount"
-      />
+  <div class="data-dashboard">
+    <!-- 椤堕儴鎸囨爣鍗$墖鍖� -->
+    <div class="top-cards">
+      <!-- 鏃堕棿鍛ㄦ湡閫夐」鍗$墖 -->
+      <div class="time-period-card">
+        <!-- <div class="card-title">鏃堕棿閫夋嫨</div> -->
+        <div class="time-controls">
+          <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 class="time-navigator">
+            <button class="nav-btn" @click="navigateTime(-1)" title="涓婁竴涓懆鏈�">
+              <svg
+                width="16"
+                height="16"
+                viewBox="0 0 24 24"
+                fill="none"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="M15 18L9 12L15 6"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
+              </svg>
+            </button>
+            <div class="current-time">{{ currentTimeDisplay }}</div>
+            <button class="nav-btn" @click="navigateTime(1)" title="涓嬩竴涓懆鏈�">
+              <svg
+                width="16"
+                height="16"
+                viewBox="0 0 24 24"
+                fill="none"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="M9 18L15 12L9 6"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
+              </svg>
+            </button>
+          </div>
+        </div>
+      </div>
+      <div class="cards-container">
+        <!-- 娴撳害棰勮 -->
+        <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 }}<el-text>娆�</el-text></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>
 
-      <!-- 璁惧瀹炴椂鏁版嵁鍖哄煙 -->
-      <RealTimeData :current-device="currentDevice" :hourly-data="hourlyData" />
+        <!-- 璁惧鍦ㄧ嚎鐜� -->
+        <el-popover placement="right-start" title="璁惧鐩戞帶" width="400" trigger="click">
+          <div class="popover-content">
+            <div class="overview-items-container">
+              <div class="overview-item">
+                <div class="overview-label">椁愰ギ搴楅摵鎬绘暟</div>
+                <div class="overview-value">{{ overview.totalShops }}</div>
+              </div>
 
-      <!-- 鍒嗗尯鏁版嵁鎺掑悕鍖哄煙 -->
-      <DistrictRanking
-        :selected-month="selectedMonth"
-        :ranking-type="rankingType"
-        :ranking-data="rankingData"
-        :sorted-ranking-data="sortedRankingData"
-        @month-change="handleMonthChange"
-        @type-change="handleTypeChange"
-      />
+              <div class="overview-item">
+                <div class="overview-label">鍦ㄧ嚎璁惧鏁�</div>
+                <div class="overview-value">{{ overview.onlineDevices }}</div>
+              </div>
 
-      <!-- 鍦ㄧ嚎璁惧鍜屽簵閾烘竻鍗曞尯鍩� -->
-      <ShopList
-        :shops="shops"
-        :shop-types="shopTypes"
-        :districts="districts"
-        :filter="filter"
-        @filter-change="handleFilterChange"
+              <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>
+          <template #reference>
+            <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 class="view-details">
+                <span>璇︽儏</span>
+                <svg
+                  width="12"
+                  height="12"
+                  viewBox="0 0 24 24"
+                  fill="none"
+                  xmlns="http://www.w3.org/2000/svg"
+                >
+                  <path
+                    d="M9 18L15 12L9 6"
+                    stroke="currentColor"
+                    stroke-width="2"
+                    stroke-linecap="round"
+                    stroke-linejoin="round"
+                  />
+                </svg>
+              </div>
+            </div>
+          </template>
+        </el-popover>
+
+        <!-- 鐜俊鐮佺豢鐮佺巼 -->
+        <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>
+
+        <!-- 宸℃煡鐐规 -->
+        <el-popover placement="right-start" title="鐜板満宸℃煡缁熻" width="350" trigger="click">
+          <div class="inspection-popover-content">
+            <!-- 宸℃煡閲忕粺璁� -->
+            <div class="inspection-metrics">
+              <div class="inspection-metric-item">
+                <div class="inspection-metric-label">搴楅摵鎬昏</div>
+                <div class="inspection-metric-value">{{ inspectionStats.totalShops }}</div>
+              </div>
+              <div class="inspection-metric-item">
+                <div class="inspection-metric-label">宸℃煡搴楅摵</div>
+                <div class="inspection-metric-value">{{ inspectionStats.inspectedShops }}</div>
+              </div>
+              <div class="inspection-metric-item">
+                <div class="inspection-metric-label">宸℃煡鐐规</div>
+                <div class="inspection-metric-value">{{ inspectionStats.inspectionPoints }}</div>
+              </div>
+              <div class="inspection-metric-item">
+                <div class="inspection-metric-label">澶嶆煡鐐规</div>
+                <div class="inspection-metric-value">{{ inspectionStats.reviewPoints }}</div>
+              </div>
+            </div>
+
+            <!-- 闂鏁存敼鎯呭喌 -->
+            <div class="inspection-chart-container">
+              <div class="section-header"><h3>闂鏁存敼</h3></div>
+              <canvas id="rectificationChart"></canvas>
+            </div>
+
+            <!-- 闂瀹℃牳鎯呭喌 -->
+            <div class="inspection-table-container" style="display: none">
+              <div class="section-header"><h3>瀹℃牳姹囨��</h3></div>
+              <div class="inspection-metric-label">闂瀹℃牳</div>
+              <div class="inspection-table">
+                <div class="inspection-metric-item">
+                  <div class="inspection-metric-label">鏃犻棶棰�</div>
+                  <div class="inspection-metric-value">{{ inspectionStats.noProblemShops }}</div>
+                </div>
+                <div class="inspection-metric-item">
+                  <div class="inspection-metric-label">鏈鏍�</div>
+                  <div class="inspection-metric-value">
+                    {{ inspectionStats.unreviewedProblemShops }}
+                  </div>
+                </div>
+                <div class="inspection-metric-item">
+                  <div class="inspection-metric-label">閮ㄥ垎瀹℃牳</div>
+                  <div class="inspection-metric-value">
+                    {{ inspectionStats.partiallyReviewedProblemShops }}
+                  </div>
+                </div>
+                <div class="inspection-metric-item">
+                  <div class="inspection-metric-label">鍏ㄩ儴瀹℃牳</div>
+                  <div class="inspection-metric-value">
+                    {{ inspectionStats.fullyReviewedProblemShops }}
+                  </div>
+                </div>
+              </div>
+              <div class="inspection-metric-label">鏁存敼瀹℃牳</div>
+              <div class="inspection-table">
+                <div class="inspection-metric-item">
+                  <div class="inspection-metric-label">鏈暣鏀�</div>
+                  <div class="inspection-metric-value">{{ inspectionStats.unrectifiedShops }}</div>
+                </div>
+                <div class="inspection-metric-item">
+                  <div class="inspection-metric-label">鏈鏍�</div>
+                  <div class="inspection-metric-value">
+                    {{ inspectionStats.unreviewedRectifiedShops }}
+                  </div>
+                </div>
+                <div class="inspection-metric-item">
+                  <div class="inspection-metric-label">閮ㄥ垎瀹℃牳</div>
+                  <div class="inspection-metric-value">
+                    {{ inspectionStats.partiallyReviewedRectifiedShops }}
+                  </div>
+                </div>
+                <div class="inspection-metric-item">
+                  <div class="inspection-metric-label">鍏ㄩ儴瀹℃牳</div>
+                  <div class="inspection-metric-value">
+                    {{ inspectionStats.fullyReviewedRectifiedShops }}
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <template #reference>
+            <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.inspectionPoints }}</div>
+              <div class="card-trend">
+                <span
+                  class="trend-arrow"
+                  :class="{
+                    up: metrics.inspectionPointsTrend > 0,
+                    down: metrics.inspectionPointsTrend < 0,
+                  }"
+                >
+                  {{ metrics.inspectionPointsTrend > 0 ? '鈫�' : '鈫�' }}
+                </span>
+                <span class="trend-text">{{ Math.abs(metrics.inspectionPointsTrend) }}</span>
+                <span class="trend-label">{{ getCompareLabel() }}</span>
+              </div>
+              <div class="view-details">
+                <span>璇︽儏</span>
+                <svg
+                  width="12"
+                  height="12"
+                  viewBox="0 0 24 24"
+                  fill="none"
+                  xmlns="http://www.w3.org/2000/svg"
+                >
+                  <path
+                    d="M9 18L15 12L9 6"
+                    stroke="currentColor"
+                    stroke-width="2"
+                    stroke-linecap="round"
+                    stroke-linejoin="round"
+                  />
+                </svg>
+              </div>
+            </div>
+          </template>
+        </el-popover>
+      </div>
+    </div>
+
+    <!-- 涓昏鍐呭鍖� -->
+    <div class="main-content">
+      <!-- 涓儴GIS鍦板浘鍖� -->
+      <div class="map-section">
+        <div id="map" class="map-container">
+          <BaseMap :showSatellite="true"></BaseMap>
+        </div>
+      </div>
+    </div>
+    <div class="monitor-control-container">
+      <el-button size="large" @click="toggleMonitorControl" class="push-btn">
+        <div style="display: flex; flex-direction: column">
+          <el-icon>
+            <ArrowRight v-if="isMonitorControlExpanded" />
+            <ArrowLeft v-else />
+          </el-icon>
+          <div>鐜�</div>
+          <div>鍦�</div>
+          <div>宸�</div>
+          <div>鏌�</div>
+        </div>
+      </el-button>
+      <MonitorControl
+        v-if="isMonitorControlExpanded"
+        :class="{ 'monitor-control': true, collapsed: !isMonitorControlExpanded }"
+        style="height: calc(90vh - 40px)"
       />
-    </el-main>
-  </el-container>
+    </div>
+
+    <!-- 鍦板浘鍥句緥 -->
+    <div class="map-legend">
+      <div class="legend-header">
+        <h4>鍥句緥</h4>
+      </div>
+      <div class="legend-items">
+        <div class="legend-item">
+          <img src="@/assets/exceed.png" alt="娌圭儫娴撳害瓒呮爣" class="legend-icon" />
+          <span class="legend-text">娌圭儫娴撳害瓒呮爣</span>
+        </div>
+        <div class="legend-item">
+          <img src="@/assets/exception.png" alt="渚涚數寮傚父" class="legend-icon" />
+          <span class="legend-text">渚涚數寮傚父</span>
+        </div>
+        <div class="legend-item">
+          <img src="@/assets/offline.png" alt="璁惧鎴栫綉缁滃紓甯�" class="legend-icon" />
+          <span class="legend-text">璁惧鎴栫綉缁滃紓甯�</span>
+        </div>
+        <div class="legend-item">
+          <img
+            src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB4PSI1IiB5PSI4IiB3aWR0aD0iMjIiIGhlaWdodD0iMTYiIHJ4PSIzIiBmaWxsPSIjNTJjNDFhIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiLz48cGF0aCBkPSJNNSA4IFEgMTYgMyAyNyA4IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9IiMzODllMGQiLz48cGF0aCBkPSJNNSAyNCBRIDE2IDI5IDI3IDI0IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9IiM2NjY2NjYiLz48cmVjdCB4PSI4IiB5PSIxMSIgd2lkdGg9IjE2IiBoZWlnaHQ9IjEwIiByeD0iMiIgZmlsbD0id2hpdGUiLz48cGF0aCBkPSJNMTIgMTQgTCAyMSAxNCIgc3Ryb2tlPSIjNTJjNDFhIiBzdHJva2Utd2lkdGg9IjEuNSIvPjxwYXRoIGQ9Ik0xMiAxNyBMIDE4IDE3IiBzdHJva2U9IiM1MmM0MWEiIHN0cm9rZS13aWR0aD0iMS41Ii8+PHBhdGggZD0iTTEyIDIwIEwgMTUgMjAiIHN0cm9rZT0iIzUyYzQxYSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz48bGluZSB4MT0iMTYiIHkxPSI4IiB4Mj0iMTYiIHkyPSIzIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjEuNSIvPjxjaXJjbGUgY3g9IjE2IiBjeT0iMyIgcj0iMS41IiBmaWxsPSJ3aGl0ZSIvPjxjaXJjbGUgY3g9IjI3IiBjeT0iMTYiIHI9IjMiIGZpbGw9IiNmZmZmZmYiLz48Y2lyY2xlIGN4PSIyNyIgY3k9IjE2IiByPSIxLjUiIGZpbGw9IiM1MmM0MWEiLz48bGluZSB4MT0iNSIgeTE9IjEzIiB4Mj0iNiIgeTI9IjEzIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjEuNSIvPjxsaW5lIHgxPSI1IiB5MT0iMTkiIHgyPSI2IiB5Mj0iMTkiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMS41Ii8+PC9zdmc+"
+            alt="鍦ㄧ嚎鐘舵��"
+            class="legend-icon"
+          />
+          <span class="legend-text">鍦ㄧ嚎鐘舵��</span>
+        </div>
+        <div class="legend-item">
+          <img
+            src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB4PSI1IiB5PSI4IiB3aWR0aD0iMjIiIGhlaWdodD0iMTYiIHJ4PSIzIiBmaWxsPSIjOGM4YzhjIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiLz48cGF0aCBkPSJNNSA4IFEgMTYgMyAyNyA4IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9IiM2NjY2NjYiLz48cGF0aCBkPSJNNSAyNCBRIDE2IDI5IDI3IDI0IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9IiM2NjY2NjYiLz48cmVjdCB4PSI4IiB5PSIxMSIgd2lkdGg9IjE2IiBoZWlnaHQ9IjEwIiByeD0iMiIgZmlsbD0id2hpdGUiLz48bGluZSB4MT0iMTEiIHkxPSIxMiIgeDI9IjIxIiB5Mj0iMjIiIHN0cm9rZT0iIzhjOGM4YyIgc3Ryb2tlLXdpZHRoPSIyIi8+PGxpbmUgeDE9IjExIiB5MT0iMjIiIHgyPSIyMSIgeTI9IjEyIiBzdHJva2U9IiM4YzhjOGMiIHN0cm9rZS13aWR0aD0iMiIvPjxsaW5lIHgxPSIxNiIgeTE9IjgiIHgyPSIxNiIgeTI9IjMiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMS41Ii8+PGNpcmNsZSBjeD0iMTYiIGN5PSIzIiByPSIxLjUiIGZpbGw9IndoaXRlIi8+PGNpcmNsZSBjeD0iMjciIGN5PSIxNiIgcj0iMyIgZmlsbD0iI2ZmZmZmZiIvPjxjaXJjbGUgY3g9IjI3IiBjeT0iMTYiIHI9IjEuNSIgZmlsbD0iIzhjOGM4YyIvPjxsaW5lIHgxPSI1IiB5MT0iMTMiIHgyPSI2IiB5Mj0iMTMiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMS41Ii8+PGxpbmUgeDE9IjUiIHkxPSIxOSIgeDI9IjYiIHkyPSIxOSIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz48L3N2Zz4="
+            alt="绂荤嚎鐘舵��"
+            class="legend-icon"
+          />
+          <span class="legend-text">绂荤嚎鐘舵��</span>
+        </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, satellite } from '@/utils/map/index'
+import districtSearch from '@/utils/map/districtsearch.js'
+import marks from '@/utils/map/marks.js'
+import { generateTestShops } from '@/debug/debugdata'
+import MonitorControl from '@/views/inspection/MonitorControl.vue'
 
 export default {
   name: 'DataDashboard',
   components: {
-    DeviceStatus,
-    RealTimeData,
-    DistrictRanking,
-    ShopList,
+    MonitorControl,
   },
   data() {
     return {
-      // 璁惧鍦ㄧ嚎鎯呭喌鏁版嵁
-      onlineCount: 0,
-      offlineCount: 0,
-      normalCount: 0,
-      faultCount: 0,
-
-      // 璁惧瀹炴椂鏁版嵁
-      currentDevice: null,
-      hourlyData: [],
-
-      // 鍒嗗尯鏁版嵁鎺掑悕
-      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',
+      currentDate: new Date('2023-08-01'),
+      timeTabs: [
+        { label: '鏃�', value: 'day' },
+        { label: '鍛�', value: 'week' },
+        { label: '鏈�', value: 'month' },
       ],
+      selectedPoint: {
+        enterpriseName: '',
+        deviceId: '',
+        oilSmokeConcentration: 0,
+        particulateMatter: 0,
+        nonMethaneHydrocarbon: 0,
+        monitoringTime: '',
+        isOverStandard: false,
+      },
+      metrics: {
+        overStandardCount: 12,
+        overStandardTrend: 5,
+        onlineRate: 92,
+        onlineRateTrend: 2,
+        purifierEfficiency: 95,
+        purifierEfficiencyTrend: 2,
+        inspectionPoints: 350,
+        inspectionPointsTrend: 50,
+      },
+      overview: {
+        totalShops: 245,
+        onlineDevices: 220,
+        offlineDevices: 25,
+      },
+      inspectionStats: {
+        // 宸℃煡閲�
+        totalShops: 245,
+        inspectedShops: 180,
+        inspectionPoints: 350,
+        reviewPoints: 80,
+        // 闂鏁存敼鎯呭喌
+        problemCount: 45,
+        rectifiedCount: 38,
+        rectificationRate: 84.4,
+        // 闂瀹℃牳鎯呭喌
+        noProblemShops: 135,
+        unreviewedProblemShops: 8,
+        partiallyReviewedProblemShops: 5,
+        fullyReviewedProblemShops: 32,
+        unreviewedRectifiedShops: 3,
+        partiallyReviewedRectifiedShops: 2,
+        fullyReviewedRectifiedShops: 33,
+        unrectifiedShops: 7,
+      },
+      map: null,
+      refreshTimer: null,
+      isMonitorControlExpanded: true,
     }
   },
-  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鑾峰彇
-      const devices = [
-        {
-          deviceId: 'DEV-001',
-          supplier: '渚涘簲鍟咥',
-          娌圭儫娴撳害: (Math.random() * 2).toFixed(2),
-          椋庢満鐢垫祦: (Math.random() * 5 + 1).toFixed(2),
-          鍑�鍖栧櫒鐢垫祦: (Math.random() * 3 + 0.5).toFixed(2),
-        },
-      ]
-
-      this.currentDevice = devices[0]
-
-      // 鐢熸垚妯℃嫙鐨勮繎涓�灏忔椂鏁版嵁
-      this.hourlyData = []
-      for (let i = 59; i >= 0; i--) {
-        const time = new Date()
-        time.setMinutes(time.getMinutes() - i)
-        this.hourlyData.push({
-          time: time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
-          娌圭儫娴撳害: (Math.random() * 2).toFixed(2),
-          椋庢満鐢垫祦: (Math.random() * 5 + 1).toFixed(2),
-          鍑�鍖栧櫒鐢垫祦: (Math.random() * 3 + 0.5).toFixed(2),
-        })
+  computed: {
+    currentTimeDisplay() {
+      const date = this.currentDate
+      let weekStart = new Date(date)
+      let weekEnd = new Date(date)
+      switch (this.activeTime) {
+        case 'day':
+          return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
+        case 'week':
+          // 绠�鍗曡绠楀懆鏄剧ず锛屽疄闄呴」鐩腑鍙兘闇�瑕佹洿澶嶆潅鐨勫懆璁$畻閫昏緫
+          weekStart.setDate(date.getDate() - date.getDay() + 1)
+          weekEnd.setDate(date.getDate() + (7 - date.getDay()))
+          return `${weekStart.getFullYear()}-${String(weekStart.getMonth() + 1).padStart(2, '0')}-${String(weekStart.getDate()).padStart(2, '0')} ~ ${weekEnd.getFullYear()}-${String(weekEnd.getMonth() + 1).padStart(2, '0')}-${String(weekEnd.getDate()).padStart(2, '0')}`
+        case 'month':
+          return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`
+        default:
+          return ''
       }
     },
-
-    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 },
-      ]
-
-      // 鎺掑簭
-      this.sortedRankingData = [...this.rankingData].sort(
-        (a, b) => parseFloat(b.value) - parseFloat(a.value),
-      )
+  },
+  mounted() {
+    this.initMap()
+    this.initDeviceStatusChart()
+    this.initRectificationChart()
+    // this.startAutoRefresh()
+  },
+  beforeUnmount() {
+    if (this.refreshTimer) {
+      clearInterval(this.refreshTimer)
+    }
+  },
+  methods: {
+    toggleMonitorControl() {
+      this.isMonitorControlExpanded = !this.isMonitorControlExpanded
     },
+    handleTimeChange(tab) {
+      this.activeTime = tab.value
+      // 妯℃嫙鍒囨崲鏃堕棿鍛ㄦ湡鍚庣殑鏁版嵁鏇存柊
+      this.updateMetrics()
+    },
+    navigateTime(direction) {
+      const newDate = new Date(this.currentDate)
+      switch (this.activeTime) {
+        case 'day':
+          newDate.setDate(newDate.getDate() + direction)
+          break
+        case 'week':
+          newDate.setDate(newDate.getDate() + direction * 7)
+          break
+        case 'month':
+          newDate.setMonth(newDate.getMonth() + direction)
+          break
+      }
+      this.currentDate = newDate
+      // 妯℃嫙鍒囨崲鏃堕棿鍚庣殑鏁版嵁鏇存柊
+      this.updateMetrics()
+    },
+    getPeriodLabel() {
+      const today = new Date()
+      const isToday =
+        this.activeTime === 'day' &&
+        this.currentDate.getDate() === today.getDate() &&
+        this.currentDate.getMonth() === today.getMonth() &&
+        this.currentDate.getFullYear() === today.getFullYear()
 
-    startRealTimeUpdate() {
-      // 姣�30绉掓洿鏂颁竴娆℃暟鎹�
-      this.realTimeInterval = setInterval(() => {
-        this.updateDeviceStatus()
-        this.updateRealTimeData()
+      if (isToday) {
+        return '浠婃棩'
+      }
+
+      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(() => {
+        const m = Math.floor(Math.random() * 50) + 150
+        this.overview = {
+          totalShops: 245,
+          onlineDevices: m,
+          offlineDevices: 245 - m,
+        }
+        this.metrics = {
+          overStandardCount: Math.floor(Math.random() * 30),
+          overStandardTrend: Math.floor(Math.random() * 20) - 10,
+          onlineRate: ((this.overview.onlineDevices / this.overview.totalShops) * 100).toFixed(0),
+          onlineRateTrend: Math.floor(Math.random() * 10) - 5,
+          purifierEfficiency: Math.floor(Math.random() * 20) + 80,
+          purifierEfficiencyTrend: Math.floor(Math.random() * 10) - 5,
+          inspectionPoints: Math.floor(Math.random() * 100) + 300,
+          inspectionPointsTrend: Math.floor(Math.random() * 100) - 50,
+        }
+
+        // 鏇存柊宸℃煡缁熻鏁版嵁
+        this.inspectionStats = {
+          totalShops: 245,
+          inspectedShops: Math.floor(Math.random() * 50) + 150,
+          inspectionPoints: Math.floor(Math.random() * 100) + 300,
+          reviewPoints: Math.floor(Math.random() * 50) + 50,
+          problemCount: Math.floor(Math.random() * 30) + 20,
+          rectifiedCount: Math.floor(Math.random() * 25) + 15,
+          rectificationRate: Math.round((Math.random() * 30 + 70) * 10) / 10,
+          noProblemShops: Math.floor(Math.random() * 50) + 100,
+          unreviewedProblemShops: Math.floor(Math.random() * 10),
+          partiallyReviewedProblemShops: Math.floor(Math.random() * 8),
+          fullyReviewedProblemShops: Math.floor(Math.random() * 20) + 15,
+          unreviewedRectifiedShops: Math.floor(Math.random() * 5),
+          partiallyReviewedRectifiedShops: Math.floor(Math.random() * 5),
+          fullyReviewedRectifiedShops: Math.floor(Math.random() * 20) + 15,
+          unrectifiedShops: Math.floor(Math.random() * 10),
+        }
+
+        // 鏇存柊鍥捐〃
+        this.initDeviceStatusChart()
+        this.initRectificationChart()
+      }, 300)
+    },
+    initMap() {
+      // setTimeout(() => {
+      districtSearch.removeDistrict()
+      districtSearch.drawDistrictMask('涓婃捣甯�')
+      // districtSearch.districtLayer('310106')
+      // }, 2000)
+
+      onMapMounted(() => {
+        setTimeout(() => {
+          marks.clearMassMarks()
+          const shops = generateTestShops()
+          console.log(shops)
+
+          marks.drawMassMarks(shops)
+        }, 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)
+
+        // 鍝嶅簲寮忚皟鏁�
+        // window.addEventListener('resize', () => {
+        //   chart.resize()
+        // })
+      }
+    },
+    initRectificationChart() {
+      const chartDom = document.getElementById('rectificationChart')
+      if (chartDom) {
+        const chart = echarts.init(chartDom)
+        const option = {
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'shadow',
+            },
+            backgroundColor: 'rgba(255, 255, 255, 0.95)',
+            borderColor: '#e8e8e8',
+            borderWidth: 1,
+            textStyle: {
+              color: '#333',
+            },
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            top: '5%',
+            containLabel: true,
+          },
+          xAxis: {
+            type: 'category',
+            data: ['闂鏁�', '鏁存敼鏁�'],
+            axisLabel: {
+              color: '#86909c',
+              fontSize: 12,
+            },
+          },
+          yAxis: {
+            type: 'value',
+            axisLabel: {
+              color: '#86909c',
+              fontSize: 12,
+            },
+          },
+          series: [
+            {
+              name: '鏁伴噺',
+              type: 'bar',
+              data: [
+                {
+                  value: this.inspectionStats.problemCount,
+                  itemStyle: {
+                    color: '#fa8c16',
+                  },
+                },
+                {
+                  value: this.inspectionStats.rectifiedCount,
+                  itemStyle: {
+                    color: '#52c41a',
+                  },
+                },
+              ],
+              barWidth: '60%',
+              label: {
+                show: true,
+                position: 'top',
+                color: '#262626',
+                fontSize: 12,
+              },
+            },
+          ],
+        }
+        chart.setOption(option)
+
+        // 鍝嶅簲寮忚皟鏁�
+        // window.addEventListener('resize', () => {
+        //   chart.resize()
+        // })
+      }
+    },
+    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 - 70px);
   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: 4px;
+  left: 4px;
+  z-index: 10;
+  margin-bottom: 24px;
+}
+
+.cards-container {
+  display: grid;
+  grid-template-columns: repeat(2, 180px);
+  grid-template-rows: auto repeat(2, auto);
+  gap: 8px;
+  /* background-color: rgba(255, 255, 255, 0.9); */
+  /* padding: 16px; */
+  border-radius: 8px;
+  /* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */
+}
+
+/* 鐩戞帶鎺у埗鍗$墖 */
+.monitor-control {
+  /* position: absolute; */
+  width: 500px;
+  transition: all 0.3s ease;
+  /* top: 0px; */
+  /* right: 0px; */
+  /* z-index: 10; */
+}
+
+.push-btn {
+  z-index: 1;
+  width: 2.5rem;
+  height: initial;
+  margin: initial;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  /* background-color: white; */
+  /* border-color: white; */
+  /* border-top: 1px solid;
+  border-left: 1px solid;
+  border-bottom: 1px solid; */
+  border-top-right-radius: 0px;
+  border-bottom-right-radius: 0px;
+  /* box-shadow: var(--el-box-shadow-light); */
+}
+
+/* 鏃堕棿鍛ㄦ湡鍗$墖 */
+.time-period-card {
+  background-color: #ffffff;
+  border-radius: 8px;
+  padding: 4px 16px;
+  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  margin-bottom: 8px;
+  min-width: 300px;
+}
+
+.time-period-card .card-title {
+  font-size: 14px;
+  color: #86909c;
+  font-weight: 500;
+  margin-bottom: 16px;
+  text-align: center;
+}
+
+.time-controls {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+}
+
+.time-tab-container {
+  display: flex;
+  flex-direction: row;
+  gap: 8px;
+  width: 100%;
+  justify-content: center;
+}
+
+.time-tab {
+  padding: 4px 8px;
+  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;
+  flex: 1;
+}
+
+.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;
+}
+
+.time-navigator {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 12px;
+  padding: 8px 0;
+}
+
+.nav-btn {
+  width: 32px;
+  height: 32px;
+  border: 1px solid #e8e8e8;
+  background-color: #fafafa;
+  border-radius: 4px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  transition: all 0.3s ease;
+  color: #4e5969;
+}
+
+.nav-btn:hover {
+  border-color: #1890ff;
+  color: #1890ff;
+  background-color: #e6f7ff;
+}
+
+.current-time {
+  font-size: 14px;
+  font-weight: 500;
+  color: #262626;
+  min-width: 180px;
+  text-align: center;
+  padding: 0 12px;
+}
+
+/* 鎸囨爣鍗$墖 */
+.metric-card {
+  background-color: #ffffff;
+  border-radius: 8px;
   padding: 20px;
-  background-color: #f5f7fa;
+  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
+  transition: all 0.3s ease;
+  position: relative;
+  overflow: hidden;
 }
 
-.el-header h1 {
-  font-size: 24px;
+.metric-card:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+  cursor: pointer;
+}
+
+.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: #52c41a;
+}
+
+.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;
+}
+
+/* 鍙充晶瀹炴椂鐩戞祴鎬昏鍖� */
+.popover-content {
+  padding: 10px;
+}
+
+.overview-items-container {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding-bottom: 16px;
+  border-bottom: 1px solid #f0f0f0;
+  margin-bottom: 20px;
+}
+
+.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;
+  min-height: 200px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 16px;
+}
+
+.view-details {
+  position: absolute;
+  bottom: 12px;
+  right: 16px;
+  display: flex;
+  align-items: center;
+  gap: 4px;
+  font-size: 12px;
+  color: #1890ff;
+  cursor: pointer;
+}
+
+.view-details:hover {
+  text-decoration: underline;
+}
+
+.overview-items-container {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  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;
+}
+
+/* 宸℃煡鎯呭喌缁熻 */
+.inspection-popover-content {
+  padding: 10px;
+  max-height: 400px;
+  overflow-y: auto;
+}
+
+.monitor-control-container {
+  position: absolute;
+  top: 4px;
+  right: 4px;
+  z-index: 10;
+  transition: all 0.3s ease;
+  /* background-color: rgba(255, 255, 255, 0.9); */
+  display: flex;
+  border-radius: 8px;
+  /* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */
+  overflow: hidden;
+}
+
+.monitor-control-container.collapsed {
+  width: 60px;
+}
+
+.monitor-control-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 15px;
+  border-bottom: 1px solid #e8e8e8;
+  height: 40px;
+  position: relative;
+}
+
+.monitor-control-header span {
+  font-weight: 600;
+  color: #333;
+  writing-mode: vertical-rl;
+  text-orientation: mixed;
+  letter-spacing: 2px;
+  white-space: nowrap;
+}
+
+.collapse-btn {
+  /* transform: translateY(-50%); */
+}
+
+.inspection-metrics {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 12px;
+  margin-bottom: 20px;
+}
+
+.inspection-metric-item {
+  background-color: #fafafa;
+  border-radius: 6px;
+  padding: 12px;
+  text-align: center;
+}
+
+.inspection-metric-label {
+  font-size: 12px;
+  color: #86909c;
+  margin-bottom: 4px;
+}
+
+.inspection-metric-value {
+  font-size: 18px;
+  font-weight: bold;
+  color: #262626;
+}
+
+.inspection-chart-container {
+  margin-bottom: 20px;
+}
+
+.chart-title {
+  font-size: 14px;
+  font-weight: 500;
+  color: #262626;
+  margin-bottom: 12px;
+}
+
+.inspection-table-container {
+  /* max-height: 200px; */
+  /* overflow-y: auto; */
+}
+
+.inspection-table {
+  /* width: 100%;
+  border-collapse: collapse; */
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  gap: 2px;
+  margin-bottom: 20px;
+}
+
+.table-row {
+  display: flex;
+  border-bottom: 1px solid #f0f0f0;
+  padding: 8px 0;
+}
+
+.table-row:last-child {
+  border-bottom: none;
+}
+
+.table-cell {
+  flex: 1;
+  font-size: 12px;
+  color: #4e5969;
+}
+
+.table-cell.value {
+  font-weight: 500;
+  color: #262626;
+  text-align: right;
+}
+
+/* 寮圭獥鏍峰紡 */
+.dialog-content {
   color: #333;
 }
 
-.el-main {
-  padding: 20px;
+.dialog-footer {
+  text-align: right;
+}
+
+/* 闂儊鏁堟灉 */
+@keyframes blink {
+  0%,
+  100% {
+    opacity: 1;
+  }
+  50% {
+    opacity: 0.5;
+  }
+}
+
+.blink {
+  animation: blink 1s infinite;
+}
+
+/* 鍦板浘鍥句緥鏍峰紡 */
+.map-legend {
+  position: absolute;
+  bottom: 4px;
+  left: 4px;
+  /* width: 200px; */
+  background-color: rgba(255, 255, 255, 0.9);
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  padding: 4px;
+  z-index: 10;
+}
+
+.legend-header {
+  margin-bottom: 12px;
+}
+
+.legend-header h4 {
+  font-size: 14px;
+  font-weight: 600;
+  color: #262626;
+  margin: 0;
+  text-align: center;
+}
+
+.legend-items {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.legend-item {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  font-size: 12px;
+  color: #4e5969;
+}
+
+.legend-icon {
+  width: 24px;
+  height: 24px;
+  object-fit: contain;
 }
 
 /* 鍝嶅簲寮忚璁� */
-@media (max-width: 768px) {
-  .el-row {
-    flex-direction: column;
+/* @media (max-width: 1200px) {
+  .top-cards {
+    position: relative;
+    margin-bottom: 24px;
   }
 
-  .el-col {
-    width: 100% !important;
-    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>

--
Gitblit v1.9.3