| | |
| | | <template> |
| | | <div class="dashboard-container"> |
| | | <div class="data-dashboard"> |
| | | |
| | | <!-- 顶部标题栏 --> |
| | | <!-- <div class="dashboard-header"> |
| | | <!-- 顶部标题栏 --> |
| | | <!-- <div class="dashboard-header"> |
| | | <div class="factory-name">生产统计看板</div> |
| | | </div> --> |
| | | |
| | | <!-- 筛选区域 --> |
| | | <div class="filter-area"> |
| | | <div class="filter-section"> |
| | | <span class="filter-label">时间维度:</span> |
| | | <el-radio-group v-model="dateType" @change="handleDateTypeChange" class="radio-group"> |
| | | <el-radio-button label="month">月度</el-radio-button> |
| | | <el-radio-button label="year">年度</el-radio-button> |
| | | </el-radio-group> |
| | | <!-- 筛选区域 --> |
| | | <div class="filter-area"> |
| | | <div class="filter-section"> |
| | | <span class="filter-label">时间维度:</span> |
| | | <el-radio-group v-model="dateType" |
| | | @change="handleDateTypeChange" |
| | | class="radio-group"> |
| | | <el-radio-button label="month">月度</el-radio-button> |
| | | <el-radio-button label="year">年度</el-radio-button> |
| | | </el-radio-group> |
| | | </div> |
| | | <div class="filter-section"> |
| | | <span class="filter-label">产品类型:</span> |
| | | <el-radio-group v-model="productType" |
| | | @change="handleProductTypeChange" |
| | | class="radio-group"> |
| | | <el-radio-button label="block">砌块</el-radio-button> |
| | | <el-radio-button label="plate">板材</el-radio-button> |
| | | </el-radio-group> |
| | | </div> |
| | | </div> |
| | | <div class="filter-section"> |
| | | <span class="filter-label">产品类型:</span> |
| | | <el-radio-group v-model="productType" @change="handleProductTypeChange" class="radio-group"> |
| | | <el-radio-button label="block">砌块</el-radio-button> |
| | | <el-radio-button label="plate">板材</el-radio-button> |
| | | </el-radio-group> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 主要内容区域 --> |
| | | <div class="dashboard-content"> |
| | | <!-- 第一行 --> |
| | | <div class="row row-1"> |
| | | <div class="panel-card card-1"> |
| | | <div class="panel-title">产量指标</div> |
| | | <div class="chart-container"> |
| | | <div ref="productionChart" style="width: 100%; height: 100%"></div> |
| | | <!-- 主要内容区域 --> |
| | | <div class="dashboard-content"> |
| | | <!-- 第一行 --> |
| | | <div class="row row-1"> |
| | | <div class="panel-card card-1"> |
| | | <div class="panel-title">产量指标</div> |
| | | <div class="chart-container"> |
| | | <div ref="productionChart" |
| | | style="width: 100%; height: 100%"></div> |
| | | </div> |
| | | </div> |
| | | <div class="panel-card card-2"> |
| | | <div class="panel-title">固废处理量</div> |
| | | <div class="chart-container"> |
| | | <div ref="solidWasteChart" |
| | | style="width: 100%; height: 100%"></div> |
| | | </div> |
| | | </div> |
| | | <div class="panel-card card-3"> |
| | | <div class="panel-title">综合统计</div> |
| | | <div class="stats-grid"> |
| | | <div class="stat-item"> |
| | | <div class="stat-label">总产能</div> |
| | | <div class="stat-value production-color">{{ totalProduction }}</div> |
| | | <div class="stat-unit">立方米</div> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <div class="stat-label">总固废处理</div> |
| | | <div class="stat-value waste-color">{{ totalSolidWaste }}</div> |
| | | <div class="stat-unit">吨</div> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <div class="stat-label">平均单耗</div> |
| | | <div class="stat-value consumption-color">{{ averageUnitConsumption }}</div> |
| | | <div class="stat-unit">吨/立方米</div> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <div class="stat-label">总能耗</div> |
| | | <div class="stat-value energy-color">{{ totalEnergy }}</div> |
| | | <div class="stat-unit">kWh</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="panel-card card-2"> |
| | | <div class="panel-title">固废处理量</div> |
| | | <div class="chart-container"> |
| | | <div ref="solidWasteChart" style="width: 100%; height: 100%"></div> |
| | | <!-- 第二行 --> |
| | | <div class="row row-2"> |
| | | <div class="panel-card card-4"> |
| | | <div class="panel-title">生产成本单耗</div> |
| | | <div class="chart-container"> |
| | | <div ref="costChart" |
| | | style="width: 100%; height: 100%"></div> |
| | | </div> |
| | | </div> |
| | | <div class="panel-card card-5"> |
| | | <div class="panel-title">生产能耗数据</div> |
| | | <div class="chart-container"> |
| | | <div ref="energyChart" |
| | | style="width: 100%; height: 100%"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="panel-card card-3"> |
| | | <div class="panel-title">综合统计</div> |
| | | <div class="stats-grid"> |
| | | <div class="stat-item"> |
| | | <div class="stat-label">总产能</div> |
| | | <div class="stat-value">{{ totalProduction }}</div> |
| | | <div class="stat-unit">立方米</div> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <div class="stat-label">总固废处理</div> |
| | | <div class="stat-value">{{ totalSolidWaste }}</div> |
| | | <div class="stat-unit">吨</div> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <div class="stat-label">平均单耗</div> |
| | | <div class="stat-value">{{ averageUnitConsumption }}</div> |
| | | <div class="stat-unit">吨/立方米</div> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <div class="stat-label">总能耗</div> |
| | | <div class="stat-value">{{ totalEnergy }}</div> |
| | | <div class="stat-unit">kWh</div> |
| | | <!-- 第三行 --> |
| | | <div class="row row-3"> |
| | | <div class="panel-card card-6"> |
| | | <div class="panel-title">单耗数据明细</div> |
| | | <div class="table-container"> |
| | | <el-table :data="costTableData" |
| | | style="width: 100%"> |
| | | <el-table-column prop="material" |
| | | label="物料类型" |
| | | width="120" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getMaterialTypeType(scope.row.material)"> |
| | | {{ scope.row.material }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="unit" |
| | | label="单位" |
| | | width="100" /> |
| | | <el-table-column prop="monthlyConsumption" |
| | | label="月度累计用量" |
| | | align="right"> |
| | | <template #default="scope"> |
| | | <span class="data-value">{{ scope.row.monthlyConsumption }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="monthlyProduction" |
| | | label="月度累计产量" |
| | | align="right"> |
| | | <template #default="scope"> |
| | | <span class="data-value">{{ scope.row.monthlyProduction }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="monthlyUnitConsumption" |
| | | label="月度累计单耗" |
| | | align="right"> |
| | | <template #default="scope"> |
| | | <span class="data-value">{{ scope.row.monthlyUnitConsumption }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="yearlyConsumption" |
| | | label="年度累计用量" |
| | | align="right"> |
| | | <template #default="scope"> |
| | | <span class="data-value">{{ scope.row.yearlyConsumption }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="yearlyProduction" |
| | | label="年度累计产量" |
| | | align="right"> |
| | | <template #default="scope"> |
| | | <span class="data-value">{{ scope.row.yearlyProduction }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="yearlyUnitConsumption" |
| | | label="年度累计单耗" |
| | | align="right"> |
| | | <template #default="scope"> |
| | | <span class="data-value">{{ scope.row.yearlyUnitConsumption }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 第二行 --> |
| | | <div class="row row-2"> |
| | | <div class="panel-card card-4"> |
| | | <div class="panel-title">生产成本单耗</div> |
| | | <div class="chart-container"> |
| | | <div ref="costChart" style="width: 100%; height: 100%"></div> |
| | | </div> |
| | | </div> |
| | | <div class="panel-card card-5"> |
| | | <div class="panel-title">生产能耗数据</div> |
| | | <div class="chart-container"> |
| | | <div ref="energyChart" style="width: 100%; height: 100%"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 第三行 --> |
| | | <div class="row row-3"> |
| | | <div class="panel-card card-6"> |
| | | <div class="panel-title">单耗数据明细</div> |
| | | <div class="table-container"> |
| | | <el-table :data="costTableData" style="width: 100%"> |
| | | <el-table-column prop="material" label="物料类型" width="120" /> |
| | | <el-table-column prop="unit" label="单位" width="100" /> |
| | | <el-table-column prop="monthlyConsumption" label="月度累计用量" /> |
| | | <el-table-column prop="monthlyProduction" label="月度累计产量" /> |
| | | <el-table-column prop="monthlyUnitConsumption" label="月度累计单耗" /> |
| | | <el-table-column prop="yearlyConsumption" label="年度累计用量" /> |
| | | <el-table-column prop="yearlyProduction" label="年度累计产量" /> |
| | | <el-table-column prop="yearlyUnitConsumption" label="年度累计单耗" /> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted, onBeforeUnmount, nextTick, watch } from 'vue' |
| | | import * as echarts from 'echarts' |
| | | import { |
| | | ref, |
| | | computed, |
| | | onMounted, |
| | | onBeforeUnmount, |
| | | nextTick, |
| | | watch, |
| | | } from "vue"; |
| | | import * as echarts from "echarts"; |
| | | |
| | | // 筛选条件 |
| | | const dateType = ref('month') // month 或 year |
| | | const productType = ref('block') // block 或 plate |
| | | // 筛选条件 |
| | | const dateType = ref("month"); // month 或 year |
| | | const productType = ref("block"); // block 或 plate |
| | | |
| | | // 图表引用 |
| | | const productionChart = ref(null) |
| | | const solidWasteChart = ref(null) |
| | | const costChart = ref(null) |
| | | const energyChart = ref(null) |
| | | // 图表引用 |
| | | const productionChart = ref(null); |
| | | const solidWasteChart = ref(null); |
| | | const costChart = ref(null); |
| | | const energyChart = ref(null); |
| | | |
| | | // 图表实例 |
| | | let productionChartInstance = null |
| | | let solidWasteChartInstance = null |
| | | let costChartInstance = null |
| | | let energyChartInstance = null |
| | | // 图表实例 |
| | | let productionChartInstance = null; |
| | | let solidWasteChartInstance = null; |
| | | let costChartInstance = null; |
| | | let energyChartInstance = null; |
| | | |
| | | // 模拟数据 |
| | | const productionData = ref({ |
| | | month: [ |
| | | { name: '1月', block: 1200, plate: 800 }, |
| | | { name: '2月', block: 1300, plate: 850 }, |
| | | { name: '3月', block: 1100, plate: 750 }, |
| | | { name: '4月', block: 1400, plate: 900 }, |
| | | { name: '5月', block: 1500, plate: 950 }, |
| | | { name: '6月', block: 1350, plate: 880 }, |
| | | { name: '7月', block: 1450, plate: 920 }, |
| | | { name: '8月', block: 1600, plate: 1000 }, |
| | | { name: '9月', block: 1550, plate: 980 }, |
| | | { name: '10月', block: 1700, plate: 1050 }, |
| | | { name: '11月', block: 1650, plate: 1020 }, |
| | | { name: '12月', block: 1800, plate: 1100 } |
| | | ], |
| | | year: [ |
| | | { name: '2023', block: 15000, plate: 9500 }, |
| | | { name: '2024', block: 16500, plate: 10200 }, |
| | | { name: '2025', block: 18000, plate: 11000 } |
| | | ] |
| | | }) |
| | | // 模拟数据 |
| | | const productionData = ref({ |
| | | month: [ |
| | | { name: "1月", block: 1200, plate: 800 }, |
| | | { name: "2月", block: 1300, plate: 850 }, |
| | | { name: "3月", block: 1100, plate: 750 }, |
| | | { name: "4月", block: 1400, plate: 900 }, |
| | | { name: "5月", block: 1500, plate: 950 }, |
| | | { name: "6月", block: 1350, plate: 880 }, |
| | | { name: "7月", block: 1450, plate: 920 }, |
| | | { name: "8月", block: 1600, plate: 1000 }, |
| | | { name: "9月", block: 1550, plate: 980 }, |
| | | { name: "10月", block: 1700, plate: 1050 }, |
| | | { name: "11月", block: 1650, plate: 1020 }, |
| | | { name: "12月", block: 1800, plate: 1100 }, |
| | | ], |
| | | year: [ |
| | | { name: "2023", block: 15000, plate: 9500 }, |
| | | { name: "2024", block: 16500, plate: 10200 }, |
| | | { name: "2025", block: 18000, plate: 11000 }, |
| | | ], |
| | | }); |
| | | |
| | | const solidWasteData = ref({ |
| | | month: [ |
| | | { name: '1月', 粉煤灰: 200, 石膏: 150, 石灰: 100 }, |
| | | { name: '2月', 粉煤灰: 220, 石膏: 160, 石灰: 110 }, |
| | | { name: '3月', 粉煤灰: 190, 石膏: 140, 石灰: 95 }, |
| | | { name: '4月', 粉煤灰: 230, 石膏: 170, 石灰: 115 }, |
| | | { name: '5月', 粉煤灰: 240, 石膏: 180, 石灰: 120 }, |
| | | { name: '6月', 粉煤灰: 225, 石膏: 165, 石灰: 112 } |
| | | ], |
| | | year: [ |
| | | { name: '2023', 粉煤灰: 2500, 石膏: 1800, 石灰: 1200 }, |
| | | { name: '2024', 粉煤灰: 2700, 石膏: 1950, 石灰: 1300 }, |
| | | { name: '2025', 粉煤灰: 2900, 石膏: 2100, 石灰: 1400 } |
| | | ] |
| | | }) |
| | | const solidWasteData = ref({ |
| | | month: [ |
| | | { name: "1月", 粉煤灰: 200, 石膏: 150, 石灰: 100 }, |
| | | { name: "2月", 粉煤灰: 220, 石膏: 160, 石灰: 110 }, |
| | | { name: "3月", 粉煤灰: 190, 石膏: 140, 石灰: 95 }, |
| | | { name: "4月", 粉煤灰: 230, 石膏: 170, 石灰: 115 }, |
| | | { name: "5月", 粉煤灰: 240, 石膏: 180, 石灰: 120 }, |
| | | { name: "6月", 粉煤灰: 225, 石膏: 165, 石灰: 112 }, |
| | | ], |
| | | year: [ |
| | | { name: "2023", 粉煤灰: 2500, 石膏: 1800, 石灰: 1200 }, |
| | | { name: "2024", 粉煤灰: 2700, 石膏: 1950, 石灰: 1300 }, |
| | | { name: "2025", 粉煤灰: 2900, 石膏: 2100, 石灰: 1400 }, |
| | | ], |
| | | }); |
| | | |
| | | const costData = ref({ |
| | | materials: ['水泥', '铝粉膏', '脱模剂', '防腐剂', '氯化剂', '冷拔丝'], |
| | | month: { |
| | | consumption: [1200, 50, 80, 30, 40, 60], |
| | | production: [12000, 12000, 12000, 8000, 8000, 8000], |
| | | unitConsumption: [0.1, 0.0042, 0.0067, 0.0038, 0.005, 0.0075] |
| | | }, |
| | | year: { |
| | | consumption: [14000, 600, 950, 350, 480, 720], |
| | | production: [140000, 140000, 140000, 95000, 95000, 95000], |
| | | unitConsumption: [0.1, 0.0043, 0.0068, 0.0037, 0.0051, 0.0076] |
| | | } |
| | | }) |
| | | |
| | | const energyData = ref({ |
| | | month: [ |
| | | { name: '1月', 电量: 12000, 水量: 8000, 气量: 5000 }, |
| | | { name: '2月', 电量: 13000, 水量: 8500, 气量: 5500 }, |
| | | { name: '3月', 电量: 11000, 水量: 7500, 气量: 4800 }, |
| | | { name: '4月', 电量: 14000, 水量: 9000, 气量: 6000 }, |
| | | { name: '5月', 电量: 15000, 水量: 9500, 气量: 6500 }, |
| | | { name: '6月', 电量: 13500, 水量: 8800, 气量: 5800 } |
| | | ], |
| | | year: [ |
| | | { name: '2023', 电量: 140000, 水量: 95000, 气量: 65000 }, |
| | | { name: '2024', 电量: 150000, 水量: 100000, 气量: 70000 }, |
| | | { name: '2025', 电量: 160000, 水量: 105000, 气量: 75000 } |
| | | ] |
| | | }) |
| | | |
| | | // 计算属性 |
| | | const productionChartOption = computed(() => { |
| | | const data = productionData.value[dateType.value] |
| | | return { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | } |
| | | const costData = ref({ |
| | | materials: ["水泥", "铝粉膏", "脱模剂", "防腐剂", "氯化剂", "冷拔丝"], |
| | | month: { |
| | | consumption: [1200, 50, 80, 30, 40, 60], |
| | | production: [12000, 12000, 12000, 8000, 8000, 8000], |
| | | unitConsumption: [0.1, 0.0042, 0.0067, 0.0038, 0.005, 0.0075], |
| | | }, |
| | | legend: { |
| | | data: ['砌块', '板材'], |
| | | textStyle: { |
| | | color: '#333' |
| | | } |
| | | year: { |
| | | consumption: [14000, 600, 950, 350, 480, 720], |
| | | production: [140000, 140000, 140000, 95000, 95000, 95000], |
| | | unitConsumption: [0.1, 0.0043, 0.0068, 0.0037, 0.0051, 0.0076], |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: data.map(item => item.name), |
| | | axisLabel: { |
| | | color: '#333' |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: '产量 (立方米)', |
| | | axisLabel: { |
| | | color: '#333' |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '砌块', |
| | | type: 'line', |
| | | data: data.map(item => item.block), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3 |
| | | }); |
| | | |
| | | const energyData = ref({ |
| | | month: [ |
| | | { name: "1月", 电量: 12000, 水量: 8000, 气量: 5000 }, |
| | | { name: "2月", 电量: 13000, 水量: 8500, 气量: 5500 }, |
| | | { name: "3月", 电量: 11000, 水量: 7500, 气量: 4800 }, |
| | | { name: "4月", 电量: 14000, 水量: 9000, 气量: 6000 }, |
| | | { name: "5月", 电量: 15000, 水量: 9500, 气量: 6500 }, |
| | | { name: "6月", 电量: 13500, 水量: 8800, 气量: 5800 }, |
| | | ], |
| | | year: [ |
| | | { name: "2023", 电量: 140000, 水量: 95000, 气量: 65000 }, |
| | | { name: "2024", 电量: 150000, 水量: 100000, 气量: 70000 }, |
| | | { name: "2025", 电量: 160000, 水量: 105000, 气量: 75000 }, |
| | | ], |
| | | }); |
| | | |
| | | // 计算属性 |
| | | const productionChartOption = computed(() => { |
| | | const data = productionData.value[dateType.value]; |
| | | return { |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "shadow", |
| | | }, |
| | | itemStyle: { |
| | | color: '#409EFF' |
| | | } |
| | | }, |
| | | { |
| | | name: '板材', |
| | | type: 'line', |
| | | data: data.map(item => item.plate), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3 |
| | | legend: { |
| | | data: ["砌块", "板材"], |
| | | textStyle: { |
| | | color: "#333", |
| | | }, |
| | | itemStyle: { |
| | | color: '#67C23A' |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }) |
| | | |
| | | const solidWasteChartOption = computed(() => { |
| | | const data = solidWasteData.value[dateType.value] |
| | | return { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | } |
| | | }, |
| | | legend: { |
| | | data: ['粉煤灰', '石膏', '石灰'], |
| | | textStyle: { |
| | | color: '#333' |
| | | } |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: data.map(item => item.name), |
| | | axisLabel: { |
| | | color: '#333' |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: '处理量 (吨)', |
| | | axisLabel: { |
| | | color: '#333' |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '粉煤灰', |
| | | type: 'bar', |
| | | data: data.map(item => item.粉煤灰), |
| | | itemStyle: { |
| | | color: '#909399' |
| | | } |
| | | }, |
| | | { |
| | | name: '石膏', |
| | | type: 'bar', |
| | | data: data.map(item => item.石膏), |
| | | itemStyle: { |
| | | color: '#E6A23C' |
| | | } |
| | | grid: { |
| | | left: "3%", |
| | | right: "4%", |
| | | bottom: "3%", |
| | | containLabel: true, |
| | | }, |
| | | { |
| | | name: '石灰', |
| | | type: 'bar', |
| | | data: data.map(item => item.石灰), |
| | | itemStyle: { |
| | | color: '#F56C6C' |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }) |
| | | |
| | | const costChartOption = computed(() => { |
| | | const data = costData.value |
| | | return { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | } |
| | | }, |
| | | legend: { |
| | | data: ['月度单耗', '年度单耗'], |
| | | textStyle: { |
| | | color: '#333' |
| | | } |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: data.materials, |
| | | axisLabel: { |
| | | color: '#333', |
| | | rotate: 45 |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: '单耗 (吨/立方米)', |
| | | axisLabel: { |
| | | color: '#333' |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '月度单耗', |
| | | type: 'bar', |
| | | data: data.month.unitConsumption, |
| | | itemStyle: { |
| | | color: '#409EFF' |
| | | } |
| | | }, |
| | | { |
| | | name: '年度单耗', |
| | | type: 'bar', |
| | | data: data.year.unitConsumption, |
| | | itemStyle: { |
| | | color: '#67C23A' |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }) |
| | | |
| | | const energyChartOption = computed(() => { |
| | | const data = energyData.value[dateType.value] |
| | | return { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | } |
| | | }, |
| | | legend: { |
| | | data: ['电量', '水量', '气量'], |
| | | textStyle: { |
| | | color: '#333' |
| | | } |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: data.map(item => item.name), |
| | | axisLabel: { |
| | | color: '#333' |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: '能耗量', |
| | | axisLabel: { |
| | | color: '#333' |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '电量', |
| | | type: 'line', |
| | | data: data.map(item => item.电量), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3 |
| | | xAxis: { |
| | | type: "category", |
| | | data: data.map(item => item.name), |
| | | axisLabel: { |
| | | color: "#333", |
| | | }, |
| | | itemStyle: { |
| | | color: '#409EFF' |
| | | } |
| | | }, |
| | | { |
| | | name: '水量', |
| | | type: 'line', |
| | | data: data.map(item => item.水量), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3 |
| | | yAxis: { |
| | | type: "value", |
| | | name: "产量 (立方米)", |
| | | axisLabel: { |
| | | color: "#333", |
| | | }, |
| | | itemStyle: { |
| | | color: '#67C23A' |
| | | } |
| | | }, |
| | | { |
| | | name: '气量', |
| | | type: 'line', |
| | | data: data.map(item => item.气量), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3 |
| | | series: [ |
| | | { |
| | | name: "砌块", |
| | | type: "line", |
| | | data: data.map(item => item.block), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | itemStyle: { |
| | | color: "#409EFF", |
| | | }, |
| | | }, |
| | | itemStyle: { |
| | | color: '#E6A23C' |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }) |
| | | { |
| | | name: "板材", |
| | | type: "line", |
| | | data: data.map(item => item.plate), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | itemStyle: { |
| | | color: "#67C23A", |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | }); |
| | | |
| | | const costTableData = computed(() => { |
| | | const data = costData.value |
| | | const materials = data.materials |
| | | const monthData = data.month |
| | | const yearData = data.year |
| | | |
| | | return materials.map((material, index) => ({ |
| | | material, |
| | | unit: '吨/立方米', |
| | | monthlyConsumption: monthData.consumption[index], |
| | | monthlyProduction: monthData.production[index], |
| | | monthlyUnitConsumption: monthData.unitConsumption[index].toFixed(4), |
| | | yearlyConsumption: yearData.consumption[index], |
| | | yearlyProduction: yearData.production[index], |
| | | yearlyUnitConsumption: yearData.unitConsumption[index].toFixed(4) |
| | | })) |
| | | }) |
| | | const solidWasteChartOption = computed(() => { |
| | | const data = solidWasteData.value[dateType.value]; |
| | | return { |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "shadow", |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ["粉煤灰", "石膏", "石灰"], |
| | | textStyle: { |
| | | color: "#333", |
| | | }, |
| | | }, |
| | | grid: { |
| | | left: "3%", |
| | | right: "4%", |
| | | bottom: "3%", |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: data.map(item => item.name), |
| | | axisLabel: { |
| | | color: "#333", |
| | | }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | name: "处理量 (吨)", |
| | | axisLabel: { |
| | | color: "#333", |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "粉煤灰", |
| | | type: "bar", |
| | | data: data.map(item => item.粉煤灰), |
| | | itemStyle: { |
| | | color: "#909399", |
| | | }, |
| | | }, |
| | | { |
| | | name: "石膏", |
| | | type: "bar", |
| | | data: data.map(item => item.石膏), |
| | | itemStyle: { |
| | | color: "#E6A23C", |
| | | }, |
| | | }, |
| | | { |
| | | name: "石灰", |
| | | type: "bar", |
| | | data: data.map(item => item.石灰), |
| | | itemStyle: { |
| | | color: "#F56C6C", |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | }); |
| | | |
| | | const totalProduction = computed(() => { |
| | | const data = productionData.value[dateType.value] |
| | | if (dateType.value === 'month') { |
| | | return data.reduce((sum, item) => sum + item[productType.value === 'block' ? 'block' : 'plate'], 0) |
| | | } else { |
| | | return data[data.length - 1][productType.value === 'block' ? 'block' : 'plate'] |
| | | } |
| | | }) |
| | | const costChartOption = computed(() => { |
| | | const data = costData.value; |
| | | return { |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "shadow", |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ["月度单耗", "年度单耗"], |
| | | textStyle: { |
| | | color: "#333", |
| | | }, |
| | | }, |
| | | grid: { |
| | | left: "3%", |
| | | right: "4%", |
| | | bottom: "3%", |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: data.materials, |
| | | axisLabel: { |
| | | color: "#333", |
| | | rotate: 45, |
| | | }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | name: "单耗 (吨/立方米)", |
| | | axisLabel: { |
| | | color: "#333", |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "月度单耗", |
| | | type: "bar", |
| | | data: data.month.unitConsumption, |
| | | itemStyle: { |
| | | color: "#409EFF", |
| | | }, |
| | | }, |
| | | { |
| | | name: "年度单耗", |
| | | type: "bar", |
| | | data: data.year.unitConsumption, |
| | | itemStyle: { |
| | | color: "#67C23A", |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | }); |
| | | |
| | | const totalSolidWaste = computed(() => { |
| | | const data = solidWasteData.value[dateType.value] |
| | | if (dateType.value === 'month') { |
| | | return data.reduce((sum, item) => sum + item.粉煤灰 + item.石膏 + item.石灰, 0) |
| | | } else { |
| | | const lastItem = data[data.length - 1] |
| | | return lastItem.粉煤灰 + lastItem.石膏 + lastItem.石灰 |
| | | } |
| | | }) |
| | | const energyChartOption = computed(() => { |
| | | const data = energyData.value[dateType.value]; |
| | | return { |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "shadow", |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ["电量", "水量", "气量"], |
| | | textStyle: { |
| | | color: "#333", |
| | | }, |
| | | }, |
| | | grid: { |
| | | left: "3%", |
| | | right: "4%", |
| | | bottom: "3%", |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: data.map(item => item.name), |
| | | axisLabel: { |
| | | color: "#333", |
| | | }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | name: "能耗量", |
| | | axisLabel: { |
| | | color: "#333", |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "电量", |
| | | type: "line", |
| | | data: data.map(item => item.电量), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | itemStyle: { |
| | | color: "#409EFF", |
| | | }, |
| | | }, |
| | | { |
| | | name: "水量", |
| | | type: "line", |
| | | data: data.map(item => item.水量), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | itemStyle: { |
| | | color: "#67C23A", |
| | | }, |
| | | }, |
| | | { |
| | | name: "气量", |
| | | type: "line", |
| | | data: data.map(item => item.气量), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | itemStyle: { |
| | | color: "#E6A23C", |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | }); |
| | | |
| | | const averageUnitConsumption = computed(() => { |
| | | const data = costData.value |
| | | const unitConsumption = dateType.value === 'month' ? data.month.unitConsumption : data.year.unitConsumption |
| | | const average = unitConsumption.reduce((sum, value) => sum + value, 0) / unitConsumption.length |
| | | return average.toFixed(4) |
| | | }) |
| | | const costTableData = computed(() => { |
| | | const data = costData.value; |
| | | const materials = data.materials; |
| | | const monthData = data.month; |
| | | const yearData = data.year; |
| | | |
| | | const totalEnergy = computed(() => { |
| | | const data = energyData.value[dateType.value] |
| | | if (dateType.value === 'month') { |
| | | return data.reduce((sum, item) => sum + item.电量 + item.水量 + item.气量, 0) |
| | | } else { |
| | | const lastItem = data[data.length - 1] |
| | | return lastItem.电量 + lastItem.水量 + lastItem.气量 |
| | | } |
| | | }) |
| | | return materials.map((material, index) => ({ |
| | | material, |
| | | unit: "吨/立方米", |
| | | monthlyConsumption: monthData.consumption[index], |
| | | monthlyProduction: monthData.production[index], |
| | | monthlyUnitConsumption: monthData.unitConsumption[index].toFixed(4), |
| | | yearlyConsumption: yearData.consumption[index], |
| | | yearlyProduction: yearData.production[index], |
| | | yearlyUnitConsumption: yearData.unitConsumption[index].toFixed(4), |
| | | })); |
| | | }); |
| | | |
| | | // 事件处理 |
| | | const handleDateTypeChange = () => { |
| | | updateCharts() |
| | | } |
| | | const totalProduction = computed(() => { |
| | | const data = productionData.value[dateType.value]; |
| | | if (dateType.value === "month") { |
| | | return data.reduce( |
| | | (sum, item) => |
| | | sum + item[productType.value === "block" ? "block" : "plate"], |
| | | 0 |
| | | ); |
| | | } else { |
| | | return data[data.length - 1][ |
| | | productType.value === "block" ? "block" : "plate" |
| | | ]; |
| | | } |
| | | }); |
| | | |
| | | const handleProductTypeChange = () => { |
| | | updateCharts() |
| | | } |
| | | const totalSolidWaste = computed(() => { |
| | | const data = solidWasteData.value[dateType.value]; |
| | | if (dateType.value === "month") { |
| | | return data.reduce( |
| | | (sum, item) => sum + item.粉煤灰 + item.石膏 + item.石灰, |
| | | 0 |
| | | ); |
| | | } else { |
| | | const lastItem = data[data.length - 1]; |
| | | return lastItem.粉煤灰 + lastItem.石膏 + lastItem.石灰; |
| | | } |
| | | }); |
| | | |
| | | // 初始化图表 |
| | | const initCharts = () => { |
| | | if (productionChart.value) { |
| | | productionChartInstance = echarts.init(productionChart.value) |
| | | productionChartInstance.setOption(productionChartOption.value) |
| | | } |
| | | |
| | | if (solidWasteChart.value) { |
| | | solidWasteChartInstance = echarts.init(solidWasteChart.value) |
| | | solidWasteChartInstance.setOption(solidWasteChartOption.value) |
| | | } |
| | | |
| | | if (costChart.value) { |
| | | costChartInstance = echarts.init(costChart.value) |
| | | costChartInstance.setOption(costChartOption.value) |
| | | } |
| | | |
| | | if (energyChart.value) { |
| | | energyChartInstance = echarts.init(energyChart.value) |
| | | energyChartInstance.setOption(energyChartOption.value) |
| | | } |
| | | } |
| | | const averageUnitConsumption = computed(() => { |
| | | const data = costData.value; |
| | | const unitConsumption = |
| | | dateType.value === "month" |
| | | ? data.month.unitConsumption |
| | | : data.year.unitConsumption; |
| | | const average = |
| | | unitConsumption.reduce((sum, value) => sum + value, 0) / |
| | | unitConsumption.length; |
| | | return average.toFixed(4); |
| | | }); |
| | | |
| | | // 更新图表 |
| | | const updateCharts = () => { |
| | | if (productionChartInstance) { |
| | | productionChartInstance.setOption(productionChartOption.value) |
| | | } |
| | | |
| | | if (solidWasteChartInstance) { |
| | | solidWasteChartInstance.setOption(solidWasteChartOption.value) |
| | | } |
| | | |
| | | if (costChartInstance) { |
| | | costChartInstance.setOption(costChartOption.value) |
| | | } |
| | | |
| | | if (energyChartInstance) { |
| | | energyChartInstance.setOption(energyChartOption.value) |
| | | } |
| | | } |
| | | const totalEnergy = computed(() => { |
| | | const data = energyData.value[dateType.value]; |
| | | if (dateType.value === "month") { |
| | | return data.reduce( |
| | | (sum, item) => sum + item.电量 + item.水量 + item.气量, |
| | | 0 |
| | | ); |
| | | } else { |
| | | const lastItem = data[data.length - 1]; |
| | | return lastItem.电量 + lastItem.水量 + lastItem.气量; |
| | | } |
| | | }); |
| | | |
| | | // 调整图表大小 |
| | | const resizeCharts = () => { |
| | | productionChartInstance?.resize() |
| | | solidWasteChartInstance?.resize() |
| | | costChartInstance?.resize() |
| | | energyChartInstance?.resize() |
| | | } |
| | | // 事件处理 |
| | | const handleDateTypeChange = () => { |
| | | updateCharts(); |
| | | }; |
| | | |
| | | // 窗口大小变化处理 |
| | | const handleResize = () => { |
| | | // 延迟执行,确保DOM更新完成 |
| | | setTimeout(() => { |
| | | resizeCharts() |
| | | }, 100) |
| | | } |
| | | const handleProductTypeChange = () => { |
| | | updateCharts(); |
| | | }; |
| | | |
| | | // 生命周期钩子 |
| | | onMounted(() => { |
| | | // 使用nextTick确保DOM完全渲染后再初始化 |
| | | nextTick(() => { |
| | | // 初始化图表 |
| | | initCharts() |
| | | }) |
| | | // 初始化图表 |
| | | const initCharts = () => { |
| | | if (productionChart.value) { |
| | | productionChartInstance = echarts.init(productionChart.value); |
| | | productionChartInstance.setOption(productionChartOption.value); |
| | | } |
| | | |
| | | window.addEventListener('resize', handleResize) |
| | | }) |
| | | if (solidWasteChart.value) { |
| | | solidWasteChartInstance = echarts.init(solidWasteChart.value); |
| | | solidWasteChartInstance.setOption(solidWasteChartOption.value); |
| | | } |
| | | |
| | | onBeforeUnmount(() => { |
| | | window.removeEventListener('resize', handleResize) |
| | | |
| | | // 销毁图表实例 |
| | | productionChartInstance?.dispose() |
| | | solidWasteChartInstance?.dispose() |
| | | costChartInstance?.dispose() |
| | | energyChartInstance?.dispose() |
| | | }) |
| | | if (costChart.value) { |
| | | costChartInstance = echarts.init(costChart.value); |
| | | costChartInstance.setOption(costChartOption.value); |
| | | } |
| | | |
| | | if (energyChart.value) { |
| | | energyChartInstance = echarts.init(energyChart.value); |
| | | energyChartInstance.setOption(energyChartOption.value); |
| | | } |
| | | }; |
| | | |
| | | // 更新图表 |
| | | const updateCharts = () => { |
| | | if (productionChartInstance) { |
| | | productionChartInstance.setOption(productionChartOption.value); |
| | | } |
| | | |
| | | if (solidWasteChartInstance) { |
| | | solidWasteChartInstance.setOption(solidWasteChartOption.value); |
| | | } |
| | | |
| | | if (costChartInstance) { |
| | | costChartInstance.setOption(costChartOption.value); |
| | | } |
| | | |
| | | if (energyChartInstance) { |
| | | energyChartInstance.setOption(energyChartOption.value); |
| | | } |
| | | }; |
| | | |
| | | // 调整图表大小 |
| | | const resizeCharts = () => { |
| | | productionChartInstance?.resize(); |
| | | solidWasteChartInstance?.resize(); |
| | | costChartInstance?.resize(); |
| | | energyChartInstance?.resize(); |
| | | }; |
| | | |
| | | // 窗口大小变化处理 |
| | | const handleResize = () => { |
| | | // 延迟执行,确保DOM更新完成 |
| | | setTimeout(() => { |
| | | resizeCharts(); |
| | | }, 100); |
| | | }; |
| | | |
| | | // 获取物料类型标签类型 |
| | | const getMaterialTypeType = material => { |
| | | const typeMap = { |
| | | 水泥: "primary", |
| | | 铝粉膏: "success", |
| | | 脱模剂: "warning", |
| | | 防腐剂: "danger", |
| | | 氯化剂: "info", |
| | | 冷拔丝: "purple", |
| | | }; |
| | | return typeMap[material] || "info"; |
| | | }; |
| | | |
| | | // 生命周期钩子 |
| | | onMounted(() => { |
| | | // 使用nextTick确保DOM完全渲染后再初始化 |
| | | nextTick(() => { |
| | | // 初始化图表 |
| | | initCharts(); |
| | | }); |
| | | |
| | | window.addEventListener("resize", handleResize); |
| | | }); |
| | | |
| | | onBeforeUnmount(() => { |
| | | window.removeEventListener("resize", handleResize); |
| | | |
| | | // 销毁图表实例 |
| | | productionChartInstance?.dispose(); |
| | | solidWasteChartInstance?.dispose(); |
| | | costChartInstance?.dispose(); |
| | | energyChartInstance?.dispose(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | /* 外部容器 - 占据整个视口 */ |
| | | .dashboard-container { |
| | | position: relative; |
| | | width: 100%; |
| | | /* 页面在常规布局下(有顶栏)默认减去 84px,避免内容被裁切 */ |
| | | min-height: calc(100vh - 84px); |
| | | background-color: #f5f7fa; |
| | | overflow: hidden; |
| | | } |
| | | /* 外部容器 - 占据整个视口 */ |
| | | .dashboard-container { |
| | | position: relative; |
| | | width: 100%; |
| | | /* 页面在常规布局下(有顶栏)默认减去 84px,避免内容被裁切 */ |
| | | min-height: calc(100vh - 84px); |
| | | background-color: #f5f7fa; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | /* 内部内容区域 - 自适应宽度 */ |
| | | .data-dashboard { |
| | | position: relative; |
| | | width: 100%; |
| | | min-height: 100%; |
| | | background-color: #ffffff; |
| | | box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); |
| | | } |
| | | /* 内部内容区域 - 自适应宽度 */ |
| | | .data-dashboard { |
| | | position: relative; |
| | | width: 100%; |
| | | min-height: 100%; |
| | | background-color: #ffffff; |
| | | box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .dashboard-header { |
| | | position: relative; |
| | | z-index: 1; |
| | | height: 86px; |
| | | background-color: #ffffff; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | .dashboard-header { |
| | | position: relative; |
| | | z-index: 1; |
| | | height: 86px; |
| | | background-color: #ffffff; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .factory-name { |
| | | font-weight: 600; |
| | | font-size: 32px; |
| | | color: #303133; |
| | | } |
| | | .factory-name { |
| | | font-weight: 600; |
| | | font-size: 32px; |
| | | color: #303133; |
| | | } |
| | | |
| | | .filter-area { |
| | | padding: 20px; |
| | | background-color: #ffffff; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | display: flex; |
| | | gap: 40px; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | } |
| | | .filter-area { |
| | | padding: 20px; |
| | | background-color: #ffffff; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | display: flex; |
| | | gap: 40px; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .filter-section { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | .filter-section { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .filter-label { |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | white-space: nowrap; |
| | | } |
| | | .filter-label { |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .radio-group { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .radio-group { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | /* 按钮样式 */ |
| | | :deep(.el-radio-button__inner) { |
| | | border-radius: 4px; |
| | | padding: 8px 20px; |
| | | font-size: 14px; |
| | | transition: all 0.3s ease; |
| | | } |
| | | /* 按钮样式 */ |
| | | :deep(.el-radio-button__inner) { |
| | | border-radius: 4px; |
| | | padding: 8px 20px; |
| | | font-size: 14px; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | :deep(.el-radio-button__orig-radio:checked + .el-radio-button__inner) { |
| | | background-color: #409eff; |
| | | border-color: #409eff; |
| | | color: #ffffff; |
| | | box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); |
| | | } |
| | | :deep(.el-radio-button__orig-radio:checked + .el-radio-button__inner) { |
| | | background-color: #409eff; |
| | | border-color: #409eff; |
| | | color: #ffffff; |
| | | box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); |
| | | } |
| | | |
| | | :deep(.el-radio-button__inner:hover) { |
| | | color: #409eff; |
| | | border-color: #c6e2ff; |
| | | } |
| | | :deep(.el-radio-button__inner:hover) { |
| | | color: #409eff; |
| | | border-color: #c6e2ff; |
| | | } |
| | | |
| | | :deep(.el-radio-button:first-child .el-radio-button__inner) { |
| | | border-radius: 4px 0 0 4px; |
| | | } |
| | | :deep(.el-radio-button:first-child .el-radio-button__inner) { |
| | | border-radius: 4px 0 0 4px; |
| | | } |
| | | |
| | | :deep(.el-radio-button:last-child .el-radio-button__inner) { |
| | | border-radius: 0 4px 4px 0; |
| | | } |
| | | :deep(.el-radio-button:last-child .el-radio-button__inner) { |
| | | border-radius: 0 4px 4px 0; |
| | | } |
| | | |
| | | .dashboard-content { |
| | | position: relative; |
| | | z-index: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | padding: 20px; |
| | | min-height: 800px; |
| | | overflow: hidden; |
| | | } |
| | | .dashboard-content { |
| | | position: relative; |
| | | z-index: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | padding: 20px; |
| | | min-height: 800px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | /* 行布局 */ |
| | | .row { |
| | | display: flex; |
| | | gap: 20px; |
| | | align-items: stretch; |
| | | } |
| | | /* 行布局 */ |
| | | .row { |
| | | display: flex; |
| | | gap: 20px; |
| | | align-items: stretch; |
| | | } |
| | | |
| | | /* 第一行:3个卡片 */ |
| | | .row-1 { |
| | | height: 300px; |
| | | } |
| | | /* 第一行:3个卡片 */ |
| | | .row-1 { |
| | | height: 300px; |
| | | } |
| | | |
| | | /* 第二行:2个卡片 */ |
| | | .row-2 { |
| | | height: 300px; |
| | | } |
| | | /* 第二行:2个卡片 */ |
| | | .row-2 { |
| | | height: 300px; |
| | | } |
| | | |
| | | /* 第三行:1个卡片 */ |
| | | .row-3 { |
| | | min-height: 250px; |
| | | } |
| | | /* 第三行:1个卡片 */ |
| | | .row-3 { |
| | | min-height: 250px; |
| | | } |
| | | |
| | | /* 卡片样式 */ |
| | | .panel-card { |
| | | background-color: #ffffff; |
| | | border-radius: 8px; |
| | | border: 1px solid #e4e7ed; |
| | | overflow: hidden; |
| | | display: flex; |
| | | flex-direction: column; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); |
| | | transition: all 0.3s ease; |
| | | } |
| | | /* 卡片样式 */ |
| | | .panel-card { |
| | | background-color: #ffffff; |
| | | border-radius: 8px; |
| | | border: 1px solid #e4e7ed; |
| | | overflow: hidden; |
| | | display: flex; |
| | | flex-direction: column; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .panel-card:hover { |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); |
| | | transform: translateY(-2px); |
| | | } |
| | | .panel-card:hover { |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | /* 卡片布局 */ |
| | | .card-1 { |
| | | flex: 1; |
| | | } |
| | | /* 卡片布局 */ |
| | | .card-1 { |
| | | flex: 1; |
| | | } |
| | | |
| | | .card-2 { |
| | | flex: 1; |
| | | } |
| | | .card-2 { |
| | | flex: 1; |
| | | } |
| | | |
| | | .card-3 { |
| | | flex: 0.8; |
| | | } |
| | | .card-3 { |
| | | flex: 0.8; |
| | | } |
| | | |
| | | .card-4 { |
| | | flex: 1.2; |
| | | } |
| | | .card-4 { |
| | | flex: 1.2; |
| | | } |
| | | |
| | | .card-5 { |
| | | flex: 0.8; |
| | | } |
| | | .card-5 { |
| | | flex: 0.8; |
| | | } |
| | | |
| | | .card-6 { |
| | | flex: 1; |
| | | } |
| | | .card-6 { |
| | | flex: 1; |
| | | } |
| | | |
| | | .panel-card { |
| | | background-color: #ffffff; |
| | | border-radius: 8px; |
| | | border: 1px solid #e4e7ed; |
| | | overflow: hidden; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | .panel-card { |
| | | background-color: #ffffff; |
| | | border-radius: 8px; |
| | | border: 1px solid #e4e7ed; |
| | | overflow: hidden; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .panel-title { |
| | | padding: 15px 20px; |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | background-color: #fafafa; |
| | | } |
| | | .panel-title { |
| | | padding: 15px 20px; |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | background-color: #fafafa; |
| | | } |
| | | |
| | | .chart-container { |
| | | flex: 1; |
| | | padding: 20px; |
| | | } |
| | | .card-1 .panel-title { |
| | | border-left: 4px solid #409eff; |
| | | } |
| | | |
| | | .table-container { |
| | | flex: 1; |
| | | padding: 20px; |
| | | overflow: auto; |
| | | } |
| | | .card-2 .panel-title { |
| | | border-left: 4px solid #f56c6c; |
| | | } |
| | | |
| | | .stats-grid { |
| | | flex: 1; |
| | | padding: 15px; |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | grid-template-rows: repeat(2, 1fr); |
| | | gap: 15px; |
| | | } |
| | | .card-3 .panel-title { |
| | | border-left: 4px solid #e6a23c; |
| | | } |
| | | |
| | | .stat-item { |
| | | background-color: #fafafa; |
| | | border-radius: 8px; |
| | | padding: 15px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | border: 1px solid #e4e7ed; |
| | | min-height: 80px; |
| | | } |
| | | .card-4 .panel-title { |
| | | border-left: 4px solid #409eff; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | margin-bottom: 8px; |
| | | } |
| | | .card-5 .panel-title { |
| | | border-left: 4px solid #67c23a; |
| | | } |
| | | |
| | | .stat-value { |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 3px; |
| | | } |
| | | .card-6 .panel-title { |
| | | border-left: 4px solid #e6a23c; |
| | | } |
| | | |
| | | .stat-unit { |
| | | font-size: 11px; |
| | | color: #909399; |
| | | } |
| | | .chart-container { |
| | | flex: 1; |
| | | padding: 20px; |
| | | } |
| | | |
| | | /* 表格样式 */ |
| | | :deep(.el-table) { |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | } |
| | | .table-container { |
| | | flex: 1; |
| | | padding: 20px; |
| | | overflow: auto; |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background-color: #fafafa; |
| | | font-weight: 500; |
| | | } |
| | | .stats-grid { |
| | | flex: 1; |
| | | padding: 15px; |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | grid-template-rows: repeat(2, 1fr); |
| | | gap: 15px; |
| | | } |
| | | |
| | | :deep(.el-table tr:hover > td) { |
| | | background-color: #ecf5ff; |
| | | } |
| | | .stat-item { |
| | | background-color: #fafafa; |
| | | border-radius: 8px; |
| | | padding: 15px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | border: 1px solid #e4e7ed; |
| | | min-height: 80px; |
| | | } |
| | | |
| | | /* 按钮样式 */ |
| | | :deep(.el-radio-button__inner) { |
| | | border-radius: 4px; |
| | | } |
| | | .stat-label { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | :deep(.el-radio-button__orig-radio:checked + .el-radio-button__inner) { |
| | | background-color: #409eff; |
| | | border-color: #409eff; |
| | | color: #ffffff; |
| | | } |
| | | .stat-value { |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 3px; |
| | | } |
| | | |
| | | .production-color { |
| | | color: #409eff; |
| | | text-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); |
| | | } |
| | | |
| | | .waste-color { |
| | | color: #f56c6c; |
| | | text-shadow: 0 2px 4px rgba(245, 108, 108, 0.3); |
| | | } |
| | | |
| | | .consumption-color { |
| | | color: #e6a23c; |
| | | text-shadow: 0 2px 4px rgba(230, 162, 60, 0.3); |
| | | } |
| | | |
| | | .energy-color { |
| | | color: #67c23a; |
| | | text-shadow: 0 2px 4px rgba(103, 194, 58, 0.3); |
| | | } |
| | | |
| | | .stat-unit { |
| | | font-size: 11px; |
| | | color: #909399; |
| | | } |
| | | |
| | | /* 表格样式 */ |
| | | :deep(.el-table) { |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background-color: #fafafa; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.el-table tr:hover > td) { |
| | | background-color: #ecf5ff; |
| | | } |
| | | |
| | | .data-value { |
| | | font-weight: bold; |
| | | color: #409eff; |
| | | } |
| | | |
| | | /* 按钮样式 */ |
| | | :deep(.el-radio-button__inner) { |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | :deep(.el-radio-button__orig-radio:checked + .el-radio-button__inner) { |
| | | background-color: #409eff; |
| | | border-color: #409eff; |
| | | color: #ffffff; |
| | | } |
| | | </style> |