yyb
6 天以前 7f5d173ccb67eca6f823e3c9bb3f5770c12d4704
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;
  // 生产单耗图表配置
  // 生产单耗图表配置(砌块,接口数据)
  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更新后初始化图表并拉取接口数据
    nextTick(async () => {
      initCharts();
      await Promise.all([
        loadBlockMaterials(),
        loadBoardMaterials(),
        loadMaterialProduction(),
        loadMiddleRingStats(),
        loadSolidWasteData(),
        loadEnergyData(),
      ]);
    });
    // 添加窗口大小变化监听