zhangwencui
2 天以前 1c20a331d9fc1be029fadbd3d0f7619fe6a83cd0
决策分析页面
已添加1个文件
已修改2个文件
2031 ■■■■ 文件已修改
src/views/reportAnalysis/productionStatistics/index.vue 697 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/salesStatistics/index.vue 711 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/solidWasteConsumption/index1.vue 623 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/productionStatistics/index.vue
@@ -1,30 +1,31 @@
<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-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-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">
      <!-- ç¬¬ä¸€è¡Œ -->
@@ -32,13 +33,15 @@
        <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 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 ref="solidWasteChart"
                   style="width: 100%; height: 100%"></div>
          </div>
        </div>
        <div class="panel-card card-3">
@@ -46,58 +49,106 @@
          <div class="stats-grid">
            <div class="stat-item">
              <div class="stat-label">总产能</div>
              <div class="stat-value">{{ totalProduction }}</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">{{ totalSolidWaste }}</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">{{ averageUnitConsumption }}</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">{{ totalEnergy }}</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 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 ref="energyChart"
                   style="width: 100%; height: 100%"></div>
          </div>
        </div>
      </div>
      <!-- ç¬¬ä¸‰è¡Œ -->
      <div class="row row-3">
        <div class="panel-card card-6">
          <div class="panel-title">单耗数据明细</div>
          <div class="table-container">
            <el-table :data="costTableData" style="width: 100%">
              <el-table-column prop="material" label="物料类型" width="120" />
              <el-table-column prop="unit" label="单位" width="100" />
              <el-table-column prop="monthlyConsumption" label="月度累计用量" />
              <el-table-column prop="monthlyProduction" label="月度累计产量" />
              <el-table-column prop="monthlyUnitConsumption" label="月度累计单耗" />
              <el-table-column prop="yearlyConsumption" label="年度累计用量" />
              <el-table-column prop="yearlyProduction" label="年度累计产量" />
              <el-table-column prop="yearlyUnitConsumption" label="年度累计单耗" />
              <el-table :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>
@@ -108,497 +159,534 @@
</template>
<script setup>
import { ref, computed, onMounted, onBeforeUnmount, nextTick, watch } from 'vue'
import * as echarts from 'echarts'
  import {
    ref,
    computed,
    onMounted,
    onBeforeUnmount,
    nextTick,
    watch,
  } from "vue";
  import * as echarts from "echarts";
// ç­›é€‰æ¡ä»¶
const dateType = ref('month') // month æˆ– year
const productType = ref('block') // block æˆ– plate
  const dateType = ref("month"); // month æˆ– year
  const productType = ref("block"); // block æˆ– plate
// å›¾è¡¨å¼•用
const productionChart = ref(null)
const solidWasteChart = ref(null)
const costChart = ref(null)
const energyChart = ref(null)
  const productionChart = ref(null);
  const solidWasteChart = ref(null);
  const costChart = ref(null);
  const energyChart = ref(null);
// å›¾è¡¨å®žä¾‹
let productionChartInstance = null
let solidWasteChartInstance = null
let costChartInstance = null
let energyChartInstance = null
  let productionChartInstance = null;
  let solidWasteChartInstance = null;
  let costChartInstance = null;
  let energyChartInstance = null;
// æ¨¡æ‹Ÿæ•°æ®
const productionData = ref({
  month: [
    { name: '1月', block: 1200, plate: 800 },
    { name: '2月', block: 1300, plate: 850 },
    { name: '3月', block: 1100, plate: 750 },
    { name: '4月', block: 1400, plate: 900 },
    { name: '5月', block: 1500, plate: 950 },
    { name: '6月', block: 1350, plate: 880 },
    { name: '7月', block: 1450, plate: 920 },
    { name: '8月', block: 1600, plate: 1000 },
    { name: '9月', block: 1550, plate: 980 },
    { name: '10月', block: 1700, plate: 1050 },
    { name: '11月', block: 1650, plate: 1020 },
    { name: '12月', block: 1800, plate: 1100 }
      { 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 }
  ]
})
      { 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 }
      { 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 }
  ]
})
      { name: "2023", ç²‰ç…¤ç°: 2500, çŸ³è†: 1800, çŸ³ç°: 1200 },
      { name: "2024", ç²‰ç…¤ç°: 2700, çŸ³è†: 1950, çŸ³ç°: 1300 },
      { name: "2025", ç²‰ç…¤ç°: 2900, çŸ³è†: 2100, çŸ³ç°: 1400 },
    ],
  });
const costData = ref({
  materials: ['æ°´æ³¥', '铝粉膏', '脱模剂', '防腐剂', '氯化剂', '冷拔丝'],
    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]
      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]
  }
})
      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 }
      { 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 }
  ]
})
      { name: "2023", ç”µé‡: 140000, æ°´é‡: 95000, æ°”量: 65000 },
      { name: "2024", ç”µé‡: 150000, æ°´é‡: 100000, æ°”量: 70000 },
      { name: "2025", ç”µé‡: 160000, æ°´é‡: 105000, æ°”量: 75000 },
    ],
  });
// è®¡ç®—属性
const productionChartOption = computed(() => {
  const data = productionData.value[dateType.value]
    const data = productionData.value[dateType.value];
  return {
    tooltip: {
      trigger: 'axis',
        trigger: "axis",
      axisPointer: {
        type: 'shadow'
      }
          type: "shadow",
        },
    },
    legend: {
      data: ['砌块', '板材'],
        data: ["砌块", "板材"],
      textStyle: {
        color: '#333'
      }
          color: "#333",
        },
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      containLabel: true
        left: "3%",
        right: "4%",
        bottom: "3%",
        containLabel: true,
    },
    xAxis: {
      type: 'category',
        type: "category",
      data: data.map(item => item.name),
      axisLabel: {
        color: '#333'
      }
          color: "#333",
        },
    },
    yAxis: {
      type: 'value',
      name: '产量 (立方米)',
        type: "value",
        name: "产量 (立方米)",
      axisLabel: {
        color: '#333'
      }
          color: "#333",
        },
    },
    series: [
      {
        name: '砌块',
        type: 'line',
          name: "砌块",
          type: "line",
        data: data.map(item => item.block),
        smooth: true,
        lineStyle: {
          width: 3
            width: 3,
        },
        itemStyle: {
          color: '#409EFF'
        }
            color: "#409EFF",
          },
      },
      {
        name: '板材',
        type: 'line',
          name: "板材",
          type: "line",
        data: data.map(item => item.plate),
        smooth: true,
        lineStyle: {
          width: 3
            width: 3,
        },
        itemStyle: {
          color: '#67C23A'
        }
      }
    ]
  }
})
            color: "#67C23A",
          },
        },
      ],
    };
  });
const solidWasteChartOption = computed(() => {
  const data = solidWasteData.value[dateType.value]
    const data = solidWasteData.value[dateType.value];
  return {
    tooltip: {
      trigger: 'axis',
        trigger: "axis",
      axisPointer: {
        type: 'shadow'
      }
          type: "shadow",
        },
    },
    legend: {
      data: ['粉煤灰', '石膏', '石灰'],
        data: ["粉煤灰", "石膏", "石灰"],
      textStyle: {
        color: '#333'
      }
          color: "#333",
        },
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      containLabel: true
        left: "3%",
        right: "4%",
        bottom: "3%",
        containLabel: true,
    },
    xAxis: {
      type: 'category',
        type: "category",
      data: data.map(item => item.name),
      axisLabel: {
        color: '#333'
      }
          color: "#333",
        },
    },
    yAxis: {
      type: 'value',
      name: '处理量 (吨)',
        type: "value",
        name: "处理量 (吨)",
      axisLabel: {
        color: '#333'
      }
          color: "#333",
        },
    },
    series: [
      {
        name: '粉煤灰',
        type: 'bar',
          name: "粉煤灰",
          type: "bar",
        data: data.map(item => item.粉煤灰),
        itemStyle: {
          color: '#909399'
        }
            color: "#909399",
          },
      },
      {
        name: '石膏',
        type: 'bar',
          name: "石膏",
          type: "bar",
        data: data.map(item => item.石膏),
        itemStyle: {
          color: '#E6A23C'
        }
            color: "#E6A23C",
          },
      },
      {
        name: '石灰',
        type: 'bar',
          name: "石灰",
          type: "bar",
        data: data.map(item => item.石灰),
        itemStyle: {
          color: '#F56C6C'
        }
      }
    ]
  }
})
            color: "#F56C6C",
          },
        },
      ],
    };
  });
const costChartOption = computed(() => {
  const data = costData.value
    const data = costData.value;
  return {
    tooltip: {
      trigger: 'axis',
        trigger: "axis",
      axisPointer: {
        type: 'shadow'
      }
          type: "shadow",
        },
    },
    legend: {
      data: ['月度单耗', '年度单耗'],
        data: ["月度单耗", "年度单耗"],
      textStyle: {
        color: '#333'
      }
          color: "#333",
        },
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      containLabel: true
        left: "3%",
        right: "4%",
        bottom: "3%",
        containLabel: true,
    },
    xAxis: {
      type: 'category',
        type: "category",
      data: data.materials,
      axisLabel: {
        color: '#333',
        rotate: 45
      }
          color: "#333",
          rotate: 45,
        },
    },
    yAxis: {
      type: 'value',
      name: '单耗 (吨/立方米)',
        type: "value",
        name: "单耗 (吨/立方米)",
      axisLabel: {
        color: '#333'
      }
          color: "#333",
        },
    },
    series: [
      {
        name: '月度单耗',
        type: 'bar',
          name: "月度单耗",
          type: "bar",
        data: data.month.unitConsumption,
        itemStyle: {
          color: '#409EFF'
        }
            color: "#409EFF",
          },
      },
      {
        name: '年度单耗',
        type: 'bar',
          name: "年度单耗",
          type: "bar",
        data: data.year.unitConsumption,
        itemStyle: {
          color: '#67C23A'
        }
      }
    ]
  }
})
            color: "#67C23A",
          },
        },
      ],
    };
  });
const energyChartOption = computed(() => {
  const data = energyData.value[dateType.value]
    const data = energyData.value[dateType.value];
  return {
    tooltip: {
      trigger: 'axis',
        trigger: "axis",
      axisPointer: {
        type: 'shadow'
      }
          type: "shadow",
        },
    },
    legend: {
      data: ['电量', '水量', '气量'],
        data: ["电量", "水量", "气量"],
      textStyle: {
        color: '#333'
      }
          color: "#333",
        },
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      containLabel: true
        left: "3%",
        right: "4%",
        bottom: "3%",
        containLabel: true,
    },
    xAxis: {
      type: 'category',
        type: "category",
      data: data.map(item => item.name),
      axisLabel: {
        color: '#333'
      }
          color: "#333",
        },
    },
    yAxis: {
      type: 'value',
      name: '能耗量',
        type: "value",
        name: "能耗量",
      axisLabel: {
        color: '#333'
      }
          color: "#333",
        },
    },
    series: [
      {
        name: '电量',
        type: 'line',
          name: "电量",
          type: "line",
        data: data.map(item => item.电量),
        smooth: true,
        lineStyle: {
          width: 3
            width: 3,
        },
        itemStyle: {
          color: '#409EFF'
        }
            color: "#409EFF",
          },
      },
      {
        name: '水量',
        type: 'line',
          name: "水量",
          type: "line",
        data: data.map(item => item.水量),
        smooth: true,
        lineStyle: {
          width: 3
            width: 3,
        },
        itemStyle: {
          color: '#67C23A'
        }
            color: "#67C23A",
          },
      },
      {
        name: '气量',
        type: 'line',
          name: "气量",
          type: "line",
        data: data.map(item => item.气量),
        smooth: true,
        lineStyle: {
          width: 3
            width: 3,
        },
        itemStyle: {
          color: '#E6A23C'
        }
      }
    ]
  }
})
            color: "#E6A23C",
          },
        },
      ],
    };
  });
const costTableData = computed(() => {
  const data = costData.value
  const materials = data.materials
  const monthData = data.month
  const yearData = data.year
    const data = costData.value;
    const materials = data.materials;
    const monthData = data.month;
    const yearData = data.year;
  
  return materials.map((material, index) => ({
    material,
    unit: '吨/立方米',
      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)
  }))
})
      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)
    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']
      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)
    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 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 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)
    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 lastItem = data[data.length - 1];
      return lastItem.电量 + lastItem.水量 + lastItem.气量;
  }
})
  });
// äº‹ä»¶å¤„理
const handleDateTypeChange = () => {
  updateCharts()
}
    updateCharts();
  };
const handleProductTypeChange = () => {
  updateCharts()
}
    updateCharts();
  };
// åˆå§‹åŒ–图表
const initCharts = () => {
  if (productionChart.value) {
    productionChartInstance = echarts.init(productionChart.value)
    productionChartInstance.setOption(productionChartOption.value)
      productionChartInstance = echarts.init(productionChart.value);
      productionChartInstance.setOption(productionChartOption.value);
  }
  
  if (solidWasteChart.value) {
    solidWasteChartInstance = echarts.init(solidWasteChart.value)
    solidWasteChartInstance.setOption(solidWasteChartOption.value)
      solidWasteChartInstance = echarts.init(solidWasteChart.value);
      solidWasteChartInstance.setOption(solidWasteChartOption.value);
  }
  
  if (costChart.value) {
    costChartInstance = echarts.init(costChart.value)
    costChartInstance.setOption(costChartOption.value)
      costChartInstance = echarts.init(costChart.value);
      costChartInstance.setOption(costChartOption.value);
  }
  
  if (energyChart.value) {
    energyChartInstance = echarts.init(energyChart.value)
    energyChartInstance.setOption(energyChartOption.value)
      energyChartInstance = echarts.init(energyChart.value);
      energyChartInstance.setOption(energyChartOption.value);
  }
}
  };
// æ›´æ–°å›¾è¡¨
const updateCharts = () => {
  if (productionChartInstance) {
    productionChartInstance.setOption(productionChartOption.value)
      productionChartInstance.setOption(productionChartOption.value);
  }
  
  if (solidWasteChartInstance) {
    solidWasteChartInstance.setOption(solidWasteChartOption.value)
      solidWasteChartInstance.setOption(solidWasteChartOption.value);
  }
  
  if (costChartInstance) {
    costChartInstance.setOption(costChartOption.value)
      costChartInstance.setOption(costChartOption.value);
  }
  
  if (energyChartInstance) {
    energyChartInstance.setOption(energyChartOption.value)
      energyChartInstance.setOption(energyChartOption.value);
  }
}
  };
// è°ƒæ•´å›¾è¡¨å¤§å°
const resizeCharts = () => {
  productionChartInstance?.resize()
  solidWasteChartInstance?.resize()
  costChartInstance?.resize()
  energyChartInstance?.resize()
}
    productionChartInstance?.resize();
    solidWasteChartInstance?.resize();
    costChartInstance?.resize();
    energyChartInstance?.resize();
  };
// çª—口大小变化处理
const handleResize = () => {
  // å»¶è¿Ÿæ‰§è¡Œï¼Œç¡®ä¿DOM更新完成
  setTimeout(() => {
    resizeCharts()
  }, 100)
}
      resizeCharts();
    }, 100);
  };
  // èŽ·å–ç‰©æ–™ç±»åž‹æ ‡ç­¾ç±»åž‹
  const getMaterialTypeType = material => {
    const typeMap = {
      æ°´æ³¥: "primary",
      é“ç²‰è†: "success",
      è„±æ¨¡å‰‚: "warning",
      é˜²è…å‰‚: "danger",
      æ°¯åŒ–剂: "info",
      å†·æ‹”丝: "purple",
    };
    return typeMap[material] || "info";
  };
// ç”Ÿå‘½å‘¨æœŸé’©å­
onMounted(() => {
  // ä½¿ç”¨nextTick确保DOM完全渲染后再初始化
  nextTick(() => {
    // åˆå§‹åŒ–图表
    initCharts()
  })
      initCharts();
    });
  window.addEventListener('resize', handleResize)
})
    window.addEventListener("resize", handleResize);
  });
onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize)
    window.removeEventListener("resize", handleResize);
  
  // é”€æ¯å›¾è¡¨å®žä¾‹
  productionChartInstance?.dispose()
  solidWasteChartInstance?.dispose()
  costChartInstance?.dispose()
  energyChartInstance?.dispose()
})
    productionChartInstance?.dispose();
    solidWasteChartInstance?.dispose();
    costChartInstance?.dispose();
    energyChartInstance?.dispose();
  });
</script>
<style scoped>
@@ -788,6 +876,30 @@
  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;
@@ -833,6 +945,26 @@
  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;
@@ -853,6 +985,11 @@
  background-color: #ecf5ff;
}
  .data-value {
    font-weight: bold;
    color: #409eff;
  }
/* æŒ‰é’®æ ·å¼ */
:deep(.el-radio-button__inner) {
  border-radius: 4px;
src/views/reportAnalysis/salesStatistics/index.vue
@@ -5,51 +5,68 @@
      <!-- <div class="dashboard-header">
        <div class="factory-name">销售统计看板</div>
      </div> -->
      <!-- ç­›é€‰æ¡ä»¶ -->
      <div class="filter-area">
        <div class="filter-section">
          <span class="filter-label">时间范围:</span>
          <el-date-picker
            v-model="dateRange"
          <el-date-picker v-model="dateRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="YYYY-MM-DD"
            @change="handleDateChange"
            style="width: 240px;"
          />
                          style="width: 240px;" />
        </div>
        <div class="filter-section">
          <span class="filter-label">产品类型:</span>
          <el-select v-model="productType" placeholder="请选择产品类型" @change="handleFilterChange" style="width: 160px;">
            <el-option label="全部" value="" />
            <el-option label="砌块" value="block" />
            <el-option label="板材" value="board" />
            <el-option label="型材" value="profile" />
          <el-select v-model="productType"
                     placeholder="请选择产品类型"
                     @change="handleFilterChange"
                     style="width: 160px;">
            <el-option label="全部"
                       value="" />
            <el-option label="砌块"
                       value="block" />
            <el-option label="板材"
                       value="board" />
            <el-option label="型材"
                       value="profile" />
          </el-select>
        </div>
        <div class="filter-section">
          <span class="filter-label">销售区域:</span>
          <el-select v-model="salesArea" placeholder="请选择销售区域" @change="handleFilterChange" style="width: 160px;">
            <el-option label="全部" value="" />
            <el-option label="华东" value="east" />
            <el-option label="华北" value="north" />
            <el-option label="华南" value="south" />
            <el-option label="西南" value="southwest" />
            <el-option label="西北" value="northwest" />
          <el-select v-model="salesArea"
                     placeholder="请选择销售区域"
                     @change="handleFilterChange"
                     style="width: 160px;">
            <el-option label="全部"
                       value="" />
            <el-option label="华东"
                       value="east" />
            <el-option label="华北"
                       value="north" />
            <el-option label="华南"
                       value="south" />
            <el-option label="西南"
                       value="southwest" />
            <el-option label="西北"
                       value="northwest" />
          </el-select>
        </div>
        <div class="filter-section">
          <span class="filter-label">统计维度:</span>
          <el-select v-model="statDimension" placeholder="请选择统计维度" @change="handleFilterChange" style="width: 160px;">
            <el-option label="月度" value="month" />
            <el-option label="年度" value="year" />
          <el-select v-model="statDimension"
                     placeholder="请选择统计维度"
                     @change="handleFilterChange"
                     style="width: 160px;">
            <el-option label="月度"
                       value="month" />
            <el-option label="年度"
                       value="year" />
          </el-select>
        </div>
      </div>
      <div class="dashboard-content">
        <!-- æ ¸å¿ƒæŒ‡æ ‡å¡ç‰‡ -->
        <div class="row row-1">
@@ -57,7 +74,7 @@
            <div class="panel-title">合计销量</div>
            <div class="stats-grid">
              <div class="stat-item">
                <div class="stat-value">{{ totalSalesVolume }}</div>
                <div class="stat-value sales-volume-color">{{ totalSalesVolume }}</div>
                <div class="stat-unit">立方米</div>
                <div class="stat-change">{{ salesVolumeChange }}%</div>
              </div>
@@ -67,7 +84,7 @@
            <div class="panel-title">销售金额</div>
            <div class="stats-grid">
              <div class="stat-item">
                <div class="stat-value">{{ totalSalesAmount }}</div>
                <div class="stat-value sales-amount-color">{{ totalSalesAmount }}</div>
                <div class="stat-unit">万元</div>
                <div class="stat-change">{{ salesAmountChange }}%</div>
              </div>
@@ -77,7 +94,7 @@
            <div class="panel-title">新增客户</div>
            <div class="stats-grid">
              <div class="stat-item">
                <div class="stat-value">{{ newCustomerCount }}</div>
                <div class="stat-value new-customer-color">{{ newCustomerCount }}</div>
                <div class="stat-unit">个</div>
                <div class="stat-change">{{ customerCountChange }}%</div>
              </div>
@@ -87,76 +104,129 @@
            <div class="panel-title">合计客户</div>
            <div class="stats-grid">
              <div class="stat-item">
                <div class="stat-value">{{ totalCustomerCount }}</div>
                <div class="stat-value total-customer-color">{{ totalCustomerCount }}</div>
                <div class="stat-unit">个</div>
                <div class="stat-change">{{ totalCustomerChange }}%</div>
              </div>
            </div>
          </div>
        </div>
        <!-- é”€é‡å’Œé”€å”®é‡‘额趋势 -->
        <div class="row row-2">
          <div class="panel-card card-5">
            <div class="panel-title">销量趋势</div>
            <div class="chart-container">
              <div ref="salesVolumeChart" style="width: 100%; height: 100%;"></div>
              <div ref="salesVolumeChart"
                   style="width: 100%; height: 100%;"></div>
            </div>
          </div>
          <div class="panel-card card-6">
            <div class="panel-title">销售金额趋势</div>
            <div class="chart-container">
              <div ref="salesAmountChart" style="width: 100%; height: 100%;"></div>
              <div ref="salesAmountChart"
                   style="width: 100%; height: 100%;"></div>
            </div>
          </div>
        </div>
        <!-- ç´¯è®¡æ•°æ®è¶‹åŠ¿ -->
        <div class="row row-3">
        <!-- <div class="row row-3">
          <div class="panel-card card-10">
            <div class="panel-title">累计销量趋势</div>
            <div class="chart-container">
              <div ref="cumulativeSalesVolumeChart" style="width: 100%; height: 100%;"></div>
              <div ref="cumulativeSalesVolumeChart"
                   style="width: 100%; height: 100%;"></div>
            </div>
          </div>
          <div class="panel-card card-11">
            <div class="panel-title">累计销售金额趋势</div>
            <div class="chart-container">
              <div ref="cumulativeSalesAmountChart" style="width: 100%; height: 100%;"></div>
              <div ref="cumulativeSalesAmountChart"
                   style="width: 100%; height: 100%;"></div>
            </div>
          </div>
        </div>
        </div> -->
        <!-- å›¾è¡¨åŒºåŸŸå’Œè¡¨æ ¼ -->
        <div class="row row-4">
          <!-- å·¦è¾¹ï¼šè¯¦ç»†æ•°æ®è¡¨æ ¼ -->
          <div class="panel-card card-9" style="flex: 2;">
          <div class="panel-card card-9"
               style="flex: 2;">
            <div class="panel-title">销售统计详细数据</div>
            <div class="table-container">
              <el-table :data="tableData" style="width: 100%">
                <el-table-column prop="productType" label="产品类型" width="120" />
                <el-table-column prop="salesArea" label="销售区域" width="120" />
                <el-table-column prop="period" label="统计周期" width="120" />
                <el-table-column prop="salesVolume" label="销量(立方米)" />
                <el-table-column prop="salesAmount" label="销售金额(万元)" />
                <el-table-column prop="newCustomers" label="新增客户(个)" width="150" />
                <el-table-column prop="totalCustomers" label="合计客户(个)" width="150" />
              <el-table :data="tableData"
                        style="width: 100%">
                <el-table-column prop="productType"
                                 label="产品类型"
                                 width="120"
                                 align="center">
                  <template #default="scope">
                    <el-tag :type="getProductTypeType(scope.row.productType)">
                      {{ scope.row.productType }}
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="salesArea"
                                 label="销售区域"
                                 width="120"
                                 align="center">
                  <template #default="scope">
                    <el-tag :type="getSalesAreaType(scope.row.salesArea)">
                      {{ scope.row.salesArea }}
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="period"
                                 label="统计周期"
                                 width="120" />
                <el-table-column prop="salesVolume"
                                 label="销量(立方米)"
                                 align="right">
                  <template #default="scope">
                    <span class="data-value">{{ scope.row.salesVolume }}</span>
                  </template>
                </el-table-column>
                <el-table-column prop="salesAmount"
                                 label="销售金额(万元)"
                                 align="right">
                  <template #default="scope">
                    <span class="data-value">{{ scope.row.salesAmount }}</span>
                  </template>
                </el-table-column>
                <el-table-column prop="newCustomers"
                                 label="新增客户(个)"
                                 width="150"
                                 align="right">
                  <template #default="scope">
                    <span class="data-value">{{ scope.row.newCustomers }}</span>
                  </template>
                </el-table-column>
                <el-table-column prop="totalCustomers"
                                 label="合计客户(个)"
                                 width="150"
                                 align="right">
                  <template #default="scope">
                    <span class="data-value">{{ scope.row.totalCustomers }}</span>
                  </template>
                </el-table-column>
              </el-table>
            </div>
          </div>
          <!-- å³è¾¹ï¼šäº§å“ç±»åž‹åˆ†å¸ƒå’Œé”€å”®åŒºåŸŸåˆ†å¸ƒ -->
          <div class="chart-column" style="flex: 1; display: flex; flex-direction: column; gap: 20px;">
            <div class="panel-card card-7" style="flex: 1;">
          <div class="chart-column"
               style="flex: 1; display: flex; flex-direction: column; gap: 20px;">
            <div class="panel-card card-7"
                 style="flex: 1;">
              <div class="panel-title">产品类型分布</div>
              <div class="chart-container">
                <div ref="productTypeChart" style="width: 100%; height: 100%;"></div>
                <div ref="productTypeChart"
                     style="width: 100%; height: 100%;"></div>
              </div>
            </div>
            <div class="panel-card card-8" style="flex: 1;">
            <div class="panel-card card-8"
                 style="flex: 1;">
              <div class="panel-title">销售区域分布</div>
              <div class="chart-container">
                <div ref="salesAreaChart" style="width: 100%; height: 100%;"></div>
                <div ref="salesAreaChart"
                     style="width: 100%; height: 100%;"></div>
              </div>
            </div>
          </div>
@@ -167,18 +237,25 @@
</template>
<script setup>
import { ref, computed, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';
import { useRouter } from 'vue-router';
import * as echarts from 'echarts';
import dayjs from 'dayjs';
  import {
    ref,
    computed,
    onMounted,
    onBeforeUnmount,
    watch,
    nextTick,
  } from "vue";
  import { useRouter } from "vue-router";
  import * as echarts from "echarts";
  import dayjs from "dayjs";
const router = useRouter();
// ç­›é€‰æ¡ä»¶
const dateRange = ref([]);
const productType = ref('');
const salesArea = ref('');
const statDimension = ref('month');
  const productType = ref("");
  const salesArea = ref("");
  const statDimension = ref("month");
// å›¾è¡¨å¼•用
const salesVolumeChart = ref(null);
@@ -199,33 +276,208 @@
// æ¨¡æ‹Ÿæ•°æ®
const mockData = [
  // 2026å¹´1月数据
  { productType: '砌块', salesArea: '华东', period: '2026-01', salesVolume: 1200, salesAmount: 180, newCustomers: 5, totalCustomers: 120 },
  { productType: '砌块', salesArea: '华北', period: '2026-01', salesVolume: 800, salesAmount: 120, newCustomers: 3, totalCustomers: 80 },
  { productType: '砌块', salesArea: '华南', period: '2026-01', salesVolume: 600, salesAmount: 90, newCustomers: 2, totalCustomers: 60 },
  { productType: '板材', salesArea: '华东', period: '2026-01', salesVolume: 900, salesAmount: 270, newCustomers: 4, totalCustomers: 100 },
  { productType: '板材', salesArea: '华北', period: '2026-01', salesVolume: 500, salesAmount: 150, newCustomers: 2, totalCustomers: 70 },
  { productType: '型材', salesArea: '华东', period: '2026-01', salesVolume: 400, salesAmount: 200, newCustomers: 3, totalCustomers: 50 },
    {
      productType: "砌块",
      salesArea: "华东",
      period: "2026-01",
      salesVolume: 1200,
      salesAmount: 180,
      newCustomers: 5,
      totalCustomers: 120,
    },
    {
      productType: "砌块",
      salesArea: "华北",
      period: "2026-01",
      salesVolume: 800,
      salesAmount: 120,
      newCustomers: 3,
      totalCustomers: 80,
    },
    {
      productType: "砌块",
      salesArea: "华南",
      period: "2026-01",
      salesVolume: 600,
      salesAmount: 90,
      newCustomers: 2,
      totalCustomers: 60,
    },
    {
      productType: "板材",
      salesArea: "华东",
      period: "2026-01",
      salesVolume: 900,
      salesAmount: 270,
      newCustomers: 4,
      totalCustomers: 100,
    },
    {
      productType: "板材",
      salesArea: "华北",
      period: "2026-01",
      salesVolume: 500,
      salesAmount: 150,
      newCustomers: 2,
      totalCustomers: 70,
    },
    {
      productType: "型材",
      salesArea: "华东",
      period: "2026-01",
      salesVolume: 400,
      salesAmount: 200,
      newCustomers: 3,
      totalCustomers: 50,
    },
  // 2026å¹´2月数据
  { productType: '砌块', salesArea: '华东', period: '2026-02', salesVolume: 1300, salesAmount: 195, newCustomers: 4, totalCustomers: 124 },
  { productType: '砌块', salesArea: '华北', period: '2026-02', salesVolume: 850, salesAmount: 127.5, newCustomers: 2, totalCustomers: 82 },
  { productType: '砌块', salesArea: '华南', period: '2026-02', salesVolume: 650, salesAmount: 97.5, newCustomers: 1, totalCustomers: 61 },
  { productType: '板材', salesArea: '华东', period: '2026-02', salesVolume: 950, salesAmount: 285, newCustomers: 3, totalCustomers: 103 },
  { productType: '板材', salesArea: '华北', period: '2026-02', salesVolume: 550, salesAmount: 165, newCustomers: 1, totalCustomers: 71 },
  { productType: '型材', salesArea: '华东', period: '2026-02', salesVolume: 450, salesAmount: 225, newCustomers: 2, totalCustomers: 52 },
    {
      productType: "砌块",
      salesArea: "华东",
      period: "2026-02",
      salesVolume: 1300,
      salesAmount: 195,
      newCustomers: 4,
      totalCustomers: 124,
    },
    {
      productType: "砌块",
      salesArea: "华北",
      period: "2026-02",
      salesVolume: 850,
      salesAmount: 127.5,
      newCustomers: 2,
      totalCustomers: 82,
    },
    {
      productType: "砌块",
      salesArea: "华南",
      period: "2026-02",
      salesVolume: 650,
      salesAmount: 97.5,
      newCustomers: 1,
      totalCustomers: 61,
    },
    {
      productType: "板材",
      salesArea: "华东",
      period: "2026-02",
      salesVolume: 950,
      salesAmount: 285,
      newCustomers: 3,
      totalCustomers: 103,
    },
    {
      productType: "板材",
      salesArea: "华北",
      period: "2026-02",
      salesVolume: 550,
      salesAmount: 165,
      newCustomers: 1,
      totalCustomers: 71,
    },
    {
      productType: "型材",
      salesArea: "华东",
      period: "2026-02",
      salesVolume: 450,
      salesAmount: 225,
      newCustomers: 2,
      totalCustomers: 52,
    },
  // 2026å¹´3月数据
  { productType: '砌块', salesArea: '华东', period: '2026-03', salesVolume: 1400, salesAmount: 210, newCustomers: 6, totalCustomers: 130 },
  { productType: '砌块', salesArea: '华北', period: '2026-03', salesVolume: 900, salesAmount: 135, newCustomers: 3, totalCustomers: 85 },
  { productType: '砌块', salesArea: '华南', period: '2026-03', salesVolume: 700, salesAmount: 105, newCustomers: 2, totalCustomers: 63 },
  { productType: '板材', salesArea: '华东', period: '2026-03', salesVolume: 1000, salesAmount: 300, newCustomers: 5, totalCustomers: 108 },
  { productType: '板材', salesArea: '华北', period: '2026-03', salesVolume: 600, salesAmount: 180, newCustomers: 2, totalCustomers: 73 },
  { productType: '型材', salesArea: '华东', period: '2026-03', salesVolume: 500, salesAmount: 250, newCustomers: 3, totalCustomers: 55 },
    {
      productType: "砌块",
      salesArea: "华东",
      period: "2026-03",
      salesVolume: 1400,
      salesAmount: 210,
      newCustomers: 6,
      totalCustomers: 130,
    },
    {
      productType: "砌块",
      salesArea: "华北",
      period: "2026-03",
      salesVolume: 900,
      salesAmount: 135,
      newCustomers: 3,
      totalCustomers: 85,
    },
    {
      productType: "砌块",
      salesArea: "华南",
      period: "2026-03",
      salesVolume: 700,
      salesAmount: 105,
      newCustomers: 2,
      totalCustomers: 63,
    },
    {
      productType: "板材",
      salesArea: "华东",
      period: "2026-03",
      salesVolume: 1000,
      salesAmount: 300,
      newCustomers: 5,
      totalCustomers: 108,
    },
    {
      productType: "板材",
      salesArea: "华北",
      period: "2026-03",
      salesVolume: 600,
      salesAmount: 180,
      newCustomers: 2,
      totalCustomers: 73,
    },
    {
      productType: "型材",
      salesArea: "华东",
      period: "2026-03",
      salesVolume: 500,
      salesAmount: 250,
      newCustomers: 3,
      totalCustomers: 55,
    },
  // è¥¿å—和西北地区数据
  { productType: '砌块', salesArea: '西南', period: '2026-03', salesVolume: 500, salesAmount: 75, newCustomers: 2, totalCustomers: 40 },
  { productType: '板材', salesArea: '西南', period: '2026-03', salesVolume: 300, salesAmount: 90, newCustomers: 1, totalCustomers: 30 },
  { productType: '砌块', salesArea: '西北', period: '2026-03', salesVolume: 400, salesAmount: 60, newCustomers: 1, totalCustomers: 35 },
  { productType: '板材', salesArea: '西北', period: '2026-03', salesVolume: 200, salesAmount: 60, newCustomers: 1, totalCustomers: 25 },
    {
      productType: "砌块",
      salesArea: "西南",
      period: "2026-03",
      salesVolume: 500,
      salesAmount: 75,
      newCustomers: 2,
      totalCustomers: 40,
    },
    {
      productType: "板材",
      salesArea: "西南",
      period: "2026-03",
      salesVolume: 300,
      salesAmount: 90,
      newCustomers: 1,
      totalCustomers: 30,
    },
    {
      productType: "砌块",
      salesArea: "西北",
      period: "2026-03",
      salesVolume: 400,
      salesAmount: 60,
      newCustomers: 1,
      totalCustomers: 35,
    },
    {
      productType: "板材",
      salesArea: "西北",
      period: "2026-03",
      salesVolume: 200,
      salesAmount: 60,
      newCustomers: 1,
      totalCustomers: 25,
    },
];
// è®¡ç®—属性
const filteredData = computed(() => {
@@ -234,7 +486,7 @@
  // æŒ‰äº§å“ç±»åž‹ç­›é€‰
  if (productType.value) {
    result = result.filter(item => {
      const typeMap = { block: '砌块', board: '板材', profile: '型材' };
        const typeMap = { block: "砌块", board: "板材", profile: "型材" };
      return item.productType === typeMap[productType.value];
    });
  }
@@ -242,7 +494,13 @@
  // æŒ‰é”€å”®åŒºåŸŸç­›é€‰
  if (salesArea.value) {
    result = result.filter(item => {
      const areaMap = { east: '华东', north: '华北', south: '华南', southwest: '西南', northwest: '西北' };
        const areaMap = {
          east: "华东",
          north: "华北",
          south: "华南",
          southwest: "西南",
          northwest: "西北",
        };
      return item.salesArea === areaMap[salesArea.value];
    });
  }
@@ -254,7 +512,10 @@
    
    result = result.filter(item => {
      const itemDate = dayjs(item.period);
      return itemDate.isAfter(startDate.subtract(1, 'day')) && itemDate.isBefore(endDate.add(1, 'day'));
        return (
          itemDate.isAfter(startDate.subtract(1, "day")) &&
          itemDate.isBefore(endDate.add(1, "day"))
        );
    });
  }
  
@@ -267,7 +528,9 @@
});
const totalSalesAmount = computed(() => {
  return filteredData.value.reduce((sum, item) => sum + item.salesAmount, 0).toFixed(2);
    return filteredData.value
      .reduce((sum, item) => sum + item.salesAmount, 0)
      .toFixed(2);
});
const newCustomerCount = computed(() => {
@@ -287,10 +550,10 @@
});
// å˜åŒ–率计算(模拟)
const salesVolumeChange = ref('+5.2');
const salesAmountChange = ref('+7.8');
const customerCountChange = ref('+3.5');
const totalCustomerChange = ref('+2.1');
  const salesVolumeChange = ref("+5.2");
  const salesAmountChange = ref("+7.8");
  const customerCountChange = ref("+3.5");
  const totalCustomerChange = ref("+2.1");
// è¡¨æ ¼æ•°æ®
const tableData = computed(() => {
@@ -304,7 +567,7 @@
      ...item,
      cumulativeSalesVolume,
      cumulativeSalesAmount,
      cumulativeNewCustomers
        cumulativeNewCustomers,
    };
  });
});
@@ -325,28 +588,30 @@
  
  return {
    tooltip: {
      trigger: 'axis',
      formatter: '{b}: {c} ç«‹æ–¹ç±³'
        trigger: "axis",
        formatter: "{b}: {c} ç«‹æ–¹ç±³",
    },
    xAxis: {
      type: 'category',
      data: periods
        type: "category",
        data: periods,
    },
    yAxis: {
      type: 'value',
      name: '销量(立方米)'
        type: "value",
        name: "销量(立方米)",
    },
    series: [{
      series: [
        {
      data: values,
      type: 'line',
          type: "line",
      smooth: true,
      lineStyle: {
        width: 3
            width: 3,
      },
      itemStyle: {
        color: '#409EFF'
      }
    }]
            color: "#409EFF",
          },
        },
      ],
  };
});
@@ -366,24 +631,26 @@
  
  return {
    tooltip: {
      trigger: 'axis',
      formatter: '{b}: {c} ä¸‡å…ƒ'
        trigger: "axis",
        formatter: "{b}: {c} ä¸‡å…ƒ",
    },
    xAxis: {
      type: 'category',
      data: periods
        type: "category",
        data: periods,
    },
    yAxis: {
      type: 'value',
      name: '销售金额(万元)'
        type: "value",
        name: "销售金额(万元)",
    },
    series: [{
      series: [
        {
      data: values,
      type: 'bar',
          type: "bar",
      itemStyle: {
        color: '#67C23A'
      }
    }]
            color: "#67C23A",
          },
        },
      ],
  };
});
@@ -403,24 +670,26 @@
  
  return {
    tooltip: {
      trigger: 'item',
      formatter: '{b}: {c} ç«‹æ–¹ç±³ ({d}%)'
        trigger: "item",
        formatter: "{b}: {c} ç«‹æ–¹ç±³ ({d}%)",
    },
    series: [{
      type: 'pie',
      radius: '60%',
      series: [
        {
          type: "pie",
          radius: "60%",
      data: types.map((type, index) => ({
        name: type,
        value: values[index]
            value: values[index],
      })),
      emphasis: {
        itemStyle: {
          shadowBlur: 10,
          shadowOffsetX: 0,
          shadowColor: 'rgba(0, 0, 0, 0.5)'
        }
      }
    }]
              shadowColor: "rgba(0, 0, 0, 0.5)",
            },
          },
        },
      ],
  };
});
@@ -440,24 +709,26 @@
  
  return {
    tooltip: {
      trigger: 'item',
      formatter: '{b}: {c} ç«‹æ–¹ç±³ ({d}%)'
        trigger: "item",
        formatter: "{b}: {c} ç«‹æ–¹ç±³ ({d}%)",
    },
    series: [{
      type: 'pie',
      radius: '60%',
      series: [
        {
          type: "pie",
          radius: "60%",
      data: areas.map((area, index) => ({
        name: area,
        value: values[index]
            value: values[index],
      })),
      emphasis: {
        itemStyle: {
          shadowBlur: 10,
          shadowOffsetX: 0,
          shadowColor: 'rgba(0, 0, 0, 0.5)'
        }
      }
    }]
              shadowColor: "rgba(0, 0, 0, 0.5)",
            },
          },
        },
      ],
  };
});
@@ -468,7 +739,9 @@
  let cumulativeValue = 0;
  
  // æŒ‰å‘¨æœŸæŽ’序
  const sortedData = [...filteredData.value].sort((a, b) => a.period.localeCompare(b.period));
    const sortedData = [...filteredData.value].sort((a, b) =>
      a.period.localeCompare(b.period)
    );
  
  sortedData.forEach(item => {
    cumulativeValue += item.salesVolume;
@@ -480,31 +753,33 @@
  
  return {
    tooltip: {
      trigger: 'axis',
      formatter: '{b}: {c} ç«‹æ–¹ç±³'
        trigger: "axis",
        formatter: "{b}: {c} ç«‹æ–¹ç±³",
    },
    xAxis: {
      type: 'category',
      data: periods
        type: "category",
        data: periods,
    },
    yAxis: {
      type: 'value',
      name: '累计销量(立方米)'
        type: "value",
        name: "累计销量(立方米)",
    },
    series: [{
      series: [
        {
      data: values,
      type: 'line',
          type: "line",
      smooth: true,
      areaStyle: {
        opacity: 0.3
            opacity: 0.3,
      },
      itemStyle: {
        color: '#E6A23C'
            color: "#E6A23C",
      },
      lineStyle: {
        width: 3
      }
    }]
            width: 3,
          },
        },
      ],
  };
});
@@ -515,7 +790,9 @@
  let cumulativeValue = 0;
  
  // æŒ‰å‘¨æœŸæŽ’序
  const sortedData = [...filteredData.value].sort((a, b) => a.period.localeCompare(b.period));
    const sortedData = [...filteredData.value].sort((a, b) =>
      a.period.localeCompare(b.period)
    );
  
  sortedData.forEach(item => {
    cumulativeValue += item.salesAmount;
@@ -527,24 +804,26 @@
  
  return {
    tooltip: {
      trigger: 'axis',
      formatter: '{b}: {c} ä¸‡å…ƒ'
        trigger: "axis",
        formatter: "{b}: {c} ä¸‡å…ƒ",
    },
    xAxis: {
      type: 'category',
      data: periods
        type: "category",
        data: periods,
    },
    yAxis: {
      type: 'value',
      name: '累计销售金额(万元)'
        type: "value",
        name: "累计销售金额(万元)",
    },
    series: [{
      series: [
        {
      data: values,
      type: 'bar',
          type: "bar",
      itemStyle: {
        color: '#F56C6C'
      }
    }]
            color: "#F56C6C",
          },
        },
      ],
  };
});
@@ -587,12 +866,16 @@
  
  // åˆå§‹åŒ–累计销量趋势图表
  if (cumulativeSalesVolumeChart.value && !cumulativeSalesVolumeChartInstance) {
    cumulativeSalesVolumeChartInstance = echarts.init(cumulativeSalesVolumeChart.value);
      cumulativeSalesVolumeChartInstance = echarts.init(
        cumulativeSalesVolumeChart.value
      );
  }
  
  // åˆå§‹åŒ–累计销售金额趋势图表
  if (cumulativeSalesAmountChart.value && !cumulativeSalesAmountChartInstance) {
    cumulativeSalesAmountChartInstance = echarts.init(cumulativeSalesAmountChart.value);
      cumulativeSalesAmountChartInstance = echarts.init(
        cumulativeSalesAmountChart.value
      );
  }
  
  updateCharts();
@@ -622,12 +905,16 @@
  
  // æ›´æ–°ç´¯è®¡é”€é‡è¶‹åŠ¿å›¾è¡¨
  if (cumulativeSalesVolumeChartInstance) {
    cumulativeSalesVolumeChartInstance.setOption(cumulativeSalesVolumeChartOption.value);
      cumulativeSalesVolumeChartInstance.setOption(
        cumulativeSalesVolumeChartOption.value
      );
  }
  
  // æ›´æ–°ç´¯è®¡é”€å”®é‡‘额趋势图表
  if (cumulativeSalesAmountChartInstance) {
    cumulativeSalesAmountChartInstance.setOption(cumulativeSalesAmountChartOption.value);
      cumulativeSalesAmountChartInstance.setOption(
        cumulativeSalesAmountChartOption.value
      );
  }
};
@@ -657,8 +944,11 @@
onMounted(() => {
  // è®¾ç½®é»˜è®¤æ—¥æœŸèŒƒå›´ä¸ºæœ€è¿‘3个月
  const endDate = dayjs();
  const startDate = endDate.subtract(3, 'month');
  dateRange.value = [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')];
    const startDate = endDate.subtract(3, "month");
    dateRange.value = [
      startDate.format("YYYY-MM-DD"),
      endDate.format("YYYY-MM-DD"),
    ];
  
  // ç­‰å¾…DOM更新后初始化图表
  nextTick(() => {
@@ -666,8 +956,30 @@
  });
  
  // æ·»åŠ çª—å£å¤§å°å˜åŒ–ç›‘å¬
  window.addEventListener('resize', handleResize);
    window.addEventListener("resize", handleResize);
});
  // èŽ·å–äº§å“ç±»åž‹æ ‡ç­¾ç±»åž‹
  const getProductTypeType = type => {
    const typeMap = {
      ç Œå—: "primary",
      æ¿æ: "success",
      åž‹æ: "warning",
    };
    return typeMap[type] || "info";
  };
  // èŽ·å–é”€å”®åŒºåŸŸæ ‡ç­¾ç±»åž‹
  const getSalesAreaType = area => {
    const typeMap = {
      åŽä¸œ: "primary",
      åŽåŒ—: "success",
      åŽå—: "warning",
      è¥¿å—: "danger",
      è¥¿åŒ—: "info",
    };
    return typeMap[area] || "info";
  };
// ç»„件卸载时销毁图表实例
onBeforeUnmount(() => {
@@ -691,7 +1003,7 @@
  }
  
  // ç§»é™¤çª—口大小变化监听
  window.removeEventListener('resize', handleResize);
    window.removeEventListener("resize", handleResize);
});
</script>
@@ -847,6 +1159,50 @@
  background-color: #fafafa;
}
  .card-1 .panel-title {
    border-left: 4px solid #409eff;
  }
  .card-2 .panel-title {
    border-left: 4px solid #67c23a;
  }
  .card-3 .panel-title {
    border-left: 4px solid #e6a23c;
  }
  .card-4 .panel-title {
    border-left: 4px solid #f56c6c;
  }
  .card-5 .panel-title {
    border-left: 4px solid #409eff;
  }
  .card-6 .panel-title {
    border-left: 4px solid #67c23a;
  }
  .card-7 .panel-title {
    border-left: 4px solid #e6a23c;
  }
  .card-8 .panel-title {
    border-left: 4px solid #f56c6c;
  }
  .card-9 .panel-title {
    border-left: 4px solid #409eff;
  }
  .card-10 .panel-title {
    border-left: 4px solid #67c23a;
  }
  .card-11 .panel-title {
    border-left: 4px solid #e6a23c;
  }
.chart-container {
  flex: 1;
  padding: 20px;
@@ -886,6 +1242,26 @@
  margin-bottom: 5px;
}
  .sales-volume-color {
    color: #409eff;
    text-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
  }
  .sales-amount-color {
    color: #67c23a;
    text-shadow: 0 2px 4px rgba(103, 194, 58, 0.3);
  }
  .new-customer-color {
    color: #e6a23c;
    text-shadow: 0 2px 4px rgba(230, 162, 60, 0.3);
  }
  .total-customer-color {
    color: #f56c6c;
    text-shadow: 0 2px 4px rgba(245, 108, 108, 0.3);
  }
.stat-unit {
  font-size: 12px;
  color: #909399;
@@ -912,6 +1288,11 @@
  background-color: #ecf5ff;
}
  .data-value {
    font-weight: bold;
    color: #409eff;
  }
/* ä¸‹æ‹‰é€‰æ‹©æ¡†æ ·å¼ */
:deep(.el-select) {
  width: 100%;
src/views/reportAnalysis/solidWasteConsumption/index1.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,623 @@
<template>
  <div class="dashboard-container">
    <div class="data-dashboard">
      <!-- ç­›é€‰åŒºåŸŸ -->
      <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>
      <!-- ä¸»è¦å†…容区域 -->
      <div class="dashboard-content">
        <!-- ç¬¬ä¸€è¡Œï¼šæ ¸å¿ƒæŒ‡æ ‡ -->
        <div class="row row-1">
          <div class="panel-card card-1">
            <div class="panel-title">核心指标</div>
            <div class="stats-grid">
              <div class="stat-item">
                <div class="stat-label">合计量</div>
                <div class="stat-value">{{ totalSolidWaste }}</div>
                <div class="stat-unit">吨</div>
              </div>
              <div class="stat-item">
                <div class="stat-label">2022年至今累计消纳量</div>
                <div class="stat-value">{{ totalSolidWasteSince2022 }}</div>
                <div class="stat-unit">吨</div>
              </div>
            </div>
          </div>
        </div>
        <!-- ç¬¬äºŒè¡Œï¼šå›ºåºŸæ¶ˆçº³è¶‹åŠ¿ -->
        <div class="row row-2">
          <div class="panel-card card-2">
            <div class="panel-title">固废消纳趋势</div>
            <div class="chart-container">
              <div ref="trendChart"
                   style="width: 100%; height: 100%"></div>
            </div>
          </div>
        </div>
        <!-- ç¬¬ä¸‰è¡Œï¼šå›ºåºŸç±»åž‹åˆ†å¸ƒ -->
        <div class="row row-3">
          <div class="panel-card card-3">
            <div class="panel-title">固废类型分布</div>
            <div class="chart-container">
              <div ref="distributionChart"
                   style="width: 100%; height: 100%"></div>
            </div>
          </div>
        </div>
        <!-- ç¬¬å››è¡Œï¼šæ¶ˆçº³é‡æ˜Žç»† -->
        <div class="row row-4">
          <div class="panel-card card-4">
            <div class="panel-title">消纳量明细</div>
            <div class="table-container">
              <el-table :data="wasteTableData"
                        style="width: 100%">
                <el-table-column prop="time"
                                 label="时间"
                                 width="120" />
                <el-table-column prop="type"
                                 label="固废类型"
                                 width="120"
                                 align="center">
                  <template #default="scope">
                    <el-tag :type="getWasteTypeType(scope.row.type)">
                      {{ scope.row.type }}
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="quantity"
                                 label="消纳量"
                                 align="right">
                  <template #default="scope">
                    <span class="data-value">{{ scope.row.quantity }}</span>
                  </template>
                </el-table-column>
                <el-table-column prop="unit"
                                 label="单位"
                                 width="80" />
                <el-table-column prop="source"
                                 label="来源" />
              </el-table>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
  import { ref, computed, onMounted, onBeforeUnmount, nextTick } from "vue";
  import * as echarts from "echarts";
  // ç­›é€‰æ¡ä»¶
  const dateType = ref("month"); // month æˆ– year
  // å›¾è¡¨å¼•用
  const trendChart = ref(null);
  const distributionChart = ref(null);
  // å›¾è¡¨å®žä¾‹
  let trendChartInstance = null;
  let distributionChartInstance = null;
  // æ¨¡æ‹Ÿæ•°æ®
  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: "2022", ç²‰ç…¤ç°: 2300, çŸ³è†: 1700, çŸ³ç°: 1100 },
      { name: "2023", ç²‰ç…¤ç°: 2500, çŸ³è†: 1800, çŸ³ç°: 1200 },
      { name: "2024", ç²‰ç…¤ç°: 2700, çŸ³è†: 1950, çŸ³ç°: 1300 },
      { name: "2025", ç²‰ç…¤ç°: 2900, çŸ³è†: 2100, çŸ³ç°: 1400 },
    ],
  });
  // è®¡ç®—属性
  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 totalSolidWasteSince2022 = computed(() => {
    const data = solidWasteData.value.year;
    return data.reduce(
      (sum, item) => sum + item.粉煤灰 + item.石膏 + item.石灰,
      0
    );
  });
  const wasteTableData = computed(() => {
    const data = solidWasteData.value[dateType.value];
    const result = [];
    data.forEach(item => {
      result.push({
        time: item.name,
        type: "粉煤灰",
        quantity: item.粉煤灰,
        unit: "吨",
        source: "生产过程",
      });
      result.push({
        time: item.name,
        type: "石膏",
        quantity: item.石膏,
        unit: "吨",
        source: "生产过程",
      });
      result.push({
        time: item.name,
        type: "石灰",
        quantity: item.石灰,
        unit: "吨",
        source: "生产过程",
      });
    });
    return result;
  });
  // å›¾è¡¨é…ç½®
  const trendChartOption = 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 distributionChartOption = computed(() => {
    const data = solidWasteData.value[dateType.value];
    const lastItem = data[data.length - 1];
    return {
      tooltip: {
        trigger: "item",
        formatter: "{a} <br/>{b}: {c} ({d}%)",
      },
      legend: {
        orient: "vertical",
        left: "left",
        textStyle: {
          color: "#333",
        },
      },
      series: [
        {
          name: "固废类型",
          type: "pie",
          radius: "60%",
          center: ["50%", "50%"],
          data: [
            { value: lastItem.粉煤灰, name: "粉煤灰" },
            { value: lastItem.石膏, name: "石膏" },
            { value: lastItem.石灰, name: "石灰" },
          ],
          emphasis: {
            itemStyle: {
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowColor: "rgba(0, 0, 0, 0.5)",
            },
          },
          itemStyle: {
            color: function (params) {
              const colors = ["#909399", "#E6A23C", "#F56C6C"];
              return colors[params.dataIndex];
            },
          },
        },
      ],
    };
  });
  // äº‹ä»¶å¤„理
  const handleDateTypeChange = () => {
    updateCharts();
  };
  // åˆå§‹åŒ–图表
  const initCharts = () => {
    if (trendChart.value) {
      trendChartInstance = echarts.init(trendChart.value);
      trendChartInstance.setOption(trendChartOption.value);
    }
    if (distributionChart.value) {
      distributionChartInstance = echarts.init(distributionChart.value);
      distributionChartInstance.setOption(distributionChartOption.value);
    }
  };
  // æ›´æ–°å›¾è¡¨
  const updateCharts = () => {
    if (trendChartInstance) {
      trendChartInstance.setOption(trendChartOption.value);
    }
    if (distributionChartInstance) {
      distributionChartInstance.setOption(distributionChartOption.value);
    }
  };
  // è°ƒæ•´å›¾è¡¨å¤§å°
  const resizeCharts = () => {
    trendChartInstance?.resize();
    distributionChartInstance?.resize();
  };
  // çª—口大小变化处理
  const handleResize = () => {
    // å»¶è¿Ÿæ‰§è¡Œï¼Œç¡®ä¿DOM更新完成
    setTimeout(() => {
      resizeCharts();
    }, 100);
  };
  // èŽ·å–å›ºåºŸç±»åž‹æ ‡ç­¾ç±»åž‹
  const getWasteTypeType = type => {
    const typeMap = {
      ç²‰ç…¤ç°: "info",
      çŸ³è†: "warning",
      çŸ³ç°: "danger",
    };
    return typeMap[type] || "info";
  };
  // ç”Ÿå‘½å‘¨æœŸé’©å­
  onMounted(() => {
    // ä½¿ç”¨nextTick确保DOM完全渲染后再初始化
    nextTick(() => {
      // åˆå§‹åŒ–图表
      initCharts();
    });
    window.addEventListener("resize", handleResize);
  });
  onBeforeUnmount(() => {
    window.removeEventListener("resize", handleResize);
    // é”€æ¯å›¾è¡¨å®žä¾‹
    trendChartInstance?.dispose();
    distributionChartInstance?.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);
  }
  .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;
  }
  /* ç¬¬ä¸€è¡Œï¼šæ ¸å¿ƒæŒ‡æ ‡ */
  .row-1 {
    height: 250px;
  }
  /* ç¬¬äºŒè¡Œï¼šå›ºåºŸæ¶ˆçº³è¶‹åŠ¿ */
  .row-2 {
    height: 300px;
  }
  /* ç¬¬ä¸‰è¡Œï¼šå›ºåºŸç±»åž‹åˆ†å¸ƒ */
  .row-3 {
    height: 300px;
  }
  /* ç¬¬å››è¡Œï¼šæ¶ˆçº³é‡æ˜Žç»† */
  .row-4 {
    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: 1;
  }
  .card-4 {
    flex: 1;
  }
  .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 #67c23a;
  }
  .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);
    gap: 15px;
  }
  .stat-item {
    background-color: #ffffff;
    border-radius: 12px;
    padding: 25px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border: 2px solid #e4e7ed;
    min-height: 120px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    transition: all 0.3s ease;
  }
  .stat-item:hover {
    box-shadow: 0 8px 24px rgba(64, 158, 255, 0.2);
    border-color: #409eff;
    transform: translateY(-4px);
  }
  .stat-label {
    font-size: 14px;
    font-weight: 500;
    color: #303133;
    margin-bottom: 10px;
  }
  .stat-value {
    font-size: 32px;
    font-weight: 700;
    color: #409eff;
    margin-bottom: 5px;
    text-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
    transition: all 0.3s ease;
  }
  .stat-value:hover {
    transform: scale(1.05);
  }
  .stat-unit {
    font-size: 12px;
    font-weight: 500;
    color: #606266;
  }
  /* è¡¨æ ¼æ ·å¼ */
  :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;
  }
</style>