From 01051a30308b5bc5138179ddfe2b16edcc58be8d Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期三, 01 四月 2026 14:48:35 +0800
Subject: [PATCH] 销售统计看板修改

---
 src/views/reportAnalysis/salesStatistics/index.vue |  790 +++++++++++++++++++++++++++++++++++++++++++++-----------
 src/api/reportAnalysis/salesStatistics.js          |   16 +
 2 files changed, 649 insertions(+), 157 deletions(-)

diff --git a/src/api/reportAnalysis/salesStatistics.js b/src/api/reportAnalysis/salesStatistics.js
index 05b259e..bce6f28 100644
--- a/src/api/reportAnalysis/salesStatistics.js
+++ b/src/api/reportAnalysis/salesStatistics.js
@@ -14,4 +14,20 @@
     url: '/home/total',
     method: 'get'
   })
+}
+// 閿�閲忓垎鏋愯秼鍔垮浘
+export function getSalesAnalysisTrend(params) {
+  return request({
+    url: '/home/salesAnalysis',
+    method: 'get',
+    params: params
+  })
+}
+// 閿�鍞噾棰濆垎鏋�
+export function getSalesAmountAnalysis(params) {
+  return request({
+    url: '/home/salesAmount',
+    method: 'get',
+    params: params
+  })
 }
\ No newline at end of file
diff --git a/src/views/reportAnalysis/salesStatistics/index.vue b/src/views/reportAnalysis/salesStatistics/index.vue
index 9f35388..f500213 100644
--- a/src/views/reportAnalysis/salesStatistics/index.vue
+++ b/src/views/reportAnalysis/salesStatistics/index.vue
@@ -6,7 +6,7 @@
     <div class="bi-topbar">
       <img class="bi-topbar-title-bg"
            src="@/assets/BI/biaoti.png"
-           alt="閿�鍞湅鏉跨粺璁�" />
+           alt="閿�鍞粺璁$湅鏉�" />
       <div class="bi-topbar-content">
         <div class="bi-topbar-left">
           <button class="fullscreen-btn"
@@ -35,7 +35,7 @@
           <span>26鈩�</span>
           <span class="bi-topbar-sep">婀垮害锛�1</span> -->
         </div>
-        <div class="bi-topbar-title">閿�鍞湅鏉跨粺璁�</div>
+        <div class="bi-topbar-title">閿�鍞粺璁$湅鏉�</div>
         <div class="bi-topbar-meta">
           <span class="bi-topbar-time">{{ currentTime }}</span>
           <span class="bi-topbar-sep">|</span>
@@ -50,19 +50,19 @@
                      title="閿�閲忓垎鏋愯秼鍔垮浘" />
         <div class="panel-tabs">
           <span class="tab-item"
-                :class="{ active: blockTimeDimension === 'year' }"
-                @click="handleBlockTimeDimensionChange('year')">骞�</span>
+                :class="{ active: chartTimeDimension === '骞�' }"
+                @click="handleChartTimeDimensionChange('骞�')">骞�</span>
           <span class="tab-item"
-                :class="{ active: blockTimeDimension === 'month' }"
-                @click="handleBlockTimeDimensionChange('month')">鏈�</span>
+                :class="{ active: chartTimeDimension === '鏈�' }"
+                @click="handleChartTimeDimensionChange('鏈�')">鏈�</span>
         </div>
         <div class="panel-tabs2">
           <span class="tab-item"
-                :class="{ active: blockProductType === '鐮屽潡' }"
-                @click="handleBlockProductTypeChange('鐮屽潡')">鐮屽潡</span>
+                :class="{ active: chartProductType === '鐮屽潡' }"
+                @click="handleChartProductTypeChange('鐮屽潡')">鐮屽潡</span>
           <span class="tab-item"
-                :class="{ active: blockProductType === '鏉挎潗' }"
-                @click="handleBlockProductTypeChange('鏉挎潗')">鏉挎潗</span>
+                :class="{ active: chartProductType === '鏉挎潗' }"
+                @click="handleChartProductTypeChange('鏉挎潗')">鏉挎潗</span>
         </div>
         <div class="bi-panel-body">
           <div class="chart-unit-row">
@@ -78,19 +78,19 @@
                      title="閿�鍞噾棰濆垎鏋�" />
         <div class="panel-tabs">
           <span class="tab-item"
-                :class="{ active: boardTimeDimension === 'year' }"
-                @click="handleBoardTimeDimensionChange('year')">骞�</span>
+                :class="{ active: chartTimeDimension2 === '骞�' }"
+                @click="handleChartTimeDimensionChange2('骞�')">骞�</span>
           <span class="tab-item"
-                :class="{ active: boardTimeDimension === 'month' }"
-                @click="handleBoardTimeDimensionChange('month')">鏈�</span>
+                :class="{ active: chartTimeDimension2 === '鏈�' }"
+                @click="handleChartTimeDimensionChange2('鏈�')">鏈�</span>
         </div>
         <div class="panel-tabs2">
           <span class="tab-item"
-                :class="{ active: boardProductType === '鐮屽潡' }"
-                @click="handleBoardProductTypeChange('鐮屽潡')">鐮屽潡</span>
+                :class="{ active: chartProductType2 === '鐮屽潡' }"
+                @click="handleChartProductTypeChange2('鐮屽潡')">鐮屽潡</span>
           <span class="tab-item"
-                :class="{ active: boardProductType === '鏉挎潗' }"
-                @click="handleBoardProductTypeChange('鏉挎潗')">鏉挎潗</span>
+                :class="{ active: chartProductType2 === '鏉挎潗' }"
+                @click="handleChartProductTypeChange2('鏉挎潗')">鏉挎潗</span>
         </div>
         <div class="bi-panel-body">
           <div class="chart-unit-row">
@@ -131,27 +131,27 @@
                      title="閿�閲忔暟鎹粺璁�" />
         <div class="panel-tabs">
           <span class="tab-item"
-                :class="{ active: blockTimeDimension === 'year' }"
-                @click="handleBlockTimeDimensionChange('year')">骞�</span>
+                :class="{ active: tableTimeDimension === '骞�' }"
+                @click="handleTableTimeDimensionChange('骞�')">骞�</span>
           <span class="tab-item"
-                :class="{ active: blockTimeDimension === 'month' }"
-                @click="handleBlockTimeDimensionChange('month')">鏈�</span>
+                :class="{ active: tableTimeDimension === '鏈�' }"
+                @click="handleTableTimeDimensionChange('鏈�')">鏈�</span>
         </div>
         <div class="panel-tabs2">
           <span class="tab-item"
-                :class="{ active: blockProductType === '鐮屽潡' }"
-                @click="handleBlockProductTypeChange('鐮屽潡')">鐮屽潡</span>
+                :class="{ active: tableProductType === '鐮屽潡' }"
+                @click="handleTableProductTypeChange('鐮屽潡')">鐮屽潡</span>
           <span class="tab-item"
-                :class="{ active: blockProductType === '鏉挎潗' }"
-                @click="handleBlockProductTypeChange('鏉挎潗')">鏉挎潗</span>
+                :class="{ active: tableProductType === '鏉挎潗' }"
+                @click="handleTableProductTypeChange('鏉挎潗')">鏉挎潗</span>
         </div>
         <div class="bi-panel-body">
           <div class="chart-filter-tabs">
-            <span v-for="area in salesAreas"
+            <span v-for="area in tableSalesAreas"
                   :key="area"
                   class="cf-tab"
-                  :class="{ active: blockSelectedArea === area }"
-                  @click="handleBlockAreaChange(area)">{{ area }}</span>
+                  :class="{ active: tableSelectedArea === area }"
+                  @click="handleTableAreaChange(area)">{{ area }}</span>
           </div>
           <div class="scroll-table-container">
             <table class="scroll-table">
@@ -166,10 +166,10 @@
               </thead>
               <div class="scroll-table-content">
                 <tbody ref="blockTableBody">
-                  <tr :class="item.sort % 2 === 0 ? 'evenTableTr' : 'oddTableTr'"
-                      v-for="(item, index) in blockSalesData"
+                  <tr :class="(index + 1) % 2 === 0 ? 'evenTableTr' : 'oddTableTr'"
+                      v-for="(item, index) in filteredTableSalesData"
                       :key="item.period + item.area + index">
-                    <td>{{ item.sort }}</td>
+                    <td>{{ index + 1 }}</td>
                     <td>{{ item.productType }}</td>
                     <td>{{ item.period }}</td>
                     <td>{{ item.area }}</td>
@@ -181,7 +181,7 @@
           </div>
           <div class="panel-summary-row">
             <div class="summary-label">鍚堣</div>
-            <div class="summary-value">127384 m鲁</div>
+            <div class="summary-value">{{ filteredTableSalesTotal }} m鲁</div>
           </div>
         </div>
       </div>
@@ -211,44 +211,46 @@
                      title="閿�鍞鏁版嵁缁熻" />
         <div class="panel-tabs">
           <span class="tab-item"
-                :class="{ active: boardTimeDimension === 'year' }"
-                @click="handleBoardTimeDimensionChange('year')">骞�</span>
+                :class="{ active: tableTimeDimension2 === '骞�' }"
+                @click="handleTableTimeDimensionChange2('骞�')">骞�</span>
           <span class="tab-item"
-                :class="{ active: boardTimeDimension === 'month' }"
-                @click="handleBoardTimeDimensionChange('month')">鏈�</span>
+                :class="{ active: tableTimeDimension2 === '鏈�' }"
+                @click="handleTableTimeDimensionChange2('鏈�')">鏈�</span>
         </div>
         <div class="panel-tabs2">
           <span class="tab-item"
-                :class="{ active: boardProductType === '鐮屽潡' }"
-                @click="handleBoardProductTypeChange('鐮屽潡')">鐮屽潡</span>
+                :class="{ active: tableProductType2 === '鐮屽潡' }"
+                @click="handleTableProductTypeChange2('鐮屽潡')">鐮屽潡</span>
           <span class="tab-item"
-                :class="{ active: boardProductType === '鏉挎潗' }"
-                @click="handleBoardProductTypeChange('鏉挎潗')">鏉挎潗</span>
+                :class="{ active: tableProductType2 === '鏉挎潗' }"
+                @click="handleTableProductTypeChange2('鏉挎潗')">鏉挎潗</span>
         </div>
         <div class="bi-panel-body">
           <div class="chart-filter-tabs">
-            <span v-for="area in salesAreas"
+            <span v-for="area in tableSalesAreas"
                   :key="area"
                   class="cf-tab"
-                  :class="{ active: boardSelectedArea === area }"
-                  @click="handleBoardAreaChange(area)">{{ area }}</span>
+                  :class="{ active: tableSelectedArea === area }"
+                  @click="handleTableAreaChange2(area)">{{ area }}</span>
           </div>
           <div class="scroll-table-container">
             <table class="scroll-table">
               <thead>
                 <tr>
                   <th>搴忓彿</th>
+                  <th>浜у搧绫诲瀷</th>
                   <th>骞存湀</th>
                   <th>閿�鍞尯</th>
-                  <th>閿�鍞锛堜竾鍏冿級</th>
+                  <th>閿�鍞锛堝厓锛�</th>
                 </tr>
               </thead>
               <div class="scroll-table-content">
                 <tbody ref="boardTableBody">
-                  <tr :class="item.sort % 2 === 0 ? 'evenTableTr' : 'oddTableTr'"
-                      v-for="(item, index) in boardSalesData"
+                  <tr :class="(index + 1) % 2 === 0 ? 'evenTableTr' : 'oddTableTr'"
+                      v-for="(item, index) in filteredAmountSalesData"
                       :key="item.period + item.area + index">
-                    <td>{{ item.sort }}</td>
+                    <td>{{ index + 1 }}</td>
+                    <td>{{ item.productType }}</td>
                     <td>{{ item.period }}</td>
                     <td>{{ item.area }}</td>
                     <td>{{ item.sales }}</td>
@@ -259,7 +261,7 @@
           </div>
           <div class="panel-summary-row">
             <div class="summary-label">鍚堣</div>
-            <div class="summary-value2">127384 涓囧厓</div>
+            <div class="summary-value2">{{ filteredAmountSalesTotal }} 鍏�</div>
           </div>
         </div>
       </div>
@@ -283,6 +285,8 @@
   import {
     getDashboardStatistics,
     getCustomerTrends,
+    getSalesAnalysisTrend,
+    getSalesAmountAnalysis,
   } from "@/api/reportAnalysis/salesStatistics";
 
   const router = useRouter();
@@ -343,10 +347,21 @@
   const boardTableBody = ref(null);
 
   // 閫夋嫨鍣ㄦ暟鎹�
-  const blockTimeDimension = ref("year");
-  const blockSelectedArea = ref("鍏ㄩ儴");
-  const blockProductType = ref("鐮屽潡");
-  const boardTimeDimension = ref("year");
+  // 閿�閲忓垎鏋愯秼鍔垮浘
+  const chartTimeDimension = ref("骞�");
+  const chartTimeDimension2 = ref("骞�");
+
+  const chartSelectedArea = ref("鍏ㄩ儴");
+  const chartProductType = ref("鐮屽潡");
+  const chartProductType2 = ref("鐮屽潡");
+
+  // 閿�閲忔暟鎹粺璁�
+  const tableTimeDimension = ref("骞�");
+  const tableSelectedArea = ref("鍏ㄩ儴");
+  const tableSelectedArea2 = ref("鍏ㄩ儴");
+
+  const tableProductType = ref("鐮屽潡");
+  const boardTimeDimension = ref("骞�");
   const boardSelectedArea = ref("鍏ㄩ儴");
   const boardProductType = ref("鏉挎潗");
   const customerTimeDimension = ref("骞�");
@@ -675,6 +690,14 @@
 
   // 瀹㈡埛瓒嬪娍鏁版嵁
   const customerTrendsData = ref([]);
+  // 閿�閲忓垎鏋愯秼鍔挎暟鎹�
+  const salesAnalysisTrendData = ref([]);
+  // 閿�閲忔暟鎹粺璁¤〃鏍兼暟鎹�
+  const tableSalesData = ref([]);
+  // 閿�閲忔暟鎹粺璁¤〃鏍兼�昏
+  const tableSalesTotal = ref(0);
+  // 鍔ㄦ�侀攢鍞尯鍩熷垪琛�
+  const tableSalesAreas = ref([]);
 
   // 鍙樺寲鐜囪绠楋紙妯℃嫙锛�
   const salesVolumeChange = ref("+5.2");
@@ -717,6 +740,126 @@
     }
   };
 
+  // 鑾峰彇閿�閲忓垎鏋愯秼鍔挎暟鎹�
+  const fetchSalesAnalysisTrendData = async () => {
+    try {
+      const response = await getSalesAnalysisTrend({
+        type: chartProductType.value, // 鐮屽潡鎴栨澘鏉�
+        days: chartTimeDimension.value, // 骞存垨鏈�
+      });
+      if (response && response.data) {
+        // API杩斿洖鐨勬暟鎹粨鏋勫涓嬶細
+        // {
+        //   "dates": ["2026-01-01", "2025-01-01", ...],
+        //   "customerTrends": [{"鍐呰挋鍙�": 470, "閾跺窛": 3600, ...}, ...]
+        // }
+        salesAnalysisTrendData.value = response.data;
+        updateCharts();
+      }
+    } catch (error) {
+      console.error("鑾峰彇閿�閲忓垎鏋愯秼鍔挎暟鎹け璐�:", error);
+    }
+  };
+
+  // 鑾峰彇閿�閲忔暟鎹粺璁¤〃鏍兼暟鎹�
+  const fetchTableSalesData = async () => {
+    try {
+      const response = await getSalesAnalysisTrend({
+        type: tableProductType.value, // 鐮屽潡鎴栨澘鏉�
+        days: tableTimeDimension.value, // 骞存垨鏈�
+      });
+      if (response && response.data) {
+        // API杩斿洖鐨勬暟鎹粨鏋勫涓嬶細
+        // {
+        //   "dates": ["2026-01-01", "2025-01-01", ...],
+        //   "customerTrends": [{"鍐呰挋鍙�": 470, "閾跺窛": 3600, ...}, ...]
+        // }
+        updateTableSalesData(response.data);
+      }
+    } catch (error) {
+      console.error("鑾峰彇閿�閲忔暟鎹粺璁¤〃鏍兼暟鎹け璐�:", error);
+    }
+  };
+
+  // 鏇存柊閿�閲忔暟鎹粺璁¤〃鏍�
+  const updateTableSalesData = data => {
+    if (!data || !data.dates || !data.customerTrends) {
+      return;
+    }
+    console.log(data, "datas");
+    const dates = data.dates;
+    const customerTrends = data.customerTrends;
+    const tableData = [];
+    let total = 0;
+    const areaSet = new Set();
+
+    dates.forEach((date, index) => {
+      const trend = customerTrends[index];
+      if (trend) {
+        // 鎻愬彇鎵�鏈夐攢鍞尯鍩�
+        Object.keys(trend).forEach(area => {
+          if (area !== "鍏ㄩ儴") {
+            areaSet.add(area);
+            const sales = trend[area] || 0;
+            tableData.push({
+              period: date,
+              area: area,
+              productType: tableProductType.value,
+              sales: sales,
+              sort: tableData.length + 1,
+            });
+            total += sales;
+          }
+        });
+      }
+    });
+
+    // 鏇存柊閿�鍞尯鍩熷垪琛紝娣诲姞"鍏ㄩ儴"閫夐」
+    tableSalesAreas.value = ["鍏ㄩ儴", ...Array.from(areaSet)];
+    // 纭繚 tableSelectedArea 鍦ㄩ攢鍞尯鍩熷垪琛ㄤ腑
+    if (
+      tableSalesAreas.value.length > 0 &&
+      !tableSalesAreas.value.includes(tableSelectedArea.value)
+    ) {
+      tableSelectedArea.value = "鍏ㄩ儴";
+    }
+
+    console.log(tableData);
+    tableSalesData.value = tableData;
+    tableSalesTotal.value = total;
+  };
+
+  // 澶勭悊鍥捐〃鏃堕棿缁村害鍙樺寲
+  const handleChartTimeDimensionChange = dimension => {
+    chartTimeDimension.value = dimension;
+    fetchSalesAnalysisTrendData();
+  };
+
+  // 澶勭悊鍥捐〃浜у搧绫诲瀷鍙樺寲
+  const handleChartProductTypeChange = type => {
+    chartProductType.value = type;
+    fetchSalesAnalysisTrendData();
+  };
+
+  // 澶勭悊琛ㄦ牸鏃堕棿缁村害鍙樺寲
+  const handleTableTimeDimensionChange = dimension => {
+    tableTimeDimension.value = dimension;
+    fetchTableSalesData();
+    // 閲嶆柊鍚姩婊氬姩锛屾牴鎹椂闂寸淮搴﹀喅瀹氭槸鍚︽粴鍔�
+    startBlockTableScroll();
+  };
+
+  // 澶勭悊琛ㄦ牸浜у搧绫诲瀷鍙樺寲
+  const handleTableProductTypeChange = type => {
+    tableProductType.value = type;
+    fetchTableSalesData();
+  };
+
+  // 澶勭悊琛ㄦ牸閿�鍞尯鍩熷彉鍖�
+  const handleTableAreaChange = area => {
+    tableSelectedArea.value = area;
+  };
+
   // 琛ㄦ牸鏁版嵁
   const tableData = computed(() => {
     return filteredData.value.map(item => {
@@ -734,17 +877,45 @@
     });
   });
 
+  // 绛涢�夊悗鐨勮〃鏍兼暟鎹�
+  const filteredTableSalesData = computed(() => {
+    if (tableSelectedArea.value === "鍏ㄩ儴") {
+      // 鎸夊勾鏈堝垎缁勬眹鎬绘暟鎹�
+      const groupedData = {};
+      tableSalesData.value.forEach(item => {
+        const key = item.period;
+        if (!groupedData[key]) {
+          groupedData[key] = {
+            period: item.period,
+            area: "鍏ㄩ儴",
+            productType: item.productType,
+            sales: 0,
+            sort: 0,
+          };
+        }
+        groupedData[key].sales += item.sales;
+      });
+      // 杞崲涓烘暟缁勫苟鎸夊勾鏈堟帓搴�
+      return Object.values(groupedData).sort((a, b) => {
+        return new Date(b.period) - new Date(a.period);
+      });
+    } else {
+      return tableSalesData.value.filter(
+        item => item.area === tableSelectedArea.value
+      );
+    }
+  });
+
+  // 绛涢�夊悗鐨勮〃鏍兼暟鎹�昏
+  const filteredTableSalesTotal = computed(() => {
+    return filteredTableSalesData.value.reduce(
+      (total, item) => total + item.sales,
+      0
+    );
+  });
+
   // 閿�閲忚秼鍔垮浘琛ㄩ厤缃�
   const salesVolumeChartOption = computed(() => {
-    // 涓烘瘡涓攢鍞尯鐢熸垚鏁版嵁
-    const salesAreas = [
-      "鍏ㄩ儴",
-      "A閿�鍞尯",
-      "B閿�鍞尯",
-      "C閿�鍞尯",
-      "D閿�鍞尯",
-      "E閿�鍞尯",
-    ];
     const colors = [
       "#00A4ED",
       "#34D8F7",
@@ -752,54 +923,111 @@
       "#8A6BFF",
       "#C8C447",
       "#FF6B6B",
+      "#FF9500",
+      "#4CD964",
+      "#5AC8FA",
     ];
-    const year = 2024;
     const periodType = blockTimeDimension.value;
 
     // 鐢熸垚鏃堕棿娈�
     let periods = [];
-    if (periodType === "year") {
-      // 骞村害鏁版嵁锛�12涓湀
-      for (let month = 1; month <= 12; month++) {
-        periods.push(`${year}-${month.toString().padStart(2, "0")}`);
+    let salesAreas = [];
+    let series = [];
+
+    if (
+      salesAnalysisTrendData.value &&
+      salesAnalysisTrendData.value.dates &&
+      salesAnalysisTrendData.value.customerTrends
+    ) {
+      // 浣跨敤API杩斿洖鐨勬棩鏈�
+      periods = salesAnalysisTrendData.value.dates;
+      // 鎻愬彇閿�鍞尯鍩�
+      const customerTrends = salesAnalysisTrendData.value.customerTrends;
+      if (customerTrends.length > 0) {
+        // 鎻愬彇閿�鍞尯鍩熷苟纭繚"鍏ㄩ儴"鍦ㄧ涓�涓綅缃�
+        const allAreas = Object.keys(customerTrends[0]);
+        salesAreas = allAreas.sort((a, b) => {
+          if (a === "鍏ㄩ儴") return -1;
+          if (b === "鍏ㄩ儴") return 1;
+          return 0;
+        });
+        // 涓烘瘡涓攢鍞尯鐢熸垚鏁版嵁
+        series = salesAreas.map((area, index) => {
+          const data = customerTrends.map(trend => trend[area] || 0);
+          return {
+            name: area,
+            data: data,
+            type: "line",
+            smooth: false,
+            // symbolSize: getResponsiveValue(8),
+            lineStyle: {
+              width: getResponsiveValue(1),
+              color: colors[index % colors.length],
+            },
+            itemStyle: { color: colors[index % colors.length] },
+            areaStyle: {
+              opacity: 0.4,
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: colors[index % colors.length] + "80" },
+                { offset: 1, color: colors[index % colors.length] + "00" },
+              ]),
+            },
+          };
+        });
       }
     } else {
-      // 鏈堝害鏁版嵁锛�30澶�
-      const month = 1;
-      for (let day = 1; day <= 30; day++) {
-        periods.push(
-          `${year}-${month.toString().padStart(2, "0")}-${day
-            .toString()
-            .padStart(2, "0")}`
-        );
+      // 妯℃嫙鏁版嵁
+      salesAreas = [
+        "鍏ㄩ儴",
+        "A閿�鍞尯",
+        "B閿�鍞尯",
+        "C閿�鍞尯",
+        "D閿�鍞尯",
+        "E閿�鍞尯",
+      ];
+      const year = 2024;
+      if (periodType === "year") {
+        // 骞村害鏁版嵁锛�12涓湀
+        for (let month = 1; month <= 12; month++) {
+          periods.push(`${year}-${month.toString().padStart(2, "0")}`);
+        }
+      } else {
+        // 鏈堝害鏁版嵁锛�30澶�
+        const month = 1;
+        for (let day = 1; day <= 30; day++) {
+          periods.push(
+            `${year}-${month.toString().padStart(2, "0")}-${day
+              .toString()
+              .padStart(2, "0")}`
+          );
+        }
       }
-    }
+      // 涓烘瘡涓攢鍞尯鐢熸垚鏁版嵁
+      series = salesAreas.map((area, index) => {
+        const data = periods.map(() => {
+          return periodType === "year"
+            ? Math.floor(Math.random() * 500) + 800
+            : Math.floor(Math.random() * 50) + 20;
+        });
 
-    // 涓烘瘡涓攢鍞尯鐢熸垚鏁版嵁
-    const series = salesAreas.map((area, index) => {
-      const data = periods.map(() => {
-        return periodType === "year"
-          ? Math.floor(Math.random() * 500) + 800
-          : Math.floor(Math.random() * 50) + 20;
+        return {
+          name: area,
+          data: data,
+          type: "line",
+          smooth: false,
+          // symbolSize: getResponsiveValue(8),
+          lineStyle: { width: getResponsiveValue(1), color: colors[index] },
+          itemStyle: { color: colors[index] },
+          areaStyle: {
+            opacity: 0.4,
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+              { offset: 0, color: colors[index] + "80" },
+              { offset: 1, color: colors[index] + "00" },
+            ]),
+          },
+        };
       });
-
-      return {
-        name: area,
-        data: data,
-        type: "line",
-        smooth: false,
-        // symbolSize: getResponsiveValue(8),
-        lineStyle: { width: getResponsiveValue(1), color: colors[index] },
-        itemStyle: { color: colors[index] },
-        areaStyle: {
-          opacity: 0.4,
-          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-            { offset: 0, color: colors[index] + "80" },
-            { offset: 1, color: colors[index] + "00" },
-          ]),
-        },
-      };
-    });
+    }
 
     return {
       backgroundColor: "transparent",
@@ -864,15 +1092,20 @@
 
   // 閿�鍞噾棰濊秼鍔垮浘琛ㄩ厤缃�
   const salesAmountChartOption = computed(() => {
-    // 涓烘瘡涓攢鍞尯鐢熸垚鏁版嵁
-    const salesAreas = [
-      "鍏ㄩ儴",
-      "A閿�鍞尯",
-      "B閿�鍞尯",
-      "C閿�鍞尯",
-      "D閿�鍞尯",
-      "E閿�鍞尯",
-    ];
+    const { dates = [], customerTrends = [] } = salesAmountChartData.value;
+
+    // 鎻愬彇鎵�鏈夐攢鍞尯鍩�
+    const areaSet = new Set();
+    customerTrends.forEach(item => {
+      Object.keys(item).forEach(key => areaSet.add(key));
+    });
+    // 纭繚"鍏ㄩ儴"鍦ㄧ涓�涓綅缃�
+    const salesAreas = Array.from(areaSet).sort((a, b) => {
+      if (a === "鍏ㄩ儴") return -1;
+      if (b === "鍏ㄩ儴") return 1;
+      return 0;
+    });
+
     const colors = [
       "#00A4ED",
       "#34D8F7",
@@ -881,48 +1114,26 @@
       "#C8C447",
       "#FF6B6B",
     ];
-    const year = 2024;
-    const periodType = boardTimeDimension.value;
-
-    // 鐢熸垚鏃堕棿娈�
-    let periods = [];
-    if (periodType === "year") {
-      // 骞村害鏁版嵁锛�12涓湀
-      for (let month = 1; month <= 12; month++) {
-        periods.push(`${year}-${month.toString().padStart(2, "0")}`);
-      }
-    } else {
-      // 鏈堝害鏁版嵁锛�30澶�
-      const month = 1;
-      for (let day = 1; day <= 30; day++) {
-        periods.push(
-          `${year}-${month.toString().padStart(2, "0")}-${day
-            .toString()
-            .padStart(2, "0")}`
-        );
-      }
-    }
 
     // 涓烘瘡涓攢鍞尯鐢熸垚鏁版嵁
     const series = salesAreas.map((area, index) => {
-      const data = periods.map(() => {
-        return periodType === "year"
-          ? Math.floor(Math.random() * 50000) + 80000
-          : Math.floor(Math.random() * 5000) + 2000;
-      });
+      const data = customerTrends.map(item => item[area] || 0);
 
       return {
         name: area,
         data: data,
         type: "bar",
         smooth: true,
-        lineStyle: { width: getResponsiveValue(3), color: colors[index] },
-        itemStyle: { color: colors[index] },
+        lineStyle: {
+          width: getResponsiveValue(3),
+          color: colors[index % colors.length],
+        },
+        itemStyle: { color: colors[index % colors.length] },
         areaStyle: {
           opacity: 0.2,
           color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-            { offset: 0, color: colors[index] + "80" },
-            { offset: 1, color: colors[index] + "00" },
+            { offset: 0, color: colors[index % colors.length] + "80" },
+            { offset: 1, color: colors[index % colors.length] + "00" },
           ]),
         },
       };
@@ -937,7 +1148,7 @@
         borderWidth: getResponsiveValue(1),
         textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) },
         formatter: function (params) {
-          let result = params[0].name + "<br/>";
+          let result = params[0]?.name + "<br/>" || "";
           params.forEach(param => {
             result += `${param.marker}${param.seriesName}: ${param.value} 鍏�<br/>`;
           });
@@ -964,7 +1175,7 @@
       },
       xAxis: {
         type: "category",
-        data: periods,
+        data: dates,
         axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } },
         axisTick: { show: false },
         axisLabel: {
@@ -1164,7 +1375,12 @@
           areaSet.add(key);
         });
       });
-      salesAreas = Array.from(areaSet);
+      // 纭繚"鍏ㄩ儴"鍦ㄧ涓�涓綅缃�
+      salesAreas = Array.from(areaSet).sort((a, b) => {
+        if (a === "鍏ㄩ儴") return -1;
+        if (b === "鍏ㄩ儴") return 1;
+        return 0;
+      });
 
       // 涓烘瘡涓攢鍞尯鍩熺敓鎴愭暟鎹�
       series = salesAreas.map((area, index) => {
@@ -1382,15 +1598,18 @@
   let boardScrollTimer = null;
   let blockCurrentIndex = 0;
   let boardCurrentIndex = 0;
-
   const startBlockTableScroll = () => {
     if (blockScrollTimer) {
       clearInterval(blockScrollTimer);
     }
 
-    const scrollTable = () => {
-      if (!blockTableBody.value || blockSalesData.value.length === 0) return;
+    // 鍙湁褰撴椂闂寸淮搴︿笉鏄�"骞�"鏃舵墠鍚姩婊氬姩
+    if (tableTimeDimension.value === "骞�") {
+      return;
+    }
 
+    const scrollTable = () => {
+      if (!blockTableBody.value) return;
       const rows = blockTableBody.value.querySelectorAll("tr");
       if (rows.length === 0) return;
 
@@ -1403,9 +1622,10 @@
         blockTableBody.value.style.transition = "none";
         blockTableBody.value.style.transform = "translateY(0)";
 
-        const firstItem = blockSalesData.value[0];
-        blockSalesData.value.shift();
-        blockSalesData.value.push(firstItem);
+        // 鐩存帴鎿嶄綔DOM锛屽皢绗竴琛岀Щ鍒版渶鍚�
+        const firstRow = rows[0];
+        blockTableBody.value.removeChild(firstRow);
+        blockTableBody.value.appendChild(firstRow);
       }, 500);
     };
 
@@ -1450,6 +1670,10 @@
       clearInterval(boardScrollTimer);
       boardScrollTimer = null;
     }
+    if (amountScrollTimer.value) {
+      clearInterval(amountScrollTimer.value);
+      amountScrollTimer.value = null;
+    }
   };
 
   // 澶勭悊鏃堕棿缁村害閫夋嫨
@@ -1462,7 +1686,7 @@
     boardTimeDimension.value = dimension;
     generateBoardSalesData();
   };
-
+  const blockProductType = ref("鐮屽潡");
   // 澶勭悊浜у搧绫诲瀷閫夋嫨
   const handleBlockProductTypeChange = type => {
     blockProductType.value = type;
@@ -1473,7 +1697,7 @@
     boardProductType.value = type;
     generateBoardSalesData();
   };
-
+  const blockSelectedArea = ref("鍏ㄩ儴");
   // 澶勭悊閿�鍞尯閫夋嫨
   const handleBlockAreaChange = area => {
     blockSelectedArea.value = area;
@@ -1490,6 +1714,7 @@
     customerTimeDimension.value = dimension;
     fetchCustomerTrendsData();
   };
+  const blockTimeDimension = ref("骞�");
 
   // 鐢熸垚鐮屽潡閿�鍞暟鎹�
   const generateBlockSalesData = () => {
@@ -1622,18 +1847,269 @@
     // 鑾峰彇鏁版嵁
     await fetchDashboardData();
     await fetchCustomerTrendsData();
+    await fetchSalesAnalysisTrendData();
+    await fetchTableSalesData();
+    await fetchSalesAmountChartData();
+    await fetchSalesAmountTableData();
 
     // 绛夊緟DOM鏇存柊鍚庡垵濮嬪寲鍥捐〃
     nextTick(() => {
       initCharts();
       // 鍚姩琛ㄦ牸婊氬姩鍔ㄧ敾
       startBlockTableScroll();
-      startBoardTableScroll();
+      startAmountTableScroll();
     });
 
     // 娣诲姞绐楀彛澶у皬鍙樺寲鐩戝惉
     window.addEventListener("resize", handleResize);
     document.addEventListener("fullscreenchange", handleFullscreenChange);
+  });
+
+  // 鐩戝惉鍥捐〃鏃堕棿缁村害鍜屼骇鍝佺被鍨嬪彉鍖�
+  watch([chartTimeDimension, chartProductType], async () => {
+    await fetchSalesAnalysisTrendData();
+  });
+
+  // 鐩戝惉琛ㄦ牸鏃堕棿缁村害鍜屼骇鍝佺被鍨嬪彉鍖�
+  watch([tableTimeDimension, tableProductType], async () => {
+    await fetchTableSalesData();
+  });
+
+  // 閿�鍞噾棰濆垎鏋愬浘琛ㄦ暟鎹紙鍙充笂锛�
+  const salesAmountChartData = ref({
+    dates: [],
+    customerTrends: [],
+  });
+
+  // 閿�鍞鏁版嵁缁熻琛ㄦ牸鏁版嵁锛堝彸涓嬶級
+  const salesAmountTableData = ref({
+    dates: [],
+    customerTrends: [],
+  });
+
+  // 閿�鍞鏁版嵁缁熻琛ㄦ牸绛涢�夌姸鎬侊紙鍙充笅锛�
+  const tableTimeDimension2 = ref("骞�");
+  const tableProductType2 = ref("鐮屽潡");
+
+  // 閿�鍞鏁版嵁缁熻琛ㄦ牸鏁版嵁
+  const amountSalesData = ref([]);
+  const amountScrollTimer = ref(null);
+
+  // 鑾峰彇閿�鍞噾棰濆垎鏋愬浘琛ㄦ暟鎹紙鍙充笂锛�
+  const fetchSalesAmountChartData = async () => {
+    try {
+      const response = await getSalesAmountAnalysis({
+        type: chartProductType2.value,
+        days: chartTimeDimension2.value,
+      });
+      if (response?.data) {
+        salesAmountChartData.value = response.data;
+        updateCharts();
+      }
+    } catch (error) {
+      console.error("鑾峰彇閿�鍞噾棰濆垎鏋愬浘琛ㄦ暟鎹け璐�:", error);
+      // 浣跨敤妯℃嫙鏁版嵁
+      salesAmountChartData.value = {
+        dates: [
+          "2026-01-01",
+          "2025-01-01",
+          "2024-01-01",
+          "2023-01-01",
+          "2022-01-01",
+        ],
+        customerTrends: [
+          { 鍐呰挋鍙�: 100, 閾跺窛: 200, 鑷彁: 300, 鍏朵粬: 150, 鍏ㄩ儴: 750 },
+          { 鍐呰挋鍙�: 80, 閾跺窛: 180, 鑷彁: 280, 鍏朵粬: 130, 鍏ㄩ儴: 670 },
+          { 鍐呰挋鍙�: 90, 閾跺窛: 190, 鑷彁: 290, 鍏朵粬: 140, 鍏ㄩ儴: 710 },
+          { 鍐呰挋鍙�: 70, 閾跺窛: 170, 鑷彁: 270, 鍏朵粬: 120, 鍏ㄩ儴: 630 },
+          { 鍐呰挋鍙�: 110, 閾跺窛: 210, 鑷彁: 310, 鍏朵粬: 160, 鍏ㄩ儴: 790 },
+        ],
+      };
+    }
+  };
+
+  // 鑾峰彇閿�鍞鏁版嵁缁熻琛ㄦ牸鏁版嵁锛堝彸涓嬶級
+  const fetchSalesAmountTableData = async () => {
+    try {
+      const response = await getSalesAmountAnalysis({
+        type: tableProductType2.value,
+        days: tableTimeDimension2.value,
+      });
+      if (response?.data) {
+        salesAmountTableData.value = response.data;
+        updateAmountSalesData();
+      }
+    } catch (error) {
+      console.error("鑾峰彇閿�鍞鏁版嵁缁熻琛ㄦ牸鏁版嵁澶辫触:", error);
+      // 浣跨敤妯℃嫙鏁版嵁
+      salesAmountTableData.value = {
+        dates: [
+          "2026-01-01",
+          "2025-01-01",
+          "2024-01-01",
+          "2023-01-01",
+          "2022-01-01",
+        ],
+        customerTrends: [
+          { 鍐呰挋鍙�: 100, 閾跺窛: 200, 鑷彁: 300, 鍏朵粬: 150, 鍏ㄩ儴: 750 },
+          { 鍐呰挋鍙�: 80, 閾跺窛: 180, 鑷彁: 280, 鍏朵粬: 130, 鍏ㄩ儴: 670 },
+          { 鍐呰挋鍙�: 90, 閾跺窛: 190, 鑷彁: 290, 鍏朵粬: 140, 鍏ㄩ儴: 710 },
+          { 鍐呰挋鍙�: 70, 閾跺窛: 170, 鑷彁: 270, 鍏朵粬: 120, 鍏ㄩ儴: 630 },
+          { 鍐呰挋鍙�: 110, 閾跺窛: 210, 鑷彁: 310, 鍏朵粬: 160, 鍏ㄩ儴: 790 },
+        ],
+      };
+      updateAmountSalesData();
+    }
+  };
+
+  // 鏇存柊閿�鍞噾棰濆垎鏋愯〃鏍兼暟鎹�
+  const updateAmountSalesData = () => {
+    const data = [];
+    const { dates, customerTrends } = salesAmountTableData.value;
+
+    // 鎻愬彇鎵�鏈夐攢鍞尯鍩�
+    const areaSet = new Set();
+    customerTrends.forEach(item => {
+      Object.keys(item).forEach(key => areaSet.add(key));
+    });
+
+    // 鏇存柊閿�鍞尯鍩熷垪琛紝纭繚"鍏ㄩ儴"鍦ㄧ涓�浣�
+    tableSalesAreas.value = [
+      "鍏ㄩ儴",
+      ...Array.from(areaSet).filter(area => area !== "鍏ㄩ儴"),
+    ];
+
+    // 纭繚閫変腑鐨勫尯鍩熷湪鍒楄〃涓�
+    if (!tableSalesAreas.value.includes(tableSelectedArea.value)) {
+      tableSelectedArea.value = "鍏ㄩ儴";
+    }
+
+    // 鐢熸垚琛ㄦ牸鏁版嵁
+    dates.forEach((date, index) => {
+      const trends = customerTrends[index] || {};
+      Object.keys(trends).forEach(area => {
+        data.push({
+          period: date,
+          area: area,
+          productType: tableProductType2.value,
+          sales: trends[area],
+          sort: data.length + 1,
+        });
+      });
+    });
+
+    amountSalesData.value = data;
+  };
+
+  // 绛涢�夊悗鐨勯攢鍞噾棰濆垎鏋愯〃鏍兼暟鎹�
+  const filteredAmountSalesData = computed(() => {
+    if (tableSelectedArea.value === "鍏ㄩ儴") {
+      // 鎸夊勾鏈堝垎缁勬眹鎬绘暟鎹�
+      const groupedData = {};
+      amountSalesData.value.forEach(item => {
+        const key = item.period;
+        if (!groupedData[key]) {
+          groupedData[key] = {
+            period: item.period,
+            area: "鍏ㄩ儴",
+            productType: tableProductType2.value,
+            sales: 0,
+          };
+        }
+        groupedData[key].sales += item.sales;
+      });
+      // 杞崲涓烘暟缁勫苟鎸夊勾鏈堟帓搴�
+      return Object.values(groupedData).sort((a, b) => {
+        return new Date(b.period) - new Date(a.period);
+      });
+    } else {
+      return amountSalesData.value.filter(
+        item => item.area === tableSelectedArea.value
+      );
+    }
+  });
+
+  // 閿�鍞噾棰濆垎鏋愯〃鏍兼�昏
+  const filteredAmountSalesTotal = computed(() => {
+    return filteredAmountSalesData.value.reduce(
+      (total, item) => total + item.sales,
+      0
+    );
+  });
+
+  // 澶勭悊閿�鍞噾棰濆垎鏋愬浘琛ㄦ椂闂寸淮搴﹀彉鍖栵紙鍙充笂锛�
+  const handleChartTimeDimensionChange2 = dimension => {
+    chartTimeDimension2.value = dimension;
+    fetchSalesAmountChartData();
+  };
+
+  // 澶勭悊閿�鍞噾棰濆垎鏋愬浘琛ㄤ骇鍝佺被鍨嬪彉鍖栵紙鍙充笂锛�
+  const handleChartProductTypeChange2 = type => {
+    chartProductType2.value = type;
+    fetchSalesAmountChartData();
+  };
+
+  // 澶勭悊閿�鍞鏁版嵁缁熻琛ㄦ牸鏃堕棿缁村害鍙樺寲锛堝彸涓嬶級
+  const handleTableTimeDimensionChange2 = dimension => {
+    tableTimeDimension2.value = dimension;
+    fetchSalesAmountTableData();
+    // 閲嶆柊鍚姩婊氬姩锛屾牴鎹椂闂寸淮搴﹀喅瀹氭槸鍚︽粴鍔�
+    startAmountTableScroll();
+  };
+
+  // 澶勭悊閿�鍞鏁版嵁缁熻琛ㄦ牸浜у搧绫诲瀷鍙樺寲锛堝彸涓嬶級
+  const handleTableProductTypeChange2 = type => {
+    tableProductType2.value = type;
+    fetchSalesAmountTableData();
+  };
+
+  // 澶勭悊閿�鍞鏁版嵁缁熻琛ㄦ牸閿�鍞尯鍙樺寲锛堝彸涓嬶級
+  const handleTableAreaChange2 = area => {
+    tableSelectedArea.value = area;
+  };
+
+  // 鍚姩閿�鍞噾棰濆垎鏋愯〃鏍兼粴鍔�
+  const startAmountTableScroll = () => {
+    if (amountScrollTimer.value) {
+      clearInterval(amountScrollTimer.value);
+    }
+    // 鍙湁褰撴椂闂寸淮搴︿笉鏄�"骞�"鏃舵墠鍚姩婊氬姩
+    if (tableTimeDimension2.value === "骞�") {
+      return;
+    }
+
+    const scrollTable = () => {
+      if (!boardTableBody.value) return;
+      const rows = boardTableBody.value.querySelectorAll("tr");
+      if (rows.length === 0) return;
+
+      const rowHeight = rows[0].offsetHeight;
+
+      boardTableBody.value.style.transition = "transform 0.5s ease-in-out";
+      boardTableBody.value.style.transform = `translateY(-${rowHeight}px)`;
+
+      setTimeout(() => {
+        boardTableBody.value.style.transition = "none";
+        boardTableBody.value.style.transform = "translateY(0)";
+
+        // 鐩存帴鎿嶄綔DOM锛屽皢绗竴琛岀Щ鍒版渶鍚�
+        const firstRow = rows[0];
+        boardTableBody.value.removeChild(firstRow);
+        boardTableBody.value.appendChild(firstRow);
+      }, 500);
+    };
+
+    amountScrollTimer.value = setInterval(scrollTable, 2000);
+  };
+
+  // 鐩戝惉閿�鍞噾棰濆垎鏋愬浘琛ㄦ椂闂寸淮搴﹀拰浜у搧绫诲瀷鍙樺寲锛堝彸涓婏級
+  watch([chartTimeDimension2, chartProductType2], async () => {
+    // await fetchSalesAmountChartData();
+  });
+
+  // 鐩戝惉閿�鍞鏁版嵁缁熻琛ㄦ牸鏃堕棿缁村害鍜屼骇鍝佺被鍨嬪彉鍖栵紙鍙充笅锛�
+  watch([tableTimeDimension2, tableProductType2], async () => {
+    // await fetchSalesAmountTableData();
   });
 
   // 鑾峰彇浜у搧绫诲瀷鏍囩绫诲瀷
@@ -1958,12 +2434,12 @@
   }
 
   /* .scroll-table tbody tr:nth-child(odd) {
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                background-color: rgba(64, 158, 255, 0.05);
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                }
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  background-color: rgba(64, 158, 255, 0.05);
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  }
 
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              .scroll-table tbody tr:nth-child(even) {
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  background-color: rgba(64, 158, 255, 0.1);
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    } */
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                .scroll-table tbody tr:nth-child(even) {
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    background-color: rgba(64, 158, 255, 0.1);
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      } */
   .oddTableTr {
     background-color: rgba(64, 158, 255, 0.05);
   }
@@ -2062,7 +2538,7 @@
     font-size: 1.4vh;
     font-weight: 800;
     color: #00a4ed;
-    margin-right: 5.8vh;
+    margin-right: 1.8vh;
     text-shadow: 0 0 1vh rgba(0, 164, 237, 0.5);
   }
   .diamond {

--
Gitblit v1.9.3