| | |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 任务完成率 --> |
| | | <!-- 巡查点次 --> |
| | | <div class="metric-card"> |
| | | <div class="card-header"> |
| | | <div class="card-title">任务完成率</div> |
| | | <div class="card-title">巡查点次</div> |
| | | <div class="card-icon task-icon"> |
| | | <svg |
| | | width="20" |
| | |
| | | </svg> |
| | | </div> |
| | | </div> |
| | | <div class="card-value">{{ metrics.taskCompletionRate }}%</div> |
| | | <div class="card-value">{{ metrics.inspectionPoints }}</div> |
| | | <div class="card-trend"> |
| | | <span |
| | | class="trend-arrow" |
| | | :class="{ |
| | | up: metrics.taskCompletionRateTrend > 0, |
| | | down: metrics.taskCompletionRateTrend < 0, |
| | | up: metrics.inspectionPointsTrend > 0, |
| | | down: metrics.inspectionPointsTrend < 0, |
| | | }" |
| | | > |
| | | {{ metrics.taskCompletionRateTrend > 0 ? '↑' : '↓' }} |
| | | {{ metrics.inspectionPointsTrend > 0 ? '↑' : '↓' }} |
| | | </span> |
| | | <span class="trend-text">{{ Math.abs(metrics.taskCompletionRateTrend) }}%</span> |
| | | <span class="trend-text">{{ Math.abs(metrics.inspectionPointsTrend) }}</span> |
| | | <span class="trend-label">{{ getCompareLabel() }}</span> |
| | | </div> |
| | | </div> |
| | |
| | | <!-- 设备状态饼图 --> |
| | | <div class="device-status-chart"> |
| | | <canvas id="deviceStatusChart"></canvas> |
| | | </div> |
| | | </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> |
| | | <!-- 巡查情况统计卡片 --> |
| | |
| | | onlineRateTrend: 2, |
| | | purifierEfficiency: 85, |
| | | purifierEfficiencyTrend: -3, |
| | | taskCompletionRate: 78, |
| | | taskCompletionRateTrend: 10, |
| | | inspectionPoints: 350, |
| | | inspectionPointsTrend: 50, |
| | | }, |
| | | overview: { |
| | | totalShops: 245, |
| | |
| | | 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, |
| | | inspectionPoints: Math.floor(Math.random() * 100) + 300, |
| | | inspectionPointsTrend: Math.floor(Math.random() * 100) - 50, |
| | | } |
| | | |
| | | // 更新巡查统计数据 |
| | |
| | | animation: blink 1s infinite; |
| | | } |
| | | |
| | | /* 地图图例样式 */ |
| | | .map-legend { |
| | | position: absolute; |
| | | bottom: 4px; |
| | | right: 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: 16px; |
| | | 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: 1200px) { |
| | | .top-cards { |