<template>
|
<div class="coal-blending-efficiency">
|
<div class="page-header">
|
<div class="search-form">
|
<el-form :inline="true" :model="searchParams" class="demo-form-inline">
|
<el-form-item label="时间范围">
|
<el-date-picker
|
v-model="searchParams.dateRange"
|
type="daterange"
|
range-separator="至"
|
start-placeholder="开始日期"
|
end-placeholder="结束日期"
|
:shortcuts="dateShortcuts"
|
/>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="handleSearch" :loading="loading">查询</el-button>
|
<el-button @click="handleReset">重置</el-button>
|
</el-form-item>
|
</el-form>
|
</div>
|
</div>
|
|
<!-- 统计卡片区域 -->
|
<div class="stats-cards">
|
<div class="stat-card">
|
<div class="card-icon">
|
<i class="el-icon-s-operation"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-title">单位热值耗煤量</div>
|
<div class="card-value">{{ unitHeatValue.toFixed(2) }} kg/GJ</div>
|
</div>
|
</div>
|
|
<div class="stat-card">
|
<div class="card-icon">
|
<i class="el-icon-check-circle"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-title">整体达标率</div>
|
<div class="card-value">{{ wholeStandardRate.toFixed(2) }}%</div>
|
</div>
|
</div>
|
|
<div class="stat-card">
|
<div class="card-icon">
|
<i class="el-icon-data-line"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-title">平均发热量</div>
|
<div class="card-value">{{ averageFuel.toFixed(0) }} 大卡</div>
|
</div>
|
</div>
|
|
<div class="stat-card">
|
<div class="card-icon">
|
<i class="el-icon-files"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-title">配方使用频次</div>
|
<div class="card-value">{{ frequency }} 次</div>
|
</div>
|
</div>
|
|
<div class="stat-card">
|
<div class="card-icon">
|
<i class="el-icon-s-data"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-title">总批次</div>
|
<div class="card-value">{{ totalBatch }}</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 图表区域 -->
|
<div class="charts-container">
|
<!-- 达标率趋势图 -->
|
<el-card class="chart-card">
|
<template #header>
|
<div class="card-header">
|
<span>达标率趋势</span>
|
</div>
|
</template>
|
<div class="chart-wrapper">
|
<div ref="complianceChart" 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">
|
<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">
|
<div ref="yieldChart" 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">
|
<div ref="costStructureChart" class="chart-content" style="height: 300px; width: 100%;"></div>
|
</div>
|
</el-card>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
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 searchParams = ref({
|
dateRange: []
|
})
|
|
// 日期快捷选项
|
const dateShortcuts = [
|
{
|
text: '近7天',
|
value: () => {
|
const end = new Date()
|
const start = new Date()
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
|
return [start, end]
|
}
|
},
|
{
|
text: '近30天',
|
value: () => {
|
const end = new Date()
|
const start = new Date()
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
|
return [start, end]
|
}
|
},
|
{
|
text: '本月',
|
value: () => {
|
const end = new Date()
|
const start = new Date(end.getFullYear(), end.getMonth(), 1)
|
return [start, end]
|
}
|
}
|
]
|
|
// 统计数据
|
const unitHeatValue = ref(0)
|
const wholeStandardRate = ref(0)
|
const averageFuel = ref(0)
|
const frequency = ref(0)
|
const totalBatch = ref(0)
|
|
// 达标率趋势数据引用
|
const complianceChart = ref(null)
|
|
// 加工得率图表引用
|
const yieldChart = ref(null)
|
|
// 成本结构图表引用
|
const costStructureChart = ref(null)
|
|
// 煤种发热量对比图表引用
|
const coalTypeHeatValueChart = ref(null)
|
|
// Echarts组件图表不需要额外的引用变量,组件内部会处理图表初始化
|
// 移除未使用的图表引用变量,避免可能的冲突
|
|
// 达标率趋势数据 - 初始为空数据
|
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,
|
},
|
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} 大卡<br/>占比: {d}%'
|
},
|
grid: {
|
left: '3%',
|
right: '4%',
|
bottom: '3%',
|
containLabel: true
|
},
|
xAxis: {
|
type: 'category',
|
data: coalTypeHeatValueData.value.map(item => item.name) || [],
|
axisLabel: {
|
rotate: 45
|
}
|
},
|
yAxis: {
|
type: 'value',
|
name: '发热量 (大卡)'
|
},
|
series: [
|
{
|
name: '发热量',
|
type: 'bar',
|
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' },
|
{ offset: 1, color: '#FF8E53' }
|
])
|
},
|
label: {
|
show: true,
|
position: 'top',
|
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') + '%)';
|
}
|
}
|
}
|
]
|
}))
|
|
// 加工得率分析相关的配置已移除,现在使用手动初始化方式
|
|
// 成本结构图谱配置 - 使用API获取的数据
|
const costStructureOptions = computed(() => ({
|
title: {
|
show: costStructureData.value.length === 0, // 没数据才显示
|
textStyle: {
|
color: "grey",
|
fontSize: 20,
|
},
|
text: "暂无数据",
|
left: "center",
|
top: "center",
|
},
|
tooltip: {
|
trigger: 'item',
|
// 根据API返回的数据结构格式化显示
|
formatter: '{b}: {c} ({d}%)'
|
},
|
legend: {
|
orient: 'vertical',
|
left: 'left',
|
textStyle: {
|
fontSize: 12
|
}
|
},
|
series: [
|
{
|
name: '成本结构',
|
type: 'pie',
|
radius: '60%',
|
center: ['60%', '50%'],
|
data: costStructureData.value.length > 0
|
? costStructureData.value.map(item => ({
|
name: item.name,
|
value: item.value,
|
percent: item.percent
|
}))
|
: [],
|
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}%'
|
}
|
}
|
]
|
}))
|
|
// 查询数据
|
const loading = ref(false)
|
|
const handleSearch = async () => {
|
try {
|
loading.value = true
|
// 构建请求参数
|
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)
|
|
// 调用API获取报表统计数据
|
const res = await getReportStatistics(params)
|
|
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获取达标率趋势数据
|
const trendRes = await getReportTrend(params)
|
|
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()
|
})
|
} catch (error) {
|
console.error('查询失败:', error)
|
ElMessage.error('查询失败,请稍后重试')
|
} finally {
|
loading.value = false
|
}
|
}
|
|
// 刷新数据
|
const handleRefresh = () => {
|
ElMessage.info('正在刷新数据...')
|
handleSearch()
|
}
|
|
// 导出数据
|
const handleExport = async () => {
|
try {
|
loading.value = true
|
// 模拟导出操作
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
ElMessage.success('数据导出成功')
|
} catch (error) {
|
console.error('导出失败:', error)
|
ElMessage.error('导出失败,请稍后重试')
|
} finally {
|
loading.value = false
|
}
|
}
|
|
// 重置搜索参数
|
const handleReset = () => {
|
searchParams.value = {
|
dateRange: []
|
}
|
}
|
|
// 初始化页面
|
onMounted(() => {
|
// 默认查询近7天数据
|
const end = new Date()
|
const start = new Date()
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
|
searchParams.value.dateRange = [start, end]
|
|
// 初始加载数据
|
handleSearch()
|
|
// 初始化图表
|
nextTick(() => {
|
initComplianceChart()
|
initProcessingYieldChart()
|
initCostStructureChart()
|
initCoalTypeHeatValueChart()
|
})
|
})
|
</script>
|
|
<style scoped>
|
.coal-blending-efficiency {
|
padding: 20px;
|
}
|
|
.page-header {
|
margin-bottom: 20px;
|
}
|
|
.page-header h2 {
|
margin-bottom: 15px;
|
font-size: 18px;
|
font-weight: 600;
|
color: #303133;
|
}
|
|
.stats-cards {
|
display: grid;
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
gap: 16px;
|
margin-bottom: 24px;
|
}
|
|
.stat-card {
|
display: flex;
|
padding: 20px;
|
background: #fff;
|
border-radius: 8px;
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
transition: transform 0.3s, box-shadow 0.3s;
|
}
|
|
.stat-card:hover {
|
transform: translateY(-2px);
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
}
|
|
.card-icon {
|
width: 48px;
|
height: 48px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
border-radius: 50%;
|
font-size: 24px;
|
margin-right: 16px;
|
}
|
|
.stat-card:nth-child(1) .card-icon {
|
background: #ECF5FF;
|
color: #409EFF;
|
}
|
|
.stat-card:nth-child(2) .card-icon {
|
background: #F0F9FF;
|
color: #69B1FF;
|
}
|
|
.stat-card:nth-child(3) .card-icon {
|
background: #F6FFED;
|
color: #52C41A;
|
}
|
|
.stat-card:nth-child(4) .card-icon {
|
background: #FFF7E6;
|
color: #FAAD14;
|
}
|
|
.card-content {
|
flex: 1;
|
}
|
|
.card-title {
|
font-size: 14px;
|
color: #606266;
|
margin-bottom: 8px;
|
}
|
|
.card-value {
|
font-size: 24px;
|
font-weight: 600;
|
color: #303133;
|
margin-bottom: 4px;
|
}
|
|
.card-desc {
|
font-size: 12px;
|
color: #909399;
|
}
|
|
.charts-container {
|
display: grid;
|
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
|
gap: 24px;
|
}
|
|
.chart-card {
|
background: #fff;
|
border-radius: 8px;
|
overflow: hidden;
|
}
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 16px;
|
border-bottom: 1px solid #EBEEF5;
|
}
|
|
.card-header span {
|
font-weight: 600;
|
color: #303133;
|
}
|
|
.chart-wrapper {
|
padding: 20px;
|
}
|
|
.cost-structure {
|
grid-column: 1 / -1;
|
}
|
|
@media (max-width: 1200px) {
|
.charts-container {
|
grid-template-columns: 1fr;
|
}
|
}
|
</style>
|