|  |  | 
 |  |  |                 </div> | 
 |  |  |                 <div class="card-content"> | 
 |  |  |                     <div class="card-title">单位热值耗煤量</div> | 
 |  |  |                     <div class="card-value">{{ unitHeatCoalConsumption.toFixed(2) }} kg/GJ</div> | 
 |  |  |                     <div class="card-desc">越低越好</div> | 
 |  |  |                     <div class="card-value">{{ unitHeatValue.toFixed(2) }} kg/GJ</div> | 
 |  |  |                 </div> | 
 |  |  |             </div> | 
 |  |  |              | 
 |  |  | 
 |  |  |                 </div> | 
 |  |  |                 <div class="card-content"> | 
 |  |  |                     <div class="card-title">整体达标率</div> | 
 |  |  |                     <div class="card-value">{{ overallComplianceRate.toFixed(2) }}%</div> | 
 |  |  |                     <div class="card-desc">发热量≥5000大卡</div> | 
 |  |  |                     <div class="card-value">{{ wholeStandardRate.toFixed(2) }}%</div> | 
 |  |  |                 </div> | 
 |  |  |             </div> | 
 |  |  |              | 
 |  |  | 
 |  |  |                 </div> | 
 |  |  |                 <div class="card-content"> | 
 |  |  |                     <div class="card-title">平均发热量</div> | 
 |  |  |                     <div class="card-value">{{ averageCalorificValue.toFixed(0) }} 大卡</div> | 
 |  |  |                     <div class="card-desc">越高越好</div> | 
 |  |  |                     <div class="card-value">{{ averageFuel.toFixed(0) }} 大卡</div> | 
 |  |  |                 </div> | 
 |  |  |             </div> | 
 |  |  |              | 
 |  |  | 
 |  |  |                 </div> | 
 |  |  |                 <div class="card-content"> | 
 |  |  |                     <div class="card-title">配方使用频次</div> | 
 |  |  |                     <div class="card-value">{{ totalBatches }} 次</div> | 
 |  |  |                     <div class="card-desc">时间范围内</div> | 
 |  |  |                     <div class="card-value">{{ frequency }} 次</div> | 
 |  |  |                 </div> | 
 |  |  |             </div> | 
 |  |  |              | 
 |  |  | 
 |  |  |                 </div> | 
 |  |  |                 <div class="card-content"> | 
 |  |  |                     <div class="card-title">总批次</div> | 
 |  |  |                     <div class="card-value">{{ totalBatches }}</div> | 
 |  |  |                     <div class="card-desc">时间范围内</div> | 
 |  |  |                     <div class="card-value">{{ totalBatch }}</div> | 
 |  |  |                 </div> | 
 |  |  |             </div> | 
 |  |  |         </div> | 
 |  |  | 
 |  |  |                     </div> | 
 |  |  |                 </template> | 
 |  |  |                 <div class="chart-wrapper"> | 
 |  |  |                     <Echarts | 
 |  |  |                         ref="complianceChartRef" | 
 |  |  |                         :options="complianceTrendOptions" | 
 |  |  |                         :chartStyle="{ height: '300px', width: '100%' }" | 
 |  |  |                     /> | 
 |  |  |                     <div ref="complianceChart" class="chart-content" style="height: 300px; width: 100%;"></div> | 
 |  |  |                 </div> | 
 |  |  |             </el-card> | 
 |  |  |              | 
 |  |  | 
 |  |  |                     </div> | 
 |  |  |                 </template> | 
 |  |  |                 <div class="chart-wrapper"> | 
 |  |  |                     <Echarts | 
 |  |  |                         ref="calorificChartRef" | 
 |  |  |                         :options="calorificValueOptions" | 
 |  |  |                         :chartStyle="{ height: '300px', width: '100%' }" | 
 |  |  |                     /> | 
 |  |  |                     <div ref="coalTypeHeatValueChart" class="chart-content" style="height: 300px; width: 100%;"></div> | 
 |  |  |                 </div> | 
 |  |  |             </el-card> | 
 |  |  |              | 
 |  |  |             <!-- 配方使用频次 --> | 
 |  |  |             <el-card class="chart-card"> | 
 |  |  |                 <template #header> | 
 |  |  |                     <div class="card-header"> | 
 |  |  |                         <span>配方使用频次</span> | 
 |  |  |                     </div> | 
 |  |  |                 </template> | 
 |  |  |                 <div class="chart-wrapper"> | 
 |  |  |                     <Echarts | 
 |  |  |                         ref="recipeChartRef" | 
 |  |  |                         :options="recipeFrequencyOptions" | 
 |  |  |                         :chartStyle="{ height: '300px', width: '100%' }" | 
 |  |  |                     /> | 
 |  |  |                 </div> | 
 |  |  |             </el-card> | 
 |  |  | 			 | 
 |  |  |  | 
 |  |  |             <!-- 加工得率分析 --> | 
 |  |  |             <el-card class="chart-card"> | 
 |  |  |                 <template #header> | 
 |  |  | 
 |  |  |                     </div> | 
 |  |  |                 </template> | 
 |  |  |                 <div class="chart-wrapper"> | 
 |  |  |                     <Echarts | 
 |  |  |                         ref="yieldChartRef" | 
 |  |  |                         :options="processingYieldOptions" | 
 |  |  |                         :chartStyle="{ height: '300px', width: '100%' }" | 
 |  |  |                     /> | 
 |  |  |                     <div ref="yieldChart" class="chart-content" style="height: 300px; width: 100%;"></div> | 
 |  |  |                 </div> | 
 |  |  |             </el-card> | 
 |  |  |              | 
 |  |  |             <!-- 成本结构图谱 --> | 
 |  |  |             <el-card class="chart-card cost-structure"> | 
 |  |  |             <el-card class="chart-card"> | 
 |  |  |                 <template #header> | 
 |  |  |                     <div class="card-header"> | 
 |  |  |                         <span>成本结构图谱</span> | 
 |  |  |                     </div> | 
 |  |  |                 </template> | 
 |  |  |                 <div class="chart-wrapper"> | 
 |  |  |                     <Echarts | 
 |  |  |                         ref="costChartRef" | 
 |  |  |                         :options="costStructureOptions" | 
 |  |  |                         :chartStyle="{ height: '300px', width: '100%' }" | 
 |  |  |                     /> | 
 |  |  |                     <div ref="costStructureChart" class="chart-content" style="height: 300px; width: 100%;"></div> | 
 |  |  |                 </div> | 
 |  |  |             </el-card> | 
 |  |  |         </div> | 
 |  |  | 
 |  |  | </template> | 
 |  |  |  | 
 |  |  | <script setup> | 
 |  |  | import { ref, onMounted, computed } from 'vue' | 
 |  |  | import { ref, onMounted, computed, nextTick } from 'vue' | 
 |  |  | import * as echarts from 'echarts' | 
 |  |  | import Echarts from '@/components/Echarts/echarts.vue' | 
 |  |  | import { ElMessage } from 'element-plus' | 
 |  |  | import { getReportStatistics, getReportTrend } from '@/api/productionScheduling/index.js' | 
 |  |  | import { processingRateAnalysis } from '@/api/productionScheduling/index.js' | 
 |  |  | import request from '@/utils/request' | 
 |  |  |  | 
 |  |  | // 成本结构图谱API函数 - 直接在组件内定义 | 
 |  |  | const costStructure = (query) => { | 
 |  |  |   return request({ | 
 |  |  |     url: '/productHome/costStructure', | 
 |  |  |     method: 'get', | 
 |  |  |     params: query | 
 |  |  |   }) | 
 |  |  | } | 
 |  |  |  | 
 |  |  | // 煤种发热量对比API函数 - 根据接口文档定义 | 
 |  |  | const coalTypeHeatValueComparison = (query) => { | 
 |  |  |   return request({ | 
 |  |  |     url: '/productHome/coalTypeHeatValueComparison', | 
 |  |  |     method: 'get', | 
 |  |  |     params: query | 
 |  |  |   }) | 
 |  |  | } | 
 |  |  |  | 
 |  |  |  | 
 |  |  | // 搜索参数 | 
 |  |  | 
 |  |  | ] | 
 |  |  |  | 
 |  |  | // 统计数据 | 
 |  |  | const unitHeatCoalConsumption = ref(32.5) | 
 |  |  | const overallComplianceRate = ref(85.7) | 
 |  |  | const averageCalorificValue = ref(5260) | 
 |  |  | const totalBatches = ref(48) | 
 |  |  | const unitHeatValue = ref(0) | 
 |  |  | const wholeStandardRate = ref(0) | 
 |  |  | const averageFuel = ref(0) | 
 |  |  | const frequency = ref(0) | 
 |  |  | const totalBatch = ref(0) | 
 |  |  |  | 
 |  |  | // 模拟数据 | 
 |  |  | const mockComplianceData = [ | 
 |  |  |     { date: '2023-06-01', rate: 82 }, | 
 |  |  |     { date: '2023-06-02', rate: 85 }, | 
 |  |  |     { date: '2023-06-03', rate: 88 }, | 
 |  |  |     { date: '2023-06-04', rate: 84 }, | 
 |  |  |     { date: '2023-06-05', rate: 87 }, | 
 |  |  |     { date: '2023-06-06', rate: 90 }, | 
 |  |  |     { date: '2023-06-07', rate: 86 }, | 
 |  |  |     { date: '2023-06-08', rate: 89 }, | 
 |  |  |     { date: '2023-06-09', rate: 92 }, | 
 |  |  |     { date: '2023-06-10', rate: 88 } | 
 |  |  | ] | 
 |  |  | // 达标率趋势数据引用 | 
 |  |  | const complianceChart = ref(null) | 
 |  |  |  | 
 |  |  | const mockCalorificData = [ | 
 |  |  |     { name: '烟煤', value: 5800 }, | 
 |  |  |     { name: '无烟煤', value: 6200 }, | 
 |  |  |     { name: '褐煤', value: 4500 }, | 
 |  |  |     { name: '贫煤', value: 5300 }, | 
 |  |  |     { name: '瘦煤', value: 5500 } | 
 |  |  | ] | 
 |  |  | // 加工得率图表引用 | 
 |  |  | const yieldChart = ref(null) | 
 |  |  |  | 
 |  |  | const mockRecipeData = [ | 
 |  |  |     { name: '配方A (烟煤60%+无烟煤40%)', value: 18 }, | 
 |  |  |     { name: '配方B (烟煤70%+褐煤30%)', value: 12 }, | 
 |  |  |     { name: '配方C (无烟煤50%+贫煤50%)', value: 8 }, | 
 |  |  |     { name: '配方D (烟煤50%+瘦煤50%)', value: 6 }, | 
 |  |  |     { name: '其他配方', value: 4 } | 
 |  |  | ] | 
 |  |  | // 成本结构图表引用 | 
 |  |  | const costStructureChart = ref(null) | 
 |  |  |  | 
 |  |  | const mockYieldData = [ | 
 |  |  |     { name: '烟煤', yield: 85, efficiency: 92 }, | 
 |  |  |     { name: '无烟煤', yield: 88, efficiency: 89 }, | 
 |  |  |     { name: '褐煤', yield: 75, efficiency: 78 }, | 
 |  |  |     { name: '贫煤', yield: 82, efficiency: 85 }, | 
 |  |  |     { name: '瘦煤', yield: 80, efficiency: 87 } | 
 |  |  | ] | 
 |  |  | // 煤种发热量对比图表引用 | 
 |  |  | const coalTypeHeatValueChart = ref(null) | 
 |  |  |  | 
 |  |  | const mockCostData = [ | 
 |  |  |     { name: '耗材', value: 45 }, | 
 |  |  |     { name: '能耗', value: 30 }, | 
 |  |  |     { name: '人力', value: 25 } | 
 |  |  | ] | 
 |  |  | // Echarts组件图表不需要额外的引用变量,组件内部会处理图表初始化 | 
 |  |  | // 移除未使用的图表引用变量,避免可能的冲突 | 
 |  |  |  | 
 |  |  | // 达标率趋势图配置 | 
 |  |  | const complianceTrendOptions = computed(() => ({ | 
 |  |  |     tooltip: { | 
 |  |  |         trigger: 'axis', | 
 |  |  |         formatter: '{b}<br/>达标率: {c}%' | 
 |  |  |     }, | 
 |  |  |     grid: { | 
 |  |  |         left: '3%', | 
 |  |  |         right: '4%', | 
 |  |  |         bottom: '3%', | 
 |  |  |         containLabel: true | 
 |  |  |     }, | 
 |  |  |     xAxis: { | 
 |  |  |         type: 'category', | 
 |  |  |         data: mockComplianceData.map(item => item.date), | 
 |  |  |         axisLabel: { | 
 |  |  |             rotate: 45 | 
 |  |  |         } | 
 |  |  |     }, | 
 |  |  |     yAxis: { | 
 |  |  |         type: 'value', | 
 |  |  |         name: '达标率 (%)', | 
 |  |  |         min: 70, | 
 |  |  |         max: 100 | 
 |  |  |     }, | 
 |  |  |     series: [ | 
 |  |  |         { | 
 |  |  |             name: '达标率', | 
 |  |  |             type: 'line', | 
 |  |  |             smooth: true, | 
 |  |  |             data: mockComplianceData.map(item => item.rate), | 
 |  |  |             itemStyle: { | 
 |  |  |                 color: '#409EFF' | 
 |  |  | // 达标率趋势数据 - 初始为空数据 | 
 |  |  | const complianceTrendData = ref({ | 
 |  |  |     Xkeys: [], | 
 |  |  |     Yvalues: [] | 
 |  |  | }) | 
 |  |  |  | 
 |  |  | // 加工得率分析数据 - 初始为空数据 | 
 |  |  | const processingYieldData = ref({ | 
 |  |  |     Xkeys: [], | 
 |  |  |     Yvalues: [] | 
 |  |  | }) | 
 |  |  |  | 
 |  |  | // 成本结构数据 - 初始为空数据 | 
 |  |  | const costStructureData = ref([]) | 
 |  |  |  | 
 |  |  | // 煤种发热量对比数据 - 初始为空数据 | 
 |  |  | const coalTypeHeatValueData = ref([]) | 
 |  |  |  | 
 |  |  | // 成本结构图谱初始化 | 
 |  |  | const initCostStructureChart = () => { | 
 |  |  |     if (!costStructureChart.value) return | 
 |  |  | 	 | 
 |  |  |     console.log('初始化成本结构图表,数据:', costStructureData.value); | 
 |  |  |     const chart = echarts.init(costStructureChart.value); | 
 |  |  |     const option = { | 
 |  |  |         title: { | 
 |  |  |             show: costStructureData.value.length === 0, // 没数据才显示 | 
 |  |  |             textStyle: { | 
 |  |  |                 color: "grey", | 
 |  |  |                 fontSize: 20, | 
 |  |  |             }, | 
 |  |  |             lineStyle: { | 
 |  |  |                 width: 3 | 
 |  |  |             }, | 
 |  |  |             areaStyle: { | 
 |  |  |                 color: { | 
 |  |  |                     type: 'linear', | 
 |  |  |                     x: 0, | 
 |  |  |                     y: 0, | 
 |  |  |                     x2: 0, | 
 |  |  |                     y2: 1, | 
 |  |  |                     colorStops: [{ | 
 |  |  |                         offset: 0, | 
 |  |  |                         color: 'rgba(64, 158, 255, 0.3)' | 
 |  |  |                     }, { | 
 |  |  |                         offset: 1, | 
 |  |  |                         color: 'rgba(64, 158, 255, 0.05)' | 
 |  |  |                     }] | 
 |  |  |             text: "暂无数据", | 
 |  |  |             left: "center", | 
 |  |  |             top: "center", | 
 |  |  |         }, | 
 |  |  |         tooltip: { | 
 |  |  |             trigger: 'item', | 
 |  |  |             // 根据API返回的数据结构格式化显示 | 
 |  |  |             formatter: '{b}: {c} ({d}%)' | 
 |  |  |         }, | 
 |  |  |         legend: { | 
 |  |  |             orient: 'vertical', | 
 |  |  |             left: 'right', | 
 |  |  |             top: 'center', | 
 |  |  |             textStyle: { | 
 |  |  |                 fontSize: 12 | 
 |  |  |             } | 
 |  |  |         }, | 
 |  |  |         series: [ | 
 |  |  |             { | 
 |  |  |                 name: '成本结构', | 
 |  |  |                 type: 'pie', | 
 |  |  |                 radius: ['30%', '70%'], | 
 |  |  |                 center: ['40%', '50%'], | 
 |  |  |                 data: costStructureData.value.length > 0  | 
 |  |  |                     ? costStructureData.value.map(item => ({ | 
 |  |  |                         name: item.name, | 
 |  |  |                         value: item.value | 
 |  |  |                     })) | 
 |  |  |                     : [], | 
 |  |  |                 emphasis: { | 
 |  |  |                     itemStyle: { | 
 |  |  |                         shadowBlur: 10, | 
 |  |  |                         shadowOffsetX: 0, | 
 |  |  |                         shadowColor: 'rgba(0, 0, 0, 0.5)' | 
 |  |  |                     } | 
 |  |  |                 }, | 
 |  |  |                 itemStyle: { | 
 |  |  |                     borderRadius: 4, | 
 |  |  |                     borderColor: '#fff', | 
 |  |  |                     borderWidth: 2 | 
 |  |  |                 }, | 
 |  |  |                 label: { | 
 |  |  |                     show: true, | 
 |  |  |                     formatter: '{b}\n{d}%' | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     ] | 
 |  |  | })) | 
 |  |  |         ] | 
 |  |  |     }; | 
 |  |  |     chart.setOption(option); | 
 |  |  |     window.addEventListener('resize', () => { | 
 |  |  |         chart.resize(); | 
 |  |  |     }); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | // 煤种发热量对比图配置 | 
 |  |  | // 达标率趋势图初始化 | 
 |  |  | const initComplianceChart = () => { | 
 |  |  |     if (!complianceChart.value) return | 
 |  |  | 	 | 
 |  |  |     const chart = echarts.init(complianceChart.value); | 
 |  |  |     const option = { | 
 |  |  |         title: { | 
 |  |  |             show: complianceTrendData.value.Yvalues.length === 0, // 没数据才显示 | 
 |  |  |             textStyle: { | 
 |  |  |                 color: "grey", | 
 |  |  |                 fontSize: 20, | 
 |  |  |             }, | 
 |  |  |             text: "暂无数据", | 
 |  |  |             left: "center", | 
 |  |  |             top: "center", | 
 |  |  |         }, | 
 |  |  |         tooltip: { | 
 |  |  |             trigger: 'axis', | 
 |  |  |             formatter: '{b}<br/>达标率: {c}%' | 
 |  |  |         }, | 
 |  |  |         grid: { | 
 |  |  |             left: '3%', | 
 |  |  |             right: '4%', | 
 |  |  |             bottom: '3%', | 
 |  |  |             containLabel: true | 
 |  |  |         }, | 
 |  |  |         xAxis: { | 
 |  |  |             type: 'category', | 
 |  |  |             data: complianceTrendData.value.Xkeys || [], | 
 |  |  |             axisLabel: { | 
 |  |  |                 rotate: 45 | 
 |  |  |             } | 
 |  |  |         }, | 
 |  |  |         yAxis: { | 
 |  |  |             type: 'value', | 
 |  |  |             name: '达标率 (%)', | 
 |  |  |             min: 0, // 固定最小值为0 | 
 |  |  |             max: 100, // 固定最大值为100 | 
 |  |  |             // 设置坐标轴标签格式为百分比 | 
 |  |  |             axisLabel: { | 
 |  |  |                 formatter: '{value}%' | 
 |  |  |             } | 
 |  |  |         }, | 
 |  |  |         series: [ | 
 |  |  |             { | 
 |  |  |                 name: '达标率', | 
 |  |  |                 type: 'line', | 
 |  |  |                 smooth: true, | 
 |  |  |                 data: complianceTrendData.value.Yvalues || [], | 
 |  |  |                 itemStyle: { | 
 |  |  |                     color: '#409EFF' | 
 |  |  |                 }, | 
 |  |  |                 // 添加标记点和标记线 | 
 |  |  |                 markPoint: { | 
 |  |  |                     data: [ | 
 |  |  |                         { type: 'max', name: '最大值' }, | 
 |  |  |                         { type: 'min', name: '最小值' } | 
 |  |  |                     ] | 
 |  |  |                 }, | 
 |  |  |                 markLine: { | 
 |  |  |                     data: [ | 
 |  |  |                         { type: 'average', name: '平均值' } | 
 |  |  |                     ] | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         ] | 
 |  |  |     } | 
 |  |  |     chart.setOption(option); | 
 |  |  |     window.addEventListener('resize', () => { | 
 |  |  |         chart.resize(); | 
 |  |  |     }); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | // 煤种发热量对比图初始化 | 
 |  |  | const initCoalTypeHeatValueChart = () => { | 
 |  |  |     if (!coalTypeHeatValueChart.value) return | 
 |  |  | 	 | 
 |  |  |     console.log('初始化煤种发热量对比图表,数据:', coalTypeHeatValueData.value); | 
 |  |  |     const chart = echarts.init(coalTypeHeatValueChart.value); | 
 |  |  |     const option = { | 
 |  |  |         title: { | 
 |  |  |             show: coalTypeHeatValueData.value.length === 0, // 没数据才显示 | 
 |  |  |             textStyle: { | 
 |  |  |                 color: "grey", | 
 |  |  |                 fontSize: 20, | 
 |  |  |             }, | 
 |  |  |             text: "暂无数据", | 
 |  |  |             left: "center", | 
 |  |  |             top: "center", | 
 |  |  |         }, | 
 |  |  |         tooltip: { | 
 |  |  |             trigger: 'axis', | 
 |  |  |             axisPointer: { | 
 |  |  |                 type: 'shadow' | 
 |  |  |             }, | 
 |  |  |             formatter: function(params) { | 
 |  |  |                 return params[0].name + '<br/>发热量: ' + params[0].value + ' 大卡'; | 
 |  |  |             } | 
 |  |  |         }, | 
 |  |  |         grid: { | 
 |  |  |             left: '3%', | 
 |  |  |             right: '4%', | 
 |  |  |             bottom: '10%', | 
 |  |  |             containLabel: true | 
 |  |  |         }, | 
 |  |  |         xAxis: { | 
 |  |  |             type: 'category', | 
 |  |  |             data: coalTypeHeatValueData.value.map(item => item.name) || [], | 
 |  |  |             axisLabel: { | 
 |  |  |                 fontSize: 11, | 
 |  |  |                 rotate: 45 | 
 |  |  |             } | 
 |  |  |         }, | 
 |  |  |         yAxis: { | 
 |  |  |             type: 'value', | 
 |  |  |             axisLabel: { | 
 |  |  |                 fontSize: 11 | 
 |  |  |             } | 
 |  |  |         }, | 
 |  |  |         series: [ | 
 |  |  |             { | 
 |  |  |                 name: '发热量', | 
 |  |  |                 type: 'bar', | 
 |  |  |                 data: coalTypeHeatValueData.value.map(item => item.value) || [], | 
 |  |  |                 itemStyle: { | 
 |  |  |                     color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ | 
 |  |  |                         { offset: 0, color: '#409EFF' }, | 
 |  |  |                         { offset: 1, color: '#79bbff' } | 
 |  |  |                     ]) | 
 |  |  |                 }, | 
 |  |  |                 barWidth: '60%', | 
 |  |  |                 label: { | 
 |  |  |                     show: true, | 
 |  |  |                     position: 'top', | 
 |  |  |                     formatter: function(params) { | 
 |  |  |                         return params.value + '大卡'; | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         ] | 
 |  |  |     }; | 
 |  |  |     chart.setOption(option); | 
 |  |  |     window.addEventListener('resize', () => { | 
 |  |  |         chart.resize(); | 
 |  |  |     }); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | // 加工得率趋势图初始化 | 
 |  |  | const initProcessingYieldChart = () => { | 
 |  |  |     if (!yieldChart.value) return | 
 |  |  | 	 | 
 |  |  |     console.log('初始化加工得率图表,数据:', processingYieldData.value); | 
 |  |  |     const chart = echarts.init(yieldChart.value); | 
 |  |  |     const option = { | 
 |  |  |         title: { | 
 |  |  |             show: processingYieldData.value.Yvalues.length === 0, // 没数据才显示 | 
 |  |  |             textStyle: { | 
 |  |  |                 color: "grey", | 
 |  |  |                 fontSize: 20, | 
 |  |  |             }, | 
 |  |  |             text: "暂无数据", | 
 |  |  |             left: "center", | 
 |  |  |             top: "center", | 
 |  |  |         }, | 
 |  |  |         tooltip: { | 
 |  |  |             trigger: 'axis', | 
 |  |  |             formatter: '{b}<br/>得率: {c}%' | 
 |  |  |         }, | 
 |  |  |         grid: { | 
 |  |  |             left: '3%', | 
 |  |  |             right: '4%', | 
 |  |  |             bottom: '3%', | 
 |  |  |             containLabel: true | 
 |  |  |         }, | 
 |  |  |         xAxis: { | 
 |  |  |             type: 'category', | 
 |  |  |             data: processingYieldData.value.Xkeys || [], | 
 |  |  |             axisLabel: { | 
 |  |  |                 rotate: 45 | 
 |  |  |             } | 
 |  |  |         }, | 
 |  |  |         yAxis: { | 
 |  |  |             type: 'value', | 
 |  |  |             name: '得率 (%)', | 
 |  |  |             min: 0, | 
 |  |  |             // 最大值改为数据中的最大值,并增加5%的余量 | 
 |  |  |             max: processingYieldData.value.Yvalues && processingYieldData.value.Yvalues.length > 0  | 
 |  |  |                 ? Math.ceil(Math.max(...processingYieldData.value.Yvalues) * 1.05)  | 
 |  |  |                 : 100, | 
 |  |  |             // 设置坐标轴标签格式为百分比 | 
 |  |  |             axisLabel: { | 
 |  |  |                 formatter: '{value}%' | 
 |  |  |             } | 
 |  |  |         }, | 
 |  |  |         series: [ | 
 |  |  |             { | 
 |  |  |                 name: '加工得率', | 
 |  |  |                 type: 'line', | 
 |  |  |                 smooth: true, | 
 |  |  |                 data: processingYieldData.value.Yvalues || [], | 
 |  |  |                 itemStyle: { | 
 |  |  |                     color: '#52C41A' | 
 |  |  |                 }, | 
 |  |  |                 lineStyle: { | 
 |  |  |                     width: 3, // 增加线条宽度 | 
 |  |  |                     color: '#52C41A' | 
 |  |  |                 }, | 
 |  |  |                 showSymbol: true, // 显示标记点 | 
 |  |  |                 symbol: 'circle', | 
 |  |  |                 symbolSize: 8, // 增加标记点大小 | 
 |  |  |                 // 添加标记点和标记线 | 
 |  |  |                 markPoint: { | 
 |  |  |                     data: [ | 
 |  |  |                         { type: 'max', name: '最大值' }, | 
 |  |  |                         { type: 'min', name: '最小值' } | 
 |  |  |                     ] | 
 |  |  |                 }, | 
 |  |  |                 markLine: { | 
 |  |  |                     data: [ | 
 |  |  |                         { type: 'average', name: '平均值' } | 
 |  |  |                     ] | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         ] | 
 |  |  |     }; | 
 |  |  |     chart.setOption(option, true); // 强制重新渲染 | 
 |  |  |     window.addEventListener('resize', () => { | 
 |  |  |         chart.resize(); | 
 |  |  |     }); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | // 煤种发热量对比图配置 - 使用API获取的数据 | 
 |  |  | const calorificValueOptions = computed(() => ({ | 
 |  |  |     title: { | 
 |  |  |         show: coalTypeHeatValueData.value.length === 0, // 没数据才显示 | 
 |  |  |         textStyle: { | 
 |  |  |             color: "grey", | 
 |  |  |             fontSize: 20, | 
 |  |  |         }, | 
 |  |  |         text: "暂无数据", | 
 |  |  |         left: "center", | 
 |  |  |         top: "center", | 
 |  |  |     }, | 
 |  |  |     tooltip: { | 
 |  |  |         trigger: 'axis', | 
 |  |  |         axisPointer: { | 
 |  |  |             type: 'shadow' | 
 |  |  |         }, | 
 |  |  |         formatter: '{b}<br/>发热量: {c} 大卡' | 
 |  |  |         formatter: '{b}<br/>发热量: {c} 大卡<br/>占比: {d}%' | 
 |  |  |     }, | 
 |  |  |     grid: { | 
 |  |  |         left: '3%', | 
 |  |  | 
 |  |  |     }, | 
 |  |  |     xAxis: { | 
 |  |  |         type: 'category', | 
 |  |  |         data: mockCalorificData.map(item => item.name) | 
 |  |  |         data: coalTypeHeatValueData.value.map(item => item.name) || [], | 
 |  |  |         axisLabel: { | 
 |  |  |             rotate: 45 | 
 |  |  |         } | 
 |  |  |     }, | 
 |  |  |     yAxis: { | 
 |  |  |         type: 'value', | 
 |  |  | 
 |  |  |         { | 
 |  |  |             name: '发热量', | 
 |  |  |             type: 'bar', | 
 |  |  |             data: mockCalorificData.map(item => item.value), | 
 |  |  |             data: coalTypeHeatValueData.value.map(item => ({ | 
 |  |  |                 value: item.value, | 
 |  |  |                 percent: item.percent | 
 |  |  |             })) || [], | 
 |  |  |             itemStyle: { | 
 |  |  |                 color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ | 
 |  |  |                     { offset: 0, color: '#FF6B81' }, | 
 |  |  | 
 |  |  |             label: { | 
 |  |  |                 show: true, | 
 |  |  |                 position: 'top', | 
 |  |  |                 formatter: '{c}大卡' | 
 |  |  |                 formatter: function(params) { | 
 |  |  |                     // 使用原始数据中的percent值 | 
 |  |  |                     const item = coalTypeHeatValueData.value.find(item => item.name === params.name); | 
 |  |  |                     return params.value + '大卡\n(' + (item && item.percent ? item.percent.toFixed(2) : '0') + '%)'; | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     ] | 
 |  |  | })) | 
 |  |  |  | 
 |  |  | // 配方使用频次图配置 | 
 |  |  | const recipeFrequencyOptions = computed(() => ({ | 
 |  |  | // 加工得率分析相关的配置已移除,现在使用手动初始化方式 | 
 |  |  |  | 
 |  |  | // 成本结构图谱配置 - 使用API获取的数据 | 
 |  |  | const costStructureOptions = computed(() => ({ | 
 |  |  |     title: { | 
 |  |  |         show: costStructureData.value.length === 0, // 没数据才显示 | 
 |  |  |         textStyle: { | 
 |  |  |             color: "grey", | 
 |  |  |             fontSize: 20, | 
 |  |  |         }, | 
 |  |  |         text: "暂无数据", | 
 |  |  |         left: "center", | 
 |  |  |         top: "center", | 
 |  |  |     }, | 
 |  |  |     tooltip: { | 
 |  |  |         trigger: 'item', | 
 |  |  |         formatter: '{b}: {c}次 ({d}%)' | 
 |  |  |         // 根据API返回的数据结构格式化显示 | 
 |  |  |         formatter: '{b}: {c} ({d}%)' | 
 |  |  |     }, | 
 |  |  |     legend: { | 
 |  |  |         orient: 'vertical', | 
 |  |  | 
 |  |  |     }, | 
 |  |  |     series: [ | 
 |  |  |         { | 
 |  |  |             name: '配方使用频次', | 
 |  |  |             type: 'pie', | 
 |  |  |             radius: '60%', | 
 |  |  |             center: ['60%', '50%'], | 
 |  |  |             data: mockRecipeData, | 
 |  |  |             emphasis: { | 
 |  |  |                 itemStyle: { | 
 |  |  |                     shadowBlur: 10, | 
 |  |  |                     shadowOffsetX: 0, | 
 |  |  |                     shadowColor: 'rgba(0, 0, 0, 0.5)' | 
 |  |  |                 } | 
 |  |  |             }, | 
 |  |  |             itemStyle: { | 
 |  |  |                 borderRadius: 8, | 
 |  |  |                 borderColor: '#fff', | 
 |  |  |                 borderWidth: 2 | 
 |  |  |             }, | 
 |  |  |             label: { | 
 |  |  |                 show: true, | 
 |  |  |                 formatter: '{b}\n{c}次' | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     ] | 
 |  |  | })) | 
 |  |  |  | 
 |  |  | // 加工得率分析图配置 | 
 |  |  | const processingYieldOptions = computed(() => ({ | 
 |  |  |     tooltip: { | 
 |  |  |         trigger: 'axis', | 
 |  |  |         axisPointer: { | 
 |  |  |             type: 'shadow' | 
 |  |  |         } | 
 |  |  |     }, | 
 |  |  |     legend: { | 
 |  |  |         data: ['出洗率', '加工能效'] | 
 |  |  |     }, | 
 |  |  |     grid: { | 
 |  |  |         left: '3%', | 
 |  |  |         right: '4%', | 
 |  |  |         bottom: '3%', | 
 |  |  |         containLabel: true | 
 |  |  |     }, | 
 |  |  |     xAxis: { | 
 |  |  |         type: 'category', | 
 |  |  |         data: mockYieldData.map(item => item.name) | 
 |  |  |     }, | 
 |  |  |     yAxis: { | 
 |  |  |         type: 'value', | 
 |  |  |         name: '百分比 (%)', | 
 |  |  |         min: 60, | 
 |  |  |         max: 100 | 
 |  |  |     }, | 
 |  |  |     series: [ | 
 |  |  |         { | 
 |  |  |             name: '出洗率', | 
 |  |  |             type: 'bar', | 
 |  |  |             data: mockYieldData.map(item => item.yield), | 
 |  |  |             itemStyle: { | 
 |  |  |                 color: '#52C41A' | 
 |  |  |             } | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             name: '加工能效', | 
 |  |  |             type: 'bar', | 
 |  |  |             data: mockYieldData.map(item => item.efficiency), | 
 |  |  |             itemStyle: { | 
 |  |  |                 color: '#1890FF' | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     ] | 
 |  |  | })) | 
 |  |  |  | 
 |  |  | // 成本结构图谱配置 | 
 |  |  | const costStructureOptions = computed(() => ({ | 
 |  |  |     tooltip: { | 
 |  |  |         trigger: 'item', | 
 |  |  |         formatter: '{b}: {c}%' | 
 |  |  |     }, | 
 |  |  |     legend: { | 
 |  |  |         orient: 'vertical', | 
 |  |  |         left: 'left' | 
 |  |  |     }, | 
 |  |  |     series: [ | 
 |  |  |         { | 
 |  |  |             name: '成本结构', | 
 |  |  |             type: 'pie', | 
 |  |  |             radius: '60%', | 
 |  |  |             center: ['60%', '50%'], | 
 |  |  |             data: mockCostData, | 
 |  |  |             data: costStructureData.value.length > 0  | 
 |  |  |                 ? costStructureData.value.map(item => ({ | 
 |  |  |                     name: item.name, | 
 |  |  |                     value: item.value, | 
 |  |  |                     percent: item.percent | 
 |  |  |                 })) | 
 |  |  |                 : [], | 
 |  |  |             emphasis: { | 
 |  |  |                 itemStyle: { | 
 |  |  |                     shadowBlur: 10, | 
 |  |  | 
 |  |  |                     shadowColor: 'rgba(0, 0, 0, 0.5)' | 
 |  |  |                 } | 
 |  |  |             }, | 
 |  |  |             roseType: 'radius', | 
 |  |  |             itemStyle: { | 
 |  |  |                 borderRadius: 8, | 
 |  |  |                 borderRadius: 4, | 
 |  |  |                 borderColor: '#fff', | 
 |  |  |                 borderWidth: 2 | 
 |  |  |             }, | 
 |  |  |             // 设置标签格式化,显示占比 | 
 |  |  |             label: { | 
 |  |  |                 show: true, | 
 |  |  |                 formatter: '{b}\n{d}%' | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     ] | 
 |  |  | 
 |  |  | const handleSearch = async () => { | 
 |  |  |     try { | 
 |  |  |         loading.value = true | 
 |  |  |         // 在实际应用中,这里会调用API获取真实数据 | 
 |  |  |         console.log('搜索参数:', searchParams.value) | 
 |  |  |         // 构建请求参数 | 
 |  |  |         const params = { | 
 |  |  |             entryDateStart: searchParams.value.dateRange && searchParams.value.dateRange[0] ? | 
 |  |  |                 searchParams.value.dateRange[0].toISOString().split('T')[0] : '', | 
 |  |  |             entryDateEnd: searchParams.value.dateRange && searchParams.value.dateRange[1] ? | 
 |  |  |                 searchParams.value.dateRange[1].toISOString().split('T')[0] : '' | 
 |  |  |         } | 
 |  |  |         console.log('搜索参数:', params) | 
 |  |  |          | 
 |  |  |         // 获取配煤数据 | 
 |  |  |         // const blendingRes = await getCoalBlendingList({ | 
 |  |  |         //   startTime: searchParams.value.dateRange[0] ? parseTime(searchParams.value.dateRange[0]) : '', | 
 |  |  |         //   endTime: searchParams.value.dateRange[1] ? parseTime(searchParams.value.dateRange[1]) : '' | 
 |  |  |         // }) | 
 |  |  |         // 调用API获取报表统计数据 | 
 |  |  |         const res = await getReportStatistics(params) | 
 |  |  |          | 
 |  |  |         // 模拟API请求延迟 | 
 |  |  |         await new Promise(resolve => setTimeout(resolve, 800)) | 
 |  |  |         if (res.code === 200 && res.data) { | 
 |  |  |             // 更新统计数据 | 
 |  |  |             unitHeatValue.value = res.data.unitHeatValue || 0 | 
 |  |  |             wholeStandardRate.value = res.data.wholeStandardRate || 0 | 
 |  |  |             averageFuel.value = res.data.averageFuel || 0 | 
 |  |  |             frequency.value = res.data.frequency || 0 | 
 |  |  |             totalBatch.value = res.data.totalBatch || 0 | 
 |  |  |         } else { | 
 |  |  |             throw new Error(res.msg || '获取数据失败') | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |         // 模拟数据更新(实际应用中应根据API返回结果更新) | 
 |  |  |         unitHeatCoalConsumption.value = 31.8 + Math.random() * 5 | 
 |  |  |         overallComplianceRate.value = 80 + Math.random() * 15 | 
 |  |  |         averageCalorificValue.value = 5000 + Math.random() * 500 | 
 |  |  |         totalBatches.value = 40 + Math.floor(Math.random() * 20) | 
 |  |  |         // 调用API获取达标率趋势数据 | 
 |  |  |         const trendRes = await getReportTrend(params) | 
 |  |  |          | 
 |  |  |         // 随机更新部分图表数据 | 
 |  |  |         mockComplianceData.forEach(item => { | 
 |  |  |             item.rate = 80 + Math.random() * 15 | 
 |  |  |         if (trendRes.code === 200 && trendRes.data && trendRes.data.length > 0) { | 
 |  |  |             // 预处理达标率趋势数据,确保value字段是有效的数字 | 
 |  |  |             const Xkeys = [] | 
 |  |  |             const Yvalues = [] | 
 |  |  |             trendRes.data.forEach(item => { | 
 |  |  |                 Xkeys.push(item.name || '') | 
 |  |  |                 Yvalues.push(typeof item.value === 'number' ? item.value : parseFloat(item.value) || 0) | 
 |  |  |             }) | 
 |  |  |             // 更新达标率趋势数据 | 
 |  |  |             complianceTrendData.value = { | 
 |  |  |                 Xkeys, | 
 |  |  |                 Yvalues | 
 |  |  |             } | 
 |  |  |         } else { | 
 |  |  |             console.warn('获取达标率趋势数据失败:', trendRes.msg) | 
 |  |  |             // 设置空数据,显示暂无数据提示 | 
 |  |  |             complianceTrendData.value = { Xkeys: [], Yvalues: [] } | 
 |  |  |         } | 
 |  |  | 		 | 
 |  |  |         // 调用API获取加工得率分析数据 | 
 |  |  |         const yieldRes = await processingRateAnalysis(params) | 
 |  |  | 		 | 
 |  |  |         if (yieldRes.code === 200 && yieldRes.data && yieldRes.data.length > 0) { | 
 |  |  |             // 预处理加工得率数据 | 
 |  |  |             const Xkeys = [] | 
 |  |  |             const Yvalues = [] | 
 |  |  |             yieldRes.data.forEach(item => { | 
 |  |  |                 Xkeys.push(item.name || '') | 
 |  |  |                 Yvalues.push(typeof item.value === 'number' ? item.value : parseFloat(item.value) || 0) | 
 |  |  |             }) | 
 |  |  |             // 更新加工得率数据 | 
 |  |  |             processingYieldData.value = { | 
 |  |  |                 Xkeys, | 
 |  |  |                 Yvalues | 
 |  |  |             } | 
 |  |  |         } else { | 
 |  |  |             console.warn('获取加工得率数据失败:', yieldRes.msg) | 
 |  |  |             // 设置空数据,显示暂无数据提示 | 
 |  |  |             processingYieldData.value = { Xkeys: [], Yvalues: [] } | 
 |  |  |         } | 
 |  |  | 		 | 
 |  |  |         // 调用API获取成本结构数据 | 
 |  |  |         const costRes = await costStructure(params) | 
 |  |  | 		 | 
 |  |  |         if (costRes.code === 200 && costRes.data && costRes.data.length > 0) { | 
 |  |  |             // 更新成本结构数据 | 
 |  |  |             costStructureData.value = costRes.data | 
 |  |  |         } else { | 
 |  |  |             console.warn('获取成本结构数据失败:', costRes.msg) | 
 |  |  |             // 设置空数据,显示暂无数据提示 | 
 |  |  |             costStructureData.value = [] | 
 |  |  |         } | 
 |  |  | 		 | 
 |  |  |         // 调用API获取煤种发热量对比数据 | 
 |  |  |         const coalValueRes = await coalTypeHeatValueComparison(params) | 
 |  |  | 		 | 
 |  |  |         if (coalValueRes.code === 200 && coalValueRes.data && coalValueRes.data.length > 0) { | 
 |  |  |             // 更新煤种发热量对比数据 | 
 |  |  |             coalTypeHeatValueData.value = coalValueRes.data | 
 |  |  |         } else { | 
 |  |  |             console.warn('获取煤种发热量对比数据失败:', coalValueRes.msg) | 
 |  |  |             // 设置空数据,显示暂无数据提示 | 
 |  |  |             coalTypeHeatValueData.value = [] | 
 |  |  |         } | 
 |  |  | 		 | 
 |  |  |         // 数据更新后重新初始化图表 | 
 |  |  |         nextTick(() => { | 
 |  |  |             initComplianceChart() | 
 |  |  |             initProcessingYieldChart() | 
 |  |  |             initCostStructureChart() | 
 |  |  |             initCoalTypeHeatValueChart() | 
 |  |  |         }) | 
 |  |  | 		 | 
 |  |  |         ElMessage.success('查询成功') | 
 |  |  |     } catch (error) { | 
 |  |  |         console.error('查询失败:', error) | 
 |  |  |         ElMessage.error('查询失败,请稍后重试') | 
 |  |  | 
 |  |  |      | 
 |  |  |     // 初始加载数据 | 
 |  |  |     handleSearch() | 
 |  |  | 	 | 
 |  |  |     // 初始化图表 | 
 |  |  |     nextTick(() => { | 
 |  |  |         initComplianceChart() | 
 |  |  |         initProcessingYieldChart() | 
 |  |  |         initCostStructureChart() | 
 |  |  |         initCoalTypeHeatValueChart() | 
 |  |  |     }) | 
 |  |  | }) | 
 |  |  | </script> | 
 |  |  |  |