From d7ea471fbb4a834b69715cac684bab7d2731688b Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期二, 17 三月 2026 16:32:50 +0800
Subject: [PATCH] 能耗成本核算注释假数据获取方法

---
 src/views/reportAnalysis/salesStatistics/index.vue | 1304 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,304 insertions(+), 0 deletions(-)

diff --git a/src/views/reportAnalysis/salesStatistics/index.vue b/src/views/reportAnalysis/salesStatistics/index.vue
new file mode 100644
index 0000000..d1c76d4
--- /dev/null
+++ b/src/views/reportAnalysis/salesStatistics/index.vue
@@ -0,0 +1,1304 @@
+<template>
+  <div class="sales-statistics-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-date-picker v-model="dateRange"
+                          type="daterange"
+                          range-separator="鑷�"
+                          start-placeholder="寮�濮嬫棩鏈�"
+                          end-placeholder="缁撴潫鏃ユ湡"
+                          value-format="YYYY-MM-DD"
+                          @change="handleDateChange"
+                          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>
+        </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>
+        </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>
+        </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-value sales-volume-color">{{ totalSalesVolume }}</div>
+                <div class="stat-unit">绔嬫柟绫�</div>
+                <div class="stat-change">{{ salesVolumeChange }}%</div>
+              </div>
+            </div>
+          </div>
+          <div class="panel-card card-2">
+            <div class="panel-title">閿�鍞噾棰�</div>
+            <div class="stats-grid">
+              <div class="stat-item">
+                <div class="stat-value sales-amount-color">{{ totalSalesAmount }}</div>
+                <div class="stat-unit">涓囧厓</div>
+                <div class="stat-change">{{ salesAmountChange }}%</div>
+              </div>
+            </div>
+          </div>
+          <div class="panel-card card-3">
+            <div class="panel-title">鏂板瀹㈡埛</div>
+            <div class="stats-grid">
+              <div class="stat-item">
+                <div class="stat-value new-customer-color">{{ newCustomerCount }}</div>
+                <div class="stat-unit">涓�</div>
+                <div class="stat-change">{{ customerCountChange }}%</div>
+              </div>
+            </div>
+          </div>
+          <div class="panel-card card-4">
+            <div class="panel-title">鍚堣瀹㈡埛</div>
+            <div class="stats-grid">
+              <div class="stat-item">
+                <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>
+          </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>
+          </div>
+        </div>
+        <!-- 绱鏁版嵁瓒嬪娍 -->
+        <!-- <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>
+          </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>
+          </div>
+        </div> -->
+        <!-- 鍥捐〃鍖哄煙鍜岃〃鏍� -->
+        <div class="row row-4">
+          <!-- 宸﹁竟锛氳缁嗘暟鎹〃鏍� -->
+          <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"
+                                 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="panel-title">浜у搧绫诲瀷鍒嗗竷</div>
+              <div class="chart-container">
+                <div ref="productTypeChart"
+                     style="width: 100%; height: 100%;"></div>
+              </div>
+            </div>
+            <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>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</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";
+
+  const router = useRouter();
+
+  // 绛涢�夋潯浠�
+  const dateRange = ref([]);
+  const productType = ref("");
+  const salesArea = ref("");
+  const statDimension = ref("month");
+
+  // 鍥捐〃寮曠敤
+  const salesVolumeChart = ref(null);
+  const salesAmountChart = ref(null);
+  const productTypeChart = ref(null);
+  const salesAreaChart = ref(null);
+  const cumulativeSalesVolumeChart = ref(null);
+  const cumulativeSalesAmountChart = ref(null);
+
+  // 鍥捐〃瀹炰緥
+  let salesVolumeChartInstance = null;
+  let salesAmountChartInstance = null;
+  let productTypeChartInstance = null;
+  let salesAreaChartInstance = null;
+  let cumulativeSalesVolumeChartInstance = null;
+  let cumulativeSalesAmountChartInstance = null;
+
+  // 妯℃嫙鏁版嵁
+  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,
+    },
+    // 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,
+    },
+    // 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: 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(() => {
+    let result = [...mockData];
+
+    // 鎸変骇鍝佺被鍨嬬瓫閫�
+    if (productType.value) {
+      result = result.filter(item => {
+        const typeMap = { block: "鐮屽潡", board: "鏉挎潗", profile: "鍨嬫潗" };
+        return item.productType === typeMap[productType.value];
+      });
+    }
+
+    // 鎸夐攢鍞尯鍩熺瓫閫�
+    if (salesArea.value) {
+      result = result.filter(item => {
+        const areaMap = {
+          east: "鍗庝笢",
+          north: "鍗庡寳",
+          south: "鍗庡崡",
+          southwest: "瑗垮崡",
+          northwest: "瑗垮寳",
+        };
+        return item.salesArea === areaMap[salesArea.value];
+      });
+    }
+
+    // 鎸夋椂闂磋寖鍥寸瓫閫�
+    if (dateRange.value && dateRange.value.length === 2) {
+      const startDate = dayjs(dateRange.value[0]);
+      const endDate = dayjs(dateRange.value[1]);
+
+      result = result.filter(item => {
+        const itemDate = dayjs(item.period);
+        return (
+          itemDate.isAfter(startDate.subtract(1, "day")) &&
+          itemDate.isBefore(endDate.add(1, "day"))
+        );
+      });
+    }
+
+    return result;
+  });
+
+  // 鏍稿績鎸囨爣璁$畻
+  const totalSalesVolume = computed(() => {
+    return filteredData.value.reduce((sum, item) => sum + item.salesVolume, 0);
+  });
+
+  const totalSalesAmount = computed(() => {
+    return filteredData.value
+      .reduce((sum, item) => sum + item.salesAmount, 0)
+      .toFixed(2);
+  });
+
+  const newCustomerCount = computed(() => {
+    return filteredData.value.reduce((sum, item) => sum + item.newCustomers, 0);
+  });
+
+  const totalCustomerCount = computed(() => {
+    // 璁$畻姣忎釜鍖哄煙鍜屼骇鍝佺被鍨嬬殑鏈�澶у鎴锋暟
+    const customerMap = {};
+    filteredData.value.forEach(item => {
+      const key = `${item.productType}-${item.salesArea}`;
+      if (!customerMap[key] || item.totalCustomers > customerMap[key]) {
+        customerMap[key] = item.totalCustomers;
+      }
+    });
+    return Object.values(customerMap).reduce((sum, count) => sum + count, 0);
+  });
+
+  // 鍙樺寲鐜囪绠楋紙妯℃嫙锛�
+  const salesVolumeChange = ref("+5.2");
+  const salesAmountChange = ref("+7.8");
+  const customerCountChange = ref("+3.5");
+  const totalCustomerChange = ref("+2.1");
+
+  // 琛ㄦ牸鏁版嵁
+  const tableData = computed(() => {
+    return filteredData.value.map(item => {
+      // 璁$畻绱鍊硷紙妯℃嫙锛�
+      const cumulativeSalesVolume = item.salesVolume * 1.5;
+      const cumulativeSalesAmount = item.salesAmount * 1.5;
+      const cumulativeNewCustomers = item.newCustomers * 2;
+
+      return {
+        ...item,
+        cumulativeSalesVolume,
+        cumulativeSalesAmount,
+        cumulativeNewCustomers,
+      };
+    });
+  });
+
+  // 閿�閲忚秼鍔垮浘琛ㄩ厤缃�
+  const salesVolumeChartOption = computed(() => {
+    // 鎸夊懆鏈熷垎缁�
+    const periodMap = {};
+    filteredData.value.forEach(item => {
+      if (!periodMap[item.period]) {
+        periodMap[item.period] = 0;
+      }
+      periodMap[item.period] += item.salesVolume;
+    });
+
+    const periods = Object.keys(periodMap).sort();
+    const values = periods.map(period => periodMap[period]);
+
+    return {
+      tooltip: {
+        trigger: "axis",
+        formatter: "{b}: {c} 绔嬫柟绫�",
+      },
+      xAxis: {
+        type: "category",
+        data: periods,
+      },
+      yAxis: {
+        type: "value",
+        name: "閿�閲忥紙绔嬫柟绫筹級",
+      },
+      series: [
+        {
+          data: values,
+          type: "line",
+          smooth: true,
+          lineStyle: {
+            width: 3,
+          },
+          itemStyle: {
+            color: "#409EFF",
+          },
+        },
+      ],
+    };
+  });
+
+  // 閿�鍞噾棰濊秼鍔垮浘琛ㄩ厤缃�
+  const salesAmountChartOption = computed(() => {
+    // 鎸夊懆鏈熷垎缁�
+    const periodMap = {};
+    filteredData.value.forEach(item => {
+      if (!periodMap[item.period]) {
+        periodMap[item.period] = 0;
+      }
+      periodMap[item.period] += item.salesAmount;
+    });
+
+    const periods = Object.keys(periodMap).sort();
+    const values = periods.map(period => periodMap[period]);
+
+    return {
+      tooltip: {
+        trigger: "axis",
+        formatter: "{b}: {c} 涓囧厓",
+      },
+      xAxis: {
+        type: "category",
+        data: periods,
+      },
+      yAxis: {
+        type: "value",
+        name: "閿�鍞噾棰濓紙涓囧厓锛�",
+      },
+      series: [
+        {
+          data: values,
+          type: "bar",
+          itemStyle: {
+            color: "#67C23A",
+          },
+        },
+      ],
+    };
+  });
+
+  // 浜у搧绫诲瀷鍒嗗竷鍥捐〃閰嶇疆
+  const productTypeChartOption = computed(() => {
+    // 鎸変骇鍝佺被鍨嬪垎缁�
+    const typeMap = {};
+    filteredData.value.forEach(item => {
+      if (!typeMap[item.productType]) {
+        typeMap[item.productType] = 0;
+      }
+      typeMap[item.productType] += item.salesVolume;
+    });
+
+    const types = Object.keys(typeMap);
+    const values = types.map(type => typeMap[type]);
+
+    return {
+      tooltip: {
+        trigger: "item",
+        formatter: "{b}: {c} 绔嬫柟绫� ({d}%)",
+      },
+      series: [
+        {
+          type: "pie",
+          radius: "60%",
+          data: types.map((type, index) => ({
+            name: type,
+            value: values[index],
+          })),
+          emphasis: {
+            itemStyle: {
+              shadowBlur: 10,
+              shadowOffsetX: 0,
+              shadowColor: "rgba(0, 0, 0, 0.5)",
+            },
+          },
+        },
+      ],
+    };
+  });
+
+  // 閿�鍞尯鍩熷垎甯冨浘琛ㄩ厤缃�
+  const salesAreaChartOption = computed(() => {
+    // 鎸夐攢鍞尯鍩熷垎缁�
+    const areaMap = {};
+    filteredData.value.forEach(item => {
+      if (!areaMap[item.salesArea]) {
+        areaMap[item.salesArea] = 0;
+      }
+      areaMap[item.salesArea] += item.salesVolume;
+    });
+
+    const areas = Object.keys(areaMap);
+    const values = areas.map(area => areaMap[area]);
+
+    return {
+      tooltip: {
+        trigger: "item",
+        formatter: "{b}: {c} 绔嬫柟绫� ({d}%)",
+      },
+      series: [
+        {
+          type: "pie",
+          radius: "60%",
+          data: areas.map((area, index) => ({
+            name: area,
+            value: values[index],
+          })),
+          emphasis: {
+            itemStyle: {
+              shadowBlur: 10,
+              shadowOffsetX: 0,
+              shadowColor: "rgba(0, 0, 0, 0.5)",
+            },
+          },
+        },
+      ],
+    };
+  });
+
+  // 绱閿�閲忚秼鍔垮浘琛ㄩ厤缃�
+  const cumulativeSalesVolumeChartOption = computed(() => {
+    // 鎸夊懆鏈熷垎缁�
+    const periodMap = {};
+    let cumulativeValue = 0;
+
+    // 鎸夊懆鏈熸帓搴�
+    const sortedData = [...filteredData.value].sort((a, b) =>
+      a.period.localeCompare(b.period)
+    );
+
+    sortedData.forEach(item => {
+      cumulativeValue += item.salesVolume;
+      periodMap[item.period] = cumulativeValue;
+    });
+
+    const periods = Object.keys(periodMap).sort();
+    const values = periods.map(period => periodMap[period]);
+
+    return {
+      tooltip: {
+        trigger: "axis",
+        formatter: "{b}: {c} 绔嬫柟绫�",
+      },
+      xAxis: {
+        type: "category",
+        data: periods,
+      },
+      yAxis: {
+        type: "value",
+        name: "绱閿�閲忥紙绔嬫柟绫筹級",
+      },
+      series: [
+        {
+          data: values,
+          type: "line",
+          smooth: true,
+          areaStyle: {
+            opacity: 0.3,
+          },
+          itemStyle: {
+            color: "#E6A23C",
+          },
+          lineStyle: {
+            width: 3,
+          },
+        },
+      ],
+    };
+  });
+
+  // 绱閿�鍞噾棰濊秼鍔垮浘琛ㄩ厤缃�
+  const cumulativeSalesAmountChartOption = computed(() => {
+    // 鎸夊懆鏈熷垎缁�
+    const periodMap = {};
+    let cumulativeValue = 0;
+
+    // 鎸夊懆鏈熸帓搴�
+    const sortedData = [...filteredData.value].sort((a, b) =>
+      a.period.localeCompare(b.period)
+    );
+
+    sortedData.forEach(item => {
+      cumulativeValue += item.salesAmount;
+      periodMap[item.period] = cumulativeValue;
+    });
+
+    const periods = Object.keys(periodMap).sort();
+    const values = periods.map(period => periodMap[period]);
+
+    return {
+      tooltip: {
+        trigger: "axis",
+        formatter: "{b}: {c} 涓囧厓",
+      },
+      xAxis: {
+        type: "category",
+        data: periods,
+      },
+      yAxis: {
+        type: "value",
+        name: "绱閿�鍞噾棰濓紙涓囧厓锛�",
+      },
+      series: [
+        {
+          data: values,
+          type: "bar",
+          itemStyle: {
+            color: "#F56C6C",
+          },
+        },
+      ],
+    };
+  });
+
+  // 鏂规硶
+  const goBack = () => {
+    router.back();
+  };
+
+  const handleDateChange = () => {
+    // 澶勭悊鏃ユ湡鍙樺寲
+    updateCharts();
+  };
+
+  const handleFilterChange = () => {
+    // 澶勭悊绛涢�夋潯浠跺彉鍖�
+    updateCharts();
+  };
+
+  // 鍒濆鍖栧浘琛�
+  const initCharts = () => {
+    // 鍒濆鍖栭攢閲忚秼鍔垮浘琛�
+    if (salesVolumeChart.value && !salesVolumeChartInstance) {
+      salesVolumeChartInstance = echarts.init(salesVolumeChart.value);
+    }
+
+    // 鍒濆鍖栭攢鍞噾棰濊秼鍔垮浘琛�
+    if (salesAmountChart.value && !salesAmountChartInstance) {
+      salesAmountChartInstance = echarts.init(salesAmountChart.value);
+    }
+
+    // 鍒濆鍖栦骇鍝佺被鍨嬪垎甯冨浘琛�
+    if (productTypeChart.value && !productTypeChartInstance) {
+      productTypeChartInstance = echarts.init(productTypeChart.value);
+    }
+
+    // 鍒濆鍖栭攢鍞尯鍩熷垎甯冨浘琛�
+    if (salesAreaChart.value && !salesAreaChartInstance) {
+      salesAreaChartInstance = echarts.init(salesAreaChart.value);
+    }
+
+    // 鍒濆鍖栫疮璁¢攢閲忚秼鍔垮浘琛�
+    if (cumulativeSalesVolumeChart.value && !cumulativeSalesVolumeChartInstance) {
+      cumulativeSalesVolumeChartInstance = echarts.init(
+        cumulativeSalesVolumeChart.value
+      );
+    }
+
+    // 鍒濆鍖栫疮璁¢攢鍞噾棰濊秼鍔垮浘琛�
+    if (cumulativeSalesAmountChart.value && !cumulativeSalesAmountChartInstance) {
+      cumulativeSalesAmountChartInstance = echarts.init(
+        cumulativeSalesAmountChart.value
+      );
+    }
+
+    updateCharts();
+  };
+
+  // 鏇存柊鍥捐〃
+  const updateCharts = () => {
+    // 鏇存柊閿�閲忚秼鍔垮浘琛�
+    if (salesVolumeChartInstance) {
+      salesVolumeChartInstance.setOption(salesVolumeChartOption.value);
+    }
+
+    // 鏇存柊閿�鍞噾棰濊秼鍔垮浘琛�
+    if (salesAmountChartInstance) {
+      salesAmountChartInstance.setOption(salesAmountChartOption.value);
+    }
+
+    // 鏇存柊浜у搧绫诲瀷鍒嗗竷鍥捐〃
+    if (productTypeChartInstance) {
+      productTypeChartInstance.setOption(productTypeChartOption.value);
+    }
+
+    // 鏇存柊閿�鍞尯鍩熷垎甯冨浘琛�
+    if (salesAreaChartInstance) {
+      salesAreaChartInstance.setOption(salesAreaChartOption.value);
+    }
+
+    // 鏇存柊绱閿�閲忚秼鍔垮浘琛�
+    if (cumulativeSalesVolumeChartInstance) {
+      cumulativeSalesVolumeChartInstance.setOption(
+        cumulativeSalesVolumeChartOption.value
+      );
+    }
+
+    // 鏇存柊绱閿�鍞噾棰濊秼鍔垮浘琛�
+    if (cumulativeSalesAmountChartInstance) {
+      cumulativeSalesAmountChartInstance.setOption(
+        cumulativeSalesAmountChartOption.value
+      );
+    }
+  };
+
+  // 鐩戝惉绐楀彛澶у皬鍙樺寲
+  const handleResize = () => {
+    if (salesVolumeChartInstance) {
+      salesVolumeChartInstance.resize();
+    }
+    if (salesAmountChartInstance) {
+      salesAmountChartInstance.resize();
+    }
+    if (productTypeChartInstance) {
+      productTypeChartInstance.resize();
+    }
+    if (salesAreaChartInstance) {
+      salesAreaChartInstance.resize();
+    }
+    if (cumulativeSalesVolumeChartInstance) {
+      cumulativeSalesVolumeChartInstance.resize();
+    }
+    if (cumulativeSalesAmountChartInstance) {
+      cumulativeSalesAmountChartInstance.resize();
+    }
+  };
+
+  // 鐢熷懡鍛ㄦ湡
+  onMounted(() => {
+    // 璁剧疆榛樿鏃ユ湡鑼冨洿涓烘渶杩�3涓湀
+    const endDate = dayjs();
+    const startDate = endDate.subtract(3, "month");
+    dateRange.value = [
+      startDate.format("YYYY-MM-DD"),
+      endDate.format("YYYY-MM-DD"),
+    ];
+
+    // 绛夊緟DOM鏇存柊鍚庡垵濮嬪寲鍥捐〃
+    nextTick(() => {
+      initCharts();
+    });
+
+    // 娣诲姞绐楀彛澶у皬鍙樺寲鐩戝惉
+    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(() => {
+    if (salesVolumeChartInstance) {
+      salesVolumeChartInstance.dispose();
+    }
+    if (salesAmountChartInstance) {
+      salesAmountChartInstance.dispose();
+    }
+    if (productTypeChartInstance) {
+      productTypeChartInstance.dispose();
+    }
+    if (salesAreaChartInstance) {
+      salesAreaChartInstance.dispose();
+    }
+    if (cumulativeSalesVolumeChartInstance) {
+      cumulativeSalesVolumeChartInstance.dispose();
+    }
+    if (cumulativeSalesAmountChartInstance) {
+      cumulativeSalesAmountChartInstance.dispose();
+    }
+
+    // 绉婚櫎绐楀彛澶у皬鍙樺寲鐩戝惉
+    window.removeEventListener("resize", handleResize);
+  });
+</script>
+
+<style scoped>
+  /* 澶栭儴瀹瑰櫒 - 鍗犳嵁鏁翠釜瑙嗗彛 */
+  .sales-statistics-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;
+  }
+
+  .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;
+  }
+
+  /* 绗竴琛岋細4涓寚鏍囧崱鐗� */
+  .row-1 {
+    height: 180px;
+  }
+
+  /* 绗簩琛岋細2涓秼鍔垮浘琛� */
+  .row-2 {
+    height: 350px;
+  }
+
+  /* 绗笁琛岋細绱鏁版嵁瓒嬪娍 */
+  .row-3 {
+    height: 350px;
+  }
+
+  /* 绗洓琛岋細琛ㄦ牸鍜屽浘琛� */
+  .row-4 {
+    height: 600px;
+  }
+
+  /* 鍗$墖鏍峰紡 */
+  .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;
+  }
+
+  .card-5 {
+    flex: 1;
+  }
+
+  .card-6 {
+    flex: 1;
+  }
+
+  .card-7 {
+    flex: 1;
+  }
+
+  .card-8 {
+    flex: 1;
+  }
+
+  .card-9 {
+    flex: 1;
+  }
+
+  .card-10 {
+    flex: 1;
+  }
+
+  .card-11 {
+    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 #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;
+  }
+
+  .table-container {
+    flex: 1;
+    padding: 20px;
+    overflow: auto;
+  }
+
+  .stats-grid {
+    flex: 1;
+    padding: 15px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .stat-item {
+    background-color: #fafafa;
+    border-radius: 8px;
+    padding: 15px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    border: 1px solid #e4e7ed;
+    min-height: 80px;
+    width: 100%;
+  }
+
+  .stat-value {
+    font-size: 24px;
+    font-weight: 600;
+    color: #303133;
+    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;
+    margin-bottom: 3px;
+  }
+
+  .stat-change {
+    font-size: 12px;
+    color: #67c23a;
+  }
+
+  /* 琛ㄦ牸鏍峰紡 */
+  :deep(.el-table) {
+    border-radius: 8px;
+    overflow: hidden;
+  }
+
+  :deep(.el-table th) {
+    background-color: #fafafa;
+    font-weight: 500;
+  }
+
+  :deep(.el-table tr:hover > td) {
+    background-color: #ecf5ff;
+  }
+
+  .data-value {
+    font-weight: bold;
+    color: #409eff;
+  }
+
+  /* 涓嬫媺閫夋嫨妗嗘牱寮� */
+  :deep(.el-select) {
+    width: 100%;
+  }
+
+  :deep(.el-date-picker) {
+    width: 100%;
+  }
+</style>
\ No newline at end of file

--
Gitblit v1.9.3