From b9c361da3b0613c22f1d167c418d700254d5d209 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期四, 26 三月 2026 17:54:57 +0800
Subject: [PATCH] 生产统计看板(部分开发)
---
src/views/reportAnalysis/productionStatistics/index copy.vue | 1003 +++++++++++++++++
src/views/reportAnalysis/productionStatistics/index.vue | 2420 ++++++++++++++++++++++++++--------------
src/views/reportAnalysis/salesStatistics/index.vue | 14
3 files changed, 2,566 insertions(+), 871 deletions(-)
diff --git a/src/views/reportAnalysis/productionStatistics/index copy.vue b/src/views/reportAnalysis/productionStatistics/index copy.vue
new file mode 100644
index 0000000..cf00f0f
--- /dev/null
+++ b/src/views/reportAnalysis/productionStatistics/index copy.vue
@@ -0,0 +1,1003 @@
+<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 = () => {
+ // 寤惰繜鎵ц锛岀‘淇滵OM鏇存柊瀹屾垚
+ 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>
\ No newline at end of file
diff --git a/src/views/reportAnalysis/productionStatistics/index.vue b/src/views/reportAnalysis/productionStatistics/index.vue
index cf00f0f..a168ed9 100644
--- a/src/views/reportAnalysis/productionStatistics/index.vue
+++ b/src/views/reportAnalysis/productionStatistics/index.vue
@@ -1,157 +1,233 @@
<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>
@@ -164,840 +240,1456 @@
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 = () => {
- // 寤惰繜鎵ц锛岀‘淇滵OM鏇存柊瀹屾垚
- 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>
\ No newline at end of file
+</style>
diff --git a/src/views/reportAnalysis/salesStatistics/index.vue b/src/views/reportAnalysis/salesStatistics/index.vue
index c18972b..165f30a 100644
--- a/src/views/reportAnalysis/salesStatistics/index.vue
+++ b/src/views/reportAnalysis/salesStatistics/index.vue
@@ -199,7 +199,7 @@
</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>
@@ -1160,7 +1160,7 @@
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;
},
@@ -1880,12 +1880,12 @@
}
/* .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);
}
--
Gitblit v1.9.3