From 7f5d173ccb67eca6f823e3c9bb3f5770c12d4704 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期四, 02 四月 2026 09:55:44 +0800
Subject: [PATCH] 添加生产统计API并更新生产统计视图

---
 src/api/reportAnalysis/productionStatistics.js          |  118 +++++++
 src/views/reportAnalysis/productionStatistics/index.vue |  836 ++++++++++++++++++++++++++++++----------------------
 2 files changed, 601 insertions(+), 353 deletions(-)

diff --git a/src/api/reportAnalysis/productionStatistics.js b/src/api/reportAnalysis/productionStatistics.js
new file mode 100644
index 0000000..57797a7
--- /dev/null
+++ b/src/api/reportAnalysis/productionStatistics.js
@@ -0,0 +1,118 @@
+import request from '@/utils/request'
+
+/**
+ * 鐗╂枡鐢熶骇閲忓垎鏋�
+ * GET /home/productionStatistics/materialProductionAnalysis
+ *
+ * 鍏ュ弬鐢卞悗绔害瀹氾紙骞存湀鍒囨崲銆佺爩鍧�/鏉挎潗/鍏ㄩ儴绛夛級锛岄�氳繃 params 鍘熸牱浼犻�掋��
+ *
+ * 鍝嶅簲 data 绀轰緥缁撴瀯锛�
+ * {
+ *   鍏ㄩ儴: [{ dateStr, totalOutput, blockOutput, plateOutput }],
+ *   鐮屽潡: [...],
+ *   鏉挎潗: [...]
+ * }
+ */
+export function getMaterialProductionAnalysis(params) {
+  return request({
+    url: '/home/productionStatistics/materialProductionAnalysis',
+    method: 'get',
+    params,
+  })
+}
+
+/**
+ * 鐢熶骇鎴愭湰鍗曡�楃粺璁★紙鐮屽潡/鏉挎潗锛変骇鍝佸垪琛�
+ * GET /home/productionStatistics/materials
+ *
+ * @param {Object} [params]
+ * @param {string} [params.materialType] 鍙�夈��'1' 鐮屽潡 / '2' 鏉挎潗
+ * @returns {Promise<{ data?: string[] }>} data 涓轰骇鍝佸悕绉板瓧绗︿覆鏁扮粍锛屽 ["鏉挎潗","姘存偿"]
+ */
+export function getProductionMaterials(params) {
+  return request({
+    url: '/home/productionStatistics/materials',
+    method: 'get',
+    params,
+  })
+}
+
+/**
+ * 鐢熶骇鎴愭湰鍗曡�楃粺璁★紙鐮屽潡锛�
+ * GET /home/productionStatistics/blocks
+ *
+ * @param {Object} [params]
+ * @param {string} [params.materialName] 鐗╂枡鍚嶇О
+ * @param {string} [params.dateType] '1' 鏈� / '2' 骞�
+ */
+export function getProductionStatisticsBlocks(params) {
+  return request({
+    url: '/home/productionStatistics/blocks',
+    method: 'get',
+    params,
+  })
+}
+
+/**
+ * 鐢熶骇鎴愭湰鍗曡�楃粺璁★紙鏉挎潗锛�
+ * GET /home/productionStatistics/plates
+ *
+ * @param {Object} [params]
+ * @param {string} [params.materialName] 鐗╂枡鍚嶇О
+ * @param {string} [params.dateType] '1' 鏈� / '2' 骞�
+ */
+export function getProductionStatisticsPlates(params) {
+  return request({
+    url: '/home/productionStatistics/plates',
+    method: 'get',
+    params,
+  })
+}
+
+/**
+ * 涓績鐜細椤圭洰浜ч噺锛堢爩鍧�/鏉挎潗锛変笌鍥哄簾澶勭悊閲忥紙绮夌叅鐏�/鐭宠啅锛�
+ * GET /home/productionStatistics/middle
+ *
+ * data: flyAshMonth/Year, gypsumMonth/Year, blockMonth/Year, plateMonth/Year
+ */
+export function getProductionStatisticsMiddle(params) {
+  return request({
+    url: '/home/productionStatistics/middle',
+    method: 'get',
+    params,
+  })
+}
+
+/**
+ * 鍥哄簾澶勭悊閲忚秼鍔�
+ * GET /home/productionStatistics/solidWaste
+ *
+ * @param {Object} params
+ * @param {string} params.dateType '1' 鏈� / '2' 骞�
+ *
+ * data[]: dateStr, total, flyAsh, gypsum, lime
+ */
+export function getProductionStatisticsSolidWaste(params) {
+  return request({
+    url: '/home/productionStatistics/solidWaste',
+    method: 'get',
+    params,
+  })
+}
+
+/**
+ * 鑳借�楃粺璁★紙姘�/鐢�/钂告苯锛�
+ * GET /home/productionStatistics/energy
+ *
+ * @param {Object} params
+ * @param {string} params.dateType '1' 鏈� / '2' 骞�
+ *
+ * data[]: dateStr, water, electricity, steam
+ */
+export function getProductionStatisticsEnergy(params) {
+  return request({
+    url: '/home/productionStatistics/energy',
+    method: 'get',
+    params,
+  })
+}
diff --git a/src/views/reportAnalysis/productionStatistics/index.vue b/src/views/reportAnalysis/productionStatistics/index.vue
index c188b4d..34a7b8d 100644
--- a/src/views/reportAnalysis/productionStatistics/index.vue
+++ b/src/views/reportAnalysis/productionStatistics/index.vue
@@ -55,11 +55,11 @@
         </div>
         <div class="bi-panel-body">
           <div class="chart-filter-tabs">
-            <span v-for="area in salesAreas"
-                  :key="area"
+            <span v-for="name in blockMaterialList"
+                  :key="name"
                   class="cf-tab"
-                  :class="{ active: blockSelectedArea === area }"
-                  @click="handleBlockAreaChange(area)">{{ area }}</span>
+                  :class="{ active: blockSelectedMaterial === name }"
+                  @click="selectBlockMaterial(name)">{{ name }}</span>
           </div>
           <div class="material-info-card">
             <div class="material-icon">
@@ -74,16 +74,16 @@
               </svg>
             </div>
             <div class="material-details">
-              <div class="material-name">{{ blockMaterialType }}AAA</div>
+              <div class="material-name">{{ blockMaterialSummary.materialName || "鈥�" }}</div>
               <div class="material-stats">
                 <div class="stat-item">
                   <span class="stat-label">鏈堢疮璁″崟鑰�</span>
-                  <span class="stat-value">78/12</span>
+                  <span class="stat-value">{{ blockMaterialSummary.monthlyConsumption }}</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-value">{{ blockMaterialSummary.yearlyConsumption }}</span>
                   <span class="stat-unit">鍚�</span>
                 </div>
               </div>
@@ -109,6 +109,13 @@
                 @click="handleProductionTimeDimensionChange('month')">鏈�</span>
         </div>
         <div class="bi-panel-body">
+          <div class="chart-filter-tabs">
+            <span v-for="cat in productionCategories"
+                  :key="cat"
+                  class="cf-tab"
+                  :class="{ active: productionCategory === cat }"
+                  @click="selectProductionCategory(cat)">{{ cat }}</span>
+          </div>
           <div class="chart-unit-row">
             <span>鍗曚綅锛氫欢</span>
           </div>
@@ -124,21 +131,20 @@
           </div>
           <div class="ring-box-left">
             <div class="left-label">绮夌叅鐏�</div>
-            <div class="left-value">鏈堝鐞� <span style="font-weight: bold;font-size: 1.3vh;">7812</span> 鍚� 骞村鐞� <span style="font-weight: bold;font-size: 1.3vh;">7812</span> 鍚�</div>
+            <div class="left-value">鏈堝鐞� <span style="font-weight: bold;font-size: 1.3vh;">{{ middleRingStats.flyAshMonth }}</span> 鍚� 骞村鐞� <span style="font-weight: bold;font-size: 1.3vh;">{{ middleRingStats.flyAshYear }}</span> 鍚�</div>
             <div class="left-label"
                  style="margin-top: 2vh;">鐭宠啅</div>
-            <div class="left-value">鏈堝鐞� <span style="font-weight: bold;font-size: 1.3vh;">7812</span> 鍚� 骞村鐞� <span style="font-weight: bold;font-size: 1.3vh;">7812</span> 鍚�</div>
+            <div class="left-value">鏈堝鐞� <span style="font-weight: bold;font-size: 1.3vh;">{{ middleRingStats.gypsumMonth }}</span> 鍚� 骞村鐞� <span style="font-weight: bold;font-size: 1.3vh;">{{ middleRingStats.gypsumYear }}</span> 鍚�</div>
           </div>
           <div class="ring-box-topleft">
             <div class="topleft-label">椤圭洰浜ч噺</div>
           </div>
           <div class="ring-box-right">
             <div class="right-label">鐮屽潡浜ч噺</div>
-            <div class="right-value">鏈堜骇閲� <span style="font-weight: bold;font-size: 1.3vh;">7812</span> 鍚� 骞翠骇閲� <span style="font-weight: bold;font-size: 1.3vh;">7812
-              </span> 鍚�</div>
+            <div class="right-value">鏈堜骇閲� <span style="font-weight: bold;font-size: 1.3vh;">{{ middleRingStats.blockMonth }}</span> 鍚� 骞翠骇閲� <span style="font-weight: bold;font-size: 1.3vh;">{{ middleRingStats.blockYear }}</span> 鍚�</div>
             <div class="right-label"
                  style="margin-top: 2vh;">鏉挎潗浜ч噺</div>
-            <div class="right-value">鏈堜骇閲� <span style="font-weight: bold;font-size: 1.3vh;">7812</span> 鍚� 骞翠骇閲� <span style="font-weight: bold;font-size: 1.3vh;">7812</span> 鍚�</div>
+            <div class="right-value">鏈堜骇閲� <span style="font-weight: bold;font-size: 1.3vh;">{{ middleRingStats.plateMonth }}</span> 鍚� 骞翠骇閲� <span style="font-weight: bold;font-size: 1.3vh;">{{ middleRingStats.plateYear }}</span> 鍚�</div>
           </div>
         </div>
       </div>
@@ -156,11 +162,11 @@
         </div>
         <div class="bi-panel-body">
           <div class="chart-filter-tabs">
-            <span v-for="area in salesAreas"
-                  :key="area"
+            <span v-for="name in boardMaterialList"
+                  :key="name"
                   class="cf-tab"
-                  :class="{ active: blockSelectedArea === area }"
-                  @click="handleBlockAreaChange(area)">{{ area }}</span>
+                  :class="{ active: boardSelectedMaterial === name }"
+                  @click="selectBoardMaterial(name)">{{ name }}</span>
           </div>
           <div class="material-info-card">
             <div class="material-icon">
@@ -175,16 +181,16 @@
               </svg>
             </div>
             <div class="material-details">
-              <div class="material-name">{{ boardMaterialType }}AAA</div>
+              <div class="material-name">{{ boardMaterialSummary.materialName || "鈥�" }}</div>
               <div class="material-stats">
                 <div class="stat-item">
                   <span class="stat-label">鏈堢疮璁″崟鑰�</span>
-                  <span class="stat-value">78/12</span>
+                  <span class="stat-value">{{ boardMaterialSummary.monthlyConsumption }}</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-value">{{ boardMaterialSummary.yearlyConsumption }}</span>
                   <span class="stat-unit">鍚�</span>
                 </div>
               </div>
@@ -246,12 +252,20 @@
     computed,
     onMounted,
     onBeforeUnmount,
-    watch,
     nextTick,
   } from "vue";
   import * as echarts from "echarts";
   import dayjs from "dayjs";
   import PanelHeader from "@/views/reportAnalysis/PSIDataAnalysis/components/PanelHeader.vue";
+  import {
+    getMaterialProductionAnalysis,
+    getProductionMaterials,
+    getProductionStatisticsBlocks,
+    getProductionStatisticsPlates,
+    getProductionStatisticsMiddle,
+    getProductionStatisticsSolidWaste,
+    getProductionStatisticsEnergy,
+  } from "@/api/reportAnalysis/productionStatistics.js";
 
   const screenRoot = ref(null);
   const isFullscreen = ref(false);
@@ -303,30 +317,73 @@
 
   // 閫夋嫨鍣ㄦ暟鎹�
   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 productionCategories = ["鍏ㄩ儴", "鐮屽潡", "鏉挎潗"];
+  const productionCategory = ref("鍏ㄩ儴");
 
-  // 涓績鐜暟鎹�
-  const projectProduction = ref(12345);
-  const solidWaste澶勭悊閲� = ref(6789);
-  const blockProduction = ref(7812);
-  const boardProduction = ref(7812);
+  const blockMaterialList = ref([]);
+  const blockSelectedMaterial = ref("");
+  const boardMaterialList = ref([]);
+  const boardSelectedMaterial = ref("");
+
+  const blockMaterialSummary = ref({
+    materialName: "",
+    monthlyConsumption: "--",
+    yearlyConsumption: "--",
+  });
+  const boardMaterialSummary = ref({
+    materialName: "",
+    monthlyConsumption: "--",
+    yearlyConsumption: "--",
+  });
+
+  const blockCostChartSeries = ref({
+    categories: [],
+    input: [],
+    output: [],
+  });
+  const boardCostChartSeries = ref({
+    categories: [],
+    input: [],
+    output: [],
+  });
+  const productionChartSeries = ref({
+    categories: [],
+    values: [],
+  });
+
+  // 鍥哄簾澶勭悊閲忔姌绾垮浘锛�/home/productionStatistics/solidWaste锛�
+  const solidWasteChartSeries = ref({
+    categories: [],
+    total: [],
+    flyAsh: [],
+    gypsum: [],
+    lime: [],
+  });
+
+  // 鑳借�楃粺璁★紙/home/productionStatistics/energy锛�
+  const energyChartSeries = ref({
+    categories: [],
+    water: [],
+    electricity: [],
+    steam: [],
+  });
+
+  // 涓績鐜細鍥哄簾锛堢矇鐓ょ伆/鐭宠啅锛�+ 椤圭洰浜ч噺锛堢爩鍧�/鏉挎潗锛夛紝鎺ュ彛 /home/productionStatistics/middle
+  const middleRingStats = ref({
+    flyAshMonth: 0,
+    flyAshYear: 0,
+    gypsumMonth: 0,
+    gypsumYear: 0,
+    blockMonth: 0,
+    blockYear: 0,
+    plateMonth: 0,
+    plateYear: 0,
+  });
 
   // 鍥捐〃瀹炰緥
   let blockCostChartInstance = null;
@@ -335,46 +392,27 @@
   let customerTrendChartInstance = null;
   let salesRankingChartInstance = null;
 
-  // 鐢熶骇鍗曡�楀浘琛ㄩ厤缃�
+  // 鐢熶骇鍗曡�楀浘琛ㄩ厤缃紙鐮屽潡锛屾帴鍙f暟鎹級
   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,
+    const periods = blockCostChartSeries.value.categories || [];
+    const inputData = blockCostChartSeries.value.input || [];
+    const outputData = blockCostChartSeries.value.output || [];
+    const legendNames = ["鎶曞叆閲�", "浜у嚭閲�"];
+    const colors = ["#6B9DFF", "#8A6BFF"];
+    const series = [
+      {
+        name: legendNames[0],
+        data: inputData,
         type: "bar",
-        itemStyle: { color: colors[index] },
-      };
-    });
+        itemStyle: { color: colors[0] },
+      },
+      {
+        name: legendNames[1],
+        data: outputData,
+        type: "bar",
+        itemStyle: { color: colors[1] },
+      },
+    ];
 
     return {
       backgroundColor: "transparent",
@@ -385,22 +423,22 @@
         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),
-      // },
+      legend: {
+        data: legendNames,
+        top: "2%",
+        right: "1%",
+        textStyle: {
+          color: "#B8C8E0",
+          fontSize: getResponsiveValue(9),
+        },
+        itemWidth: getResponsiveValue(10),
+        itemHeight: getResponsiveValue(10),
+      },
       grid: {
         left: "1%",
         right: "1%",
         bottom: "1%",
-        top: "8%",
+        top: "18%",
         containLabel: true,
       },
       xAxis: {
@@ -425,167 +463,31 @@
         },
         splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } },
       },
-      series: 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,
+    const periods = boardCostChartSeries.value.categories || [];
+    const inputData = boardCostChartSeries.value.input || [];
+    const outputData = boardCostChartSeries.value.output || [];
+    const legendNames = ["鎶曞叆閲�", "浜у嚭閲�"];
+    const colors = ["#00A4ED", "#34D8F7"];
+    const series = [
+      {
+        name: legendNames[0],
+        data: inputData,
         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) },
+        itemStyle: { color: colors[0] },
       },
-      // 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,
+      {
+        name: legendNames[1],
+        data: outputData,
+        type: "bar",
+        itemStyle: { color: colors[1] },
       },
-      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",
@@ -597,7 +499,84 @@
         textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) },
       },
       legend: {
-        data: salesAreas,
+        data: legendNames,
+        top: "2%",
+        right: "1%",
+        textStyle: {
+          color: "#B8C8E0",
+          fontSize: getResponsiveValue(9),
+        },
+        itemWidth: getResponsiveValue(10),
+        itemHeight: getResponsiveValue(10),
+      },
+      grid: {
+        left: "1%",
+        right: "1%",
+        bottom: "1%",
+        top: "18%",
+        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,
+    };
+  });
+
+  // 鐗╂枡鐢熶骇閲忓垎鏋愶紙鎺ュ彛鏁版嵁锛�
+  const productionChartOption = computed(() => {
+    const periods = productionChartSeries.value.categories || [];
+    const values = productionChartSeries.value.values || [];
+    const lineColor = "#4A8BFF";
+    const seriesName = "浜ч噺";
+    const series = [
+      {
+        name: seriesName,
+        data: values,
+        type: "line",
+        smooth: true,
+        lineStyle: { width: getResponsiveValue(2), color: lineColor },
+        itemStyle: { color: lineColor },
+        areaStyle: {
+          opacity: 0.3,
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: lineColor + "80" },
+            { offset: 1, color: lineColor + "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: [seriesName],
         top: "10%",
         right: "1%",
         textStyle: {
@@ -636,59 +615,37 @@
         },
         splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } },
       },
-      series: series,
+      series,
     };
   });
 
-  // 鏂板瀹㈡埛瓒嬪娍鍥捐〃閰嶇疆
+  // 鍥哄簾澶勭悊閲忓浘琛紙鎺ュ彛 solidWaste锛�
   const customerTrendChartOption = computed(() => {
-    const customerTypes = ["鍏ㄩ儴", "绮夌叅鐏�", "鐭宠啅", "鐭崇伆"];
+    const legendNames = ["鍏ㄩ儴", "绮夌叅鐏�", "鐭宠啅", "鐭崇伆"];
     const colors = ["#00A4ED", "#4A8BFF", "#8A6BFF", "#C8C447"];
-    const year = 2024;
-    const periodType = customerTimeDimension.value;
+    const periods = solidWasteChartSeries.value.categories || [];
+    const dataBySeries = [
+      solidWasteChartSeries.value.total || [],
+      solidWasteChartSeries.value.flyAsh || [],
+      solidWasteChartSeries.value.gypsum || [],
+      solidWasteChartSeries.value.lime || [],
+    ];
 
-    // 鐢熸垚鏃堕棿娈�
-    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" },
-          ]),
-        },
-      };
-    });
+    const series = legendNames.map((name, index) => ({
+      name,
+      data: dataBySeries[index] || [],
+      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",
@@ -700,7 +657,7 @@
         textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) },
       },
       legend: {
-        data: customerTypes,
+        data: legendNames,
         top: "10%",
         right: "1%",
         textStyle: {
@@ -739,51 +696,18 @@
         },
         splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } },
       },
-      series: series,
+      series,
     };
   });
 
-  // 鑳借�楃粺璁″浘琛ㄩ厤缃�
+  // 鑳借�楃粺璁″浘琛ㄩ厤缃紙鎺ュ彛 energy锛�
   const salesRankingChartOption = computed(() => {
     const energyTypes = ["姘�", "鐢�", "钂告苯"];
-    const colors = ["#00A4ED", "#AC43C2", "#F5BC4A"];
-    const year = 2024;
     const periodType = salesTimeDimension.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 {
-      // 鏈堝害鏁版嵁锛�7澶�
-      const month = 1;
-      for (let day = 1; day <= 7; day++) {
-        periods.push(`${month}/${day}`);
-      }
-    }
-
-    // 涓烘瘡绉嶈兘婧愮被鍨嬬敓鎴愭暟鎹�
-    const waterData = periods.map(() => {
-      return periodType === "year"
-        ? Math.floor(Math.random() * 300) + 400
-        : Math.floor(Math.random() * 30) + 40;
-    });
-    const steamData = periods.map(() => {
-      return periodType === "year"
-        ? Math.floor(Math.random() * 400) + 500
-        : Math.floor(Math.random() * 40) + 50;
-    });
-    const electricityData = periods.map(() => {
-      return periodType === "year"
-        ? Math.floor(Math.random() * 200) + 300
-        : Math.floor(Math.random() * 20) + 30;
-    });
+    const periods = energyChartSeries.value.categories || [];
+    const waterData = energyChartSeries.value.water || [];
+    const electricityData = energyChartSeries.value.electricity || [];
+    const steamData = energyChartSeries.value.steam || [];
 
     const series = [
       {
@@ -925,6 +849,221 @@
     return Math.round((baseValue * window.innerWidth) / baseWidth.value);
   };
 
+  const mapTimeDimensionToDateType = dim => (dim === "year" ? "2" : "1");
+
+  const productionOutputKey = {
+    鍏ㄩ儴: "totalOutput",
+    鐮屽潡: "blockOutput",
+    鏉挎潗: "plateOutput",
+  };
+
+  const loadBlockCost = async () => {
+    const materialName = blockSelectedMaterial.value;
+    if (!materialName) {
+      blockMaterialSummary.value = {
+        materialName: "",
+        monthlyConsumption: "--",
+        yearlyConsumption: "--",
+      };
+      blockCostChartSeries.value = { categories: [], input: [], output: [] };
+      updateCharts();
+      return;
+    }
+    const dateType = mapTimeDimensionToDateType(blockTimeDimension.value);
+    try {
+      const res = await getProductionStatisticsBlocks({ materialName, dateType });
+      const rows = Array.isArray(res.data) ? res.data : [];
+      const row =
+        rows.find(r => r.materialName === materialName) || rows[0] || {};
+      const chartData = Array.isArray(row.chartData) ? row.chartData : [];
+      blockMaterialSummary.value = {
+        materialName: row.materialName || materialName,
+        monthlyConsumption: row.monthlyConsumption ?? "--",
+        yearlyConsumption: row.yearlyConsumption ?? "--",
+      };
+      blockCostChartSeries.value = {
+        categories: chartData.map(c => c.date),
+        input: chartData.map(c => c.inputSum ?? 0),
+        output: chartData.map(c => c.outputSum ?? 0),
+      };
+      updateCharts();
+    } catch (e) {
+      console.error(e);
+    }
+  };
+
+  const loadBoardCost = async () => {
+    const materialName = boardSelectedMaterial.value;
+    if (!materialName) {
+      boardMaterialSummary.value = {
+        materialName: "",
+        monthlyConsumption: "--",
+        yearlyConsumption: "--",
+      };
+      boardCostChartSeries.value = { categories: [], input: [], output: [] };
+      updateCharts();
+      return;
+    }
+    const dateType = mapTimeDimensionToDateType(boardTimeDimension.value);
+    try {
+      const res = await getProductionStatisticsPlates({ materialName, dateType });
+      const rows = Array.isArray(res.data) ? res.data : [];
+      const row =
+        rows.find(r => r.materialName === materialName) || rows[0] || {};
+      const chartData = Array.isArray(row.chartData) ? row.chartData : [];
+      boardMaterialSummary.value = {
+        materialName: row.materialName || materialName,
+        monthlyConsumption: row.monthlyConsumption ?? "--",
+        yearlyConsumption: row.yearlyConsumption ?? "--",
+      };
+      boardCostChartSeries.value = {
+        categories: chartData.map(c => c.date),
+        input: chartData.map(c => c.inputSum ?? 0),
+        output: chartData.map(c => c.outputSum ?? 0),
+      };
+      updateCharts();
+    } catch (e) {
+      console.error(e);
+    }
+  };
+
+  const loadBlockMaterials = async () => {
+    try {
+      const res = await getProductionMaterials({ materialType: "1" });
+      const list = Array.isArray(res.data) ? [...res.data] : [];
+      blockMaterialList.value = list;
+      if (list.length) {
+        if (!list.includes(blockSelectedMaterial.value)) {
+          blockSelectedMaterial.value = list[0];
+        }
+        await loadBlockCost();
+      } else {
+        blockSelectedMaterial.value = "";
+        blockMaterialSummary.value = {
+          materialName: "",
+          monthlyConsumption: "--",
+          yearlyConsumption: "--",
+        };
+        blockCostChartSeries.value = { categories: [], input: [], output: [] };
+        updateCharts();
+      }
+    } catch (e) {
+      console.error(e);
+    }
+  };
+
+  const loadBoardMaterials = async () => {
+    try {
+      const res = await getProductionMaterials({ materialType: "2" });
+      const list = Array.isArray(res.data) ? [...res.data] : [];
+      boardMaterialList.value = list;
+      if (list.length) {
+        if (!list.includes(boardSelectedMaterial.value)) {
+          boardSelectedMaterial.value = list[0];
+        }
+        await loadBoardCost();
+      } else {
+        boardSelectedMaterial.value = "";
+        boardMaterialSummary.value = {
+          materialName: "",
+          monthlyConsumption: "--",
+          yearlyConsumption: "--",
+        };
+        boardCostChartSeries.value = { categories: [], input: [], output: [] };
+        updateCharts();
+      }
+    } catch (e) {
+      console.error(e);
+    }
+  };
+
+  const loadMaterialProduction = async () => {
+    const dateType = mapTimeDimensionToDateType(productionTimeDimension.value);
+    try {
+      const res = await getMaterialProductionAnalysis({ dateType });
+      const payload = res.data && typeof res.data === "object" ? res.data : {};
+      const cat = productionCategory.value;
+      const list = Array.isArray(payload[cat]) ? payload[cat] : [];
+      const field = productionOutputKey[cat] || "totalOutput";
+      productionChartSeries.value = {
+        categories: list.map(i => i.dateStr),
+        values: list.map(i => Number(i[field]) || 0),
+      };
+      updateCharts();
+    } catch (e) {
+      console.error(e);
+    }
+  };
+
+  const loadMiddleRingStats = async () => {
+    try {
+      const res = await getProductionStatisticsMiddle();
+      const d = res.data && typeof res.data === "object" ? res.data : {};
+      middleRingStats.value = {
+        flyAshMonth: Number(d.flyAshMonth) || 0,
+        flyAshYear: Number(d.flyAshYear) || 0,
+        gypsumMonth: Number(d.gypsumMonth) || 0,
+        gypsumYear: Number(d.gypsumYear) || 0,
+        blockMonth: Number(d.blockMonth) || 0,
+        blockYear: Number(d.blockYear) || 0,
+        plateMonth: Number(d.plateMonth) || 0,
+        plateYear: Number(d.plateYear) || 0,
+      };
+    } catch (e) {
+      console.error(e);
+    }
+  };
+
+  const loadSolidWasteData = async () => {
+    const dateType = mapTimeDimensionToDateType(customerTimeDimension.value);
+    try {
+      const res = await getProductionStatisticsSolidWaste({ dateType });
+      const list = Array.isArray(res.data) ? res.data : [];
+      solidWasteChartSeries.value = {
+        categories: list.map(i => i.dateStr),
+        total: list.map(i => Number(i.total) || 0),
+        flyAsh: list.map(i => Number(i.flyAsh) || 0),
+        gypsum: list.map(i => Number(i.gypsum) || 0),
+        lime: list.map(i => Number(i.lime) || 0),
+      };
+      updateCharts();
+    } catch (e) {
+      console.error(e);
+    }
+  };
+
+  const loadEnergyData = async () => {
+    const dateType = mapTimeDimensionToDateType(salesTimeDimension.value);
+    try {
+      const res = await getProductionStatisticsEnergy({ dateType });
+      const list = Array.isArray(res.data) ? res.data : [];
+      energyChartSeries.value = {
+        categories: list.map(i => i.dateStr),
+        water: list.map(i => Number(i.water) || 0),
+        electricity: list.map(i => Number(i.electricity) || 0),
+        steam: list.map(i => Number(i.steam) || 0),
+      };
+      updateCharts();
+    } catch (e) {
+      console.error(e);
+    }
+  };
+
+  const selectBlockMaterial = name => {
+    blockSelectedMaterial.value = name;
+    loadBlockCost();
+  };
+
+  const selectBoardMaterial = name => {
+    boardSelectedMaterial.value = name;
+    loadBoardCost();
+  };
+
+  const selectProductionCategory = cat => {
+    productionCategory.value = cat;
+    loadMaterialProduction();
+  };
+
   // 鍒濆鍖栧浘琛�
   const initCharts = () => {
     // 鍒濆鍖栫爩鍧楁垚鏈浘琛�
@@ -986,44 +1125,27 @@
   // 澶勭悊鏃堕棿缁村害閫夋嫨
   const handleBlockTimeDimensionChange = dimension => {
     blockTimeDimension.value = dimension;
-    updateCharts();
+    loadBlockCost();
   };
 
   const handleBoardTimeDimensionChange = dimension => {
     boardTimeDimension.value = dimension;
-    updateCharts();
+    loadBoardCost();
   };
 
   const handleProductionTimeDimensionChange = dimension => {
     productionTimeDimension.value = dimension;
-    updateCharts();
+    loadMaterialProduction();
   };
 
   const handleCustomerTimeDimensionChange = dimension => {
     customerTimeDimension.value = dimension;
-    updateCharts();
+    loadSolidWasteData();
   };
 
   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();
+    loadEnergyData();
   };
 
   // 鐩戝惉绐楀彛澶у皬鍙樺寲
@@ -1057,9 +1179,17 @@
       }, 1000);
     }
 
-    // 绛夊緟DOM鏇存柊鍚庡垵濮嬪寲鍥捐〃
-    nextTick(() => {
+    // 绛夊緟DOM鏇存柊鍚庡垵濮嬪寲鍥捐〃骞舵媺鍙栨帴鍙f暟鎹�
+    nextTick(async () => {
       initCharts();
+      await Promise.all([
+        loadBlockMaterials(),
+        loadBoardMaterials(),
+        loadMaterialProduction(),
+        loadMiddleRingStats(),
+        loadSolidWasteData(),
+        loadEnergyData(),
+      ]);
     });
 
     // 娣诲姞绐楀彛澶у皬鍙樺寲鐩戝惉

--
Gitblit v1.9.3