|  |  | 
 |  |  | <template> | 
 |  |  |   <div class="kpl-monitor-container"> | 
 |  |  |     <!-- 页面头部 --> | 
 |  |  |     <div class="page-header"> | 
 |  |  |       <h1>KPL监控分析</h1> | 
 |  |  |       <div class="header-content"> | 
 |  |  |         <h1>KPL监控分析</h1> | 
 |  |  |         <p>设备关键性能指标监控与维保策略优化</p> | 
 |  |  |       </div> | 
 |  |  |       <div class="time-range"> | 
 |  |  |         <el-date-picker | 
 |  |  |           v-model="timeRange" | 
 |  |  | 
 |  |  |       </div> | 
 |  |  |     </div> | 
 |  |  |  | 
 |  |  |     <!-- 关键指标卡片 --> | 
 |  |  |     <div class="metrics-cards"> | 
 |  |  |       <div class="metric-card"> | 
 |  |  |         <div class="metric-header"> | 
 |  |  |           <span class="metric-title">MTBF</span> | 
 |  |  |           <span class="metric-trend" :class="mtbfTrendClass"> | 
 |  |  |             {{ mtbfTrendText }} | 
 |  |  |           </span> | 
 |  |  |         </div> | 
 |  |  |         <div class="metric-value">{{ currentMTBF }} 小时</div> | 
 |  |  |         <div class="metric-change"> | 
 |  |  |           较上月: {{ mtbfChange }}% | 
 |  |  |     <!-- 关键指标概览 --> | 
 |  |  |     <div class="metrics-overview"> | 
 |  |  |       <div class="metric-card mtbf-card"> | 
 |  |  |         <div class="metric-icon">⏱️</div> | 
 |  |  |         <div class="metric-content"> | 
 |  |  |           <div class="metric-title">MTBF</div> | 
 |  |  |           <div class="metric-subtitle">平均无故障时间</div> | 
 |  |  |           <div class="metric-value">{{ currentMTBF }}<span class="unit">小时</span></div> | 
 |  |  |           <div class="metric-trend" :class="mtbfTrendClass"> | 
 |  |  |             <span class="trend-icon">{{ mtbfTrendText }}</span> | 
 |  |  |             <span class="trend-text">{{ Math.abs(mtbfChange) }}%</span> | 
 |  |  |           </div> | 
 |  |  |         </div> | 
 |  |  |       </div> | 
 |  |  |  | 
 |  |  |       <div class="metric-card"> | 
 |  |  |         <div class="metric-header"> | 
 |  |  |           <span class="metric-title">MTTR</span> | 
 |  |  |           <span class="metric-trend" :class="mttrTrendClass"> | 
 |  |  |             {{ mttrTrendText }} | 
 |  |  |           </span> | 
 |  |  |         </div> | 
 |  |  |         <div class="metric-value">{{ currentMTTR }} 小时</div> | 
 |  |  |         <div class="metric-change"> | 
 |  |  |           较上月: {{ mttrChange }}% | 
 |  |  |       <div class="metric-card mttr-card"> | 
 |  |  |         <div class="metric-icon">🔧</div> | 
 |  |  |         <div class="metric-content"> | 
 |  |  |           <div class="metric-title">MTTR</div> | 
 |  |  |           <div class="metric-subtitle">平均修复时间</div> | 
 |  |  |           <div class="metric-value">{{ currentMTTR }}<span class="unit">小时</span></div> | 
 |  |  |           <div class="metric-trend" :class="mttrTrendClass"> | 
 |  |  |             <span class="trend-icon">{{ mttrTrendText }}</span> | 
 |  |  |             <span class="trend-text">{{ Math.abs(mttrChange) }}%</span> | 
 |  |  |           </div> | 
 |  |  |         </div> | 
 |  |  |       </div> | 
 |  |  |  | 
 |  |  |       <div class="metric-card"> | 
 |  |  |         <div class="metric-header"> | 
 |  |  |           <span class="metric-title">设备可用率</span> | 
 |  |  |           <span class="metric-trend" :class="availabilityTrendClass"> | 
 |  |  |             {{ availabilityTrendText }} | 
 |  |  |           </span> | 
 |  |  |         </div> | 
 |  |  |         <div class="metric-value">{{ currentAvailability }}%</div> | 
 |  |  |         <div class="metric-change"> | 
 |  |  |           较上月: {{ availabilityChange }}% | 
 |  |  |         </div> | 
 |  |  |       </div> | 
 |  |  |  | 
 |  |  |       <div class="metric-card"> | 
 |  |  |         <div class="metric-header"> | 
 |  |  |           <span class="metric-title">故障次数</span> | 
 |  |  |           <span class="metric-trend" :class="failureTrendClass"> | 
 |  |  |             {{ failureTrendText }} | 
 |  |  |           </span> | 
 |  |  |         </div> | 
 |  |  |         <div class="metric-value">{{ currentFailures }} 次</div> | 
 |  |  |         <div class="metric-change"> | 
 |  |  |           较上月: {{ failureChange }}% | 
 |  |  |       <div class="metric-card availability-card"> | 
 |  |  |         <div class="metric-icon">📊</div> | 
 |  |  |         <div class="metric-content"> | 
 |  |  |           <div class="metric-title">设备可用率</div> | 
 |  |  |           <div class="metric-subtitle">运行效率指标</div> | 
 |  |  |           <div class="metric-value">{{ currentAvailability }}<span class="unit">%</span></div> | 
 |  |  |           <div class="metric-trend" :class="availabilityTrendClass"> | 
 |  |  |             <span class="trend-icon">{{ availabilityTrendText }}</span> | 
 |  |  |             <span class="trend-text">{{ Math.abs(availabilityChange) }}%</span> | 
 |  |  |           </div> | 
 |  |  |         </div> | 
 |  |  |       </div> | 
 |  |  |     </div> | 
 |  |  |  | 
 |  |  |     <!-- 趋势图表 --> | 
 |  |  |     <!-- 趋势分析图表 --> | 
 |  |  |     <div class="charts-section"> | 
 |  |  |       <div class="chart-card"> | 
 |  |  |         <div class="chart-header">MTBF趋势分析</div> | 
 |  |  |         <div class="chart-container"> | 
 |  |  |           <div ref="mtbfChart" class="chart"></div> | 
 |  |  |       <div class="chart-container"> | 
 |  |  |         <div class="chart-header"> | 
 |  |  |           <h3>MTBF & MTTR 趋势分析</h3> | 
 |  |  |           <div class="chart-legend"> | 
 |  |  |             <span class="legend-item mtbf-legend"> | 
 |  |  |               <span class="legend-color"></span> | 
 |  |  |               MTBF (平均无故障时间) | 
 |  |  |             </span> | 
 |  |  |             <span class="legend-item mttr-legend"> | 
 |  |  |               <span class="legend-color"></span> | 
 |  |  |               MTTR (平均修复时间) | 
 |  |  |             </span> | 
 |  |  |           </div> | 
 |  |  |         </div> | 
 |  |  |       </div> | 
 |  |  |  | 
 |  |  |       <div class="chart-card"> | 
 |  |  |         <div class="chart-header">MTTR趋势分析</div> | 
 |  |  |         <div class="chart-container"> | 
 |  |  |           <div ref="mttrChart" class="chart"></div> | 
 |  |  |         <div class="chart-wrapper"> | 
 |  |  |           <div ref="trendChart" class="chart"></div> | 
 |  |  |         </div> | 
 |  |  |       </div> | 
 |  |  |     </div> | 
 |  |  |  | 
 |  |  |     <!-- 优化建议 --> | 
 |  |  |     <div class="recommendation-card"> | 
 |  |  |       <div class="card-header">维保策略优化建议</div> | 
 |  |  |       <div class="recommendation-content"> | 
 |  |  |     <!-- 维保策略建议 --> | 
 |  |  |     <div class="recommendations-section"> | 
 |  |  |       <div class="section-header"> | 
 |  |  |         <h3>维保策略优化建议</h3> | 
 |  |  |         <p>基于当前指标分析,为您提供针对性的优化建议</p> | 
 |  |  |       </div> | 
 |  |  |       <div class="recommendations-grid"> | 
 |  |  |         <div  | 
 |  |  |           v-for="(recommendation, index) in recommendations"  | 
 |  |  |           :key="index" | 
 |  |  |           class="recommendation-item" | 
 |  |  |           class="recommendation-card" | 
 |  |  |         > | 
 |  |  |           <div class="recommendation-icon">💡</div> | 
 |  |  |           <div class="recommendation-text">{{ recommendation }}</div> | 
 |  |  |           <div class="recommendation-icon">{{ recommendation.icon }}</div> | 
 |  |  |           <div class="recommendation-content"> | 
 |  |  |             <h4>{{ recommendation.title }}</h4> | 
 |  |  |             <p>{{ recommendation.description }}</p> | 
 |  |  |             <div class="recommendation-priority" :class="recommendation.priority"> | 
 |  |  |               {{ recommendation.priorityText }} | 
 |  |  |             </div> | 
 |  |  |           </div> | 
 |  |  |         </div> | 
 |  |  |       </div> | 
 |  |  |     </div> | 
 |  |  | 
 |  |  | import { ref, reactive, onMounted, computed, nextTick } from 'vue' | 
 |  |  | import * as echarts from 'echarts' | 
 |  |  |  | 
 |  |  | // 模拟数据 | 
 |  |  | // 生成模拟数据 | 
 |  |  | const generateMockData = () => { | 
 |  |  |   const months = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'] | 
 |  |  |   const mtbfData = months.map(() => Math.floor(Math.random() * 200 + 300)) // 300-500小时 | 
 |  |  | 
 |  |  |  | 
 |  |  | const mockData = reactive(generateMockData()) | 
 |  |  |  | 
 |  |  | // 计算当前值(最新月份的数据) | 
 |  |  | // 计算当前指标值 | 
 |  |  | const currentMTBF = computed(() => mockData.mtbfData[mockData.mtbfData.length - 1]) | 
 |  |  | const currentMTTR = computed(() => mockData.mttrData[mockData.mttrData.length - 1]) | 
 |  |  | const currentAvailability = computed(() =>  | 
 |  |  |   Math.round((currentMTBF.value / (currentMTBF.value + currentMTTR.value)) * 100) | 
 |  |  | ) | 
 |  |  | const currentFailures = computed(() => Math.floor(Math.random() * 10 + 5)) | 
 |  |  |  | 
 |  |  | // 计算变化趋势 | 
 |  |  | const mtbfChange = computed(() => { | 
 |  |  | 
 |  |  |   return Math.round(((current - previous) / previous) * 100) | 
 |  |  | }) | 
 |  |  |  | 
 |  |  | const failureChange = computed(() => { | 
 |  |  |   const current = currentFailures.value | 
 |  |  |   const previous = Math.floor(Math.random() * 10 + 5) | 
 |  |  |   return Math.round(((current - previous) / previous) * 100) | 
 |  |  | }) | 
 |  |  |  | 
 |  |  | // 趋势判断 | 
 |  |  | // 趋势样式和文本 | 
 |  |  | const mtbfTrendClass = computed(() => mtbfChange.value >= 0 ? 'trend-up' : 'trend-down') | 
 |  |  | const mttrTrendClass = computed(() => mttrChange.value <= 0 ? 'trend-up' : 'trend-down') | 
 |  |  | const availabilityTrendClass = computed(() => availabilityChange.value >= 0 ? 'trend-up' : 'trend-down') | 
 |  |  | const failureTrendClass = computed(() => failureChange.value <= 0 ? 'trend-up' : 'trend-down') | 
 |  |  |  | 
 |  |  | const mtbfTrendText = computed(() => mtbfChange.value >= 0 ? '↑' : '↓') | 
 |  |  | const mttrTrendText = computed(() => mttrChange.value <= 0 ? '↑' : '↓') | 
 |  |  | const availabilityTrendText = computed(() => availabilityChange.value >= 0 ? '↑' : '↓') | 
 |  |  | const failureTrendText = computed(() => failureChange.value <= 0 ? '↑' : '↓') | 
 |  |  | const mtbfTrendText = computed(() => mtbfChange.value >= 0 ? '↗' : '↘') | 
 |  |  | const mttrTrendText = computed(() => mttrChange.value <= 0 ? '↗' : '↘') | 
 |  |  | const availabilityTrendText = computed(() => availabilityChange.value >= 0 ? '↗' : '↘') | 
 |  |  |  | 
 |  |  | // 优化建议 | 
 |  |  | // 智能维保建议 | 
 |  |  | const recommendations = computed(() => { | 
 |  |  |   const suggestions = [] | 
 |  |  |    | 
 |  |  |   // MTBF相关建议 | 
 |  |  |   if (currentMTBF.value < 400) { | 
 |  |  |     suggestions.push('MTBF较低,建议加强预防性维护,定期检查关键部件') | 
 |  |  |     suggestions.push({ | 
 |  |  |       icon: '🔧', | 
 |  |  |       title: '提升MTBF', | 
 |  |  |       description: '当前MTBF较低,建议加强预防性维护,定期检查关键部件,延长设备无故障运行时间', | 
 |  |  |       priority: 'high', | 
 |  |  |       priorityText: '高优先级' | 
 |  |  |     }) | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |   // MTTR相关建议 | 
 |  |  |   if (currentMTTR.value > 8) { | 
 |  |  |     suggestions.push('MTTR较高,建议优化维修流程,提高维修效率') | 
 |  |  |     suggestions.push({ | 
 |  |  |       icon: '⚡', | 
 |  |  |       title: '优化MTTR', | 
 |  |  |       description: '当前MTTR较高,建议优化维修流程,提高维修人员技能,缩短故障修复时间', | 
 |  |  |       priority: 'high', | 
 |  |  |       priorityText: '高优先级' | 
 |  |  |     }) | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |   // 可用率相关建议 | 
 |  |  |   if (currentAvailability.value < 95) { | 
 |  |  |     suggestions.push('设备可用率有待提升,建议优化维保计划安排') | 
 |  |  |     suggestions.push({ | 
 |  |  |       icon: '📈', | 
 |  |  |       title: '提升可用率', | 
 |  |  |       description: '设备可用率有待提升,建议优化维保计划安排,减少计划外停机时间', | 
 |  |  |       priority: 'medium', | 
 |  |  |       priorityText: '中优先级' | 
 |  |  |     }) | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |   if (currentFailures.value > 8) { | 
 |  |  |     suggestions.push('故障次数较多,建议加强设备日常巡检') | 
 |  |  |   // 综合建议 | 
 |  |  |   if (currentMTBF.value >= 400 && currentMTTR.value <= 8 && currentAvailability.value >= 95) { | 
 |  |  |     suggestions.push({ | 
 |  |  |       icon: '✅', | 
 |  |  |       title: '运行状况良好', | 
 |  |  |       description: '当前设备运行状况良好,各项指标均达到预期,建议继续保持现有维保策略', | 
 |  |  |       priority: 'low', | 
 |  |  |       priorityText: '低优先级' | 
 |  |  |     }) | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |   if (suggestions.length === 0) { | 
 |  |  |     suggestions.push('当前设备运行状况良好,继续保持现有维保策略') | 
 |  |  |   } | 
 |  |  |   // 预防性建议 | 
 |  |  |   suggestions.push({ | 
 |  |  |     icon: '📋', | 
 |  |  |     title: '预防性维护', | 
 |  |  |     description: '建议建立设备健康档案,定期分析设备运行数据,提前识别潜在故障风险', | 
 |  |  |     priority: 'medium', | 
 |  |  |     priorityText: '中优先级' | 
 |  |  |   }) | 
 |  |  |    | 
 |  |  |   return suggestions | 
 |  |  | }) | 
 |  |  |  | 
 |  |  | // 图表实例 | 
 |  |  | let mtbfChart = null | 
 |  |  | let mttrChart = null | 
 |  |  | let trendChart = null | 
 |  |  |  | 
 |  |  | const initCharts = () => { | 
 |  |  | const initChart = () => { | 
 |  |  |   nextTick(() => { | 
 |  |  |     // MTBF图表 | 
 |  |  |     mtbfChart = echarts.init(document.querySelector('.chart-card:first-child .chart')) | 
 |  |  |     mtbfChart.setOption({ | 
 |  |  |     trendChart = echarts.init(document.querySelector('.chart')) | 
 |  |  |     trendChart.setOption({ | 
 |  |  |       tooltip: { | 
 |  |  |         trigger: 'axis' | 
 |  |  |         trigger: 'axis', | 
 |  |  |         axisPointer: { | 
 |  |  |           type: 'cross' | 
 |  |  |         } | 
 |  |  |       }, | 
 |  |  |       legend: { | 
 |  |  |         data: ['MTBF', 'MTTR'], | 
 |  |  |         top: 10 | 
 |  |  |       }, | 
 |  |  |       grid: { | 
 |  |  |         left: '3%', | 
 |  |  |         right: '4%', | 
 |  |  |         bottom: '3%', | 
 |  |  |         containLabel: true | 
 |  |  |       }, | 
 |  |  |       xAxis: { | 
 |  |  |         type: 'category', | 
 |  |  |         data: mockData.months | 
 |  |  |       }, | 
 |  |  |       yAxis: { | 
 |  |  |         type: 'value', | 
 |  |  |         name: '小时' | 
 |  |  |       }, | 
 |  |  |       series: [{ | 
 |  |  |         data: mockData.mtbfData, | 
 |  |  |         type: 'line', | 
 |  |  |         smooth: true, | 
 |  |  |         lineStyle: { | 
 |  |  |           color: '#1890ff' | 
 |  |  |         }, | 
 |  |  |         areaStyle: { | 
 |  |  |           color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ | 
 |  |  |             { offset: 0, color: 'rgba(24, 144, 255, 0.3)' }, | 
 |  |  |             { offset: 1, color: 'rgba(24, 144, 255, 0.1)' } | 
 |  |  |           ]) | 
 |  |  |         data: mockData.months, | 
 |  |  |         axisLine: { | 
 |  |  |           lineStyle: { | 
 |  |  |             color: '#e0e0e0' | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |       }] | 
 |  |  |     }) | 
 |  |  |  | 
 |  |  |     // MTTR图表 | 
 |  |  |     mttrChart = echarts.init(document.querySelector('.chart-card:last-child .chart')) | 
 |  |  |     mttrChart.setOption({ | 
 |  |  |       tooltip: { | 
 |  |  |         trigger: 'axis' | 
 |  |  |       }, | 
 |  |  |       xAxis: { | 
 |  |  |         type: 'category', | 
 |  |  |         data: mockData.months | 
 |  |  |       }, | 
 |  |  |       yAxis: { | 
 |  |  |         type: 'value', | 
 |  |  |         name: '小时' | 
 |  |  |       }, | 
 |  |  |       series: [{ | 
 |  |  |         data: mockData.mttrData, | 
 |  |  |         type: 'line', | 
 |  |  |         smooth: true, | 
 |  |  |         lineStyle: { | 
 |  |  |           color: '#52c41a' | 
 |  |  |       yAxis: [ | 
 |  |  |         { | 
 |  |  |           type: 'value', | 
 |  |  |           name: 'MTBF (小时)', | 
 |  |  |           position: 'left', | 
 |  |  |           axisLine: { | 
 |  |  |             lineStyle: { | 
 |  |  |               color: '#1890ff' | 
 |  |  |             } | 
 |  |  |           }, | 
 |  |  |           axisLabel: { | 
 |  |  |             formatter: '{value}h' | 
 |  |  |           } | 
 |  |  |         }, | 
 |  |  |         areaStyle: { | 
 |  |  |           color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ | 
 |  |  |             { offset: 0, color: 'rgba(82, 196, 26, 0.3)' }, | 
 |  |  |             { offset: 1, color: 'rgba(82, 196, 26, 0.1)' } | 
 |  |  |           ]) | 
 |  |  |         { | 
 |  |  |           type: 'value', | 
 |  |  |           name: 'MTTR (小时)', | 
 |  |  |           position: 'right', | 
 |  |  |           axisLine: { | 
 |  |  |             lineStyle: { | 
 |  |  |               color: '#52c41a' | 
 |  |  |             } | 
 |  |  |           }, | 
 |  |  |           axisLabel: { | 
 |  |  |             formatter: '{value}h' | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |       }] | 
 |  |  |       ], | 
 |  |  |       series: [ | 
 |  |  |         { | 
 |  |  |           name: 'MTBF', | 
 |  |  |           type: 'line', | 
 |  |  |           yAxisIndex: 0, | 
 |  |  |           data: mockData.mtbfData, | 
 |  |  |           smooth: true, | 
 |  |  |           lineStyle: { | 
 |  |  |             color: '#1890ff', | 
 |  |  |             width: 3 | 
 |  |  |           }, | 
 |  |  |           itemStyle: { | 
 |  |  |             color: '#1890ff' | 
 |  |  |           }, | 
 |  |  |           areaStyle: { | 
 |  |  |             color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ | 
 |  |  |               { offset: 0, color: 'rgba(24, 144, 255, 0.3)' }, | 
 |  |  |               { offset: 1, color: 'rgba(24, 144, 255, 0.1)' } | 
 |  |  |             ]) | 
 |  |  |           } | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |           name: 'MTTR', | 
 |  |  |           type: 'line', | 
 |  |  |           yAxisIndex: 1, | 
 |  |  |           data: mockData.mttrData, | 
 |  |  |           smooth: true, | 
 |  |  |           lineStyle: { | 
 |  |  |             color: '#52c41a', | 
 |  |  |             width: 3 | 
 |  |  |           }, | 
 |  |  |           itemStyle: { | 
 |  |  |             color: '#52c41a' | 
 |  |  |           }, | 
 |  |  |           areaStyle: { | 
 |  |  |             color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ | 
 |  |  |               { offset: 0, color: 'rgba(82, 196, 26, 0.3)' }, | 
 |  |  |               { offset: 1, color: 'rgba(82, 196, 26, 0.1)' } | 
 |  |  |             ]) | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |       ] | 
 |  |  |     }) | 
 |  |  |   }) | 
 |  |  | } | 
 |  |  | 
 |  |  |   Object.assign(mockData, generateMockData()) | 
 |  |  |    | 
 |  |  |   // 重新渲染图表 | 
 |  |  |   if (mtbfChart && mttrChart) { | 
 |  |  |     mtbfChart.setOption({ | 
 |  |  |   if (trendChart) { | 
 |  |  |     trendChart.setOption({ | 
 |  |  |       xAxis: { | 
 |  |  |         data: mockData.months | 
 |  |  |       }, | 
 |  |  |       series: [{ | 
 |  |  |         data: mockData.mtbfData | 
 |  |  |       }] | 
 |  |  |     }) | 
 |  |  |      | 
 |  |  |     mttrChart.setOption({ | 
 |  |  |       xAxis: { | 
 |  |  |         data: mockData.months | 
 |  |  |       }, | 
 |  |  |       series: [{ | 
 |  |  |         data: mockData.mttrData | 
 |  |  |       }] | 
 |  |  |       series: [ | 
 |  |  |         { | 
 |  |  |           data: mockData.mtbfData | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |           data: mockData.mttrData | 
 |  |  |         } | 
 |  |  |       ] | 
 |  |  |     }) | 
 |  |  |   } | 
 |  |  | } | 
 |  |  |  | 
 |  |  | onMounted(() => { | 
 |  |  |   initCharts() | 
 |  |  |   initChart() | 
 |  |  |    | 
 |  |  |   // 监听窗口大小变化,重新调整图表大小 | 
 |  |  |   window.addEventListener('resize', () => { | 
 |  |  |     if (mtbfChart) mtbfChart.resize() | 
 |  |  |     if (mttrChart) mttrChart.resize() | 
 |  |  |     if (trendChart) trendChart.resize() | 
 |  |  |   }) | 
 |  |  | }) | 
 |  |  | </script> | 
 |  |  | 
 |  |  | <style scoped> | 
 |  |  | .kpl-monitor-container { | 
 |  |  |   min-height: 100vh; | 
 |  |  |   background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | 
 |  |  |   padding: 20px; | 
 |  |  |   background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); | 
 |  |  |   padding: 24px; | 
 |  |  |   font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | /* 页面头部 */ | 
 |  |  | .page-header { | 
 |  |  |   background: rgba(255, 255, 255, 0.95); | 
 |  |  |   border-radius: 16px; | 
 |  |  |   padding: 20px; | 
 |  |  |   margin-bottom: 20px; | 
 |  |  |   background: white; | 
 |  |  |   border-radius: 12px; | 
 |  |  |   padding: 24px; | 
 |  |  |   margin-bottom: 24px; | 
 |  |  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); | 
 |  |  |   display: flex; | 
 |  |  |   justify-content: space-between; | 
 |  |  |   align-items: center; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .page-header h1 { | 
 |  |  | .header-content h1 { | 
 |  |  |   margin: 0 0 8px 0; | 
 |  |  |   color: #1f2937; | 
 |  |  |   font-size: 28px; | 
 |  |  |   font-weight: 700; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .header-content p { | 
 |  |  |   margin: 0; | 
 |  |  |   color: #2c3e50; | 
 |  |  |   font-size: 24px; | 
 |  |  |   color: #6b7280; | 
 |  |  |   font-size: 16px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .time-range { | 
 |  |  |   display: flex; | 
 |  |  |   align-items: center; | 
 |  |  |   gap: 10px; | 
 |  |  |   gap: 12px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .metrics-cards { | 
 |  |  | /* 指标概览 */ | 
 |  |  | .metrics-overview { | 
 |  |  |   display: grid; | 
 |  |  |   grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); | 
 |  |  |   grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | 
 |  |  |   gap: 20px; | 
 |  |  |   margin-bottom: 20px; | 
 |  |  |   margin-bottom: 24px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .metric-card { | 
 |  |  |   background: rgba(255, 255, 255, 0.95); | 
 |  |  |   border-radius: 16px; | 
 |  |  |   padding: 20px; | 
 |  |  |   box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | 
 |  |  |   background: white; | 
 |  |  |   border-radius: 12px; | 
 |  |  |   padding: 24px; | 
 |  |  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); | 
 |  |  |   display: flex; | 
 |  |  |   align-items: center; | 
 |  |  |   gap: 16px; | 
 |  |  |   transition: transform 0.2s ease, box-shadow 0.2s ease; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .metric-header { | 
 |  |  | .metric-card:hover { | 
 |  |  |   transform: translateY(-2px); | 
 |  |  |   box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .metric-icon { | 
 |  |  |   font-size: 32px; | 
 |  |  |   width: 60px; | 
 |  |  |   height: 60px; | 
 |  |  |   display: flex; | 
 |  |  |   justify-content: space-between; | 
 |  |  |   align-items: center; | 
 |  |  |   margin-bottom: 15px; | 
 |  |  |   justify-content: center; | 
 |  |  |   border-radius: 12px; | 
 |  |  |   background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .mtbf-card .metric-icon { | 
 |  |  |   background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .mttr-card .metric-icon { | 
 |  |  |   background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .availability-card .metric-icon { | 
 |  |  |   background: linear-gradient(135deg, #fa709a 0%, #fee140 100%); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .metric-content { | 
 |  |  |   flex: 1; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .metric-title { | 
 |  |  |   font-size: 16px; | 
 |  |  |   color: #666; | 
 |  |  |   font-weight: 500; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .metric-trend { | 
 |  |  |   font-size: 14px; | 
 |  |  |   font-size: 18px; | 
 |  |  |   font-weight: 600; | 
 |  |  |   color: #1f2937; | 
 |  |  |   margin-bottom: 4px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .trend-up { | 
 |  |  |   color: #52c41a; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .trend-down { | 
 |  |  |   color: #ff4d4f; | 
 |  |  | .metric-subtitle { | 
 |  |  |   font-size: 14px; | 
 |  |  |   color: #6b7280; | 
 |  |  |   margin-bottom: 12px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .metric-value { | 
 |  |  |   font-size: 32px; | 
 |  |  |   font-weight: 700; | 
 |  |  |   color: #2c3e50; | 
 |  |  |   color: #1f2937; | 
 |  |  |   margin-bottom: 8px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .metric-change { | 
 |  |  | .unit { | 
 |  |  |   font-size: 16px; | 
 |  |  |   font-weight: 500; | 
 |  |  |   color: #6b7280; | 
 |  |  |   margin-left: 4px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .metric-trend { | 
 |  |  |   display: flex; | 
 |  |  |   align-items: center; | 
 |  |  |   gap: 4px; | 
 |  |  |   font-size: 14px; | 
 |  |  |   color: #666; | 
 |  |  |   font-weight: 600; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .trend-up { | 
 |  |  |   color: #10b981; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .trend-down { | 
 |  |  |   color: #ef4444; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .trend-icon { | 
 |  |  |   font-size: 16px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | /* 图表区域 */ | 
 |  |  | .charts-section { | 
 |  |  |   display: grid; | 
 |  |  |   grid-template-columns: repeat(auto-fit, minmax(500px, 1fr)); | 
 |  |  |   gap: 20px; | 
 |  |  |   margin-bottom: 20px; | 
 |  |  |   margin-bottom: 24px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .chart-card { | 
 |  |  |   background: rgba(255, 255, 255, 0.95); | 
 |  |  |   border-radius: 16px; | 
 |  |  | .chart-container { | 
 |  |  |   background: white; | 
 |  |  |   border-radius: 12px; | 
 |  |  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); | 
 |  |  |   overflow: hidden; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .chart-header { | 
 |  |  |   background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | 
 |  |  |   color: white; | 
 |  |  |   padding: 16px 20px; | 
 |  |  |   font-weight: 500; | 
 |  |  |   font-size: 16px; | 
 |  |  |   padding: 20px 24px; | 
 |  |  |   border-bottom: 1px solid #e5e7eb; | 
 |  |  |   display: flex; | 
 |  |  |   justify-content: space-between; | 
 |  |  |   align-items: center; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .chart-container { | 
 |  |  | .chart-header h3 { | 
 |  |  |   margin: 0; | 
 |  |  |   color: #1f2937; | 
 |  |  |   font-size: 18px; | 
 |  |  |   font-weight: 600; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .chart-legend { | 
 |  |  |   display: flex; | 
 |  |  |   gap: 20px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .legend-item { | 
 |  |  |   display: flex; | 
 |  |  |   align-items: center; | 
 |  |  |   gap: 8px; | 
 |  |  |   font-size: 14px; | 
 |  |  |   color: #6b7280; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .legend-color { | 
 |  |  |   width: 12px; | 
 |  |  |   height: 12px; | 
 |  |  |   border-radius: 2px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .mtbf-legend .legend-color { | 
 |  |  |   background: #1890ff; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .mttr-legend .legend-color { | 
 |  |  |   background: #52c41a; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .chart-wrapper { | 
 |  |  |   padding: 20px; | 
 |  |  |   height: 300px; | 
 |  |  |   height: 400px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .chart { | 
 |  |  | 
 |  |  |   height: 100%; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendation-card { | 
 |  |  |   background: rgba(255, 255, 255, 0.95); | 
 |  |  |   border-radius: 16px; | 
 |  |  | /* 建议区域 */ | 
 |  |  | .recommendations-section { | 
 |  |  |   background: white; | 
 |  |  |   border-radius: 12px; | 
 |  |  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); | 
 |  |  |   overflow: hidden; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .card-header { | 
 |  |  |   background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | 
 |  |  |   color: white; | 
 |  |  |   padding: 16px 20px; | 
 |  |  |   font-weight: 500; | 
 |  |  |   font-size: 16px; | 
 |  |  | .section-header { | 
 |  |  |   padding: 24px; | 
 |  |  |   border-bottom: 1px solid #e5e7eb; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendation-content { | 
 |  |  |   padding: 20px; | 
 |  |  | .section-header h3 { | 
 |  |  |   margin: 0 0 8px 0; | 
 |  |  |   color: #1f2937; | 
 |  |  |   font-size: 20px; | 
 |  |  |   font-weight: 600; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendation-item { | 
 |  |  |   display: flex; | 
 |  |  |   align-items: flex-start; | 
 |  |  |   margin-bottom: 15px; | 
 |  |  |   padding: 12px; | 
 |  |  |   background: #f8f9fa; | 
 |  |  | .section-header p { | 
 |  |  |   margin: 0; | 
 |  |  |   color: #6b7280; | 
 |  |  |   font-size: 14px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendations-grid { | 
 |  |  |   display: grid; | 
 |  |  |   grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); | 
 |  |  |   gap: 20px; | 
 |  |  |   padding: 24px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendation-card { | 
 |  |  |   background: #f8fafc; | 
 |  |  |   border-radius: 8px; | 
 |  |  |   padding: 20px; | 
 |  |  |   display: flex; | 
 |  |  |   gap: 16px; | 
 |  |  |   transition: transform 0.2s ease, box-shadow 0.2s ease; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendation-card:hover { | 
 |  |  |   transform: translateY(-1px); | 
 |  |  |   box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendation-icon { | 
 |  |  |   font-size: 18px; | 
 |  |  |   margin-right: 12px; | 
 |  |  |   margin-top: 2px; | 
 |  |  |   font-size: 24px; | 
 |  |  |   width: 40px; | 
 |  |  |   height: 40px; | 
 |  |  |   display: flex; | 
 |  |  |   align-items: center; | 
 |  |  |   justify-content: center; | 
 |  |  |   border-radius: 8px; | 
 |  |  |   background: white; | 
 |  |  |   flex-shrink: 0; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendation-text { | 
 |  |  | .recommendation-content { | 
 |  |  |   flex: 1; | 
 |  |  |   color: #2c3e50; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendation-content h4 { | 
 |  |  |   margin: 0 0 8px 0; | 
 |  |  |   color: #1f2937; | 
 |  |  |   font-size: 16px; | 
 |  |  |   font-weight: 600; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendation-content p { | 
 |  |  |   margin: 0 0 12px 0; | 
 |  |  |   color: #6b7280; | 
 |  |  |   font-size: 14px; | 
 |  |  |   line-height: 1.5; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .recommendation-priority { | 
 |  |  |   display: inline-block; | 
 |  |  |   padding: 4px 8px; | 
 |  |  |   border-radius: 4px; | 
 |  |  |   font-size: 12px; | 
 |  |  |   font-weight: 500; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .priority.high { | 
 |  |  |   background: #fef2f2; | 
 |  |  |   color: #dc2626; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .priority.medium { | 
 |  |  |   background: #fffbeb; | 
 |  |  |   color: #d97706; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .priority.low { | 
 |  |  |   background: #f0fdf4; | 
 |  |  |   color: #16a34a; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | /* 响应式设计 */ | 
 |  |  | @media (max-width: 768px) { | 
 |  |  |   .kpl-monitor-container { | 
 |  |  |     padding: 16px; | 
 |  |  | 
 |  |  |    | 
 |  |  |   .page-header { | 
 |  |  |     flex-direction: column; | 
 |  |  |     gap: 15px; | 
 |  |  |     gap: 16px; | 
 |  |  |     align-items: stretch; | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |   .metrics-cards { | 
 |  |  |   .metrics-overview { | 
 |  |  |     grid-template-columns: 1fr; | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |   .charts-section { | 
 |  |  |   .recommendations-grid { | 
 |  |  |     grid-template-columns: 1fr; | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |   .chart-container { | 
 |  |  |     height: 250px; | 
 |  |  |   .chart-wrapper { | 
 |  |  |     height: 300px; | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |   .chart-legend { | 
 |  |  |     flex-direction: column; | 
 |  |  |     gap: 8px; | 
 |  |  |   } | 
 |  |  | } | 
 |  |  |  | 
 |  |  | @media (max-width: 480px) { | 
 |  |  |   .metric-card { | 
 |  |  |     flex-direction: column; | 
 |  |  |     text-align: center; | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |   .recommendation-card { | 
 |  |  |     flex-direction: column; | 
 |  |  |     text-align: center; | 
 |  |  |   } | 
 |  |  | } | 
 |  |  | </style> |