| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="dashboard-container"> |
| | | <div class="data-dashboard"> |
| | | <!-- 顶鍿 颿 --> |
| | | <!-- <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> |
| | | <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> |
| | | </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="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" |
| | | 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> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | 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 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; |
| | | |
| | | // æ¨¡ææ°æ® |
| | | 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 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", |
| | | }, |
| | | }, |
| | | 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.block), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | itemStyle: { |
| | | color: "#409EFF", |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ¿æ", |
| | | type: "line", |
| | | data: data.map(item => item.plate), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | 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", |
| | | }, |
| | | }, |
| | | { |
| | | 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, |
| | | }, |
| | | 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 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 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 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 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 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 handleDateTypeChange = () => { |
| | | updateCharts(); |
| | | }; |
| | | |
| | | const handleProductTypeChange = () => { |
| | | updateCharts(); |
| | | }; |
| | | |
| | | // åå§åå¾è¡¨ |
| | | 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 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; |
| | | } |
| | | |
| | | /* å
é¨å
容åºå - èªéåºå®½åº¦ */ |
| | | .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; |
| | | } |
| | | |
| | | .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-section { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .filter-label { |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .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__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: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; |
| | | } |
| | | |
| | | .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; |
| | | } |
| | | |
| | | /* 第ä¸è¡ï¼3个å¡ç */ |
| | | .row-1 { |
| | | height: 300px; |
| | | } |
| | | |
| | | /* 第äºè¡ï¼2个å¡ç */ |
| | | .row-2 { |
| | | height: 300px; |
| | | } |
| | | |
| | | /* 第ä¸è¡ï¼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:hover { |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | /* å¡çå¸å± */ |
| | | .card-1 { |
| | | flex: 1; |
| | | } |
| | | |
| | | .card-2 { |
| | | flex: 1; |
| | | } |
| | | |
| | | .card-3 { |
| | | flex: 0.8; |
| | | } |
| | | |
| | | .card-4 { |
| | | flex: 1.2; |
| | | } |
| | | |
| | | .card-5 { |
| | | flex: 0.8; |
| | | } |
| | | |
| | | .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-title { |
| | | padding: 15px 20px; |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | background-color: #fafafa; |
| | | } |
| | | |
| | | .card-1 .panel-title { |
| | | border-left: 4px solid #409eff; |
| | | } |
| | | |
| | | .card-2 .panel-title { |
| | | border-left: 4px solid #f56c6c; |
| | | } |
| | | |
| | | .card-3 .panel-title { |
| | | border-left: 4px solid #e6a23c; |
| | | } |
| | | |
| | | .card-4 .panel-title { |
| | | border-left: 4px solid #409eff; |
| | | } |
| | | |
| | | .card-5 .panel-title { |
| | | border-left: 4px solid #67c23a; |
| | | } |
| | | |
| | | .card-6 .panel-title { |
| | | border-left: 4px solid #e6a23c; |
| | | } |
| | | |
| | | .chart-container { |
| | | flex: 1; |
| | | padding: 20px; |
| | | } |
| | | |
| | | .table-container { |
| | | flex: 1; |
| | | padding: 20px; |
| | | overflow: auto; |
| | | } |
| | | |
| | | .stats-grid { |
| | | flex: 1; |
| | | padding: 15px; |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | grid-template-rows: repeat(2, 1fr); |
| | | gap: 15px; |
| | | } |
| | | |
| | | .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; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .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> |
| | |
| | | <template> |
| | | <div class="dashboard-container"> |
| | | <div class="data-dashboard"> |
| | | <!-- 顶鍿 颿 --> |
| | | <!-- <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 ref="screenRoot" |
| | | class="sales-statistics-container" |
| | | :class="{ 'is-fullscreen': isFullscreen }"> |
| | | <div class="bi-bg"></div> |
| | | <div class="bi-topbar"> |
| | | <img class="bi-topbar-title-bg" |
| | | src="@/assets/BI/biaoti.png" |
| | | alt="çäº§çæ¿ç»è®¡" /> |
| | | <div class="bi-topbar-content"> |
| | | <div class="bi-topbar-left"> |
| | | <button class="fullscreen-btn" |
| | | @click="toggleFullscreen" |
| | | :title="isFullscreen ? 'éåºå
¨å±' : 'å
¨å±æ¾ç¤º'"> |
| | | <svg v-if="!isFullscreen" |
| | | width="1.6vh" |
| | | height="1.6vh" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2"> |
| | | <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3" /> |
| | | </svg> |
| | | <svg v-else |
| | | width="1.6vh" |
| | | height="1.6vh" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2"> |
| | | <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" /> |
| | | </svg> |
| | | </button> |
| | | </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 class="bi-topbar-title">çäº§çæ¿ç»è®¡</div> |
| | | <div class="bi-topbar-meta"> |
| | | <span class="bi-topbar-time">{{ currentTime }}</span> |
| | | <span class="bi-topbar-sep">|</span> |
| | | <span class="bi-topbar-date">{{ currentDateText }}</span> |
| | | </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> |
| | | </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="bi-dashboard-grid"> |
| | | <!-- å·¦ä¸ï¼çäº§ææ¬åèç»è®¡ï¼ç åï¼ --> |
| | | <div class="bi-panel bi-panel-top-left"> |
| | | <PanelHeader :isFullscreen="true" |
| | | title="çäº§ææ¬åèç»è®¡ï¼ç åï¼" /> |
| | | <div class="panel-tabs"> |
| | | <span class="tab-item" |
| | | :class="{ active: blockTimeDimension === 'year' }" |
| | | @click="handleBlockTimeDimensionChange('year')">å¹´</span> |
| | | <span class="tab-item" |
| | | :class="{ active: blockTimeDimension === 'month' }" |
| | | @click="handleBlockTimeDimensionChange('month')">æ</span> |
| | | </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 class="bi-panel-body"> |
| | | <div class="chart-filter-tabs"> |
| | | <span v-for="area in salesAreas" |
| | | :key="area" |
| | | class="cf-tab" |
| | | :class="{ active: blockSelectedArea === area }" |
| | | @click="handleBlockAreaChange(area)">{{ area }}</span> |
| | | </div> |
| | | <div class="material-info-card"> |
| | | <div class="material-icon"> |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| | | <path d="M20 7h-4V4c0-1.1-.9-2-2-2h-4c-1.1 0-2 .9-2 2v3H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2z" /> |
| | | <polyline points="22,7 12,13 2,7" /> |
| | | </svg> |
| | | </div> |
| | | <div class="material-details"> |
| | | <div class="material-name">{{ blockMaterialType }}AAA</div> |
| | | <div class="material-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">æç´¯è®¡åè</span> |
| | | <span class="stat-value">78/12</span> |
| | | <span class="stat-unit">å¨</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">年累计åè</span> |
| | | <span class="stat-value">78/12</span> |
| | | <span class="stat-unit">å¨</span> |
| | | </div> |
| | | </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 class="chart-unit-row"> |
| | | <span>åä½ï¼ç«æ¹ç±³</span> |
| | | </div> --> |
| | | <div ref="blockCostChart" |
| | | class="echart-fill"></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" |
| | | 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 class="bi-panel bi-panel-top-right"> |
| | | <PanelHeader :isFullscreen="true" |
| | | title="ç©æç产éåæ" /> |
| | | <div class="panel-tabs"> |
| | | <span class="tab-item" |
| | | :class="{ active: productionTimeDimension === 'year' }" |
| | | @click="handleProductionTimeDimensionChange('year')">å¹´</span> |
| | | <span class="tab-item" |
| | | :class="{ active: productionTimeDimension === 'month' }" |
| | | @click="handleProductionTimeDimensionChange('month')">æ</span> |
| | | </div> |
| | | <div class="bi-panel-body"> |
| | | <div class="chart-unit-row"> |
| | | <span>åä½ï¼ä»¶</span> |
| | | </div> |
| | | <div ref="productionChart" |
| | | class="echart-fill"></div> |
| | | </div> |
| | | </div> |
| | | <!-- ä¸é´ä¸å¿ç¯ --> |
| | | <div class="center-ring"> |
| | | <!-- <div class="center-ring-box"> |
| | | <div class="center-metric m1"> |
| | | <div class="center-metric-label">项ç®äº§é</div> |
| | | <div class="center-metric-value">{{ projectProduction }}</div> |
| | | <div class="center-metric-unit">ä»¶</div> |
| | | </div> |
| | | <div class="center-metric m2"> |
| | | <div class="center-metric-label">åºä½å¤çé</div> |
| | | <div class="center-metric-value">{{ solidWasteå¤çé }}</div> |
| | | <div class="center-metric-unit">å¨</div> |
| | | </div> |
| | | <div class="center-metric m3"> |
| | | <div class="center-metric-label">ç å产é</div> |
| | | <div class="center-metric-value">{{ blockProduction }}</div> |
| | | <div class="center-metric-unit">ä»¶</div> |
| | | </div> |
| | | <div class="center-metric m4"> |
| | | <div class="center-metric-label">æ¿æäº§é</div> |
| | | <div class="center-metric-value">{{ boardProduction }}</div> |
| | | <div class="center-metric-unit">ä»¶</div> |
| | | </div> |
| | | </div> --> |
| | | </div> |
| | | <!-- å·¦ä¸ï¼çäº§ææ¬åèç»è®¡ï¼æ¿æï¼ --> |
| | | <div class="bi-panel bi-panel-bottom-left"> |
| | | <PanelHeader :isFullscreen="true" |
| | | title="çäº§ææ¬åèç»è®¡ï¼æ¿æï¼" /> |
| | | <div class="panel-tabs"> |
| | | <span class="tab-item" |
| | | :class="{ active: boardTimeDimension === 'year' }" |
| | | @click="handleBoardTimeDimensionChange('year')">å¹´</span> |
| | | <span class="tab-item" |
| | | :class="{ active: boardTimeDimension === 'month' }" |
| | | @click="handleBoardTimeDimensionChange('month')">æ</span> |
| | | </div> |
| | | <div class="bi-panel-body"> |
| | | <div class="chart-filter-tabs"> |
| | | <span v-for="area in salesAreas" |
| | | :key="area" |
| | | class="cf-tab" |
| | | :class="{ active: blockSelectedArea === area }" |
| | | @click="handleBlockAreaChange(area)">{{ area }}</span> |
| | | </div> |
| | | <div class="material-info-card"> |
| | | <div class="material-icon"> |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| | | <path d="M20 7h-4V4c0-1.1-.9-2-2-2h-4c-1.1 0-2 .9-2 2v3H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2z" /> |
| | | <polyline points="22,7 12,13 2,7" /> |
| | | </svg> |
| | | </div> |
| | | <div class="material-details"> |
| | | <div class="material-name">{{ boardMaterialType }}AAA</div> |
| | | <div class="material-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">æç´¯è®¡åè</span> |
| | | <span class="stat-value">78/12</span> |
| | | <span class="stat-unit">å¨</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">年累计åè</span> |
| | | <span class="stat-value">78/12</span> |
| | | <span class="stat-unit">å¨</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- <div class="chart-unit-row"> |
| | | <span>åä½ï¼ç«æ¹ç±³</span> |
| | | </div> --> |
| | | <div ref="boardCostChart" |
| | | class="echart-fill"></div> |
| | | </div> |
| | | </div> |
| | | <!-- ä¸ä¸ï¼æ°å¢å®¢æ·è¶å¿åæ --> |
| | | <div class="bi-panel bi-panel-bottom-center"> |
| | | <PanelHeader :isFullscreen="true" |
| | | title="åºåºå¤çé" /> |
| | | <div class="panel-tabs"> |
| | | <span class="tab-item" |
| | | :class="{ active: customerTimeDimension === 'year' }" |
| | | @click="handleCustomerTimeDimensionChange('year')">å¹´</span> |
| | | <span class="tab-item" |
| | | :class="{ active: customerTimeDimension === 'month' }" |
| | | @click="handleCustomerTimeDimensionChange('month')">æ</span> |
| | | </div> |
| | | <!-- <div class="bi-panel-body"> |
| | | <div class="chart-unit-row chart-unit-single"> |
| | | <span>åä½ï¼å®¶</span> |
| | | </div> |
| | | <div ref="customerTrendChart" |
| | | class="echart-fill"></div> |
| | | </div> --> |
| | | </div> |
| | | <!-- å³ä¸ï¼ééæååæ --> |
| | | <div class="bi-panel bi-panel-bottom-right"> |
| | | <PanelHeader :isFullscreen="true" |
| | | title="ç©æç产éç»è®¡" /> |
| | | <div class="panel-tabs"> |
| | | <span class="tab-item" |
| | | :class="{ active: salesTimeDimension === 'year' }" |
| | | @click="handleSalesTimeDimensionChange('year')">å¹´</span> |
| | | <span class="tab-item" |
| | | :class="{ active: salesTimeDimension === 'month' }" |
| | | @click="handleSalesTimeDimensionChange('month')">æ</span> |
| | | </div> |
| | | <div class="bi-panel-body"> |
| | | <!-- <div class="chart-filter-tabs"> |
| | | <span v-for="area in salesAreas" |
| | | :key="area" |
| | | class="cf-tab" |
| | | :class="{ active: selectedArea === area }" |
| | | @click="handleAreaChange(area)">{{ area }}</span> |
| | | </div> |
| | | <div ref="salesRankingChart" |
| | | class="echart-fill"></div> --> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | computed, |
| | | onMounted, |
| | | onBeforeUnmount, |
| | | nextTick, |
| | | watch, |
| | | nextTick, |
| | | } from "vue"; |
| | | import * as echarts from "echarts"; |
| | | import dayjs from "dayjs"; |
| | | import PanelHeader from "@/views/reportAnalysis/PSIDataAnalysis/components/PanelHeader.vue"; |
| | | |
| | | // ç鿡件 |
| | | const dateType = ref("month"); // month æ year |
| | | const productType = ref("block"); // block æ plate |
| | | const screenRoot = ref(null); |
| | | const isFullscreen = ref(false); |
| | | |
| | | // å¾è¡¨å¼ç¨ |
| | | 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; |
| | | |
| | | // æ¨¡ææ°æ® |
| | | 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 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", |
| | | }, |
| | | }, |
| | | 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.block), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | itemStyle: { |
| | | color: "#409EFF", |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ¿æ", |
| | | type: "line", |
| | | data: data.map(item => item.plate), |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | itemStyle: { |
| | | color: "#67C23A", |
| | | }, |
| | | }, |
| | | ], |
| | | // 顶鍿 æ¶é´ |
| | | const now = ref(dayjs()); |
| | | const currentTime = computed(() => now.value.format("HH:mm:ss")); |
| | | const currentDateText = computed(() => { |
| | | const weekMap = { |
| | | 0: "æææ¥", |
| | | 1: "ææä¸", |
| | | 2: "ææäº", |
| | | 3: "ææä¸", |
| | | 4: "ææå", |
| | | 5: "ææäº", |
| | | 6: "ææå
", |
| | | }; |
| | | return `${now.value.format("YYYY-MM-DD")} ${weekMap[now.value.day()] || ""}`; |
| | | }); |
| | | let timeTicker = null; |
| | | |
| | | 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 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, |
| | | }, |
| | | 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 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 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 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 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 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 handleDateTypeChange = () => { |
| | | updateCharts(); |
| | | const handleFullscreenChange = () => { |
| | | isFullscreen.value = !!document.fullscreenElement; |
| | | nextTick(() => { |
| | | handleResize(); |
| | | }); |
| | | }; |
| | | |
| | | const handleProductTypeChange = () => { |
| | | updateCharts(); |
| | | const toggleFullscreen = async () => { |
| | | const rootEl = screenRoot.value; |
| | | if (!rootEl) return; |
| | | try { |
| | | if (!document.fullscreenElement) { |
| | | await rootEl.requestFullscreen(); |
| | | } else { |
| | | await document.exitFullscreen(); |
| | | } |
| | | } catch (error) { |
| | | console.error("å
¨å±åæ¢å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // å¾è¡¨å¼ç¨ |
| | | const blockCostChart = ref(null); |
| | | const boardCostChart = ref(null); |
| | | const productionChart = ref(null); |
| | | const customerTrendChart = ref(null); |
| | | const salesRankingChart = ref(null); |
| | | |
| | | // 鿩卿°æ® |
| | | const blockTimeDimension = ref("year"); |
| | | const blockMaterialType = ref("ç³ç°"); |
| | | const boardTimeDimension = ref("year"); |
| | | const boardMaterialType = ref("ç³ç°"); |
| | | const productionTimeDimension = ref("year"); |
| | | const customerTimeDimension = ref("year"); |
| | | const salesTimeDimension = ref("year"); |
| | | const selectedArea = ref("å
¨é¨"); |
| | | |
| | | const salesAreas = [ |
| | | "å
¨é¨", |
| | | "ç³ç°", |
| | | "æ°´æ³¥", |
| | | "éç²è", |
| | | "è±æ¨¡å", |
| | | "é²è
å", |
| | | "æ°§åé", |
| | | "å·æä¸", |
| | | ]; |
| | | |
| | | // ä¸å¿ç¯æ°æ® |
| | | const projectProduction = ref(12345); |
| | | const solidWasteå¤çé = ref(6789); |
| | | const blockProduction = ref(7812); |
| | | const boardProduction = ref(7812); |
| | | |
| | | // å¾è¡¨å®ä¾ |
| | | let blockCostChartInstance = null; |
| | | let boardCostChartInstance = null; |
| | | let productionChartInstance = null; |
| | | let customerTrendChartInstance = null; |
| | | let salesRankingChartInstance = null; |
| | | |
| | | // ç产åèå¾è¡¨é
ç½® |
| | | const blockCostChartOption = computed(() => { |
| | | const materials = ["æ¶èé"]; |
| | | const colors = ["#8A6BFF"]; |
| | | const year = 2024; |
| | | const periodType = blockTimeDimension.value; |
| | | |
| | | // çææ¶é´æ®µ |
| | | let periods = []; |
| | | if (periodType === "year") { |
| | | // å¹´åº¦æ°æ®ï¼6个æ |
| | | for (let month = 9; month <= 12; month++) { |
| | | periods.push(`${month}/${year.toString().slice(2)}`); |
| | | } |
| | | for (let month = 1; month <= 3; month++) { |
| | | periods.push(`${month}/${(year + 1).toString().slice(2)}`); |
| | | } |
| | | } else { |
| | | // æåº¦æ°æ®ï¼30天 |
| | | const month = 1; |
| | | for (let day = 1; day <= 30; day++) { |
| | | periods.push(`${month}/${day}`); |
| | | } |
| | | } |
| | | |
| | | // 为æ¯ç§ææçææ°æ® |
| | | const series = materials.map((material, index) => { |
| | | const data = periods.map(() => { |
| | | return periodType === "year" |
| | | ? Math.floor(Math.random() * 50) + 150 |
| | | : Math.floor(Math.random() * 5) + 15; |
| | | }); |
| | | |
| | | return { |
| | | name: material, |
| | | data: data, |
| | | type: "bar", |
| | | itemStyle: { color: colors[index] }, |
| | | }; |
| | | }); |
| | | |
| | | return { |
| | | backgroundColor: "transparent", |
| | | tooltip: { |
| | | trigger: "axis", |
| | | backgroundColor: "rgba(0,0,0,0.55)", |
| | | borderColor: "rgba(64,158,255,0.25)", |
| | | borderWidth: getResponsiveValue(1), |
| | | textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | // legend: { |
| | | // data: materials, |
| | | // top: "10%", |
| | | // right: "1%", |
| | | // textStyle: { |
| | | // color: "#B8C8E0", |
| | | // fontSize: getResponsiveValue(9), |
| | | // }, |
| | | // itemWidth: getResponsiveValue(10), |
| | | // itemHeight: getResponsiveValue(10), |
| | | // }, |
| | | grid: { |
| | | left: "1%", |
| | | right: "1%", |
| | | bottom: "1%", |
| | | top: "8%", |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: periods, |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(10), |
| | | }, |
| | | splitLine: { show: false }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(8), |
| | | }, |
| | | splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } }, |
| | | }, |
| | | series: series, |
| | | }; |
| | | }); |
| | | |
| | | // æ¿æåèå¾è¡¨é
ç½® |
| | | const boardCostChartOption = computed(() => { |
| | | const materials = ["æ¶èé"]; |
| | | const colors = ["#00A4ED", "#34D8F7", "#4A8BFF", "#8A6BFF", "#C8C447", "#FF6B6B"]; |
| | | const year = 2024; |
| | | const periodType = boardTimeDimension.value; |
| | | |
| | | // çææ¶é´æ®µ |
| | | let periods = []; |
| | | if (periodType === "year") { |
| | | // å¹´åº¦æ°æ®ï¼6个æ |
| | | for (let month = 9; month <= 12; month++) { |
| | | periods.push(`${month}/${year.toString().slice(2)}`); |
| | | } |
| | | for (let month = 1; month <= 3; month++) { |
| | | periods.push(`${month}/${(year + 1).toString().slice(2)}`); |
| | | } |
| | | } else { |
| | | // æåº¦æ°æ®ï¼30天 |
| | | const month = 1; |
| | | for (let day = 1; day <= 30; day++) { |
| | | periods.push(`${month}/${day}`); |
| | | } |
| | | } |
| | | |
| | | // 为æ¯ç§ææçææ°æ® |
| | | const series = materials.map((material, index) => { |
| | | const data = periods.map(() => { |
| | | return periodType === "year" |
| | | ? Math.floor(Math.random() * 50) + 150 |
| | | : Math.floor(Math.random() * 5) + 15; |
| | | }); |
| | | |
| | | return { |
| | | name: material, |
| | | data: data, |
| | | type: "bar", |
| | | itemStyle: { color: colors[index] }, |
| | | }; |
| | | }); |
| | | |
| | | return { |
| | | backgroundColor: "transparent", |
| | | tooltip: { |
| | | trigger: "axis", |
| | | backgroundColor: "rgba(0,0,0,0.55)", |
| | | borderColor: "rgba(64,158,255,0.25)", |
| | | borderWidth: getResponsiveValue(1), |
| | | textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | // legend: { |
| | | // data: materials, |
| | | // top: "10%", |
| | | // right: "1%", |
| | | // textStyle: { |
| | | // color: "#B8C8E0", |
| | | // fontSize: getResponsiveValue(9), |
| | | // }, |
| | | // itemWidth: getResponsiveValue(10), |
| | | // itemHeight: getResponsiveValue(10), |
| | | // }, |
| | | grid: { |
| | | left: "1%", |
| | | right: "1%", |
| | | bottom: "1%", |
| | | top: "8%", |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: periods, |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(10), |
| | | }, |
| | | splitLine: { show: false }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(8), |
| | | }, |
| | | splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } }, |
| | | }, |
| | | series: series, |
| | | }; |
| | | }); |
| | | |
| | | // 产éåæå¾è¡¨é
ç½® |
| | | const productionChartOption = computed(() => { |
| | | const salesAreas = ["å
¨é¨", "ç å", "æ¿æ"]; |
| | | const colors = ["#00A4ED", "#34D8F7", "#4A8BFF", "#8A6BFF", "#C8C447", "#FF6B6B"]; |
| | | const year = 2024; |
| | | const periodType = productionTimeDimension.value; |
| | | |
| | | // çææ¶é´æ®µ |
| | | let periods = []; |
| | | if (periodType === "year") { |
| | | // å¹´åº¦æ°æ®ï¼6个æ |
| | | for (let month = 9; month <= 12; month++) { |
| | | periods.push(`${month}/${year.toString().slice(2)}`); |
| | | } |
| | | for (let month = 1; month <= 3; month++) { |
| | | periods.push(`${month}/${(year + 1).toString().slice(2)}`); |
| | | } |
| | | } else { |
| | | // æåº¦æ°æ®ï¼30天 |
| | | const month = 1; |
| | | for (let day = 1; day <= 30; day++) { |
| | | periods.push(`${month}/${day}`); |
| | | } |
| | | } |
| | | |
| | | // 为æ¯ä¸ªéå®åºçææ°æ® |
| | | const series = salesAreas.map((area, index) => { |
| | | const data = periods.map(() => { |
| | | return periodType === "year" |
| | | ? Math.floor(Math.random() * 50) + 150 |
| | | : Math.floor(Math.random() * 5) + 15; |
| | | }); |
| | | |
| | | return { |
| | | name: area, |
| | | data: data, |
| | | type: "line", |
| | | smooth: true, |
| | | lineStyle: { width: getResponsiveValue(2), color: colors[index] }, |
| | | itemStyle: { color: colors[index] }, |
| | | areaStyle: { |
| | | opacity: 0.3, |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: colors[index] + "80" }, |
| | | { offset: 1, color: colors[index] + "00" }, |
| | | ]), |
| | | }, |
| | | }; |
| | | }); |
| | | |
| | | return { |
| | | backgroundColor: "transparent", |
| | | tooltip: { |
| | | trigger: "axis", |
| | | backgroundColor: "rgba(0,0,0,0.55)", |
| | | borderColor: "rgba(64,158,255,0.25)", |
| | | borderWidth: getResponsiveValue(1), |
| | | textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | legend: { |
| | | data: salesAreas, |
| | | top: "10%", |
| | | right: "1%", |
| | | textStyle: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(9), |
| | | }, |
| | | itemWidth: getResponsiveValue(10), |
| | | itemHeight: getResponsiveValue(10), |
| | | }, |
| | | grid: { |
| | | left: "1%", |
| | | right: "1%", |
| | | bottom: "1%", |
| | | top: "28%", |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: periods, |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(10), |
| | | }, |
| | | splitLine: { show: false }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(8), |
| | | }, |
| | | splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } }, |
| | | }, |
| | | series: series, |
| | | }; |
| | | }); |
| | | |
| | | // æ°å¢å®¢æ·è¶å¿å¾è¡¨é
ç½® |
| | | const customerTrendChartOption = computed(() => { |
| | | const customerTypes = ["å
¨é¨", "ç³ç°", "æ°´æ³¥", "éç²è", "è±æ¨¡å"]; |
| | | const colors = ["#00A4ED", "#34D8F7", "#4A8BFF", "#8A6BFF", "#C8C447"]; |
| | | const year = 2024; |
| | | const periodType = customerTimeDimension.value; |
| | | |
| | | // çææ¶é´æ®µ |
| | | let periods = []; |
| | | if (periodType === "year") { |
| | | // å¹´åº¦æ°æ®ï¼6个æ |
| | | for (let month = 9; month <= 12; month++) { |
| | | periods.push(`${month}/${year.toString().slice(2)}`); |
| | | } |
| | | for (let month = 1; month <= 5; month++) { |
| | | periods.push(`${month}/${(year + 1).toString().slice(2)}`); |
| | | } |
| | | } else { |
| | | // æåº¦æ°æ®ï¼30天 |
| | | const month = 1; |
| | | for (let day = 1; day <= 30; day++) { |
| | | periods.push(`${month}/${day}`); |
| | | } |
| | | } |
| | | |
| | | // 为æ¯ç§å®¢æ·ç±»åçææ°æ® |
| | | const series = customerTypes.map((type, index) => { |
| | | const data = periods.map(() => { |
| | | return periodType === "year" |
| | | ? Math.floor(Math.random() * 10) + 5 |
| | | : Math.floor(Math.random() * 3) + 1; |
| | | }); |
| | | |
| | | return { |
| | | name: type, |
| | | data: data, |
| | | type: "line", |
| | | smooth: true, |
| | | lineStyle: { width: getResponsiveValue(2), color: colors[index] }, |
| | | itemStyle: { color: colors[index] }, |
| | | areaStyle: { |
| | | opacity: 0.3, |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: colors[index] + "80" }, |
| | | { offset: 1, color: colors[index] + "00" }, |
| | | ]), |
| | | }, |
| | | }; |
| | | }); |
| | | |
| | | return { |
| | | backgroundColor: "transparent", |
| | | tooltip: { |
| | | trigger: "axis", |
| | | backgroundColor: "rgba(0,0,0,0.55)", |
| | | borderColor: "rgba(64,158,255,0.25)", |
| | | borderWidth: getResponsiveValue(1), |
| | | textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | }, |
| | | legend: { |
| | | data: customerTypes, |
| | | top: "10%", |
| | | right: "1%", |
| | | textStyle: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(9), |
| | | }, |
| | | itemWidth: getResponsiveValue(10), |
| | | itemHeight: getResponsiveValue(10), |
| | | }, |
| | | grid: { |
| | | left: "1%", |
| | | right: "1%", |
| | | bottom: "1%", |
| | | top: "28%", |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: periods, |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(10), |
| | | }, |
| | | splitLine: { show: false }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(8), |
| | | }, |
| | | splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } }, |
| | | }, |
| | | series: series, |
| | | }; |
| | | }); |
| | | |
| | | // ééæååæå¾è¡¨é
ç½® |
| | | const salesRankingChartOption = computed(() => { |
| | | const customers = ["客æ·BB", "客æ·AA", "客æ·CC", "客æ·DD", "客æ·DD", "客æ·DD"]; |
| | | const values = [130, 120, 102, 90, 90, 70]; |
| | | const barColors = [ |
| | | "#34D8F7", |
| | | "#4A8BFF", |
| | | "#8A6BFF", |
| | | "#C8C447", |
| | | "#C8C447", |
| | | "#C8C447", |
| | | ]; |
| | | |
| | | return { |
| | | backgroundColor: "transparent", |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { type: "shadow" }, |
| | | backgroundColor: "rgba(0,0,0,0.55)", |
| | | borderColor: "rgba(64,158,255,0.25)", |
| | | borderWidth: getResponsiveValue(1), |
| | | textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | formatter: "{b}: {c} ç«æ¹ç±³", |
| | | }, |
| | | grid: { |
| | | left: "14%", |
| | | right: "6%", |
| | | top: "16%", |
| | | bottom: "8%", |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "value", |
| | | axisLine: { show: false }, |
| | | axisLabel: { color: "#B8C8E0", fontSize: getResponsiveValue(11) }, |
| | | splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } }, |
| | | }, |
| | | yAxis: { |
| | | type: "category", |
| | | data: customers, |
| | | axisTick: { show: false }, |
| | | axisLine: { show: false }, |
| | | axisLabel: { |
| | | color: "#B8C8E0", |
| | | fontSize: getResponsiveValue(11), |
| | | margin: getResponsiveValue(8), |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "ééï¼ç«æ¹ç±³ï¼", |
| | | type: "bar", |
| | | barWidth: getResponsiveValue(14), |
| | | data: values, |
| | | itemStyle: { |
| | | color: params => barColors[params.dataIndex] || "#00A4ED", |
| | | borderRadius: [ |
| | | getResponsiveValue(6), |
| | | getResponsiveValue(6), |
| | | getResponsiveValue(6), |
| | | getResponsiveValue(6), |
| | | ], |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | }); |
| | | |
| | | const baseWidth = ref(1650); |
| | | // 计ç®ååºå¼å¼ |
| | | const getResponsiveValue = baseValue => { |
| | | return Math.round((baseValue * window.innerWidth) / baseWidth.value); |
| | | }; |
| | | |
| | | // åå§åå¾è¡¨ |
| | | const initCharts = () => { |
| | | if (productionChart.value) { |
| | | // åå§åç åææ¬å¾è¡¨ |
| | | if (blockCostChart.value && !blockCostChartInstance) { |
| | | blockCostChartInstance = echarts.init(blockCostChart.value); |
| | | } |
| | | |
| | | // åå§åæ¿æææ¬å¾è¡¨ |
| | | if (boardCostChart.value && !boardCostChartInstance) { |
| | | boardCostChartInstance = echarts.init(boardCostChart.value); |
| | | } |
| | | |
| | | // åå§å产éåæå¾è¡¨ |
| | | if (productionChart.value && !productionChartInstance) { |
| | | productionChartInstance = echarts.init(productionChart.value); |
| | | productionChartInstance.setOption(productionChartOption.value); |
| | | } |
| | | |
| | | if (solidWasteChart.value) { |
| | | solidWasteChartInstance = echarts.init(solidWasteChart.value); |
| | | solidWasteChartInstance.setOption(solidWasteChartOption.value); |
| | | // åå§åæ°å¢å®¢æ·è¶å¿å¾è¡¨ |
| | | if (customerTrendChart.value && !customerTrendChartInstance) { |
| | | customerTrendChartInstance = echarts.init(customerTrendChart.value); |
| | | } |
| | | |
| | | if (costChart.value) { |
| | | costChartInstance = echarts.init(costChart.value); |
| | | costChartInstance.setOption(costChartOption.value); |
| | | // åå§åééæååæå¾è¡¨ |
| | | if (salesRankingChart.value && !salesRankingChartInstance) { |
| | | salesRankingChartInstance = echarts.init(salesRankingChart.value); |
| | | } |
| | | |
| | | if (energyChart.value) { |
| | | energyChartInstance = echarts.init(energyChart.value); |
| | | energyChartInstance.setOption(energyChartOption.value); |
| | | } |
| | | updateCharts(); |
| | | }; |
| | | |
| | | // æ´æ°å¾è¡¨ |
| | | const updateCharts = () => { |
| | | // æ´æ°ç åææ¬å¾è¡¨ |
| | | if (blockCostChartInstance) { |
| | | blockCostChartInstance.setOption(blockCostChartOption.value); |
| | | } |
| | | |
| | | // æ´æ°æ¿æææ¬å¾è¡¨ |
| | | if (boardCostChartInstance) { |
| | | boardCostChartInstance.setOption(boardCostChartOption.value); |
| | | } |
| | | |
| | | // æ´æ°äº§éåæå¾è¡¨ |
| | | if (productionChartInstance) { |
| | | productionChartInstance.setOption(productionChartOption.value); |
| | | } |
| | | |
| | | if (solidWasteChartInstance) { |
| | | solidWasteChartInstance.setOption(solidWasteChartOption.value); |
| | | // æ´æ°æ°å¢å®¢æ·è¶å¿å¾è¡¨ |
| | | if (customerTrendChartInstance) { |
| | | customerTrendChartInstance.setOption(customerTrendChartOption.value); |
| | | } |
| | | |
| | | if (costChartInstance) { |
| | | costChartInstance.setOption(costChartOption.value); |
| | | } |
| | | |
| | | if (energyChartInstance) { |
| | | energyChartInstance.setOption(energyChartOption.value); |
| | | // æ´æ°ééæååæå¾è¡¨ |
| | | if (salesRankingChartInstance) { |
| | | salesRankingChartInstance.setOption(salesRankingChartOption.value); |
| | | } |
| | | }; |
| | | |
| | | // è°æ´å¾è¡¨å¤§å° |
| | | const resizeCharts = () => { |
| | | productionChartInstance?.resize(); |
| | | solidWasteChartInstance?.resize(); |
| | | costChartInstance?.resize(); |
| | | energyChartInstance?.resize(); |
| | | // å¤çæ¶é´ç»´åº¦éæ© |
| | | const handleBlockTimeDimensionChange = dimension => { |
| | | blockTimeDimension.value = dimension; |
| | | updateCharts(); |
| | | }; |
| | | |
| | | // çªå£å¤§å°ååå¤ç |
| | | const handleBoardTimeDimensionChange = dimension => { |
| | | boardTimeDimension.value = dimension; |
| | | updateCharts(); |
| | | }; |
| | | |
| | | const handleProductionTimeDimensionChange = dimension => { |
| | | productionTimeDimension.value = dimension; |
| | | updateCharts(); |
| | | }; |
| | | |
| | | const handleCustomerTimeDimensionChange = dimension => { |
| | | customerTimeDimension.value = dimension; |
| | | updateCharts(); |
| | | }; |
| | | |
| | | const handleSalesTimeDimensionChange = dimension => { |
| | | salesTimeDimension.value = dimension; |
| | | updateCharts(); |
| | | }; |
| | | |
| | | // å¤çææç±»åéæ© |
| | | const handleBlockMaterialTypeChange = type => { |
| | | blockMaterialType.value = type; |
| | | updateCharts(); |
| | | }; |
| | | |
| | | const handleBoardMaterialTypeChange = type => { |
| | | boardMaterialType.value = type; |
| | | updateCharts(); |
| | | }; |
| | | |
| | | // å¤çéå®åºéæ© |
| | | const handleAreaChange = area => { |
| | | selectedArea.value = area; |
| | | updateCharts(); |
| | | }; |
| | | |
| | | // çå¬çªå£å¤§å°åå |
| | | const handleResize = () => { |
| | | // å»¶è¿æ§è¡ï¼ç¡®ä¿DOMæ´æ°å®æ |
| | | setTimeout(() => { |
| | | resizeCharts(); |
| | | }, 100); |
| | | // å
æ´æ°å¾è¡¨é项ï¼éæ°è®¡ç®ååºå¼å¼ |
| | | updateCharts(); |
| | | // ç¶åè°æ´å¾è¡¨å¤§å° |
| | | if (blockCostChartInstance) { |
| | | blockCostChartInstance.resize(); |
| | | } |
| | | if (boardCostChartInstance) { |
| | | boardCostChartInstance.resize(); |
| | | } |
| | | if (productionChartInstance) { |
| | | productionChartInstance.resize(); |
| | | } |
| | | if (customerTrendChartInstance) { |
| | | customerTrendChartInstance.resize(); |
| | | } |
| | | if (salesRankingChartInstance) { |
| | | salesRankingChartInstance.resize(); |
| | | } |
| | | }; |
| | | |
| | | // è·åç©æç±»åæ ç¾ç±»å |
| | | const getMaterialTypeType = material => { |
| | | const typeMap = { |
| | | æ°´æ³¥: "primary", |
| | | éç²è: "success", |
| | | è±æ¨¡å: "warning", |
| | | é²è
å: "danger", |
| | | æ°¯åå: "info", |
| | | å·æä¸: "purple", |
| | | }; |
| | | return typeMap[material] || "info"; |
| | | }; |
| | | |
| | | // çå½å¨æé©å |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | // 使ç¨nextTickç¡®ä¿DOMå®å
¨æ¸²æåååå§å |
| | | // å¯å¨é¡¶é¨æ æ¶é´å·æ° |
| | | if (!timeTicker) { |
| | | timeTicker = setInterval(() => { |
| | | now.value = dayjs(); |
| | | }, 1000); |
| | | } |
| | | |
| | | // çå¾
DOMæ´æ°ååå§åå¾è¡¨ |
| | | nextTick(() => { |
| | | // åå§åå¾è¡¨ |
| | | initCharts(); |
| | | }); |
| | | |
| | | // æ·»å çªå£å¤§å°ååçå¬ |
| | | window.addEventListener("resize", handleResize); |
| | | document.addEventListener("fullscreenchange", handleFullscreenChange); |
| | | }); |
| | | |
| | | // ç»ä»¶å¸è½½æ¶éæ¯å¾è¡¨å®ä¾ |
| | | onBeforeUnmount(() => { |
| | | window.removeEventListener("resize", handleResize); |
| | | if (timeTicker) { |
| | | clearInterval(timeTicker); |
| | | timeTicker = null; |
| | | } |
| | | |
| | | // 鿝å¾è¡¨å®ä¾ |
| | | productionChartInstance?.dispose(); |
| | | solidWasteChartInstance?.dispose(); |
| | | costChartInstance?.dispose(); |
| | | energyChartInstance?.dispose(); |
| | | if (blockCostChartInstance) { |
| | | blockCostChartInstance.dispose(); |
| | | } |
| | | if (boardCostChartInstance) { |
| | | boardCostChartInstance.dispose(); |
| | | } |
| | | if (productionChartInstance) { |
| | | productionChartInstance.dispose(); |
| | | } |
| | | if (customerTrendChartInstance) { |
| | | customerTrendChartInstance.dispose(); |
| | | } |
| | | if (salesRankingChartInstance) { |
| | | salesRankingChartInstance.dispose(); |
| | | } |
| | | |
| | | // ç§»é¤çªå£å¤§å°ååçå¬ |
| | | window.removeEventListener("resize", handleResize); |
| | | document.removeEventListener("fullscreenchange", handleFullscreenChange); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | /* å¤é¨å®¹å¨ - å æ®æ´ä¸ªè§å£ */ |
| | | .dashboard-container { |
| | | .sales-statistics-container { |
| | | position: relative; |
| | | width: 100%; |
| | | /* 页é¢å¨å¸¸è§å¸å±ä¸ï¼æé¡¶æ ï¼é»è®¤åå» 84pxï¼é¿å
å
容被è£å */ |
| | | min-height: calc(100vh - 84px); |
| | | background-color: #f5f7fa; |
| | | min-height: calc(100vh - 8.4vh); |
| | | overflow: hidden; |
| | | color: #b8c8e0; |
| | | background: #041026; |
| | | } |
| | | |
| | | /* å
é¨å
容åºå - èªéåºå®½åº¦ */ |
| | | .data-dashboard { |
| | | position: relative; |
| | | width: 100%; |
| | | min-height: 100%; |
| | | background-color: #ffffff; |
| | | box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); |
| | | .sales-statistics-container.is-fullscreen { |
| | | min-height: 100vh; |
| | | height: 100vh; |
| | | } |
| | | |
| | | .dashboard-header { |
| | | /* æ·±è²èæ¯å¾ */ |
| | | .bi-bg { |
| | | position: absolute; |
| | | inset: 0; |
| | | /* background-image: url("@/assets/BI/backImage@2x.png"); */ |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | z-index: 0; |
| | | } |
| | | |
| | | /* 顶鍿 颿 */ |
| | | .bi-topbar { |
| | | position: relative; |
| | | z-index: 1; |
| | | height: 86px; |
| | | background-color: #ffffff; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | z-index: 2; |
| | | height: 5.8vh; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .factory-name { |
| | | font-weight: 600; |
| | | font-size: 32px; |
| | | color: #303133; |
| | | .bi-topbar-title-bg { |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | height: 8vh; |
| | | width: 100%; |
| | | object-fit: cover; |
| | | z-index: 0; |
| | | pointer-events: none; |
| | | } |
| | | |
| | | .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-label { |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .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__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: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; |
| | | } |
| | | |
| | | .dashboard-content { |
| | | .bi-topbar-content { |
| | | position: relative; |
| | | z-index: 1; |
| | | width: 100%; |
| | | padding: 0 2.8vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | padding: 20px; |
| | | min-height: 800px; |
| | | overflow: hidden; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | /* è¡å¸å± */ |
| | | .row { |
| | | .bi-topbar-title { |
| | | position: absolute; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | font-size: 2.6vh; |
| | | font-weight: 800; |
| | | letter-spacing: 0.1vh; |
| | | background: linear-gradient(180deg, #ffffff 0%, #b8dfff 100%); |
| | | -webkit-background-clip: text; |
| | | background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | color: transparent; |
| | | text-shadow: 0 0 2.6vh rgba(0, 164, 237, 0.55); |
| | | } |
| | | |
| | | .bi-topbar-left { |
| | | position: absolute; |
| | | left: 1vh; |
| | | display: flex; |
| | | gap: 20px; |
| | | align-items: stretch; |
| | | align-items: center; |
| | | gap: 0.8vh; |
| | | color: rgba(208, 231, 255, 0.85); |
| | | font-size: 1.3vh; |
| | | } |
| | | |
| | | /* 第ä¸è¡ï¼3个å¡ç */ |
| | | .row-1 { |
| | | height: 300px; |
| | | .status-sun { |
| | | color: #ffd85e; |
| | | text-shadow: 0 0 1vh rgba(255, 216, 94, 0.8); |
| | | font-size: 1.3vh; |
| | | line-height: 1; |
| | | } |
| | | |
| | | /* 第äºè¡ï¼2个å¡ç */ |
| | | .row-2 { |
| | | height: 300px; |
| | | } |
| | | |
| | | /* 第ä¸è¡ï¼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:hover { |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | /* å¡çå¸å± */ |
| | | .card-1 { |
| | | flex: 1; |
| | | } |
| | | |
| | | .card-2 { |
| | | flex: 1; |
| | | } |
| | | |
| | | .card-3 { |
| | | flex: 0.8; |
| | | } |
| | | |
| | | .card-4 { |
| | | flex: 1.2; |
| | | } |
| | | |
| | | .card-5 { |
| | | flex: 0.8; |
| | | } |
| | | |
| | | .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-title { |
| | | padding: 15px 20px; |
| | | font-size: 16px; |
| | | .bi-topbar-meta { |
| | | position: absolute; |
| | | right: 5.2vh; |
| | | /* top: 1.6vh; */ |
| | | font-size: 1.2vh; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | background-color: #fafafa; |
| | | letter-spacing: 0.05vh; |
| | | color: rgba(208, 231, 255, 0.85); |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 1vh; |
| | | } |
| | | |
| | | .card-1 .panel-title { |
| | | border-left: 4px solid #409eff; |
| | | .fullscreen-btn { |
| | | position: absolute; |
| | | bottom: -1vh; |
| | | transform: none; |
| | | border: 0.1vh solid rgba(64, 158, 255, 0.45); |
| | | background: rgba(0, 164, 237, 0.14); |
| | | color: #d0e7ff; |
| | | width: 3.4vh; |
| | | height: 3.4vh; |
| | | border-radius: 0.6vh; |
| | | padding: 0; |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | | z-index: 10; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .card-2 .panel-title { |
| | | border-left: 4px solid #f56c6c; |
| | | .fullscreen-btn:hover { |
| | | background: rgba(0, 164, 237, 0.24); |
| | | box-shadow: 0 0 1.2vh rgba(0, 164, 237, 0.3); |
| | | } |
| | | |
| | | .card-3 .panel-title { |
| | | border-left: 4px solid #e6a23c; |
| | | .bi-topbar-sep { |
| | | opacity: 0.7; |
| | | } |
| | | |
| | | .card-4 .panel-title { |
| | | border-left: 4px solid #409eff; |
| | | /* 主ä½ç½æ ¼å¸å± */ |
| | | .bi-dashboard-grid { |
| | | position: relative; |
| | | z-index: 2; |
| | | height: calc(100vh - 8.4vh - 5.8vh); |
| | | min-height: 45vh; |
| | | padding: 1vh 1.8vh 1.4vh; |
| | | display: grid; |
| | | grid-template-columns: 1fr 1.05fr 1fr; |
| | | grid-template-rows: 1fr 1fr; |
| | | gap: 1.2vh; |
| | | } |
| | | |
| | | .card-5 .panel-title { |
| | | border-left: 4px solid #67c23a; |
| | | .sales-statistics-container.is-fullscreen .bi-dashboard-grid { |
| | | height: calc(100vh - 5.8vh); |
| | | } |
| | | |
| | | .card-6 .panel-title { |
| | | border-left: 4px solid #e6a23c; |
| | | .bi-panel { |
| | | background: rgba(3, 18, 46, 0.62); |
| | | border: 0.1vh solid rgba(64, 158, 255, 0.35); |
| | | border-radius: 0.4vh; |
| | | overflow: hidden; |
| | | box-shadow: 0 0 2.2vh rgba(0, 164, 237, 0.12); |
| | | display: flex; |
| | | flex-direction: column; |
| | | position: relative; |
| | | } |
| | | |
| | | .chart-container { |
| | | .bi-panel-title { |
| | | height: 4.4vh; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 0 1.8vh; |
| | | font-size: 1.5vh; |
| | | font-weight: 700; |
| | | color: #b8c8e0; |
| | | background: linear-gradient( |
| | | 90deg, |
| | | rgba(0, 164, 237, 0.2), |
| | | rgba(0, 164, 237, 0.04) |
| | | ); |
| | | border-bottom: 0.1vh solid rgba(64, 158, 255, 0.25); |
| | | } |
| | | |
| | | .panel-tabs, |
| | | .panel-tabs2 { |
| | | position: absolute; |
| | | top: 0.8vh; |
| | | display: flex; |
| | | gap: 0.6vh; |
| | | z-index: 4; |
| | | } |
| | | |
| | | .panel-tabs { |
| | | right: 1.2vh; |
| | | } |
| | | |
| | | .panel-tabs2 { |
| | | right: 8vh; |
| | | } |
| | | .tab-item { |
| | | font-size: 1.2vh; |
| | | color: rgba(184, 200, 224, 0.75); |
| | | padding: 0.1vh 0.5vh; |
| | | border: 0.1vh solid rgba(64, 158, 255, 0.25); |
| | | border-radius: 0.3vh; |
| | | line-height: 1.4; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .tab-item.active { |
| | | color: #ffffff; |
| | | border-color: rgba(0, 164, 237, 0.65); |
| | | background: rgba(0, 164, 237, 0.22); |
| | | } |
| | | |
| | | .bi-panel-body { |
| | | flex: 1; |
| | | padding: 20px; |
| | | padding: 0.8vh 1vh; |
| | | position: relative; |
| | | } |
| | | |
| | | .table-container { |
| | | flex: 1; |
| | | padding: 20px; |
| | | .scroll-table-container { |
| | | height: 33vh; |
| | | overflow: hidden; |
| | | position: relative; |
| | | } |
| | | |
| | | .scroll-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | color: #b8c8e0; |
| | | } |
| | | |
| | | .scroll-table th { |
| | | /* background-color: #0e2a54; */ |
| | | padding: 1.2vh; |
| | | text-align: left; |
| | | font-size: 1.2vh; |
| | | font-weight: bold; |
| | | border: 1px solid rgba(184, 200, 224, 0.2); |
| | | } |
| | | |
| | | .scroll-table td { |
| | | padding: 1vh; |
| | | font-size: 1.1vh; |
| | | border-bottom: 1px solid rgba(184, 200, 224, 0.1); |
| | | } |
| | | |
| | | .scroll-table tbody { |
| | | display: block; |
| | | height: 35vh; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .scroll-table thead, |
| | | .scroll-table tbody tr { |
| | | display: table; |
| | | width: 100%; |
| | | table-layout: fixed; |
| | | } |
| | | |
| | | .scroll-table th, |
| | | .scroll-table td { |
| | | width: 25%; |
| | | box-sizing: border-box; |
| | | font-size: 1.4vh; |
| | | } |
| | | |
| | | .scroll-table tbody tr { |
| | | transition: all 0.5s ease-in-out; |
| | | } |
| | | |
| | | /* .scroll-table tbody tr:nth-child(odd) { |
| | | background-color: rgba(64, 158, 255, 0.05); |
| | | } |
| | | |
| | | .scroll-table tbody tr:nth-child(even) { |
| | | background-color: rgba(64, 158, 255, 0.1); |
| | | } */ |
| | | .oddTableTr { |
| | | background-color: rgba(64, 158, 255, 0.05); |
| | | } |
| | | .evenTableTr { |
| | | background-color: rgba(64, 158, 255, 0.1); |
| | | } |
| | | |
| | | .scroll-table-container:hover tbody { |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .echart-fill { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .chart-filter-tabs { |
| | | display: flex; |
| | | gap: 0.6vh; |
| | | margin: 0 0 0.5vh 0; |
| | | justify-self: end; |
| | | } |
| | | |
| | | .cf-tab { |
| | | font-size: 1.1vh; |
| | | color: rgba(184, 200, 224, 0.68); |
| | | background: rgba(18, 56, 106, 0.65); |
| | | border: 0.1vh solid rgba(64, 158, 255, 0.25); |
| | | padding: 0.3vh 0.9vh; |
| | | line-height: 1; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .cf-tab.active { |
| | | color: #d9ecff; |
| | | background: rgba(0, 108, 208, 0.85); |
| | | border-color: rgba(64, 158, 255, 0.65); |
| | | } |
| | | |
| | | .chart-unit-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | font-size: 1.2vh; |
| | | color: rgba(208, 231, 255, 0.88); |
| | | margin-bottom: 0.4vh; |
| | | padding: 0 0.2vh; |
| | | } |
| | | |
| | | .dot-legend::before { |
| | | content: ""; |
| | | display: inline-block; |
| | | width: 0.8vh; |
| | | height: 0.8vh; |
| | | background: #65a0ff; |
| | | margin-right: 0.6vh; |
| | | } |
| | | |
| | | .chart-mini-title { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 0.8vh; |
| | | font-size: 1.8vh; |
| | | color: #d9ecff; |
| | | } |
| | | |
| | | /* 颿¿åºé¨åè®¡è¡ */ |
| | | .panel-summary-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 0.8vh 1.2vh; |
| | | /* margin-top: 0.8vh; */ |
| | | background: #041e3c; |
| | | border-top: 0.1vh solid rgba(64, 158, 255, 0.25); |
| | | border-radius: 0 0 0.4vh 0.4vh; |
| | | width: 100%; |
| | | position: absolute; |
| | | bottom: 0; |
| | | } |
| | | |
| | | .summary-label { |
| | | font-size: 1.3vh; |
| | | font-weight: 700; |
| | | color: #b8c8e0; |
| | | } |
| | | |
| | | .summary-value { |
| | | font-size: 1.4vh; |
| | | font-weight: 800; |
| | | color: #00a4ed; |
| | | margin-right: 3.8vh; |
| | | text-shadow: 0 0 1vh rgba(0, 164, 237, 0.5); |
| | | } |
| | | |
| | | .summary-value2 { |
| | | font-size: 1.4vh; |
| | | font-weight: 800; |
| | | color: #00a4ed; |
| | | margin-right: 5.8vh; |
| | | text-shadow: 0 0 1vh rgba(0, 164, 237, 0.5); |
| | | } |
| | | .diamond { |
| | | width: 1vh; |
| | | height: 1vh; |
| | | background: #1e8bff; |
| | | transform: rotate(45deg); |
| | | display: inline-block; |
| | | } |
| | | |
| | | .chart-unit-single { |
| | | justify-content: flex-start; |
| | | margin-bottom: 0.2vh; |
| | | } |
| | | |
| | | .bi-panel-top-left .echart-fill, |
| | | .bi-panel-bottom-left .echart-fill { |
| | | height: 24vh; |
| | | } |
| | | |
| | | |
| | | .bi-panel-bottom-right .echart-fill { |
| | | height: calc(100% - 2.8vh); |
| | | } |
| | | |
| | | .bi-panel-bottom-center .echart-fill, |
| | | .bi-panel-top-right .echart-fill { |
| | | height: calc(100% - 4.4vh); |
| | | } |
| | | |
| | | .bi-panel-top-left { |
| | | grid-column: 1; |
| | | grid-row: 1; |
| | | position: relative; |
| | | } |
| | | |
| | | .bi-panel-top-right { |
| | | grid-column: 3; |
| | | grid-row: 1; |
| | | position: relative; |
| | | } |
| | | |
| | | .bi-panel-bottom-left { |
| | | grid-column: 1; |
| | | grid-row: 2; |
| | | overflow-y: auto; |
| | | } |
| | | .bi-panel-bottom-left::-webkit-scrollbar { |
| | | width: 0vh; |
| | | height: 0vh; |
| | | } |
| | | |
| | | .bi-panel-bottom-center { |
| | | grid-column: 2; |
| | | grid-row: 2; |
| | | } |
| | | |
| | | .bi-panel-bottom-right { |
| | | grid-column: 3; |
| | | grid-row: 2; |
| | | overflow-y: auto; |
| | | } |
| | | .bi-panel-bottom-right::-webkit-scrollbar { |
| | | width: 0vh; |
| | | height: 0vh; |
| | | } |
| | | |
| | | /* ä¸å¿ç¯æµ®å±ï¼ç»å¯¹å®ä½å¨ç½æ ¼ä¸æ¹ï¼ */ |
| | | .center-ring { |
| | | grid-column: 2; |
| | | grid-row: 1 / span 2; |
| | | position: absolute; |
| | | background: url("@/assets/BI/imageSS@2x.png") no-repeat bottom center; |
| | | background-size: 100% 30%; |
| | | left: 25%; |
| | | top: 25%; |
| | | transform: translate(-50%, -50%); |
| | | width: 60vh; |
| | | height: 40.5vh; |
| | | z-index: 3; |
| | | pointer-events: none; |
| | | } |
| | | .center-ring-box { |
| | | position: absolute; |
| | | /* inset: 0; */ |
| | | height: 100%; |
| | | width: 100%; |
| | | /* background-color: #fff; */ |
| | | background: url("@/assets/BI/imageSStop.png") no-repeat center center; |
| | | background-size: 80% 90%; |
| | | } |
| | | |
| | | .center-ring-bg { |
| | | width: 100%; |
| | | height: 100%; |
| | | object-fit: contain; |
| | | filter: drop-shadow(0 0 2vh rgba(0, 164, 237, 0.35)); |
| | | } |
| | | |
| | | .center-ring-content { |
| | | position: absolute; |
| | | inset: 0; |
| | | } |
| | | |
| | | .center-ring-content::before, |
| | | .center-ring-content::after { |
| | | content: ""; |
| | | position: absolute; |
| | | left: 50%; |
| | | top: 56%; |
| | | width: 37vh; |
| | | height: 14.6vh; |
| | | transform: translate(-50%, -50%) rotate(-18deg); |
| | | border: 0.2vh solid rgba(40, 186, 255, 0.45); |
| | | border-radius: 50%; |
| | | filter: drop-shadow(0 0 0.8vh rgba(0, 164, 237, 0.35)); |
| | | opacity: 0.7; |
| | | } |
| | | |
| | | .center-ring-content::after { |
| | | width: 36vh; |
| | | height: 15vh; |
| | | transform: translate(-50%, -50%) rotate(26deg); |
| | | border-color: rgba(80, 220, 255, 0.35); |
| | | opacity: 0.55; |
| | | } |
| | | |
| | | .center-ring-title { |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 50%; |
| | | transform: translate(-50%, -50%); |
| | | font-size: 3.6vh; |
| | | line-height: 1.05; |
| | | text-align: center; |
| | | font-weight: 900; |
| | | color: #eaf6ff; |
| | | text-shadow: 0 0 2.2vh rgba(0, 164, 237, 0.55); |
| | | z-index: 2; |
| | | } |
| | | |
| | | .center-ring-title::before { |
| | | content: ""; |
| | | position: absolute; |
| | | left: 50%; |
| | | top: 50%; |
| | | width: 15.5vh; |
| | | height: 15.5vh; |
| | | transform: translate(-50%, -50%); |
| | | background: radial-gradient( |
| | | circle, |
| | | rgba(43, 199, 255, 0.26) 0%, |
| | | rgba(8, 28, 61, 0.86) 70% |
| | | ); |
| | | border: 0.2vh solid rgba(39, 198, 255, 0.46); |
| | | border-radius: 50%; |
| | | box-shadow: 0 0 2vh rgba(0, 164, 237, 0.45), |
| | | inset 0 0 2.6vh rgba(0, 164, 237, 0.2); |
| | | z-index: -1; |
| | | } |
| | | |
| | | .center-metric { |
| | | position: absolute; |
| | | width: 15.5vh; |
| | | z-index: 3; |
| | | text-align: center; |
| | | height: 12vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .center-metric-label { |
| | | font-size: 1.2vh; |
| | | font-weight: 500; |
| | | color: rgba(234, 246, 255, 0.9); |
| | | margin-top: 0; |
| | | } |
| | | |
| | | .center-metric-value { |
| | | font-size: 3.4vh; |
| | | font-weight: 800; |
| | | color: #eaf6ff; |
| | | text-shadow: 0 0 0.8vh rgba(0, 229, 255, 0.22); |
| | | line-height: 1; |
| | | } |
| | | |
| | | .center-metric-unit { |
| | | margin-top: 0; |
| | | font-size: 1.2vh; |
| | | color: rgba(208, 231, 255, 0.85); |
| | | } |
| | | |
| | | .m1 { |
| | | top: 2.5vh; |
| | | left: 4.8vh; |
| | | text-align: left; |
| | | } |
| | | |
| | | .m2 { |
| | | top: 4.1vh; |
| | | right: 8.6vh; |
| | | text-align: right; |
| | | } |
| | | |
| | | .m3 { |
| | | bottom: 7.9vh; |
| | | left: 4vh; |
| | | text-align: left; |
| | | } |
| | | |
| | | .m4 { |
| | | bottom: 7vh; |
| | | right: 5.4vh; |
| | | text-align: right; |
| | | } |
| | | |
| | | @media (max-width: 1100px) { |
| | | .bi-topbar-content { |
| | | padding: 0 1.4vh; |
| | | } |
| | | .center-ring { |
| | | left: 45.2%; |
| | | width: 33vh; |
| | | height: 24.5vh; |
| | | top: 2.4vh; |
| | | } |
| | | .center-ring-title { |
| | | top: 50%; |
| | | font-size: 2.8vh; |
| | | transform: translate(-50%, -50%); |
| | | } |
| | | .center-metric { |
| | | height: 10.5vh; |
| | | } |
| | | .m1 { |
| | | top: 5.2vh; |
| | | left: 4.2vh; |
| | | } |
| | | .m2 { |
| | | top: 5.4vh; |
| | | right: 4.2vh; |
| | | } |
| | | .m3 { |
| | | bottom: 6.2vh; |
| | | left: 4.8vh; |
| | | } |
| | | .m4 { |
| | | bottom: 6.8vh; |
| | | right: 4.4vh; |
| | | } |
| | | } |
| | | .scroll-table-content { |
| | | height: 39vh; |
| | | overflow: auto; |
| | | } |
| | | .scroll-table-content::-webkit-scrollbar { |
| | | width: 0; |
| | | height: 0; |
| | | background-color: transparent; |
| | | } |
| | | .total-row { |
| | | position: absolute; |
| | | bottom: 0vh; |
| | | left: 0; |
| | | width: 100%; |
| | | display: flex; |
| | | height: 3.5vh; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | background-color: #081843; |
| | | } |
| | | |
| | | .stats-grid { |
| | | .total-cell { |
| | | width: 20%; |
| | | font-size: 1.4vh; |
| | | margin-bottom: 0.5vh; |
| | | line-height: 3.5vh; |
| | | padding-left: 0.8vh; |
| | | color: #eaf6ff; |
| | | text-shadow: 0 0 0.8vh rgba(0, 229, 255, 0.22); |
| | | text-align: left; |
| | | color: #c3c3c3; |
| | | } |
| | | .total-cell2 { |
| | | width: 20%; |
| | | font-size: 1.4vh; |
| | | margin-bottom: 0.5vh; |
| | | line-height: 3.5vh; |
| | | color: #eaf6ff; |
| | | text-shadow: 0 0 0.8vh rgba(0, 229, 255, 0.22); |
| | | text-align: left; |
| | | color: #c3c3c3; |
| | | } |
| | | /* ææä¿¡æ¯å¡ç */ |
| | | .material-info-card { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 1.2vh 1.6vh; |
| | | background: rgba(0, 164, 237, 0.1); |
| | | border-radius: 0.8vh; |
| | | margin: 1.2vh 1.6vh; |
| | | } |
| | | |
| | | .material-icon { |
| | | width: 4vh; |
| | | height: 4vh; |
| | | background: rgba(0, 164, 237, 0.2); |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-right: 1.2vh; |
| | | color: #00a4ed; |
| | | } |
| | | |
| | | .material-details { |
| | | flex: 1; |
| | | padding: 15px; |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | grid-template-rows: repeat(2, 1fr); |
| | | gap: 15px; |
| | | } |
| | | |
| | | .material-name { |
| | | font-size: 1.3vh; |
| | | font-weight: 600; |
| | | color: #d0e7ff; |
| | | margin-bottom: 0.6vh; |
| | | } |
| | | |
| | | .material-stats { |
| | | display: flex; |
| | | gap: 1.6vh; |
| | | } |
| | | |
| | | .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; |
| | | gap: 0.4vh; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | margin-bottom: 8px; |
| | | font-size: 1vh; |
| | | opacity: 0.7; |
| | | } |
| | | |
| | | .stat-value { |
| | | font-size: 20px; |
| | | font-size: 1.2vh; |
| | | 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); |
| | | color: #00a4ed; |
| | | } |
| | | |
| | | .stat-unit { |
| | | font-size: 11px; |
| | | color: #909399; |
| | | font-size: 1vh; |
| | | opacity: 0.7; |
| | | } |
| | | |
| | | /* è¡¨æ ¼æ ·å¼ */ |
| | | :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> |
| | | </style> |
| | |
| | | </div> |
| | | <div class="bi-panel-body"> |
| | | <div class="chart-unit-row chart-unit-single"> |
| | | <span>åä½ï¼äºº</span> |
| | | <span>åä½ï¼å®¶</span> |
| | | </div> |
| | | <div ref="productTypeTrendChart" |
| | | class="echart-fill"></div> |
| | |
| | | formatter: function (params) { |
| | | let result = params[0].name + "<br/>"; |
| | | params.forEach(param => { |
| | | result += `${param.marker}${param.seriesName}: ${param.value} 人<br/>`; |
| | | result += `${param.marker}${param.seriesName}: ${param.value} å®¶<br/>`; |
| | | }); |
| | | return result; |
| | | }, |
| | |
| | | } |
| | | |
| | | /* .scroll-table tbody tr:nth-child(odd) { |
| | | background-color: rgba(64, 158, 255, 0.05); |
| | | } |
| | | background-color: rgba(64, 158, 255, 0.05); |
| | | } |
| | | |
| | | .scroll-table tbody tr:nth-child(even) { |
| | | background-color: rgba(64, 158, 255, 0.1); |
| | | } */ |
| | | .scroll-table tbody tr:nth-child(even) { |
| | | background-color: rgba(64, 158, 255, 0.1); |
| | | } */ |
| | | .oddTableTr { |
| | | background-color: rgba(64, 158, 255, 0.05); |
| | | } |