From 0488cc32d225a28289ba6c70a2a297f347cacdad Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期一, 16 三月 2026 17:34:18 +0800
Subject: [PATCH] 2026.3.16
---
src/views/monitor/DataDashboard.vue | 1502 +++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 1,293 insertions(+), 209 deletions(-)
diff --git a/src/views/monitor/DataDashboard.vue b/src/views/monitor/DataDashboard.vue
index 4e266ec..65cd655 100644
--- a/src/views/monitor/DataDashboard.vue
+++ b/src/views/monitor/DataDashboard.vue
@@ -1,254 +1,1338 @@
-<!-- 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 }}</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" />
+ <!-- 鍦ㄧ嚎鐜� -->
+ <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>
- <!-- 鍒嗗尯鏁版嵁鎺掑悕鍖哄煙 -->
- <DistrictRanking
- :selected-month="selectedMonth"
- :ranking-type="rankingType"
- :ranking-data="rankingData"
- :sorted-ranking-data="sortedRankingData"
- @month-change="handleMonthChange"
- @type-change="handleTypeChange"
- />
+ <!-- 鍑�鍖栧櫒杩愯鏁堢巼 -->
+ <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>
- <!-- 鍦ㄧ嚎璁惧鍜屽簵閾烘竻鍗曞尯鍩� -->
- <ShopList
- :shops="shops"
- :shop-types="shopTypes"
- :districts="districts"
- :filter="filter"
- @filter-change="handleFilterChange"
- />
- </el-main>
- </el-container>
+ <!-- 浠诲姟瀹屾垚鐜� -->
+ <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>
+
+ <!-- 涓昏鍐呭鍖� -->
+ <div class="main-content">
+ <!-- 涓儴GIS鍦板浘鍖� -->
+ <div class="map-section">
+ <div id="map" class="map-container">
+ <BaseMap :showSatellite="true"></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>
+ <!-- 鍙充晶瀹炴椂鐩戞祴鎬昏鍖� -->
+ <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>
+ <!-- 宸℃煡鎯呭喌缁熻鍗$墖 -->
+ <el-scrollbar class="inspection-section">
+ <div class="section-header">
+ <h3>宸℃煡姹囨��</h3>
+ </div>
+
+ <!-- 宸℃煡閲忕粺璁� -->
+ <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">
+ <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 class="table-row">
+ <div class="table-cell">鏃犻棶棰樺簵閾烘暟閲�</div>
+ <div class="table-cell value">{{ inspectionStats.noProblemShops }}</div>
+ </div>
+ <div class="table-row">
+ <div class="table-cell">闂鏈鏍稿簵閾烘暟閲�</div>
+ <div class="table-cell value">{{ inspectionStats.unreviewedProblemShops }}</div>
+ </div>
+ <div class="table-row">
+ <div class="table-cell">闂閮ㄥ垎瀹℃牳搴楅摵鏁伴噺</div>
+ <div class="table-cell value">
+ {{ inspectionStats.partiallyReviewedProblemShops }}
+ </div>
+ </div>
+ <div class="table-row">
+ <div class="table-cell">闂鍏ㄩ儴瀹℃牳搴楅摵鏁伴噺</div>
+ <div class="table-cell value">{{ inspectionStats.fullyReviewedProblemShops }}</div>
+ </div>
+ <div class="table-row">
+ <div class="table-cell">鏈暣鏀瑰簵閾烘暟</div>
+ <div class="table-cell value">{{ inspectionStats.unrectifiedShops }}</div>
+ </div>
+ <div class="table-row">
+ <div class="table-cell">鏁存敼鏈鏍稿簵閾烘暟</div>
+ <div class="table-cell value">{{ inspectionStats.unreviewedRectifiedShops }}</div>
+ </div>
+ <div class="table-row">
+ <div class="table-cell">鏁存敼閮ㄥ垎瀹℃牳搴楅摵鏁�</div>
+ <div class="table-cell value">
+ {{ inspectionStats.partiallyReviewedRectifiedShops }}
+ </div>
+ </div>
+ <div class="table-row">
+ <div class="table-cell">鏁存敼鍏ㄩ儴瀹℃牳搴楅摵鏁�</div>
+ <div class="table-cell value">{{ inspectionStats.fullyReviewedRectifiedShops }}</div>
+ </div> -->
+ </div>
+ </div>
+ </el-scrollbar>
+ </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'
export default {
name: 'DataDashboard',
- components: {
- DeviceStatus,
- RealTimeData,
- DistrictRanking,
- ShopList,
- },
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(),
+ 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,
+ },
+ 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,
}
},
- 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
+ switch (this.activeTime) {
+ case 'day':
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
+ case 'week':
+ // 绠�鍗曡绠楀懆鏄剧ず锛屽疄闄呴」鐩腑鍙兘闇�瑕佹洿澶嶆潅鐨勫懆璁$畻閫昏緫
+ let weekStart = new Date(date)
+ weekStart.setDate(date.getDate() - date.getDay() + 1)
+ let weekEnd = new Date(date)
+ 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: {
+ 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(() => {
+ 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,
+ }
+
+ // 鏇存柊宸℃煡缁熻鏁版嵁
+ 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.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%',
+ 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); */
+}
+
+/* 鏃堕棿鍛ㄦ湡鍗$墖 */
+.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);
+}
+
+.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;
+ bottom: 4px;
+ left: 4px;
+ 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;
+ 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;
+ min-height: 100px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 16px;
+}
+
+/* 宸℃煡鎯呭喌缁熻 */
+.inspection-section {
+ position: absolute;
+ top: 4px;
+ right: 4px;
+ 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(70vh);
+ border-top: 1px solid #f0f0f0;
+}
+
+.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;
}
/* 鍝嶅簲寮忚璁� */
-@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