From af4404160a9e8d14c09f1e6acab2ba00cb7fc91b Mon Sep 17 00:00:00 2001
From: xiazhengtongxue <133085197+xiazhengtongxue@users.noreply.github.com>
Date: 星期日, 19 四月 2026 16:32:04 +0800
Subject: [PATCH] fix(WMS): 修复首页、3D、websocket

---
 Code/WMS/WIDESEA_WMSClient/src/views/Home.vue |  409 +++++++++++++++++++++++++++------------------------------
 1 files changed, 193 insertions(+), 216 deletions(-)

diff --git a/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue b/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
index a14728a..ea951db 100644
--- a/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
+++ b/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
@@ -3,44 +3,21 @@
     <!-- 椤堕儴锛氭湰鏈堝嚭鍏ュ簱瓒嬪娍 (鍏ㄥ) -->
     <div class="chart-row full-width">
       <div class="chart-card">
-        <div class="card-title">鏈湀鍑哄叆搴撹秼鍔�</div>
+        <div class="card-title">姣忔湀鍑哄叆搴撹秼鍔�</div>
         <div id="chart-monthly-trend" class="chart-content"></div>
       </div>
     </div>
 
-    <!-- 绗簩琛岋細浠婃棩/鏈懆鍑哄叆搴撳姣� -->
-    <div class="chart-row">
+    <!-- 绗簩琛岋細姣忔棩鍑哄叆搴撹秼鍔� (鍏ㄥ) -->
+    <div class="chart-row full-width">
       <div class="chart-card">
-        <div class="card-title">浠婃棩鍑哄叆搴撳姣�</div>
-        <div id="chart-today" class="chart-content"></div>
-      </div>
-      <div class="chart-card">
-        <div class="card-title">鏈懆鍑哄叆搴撳姣�</div>
-        <div id="chart-week" class="chart-content"></div>
+        <div class="card-title">姣忔棩鍑哄叆搴撹秼鍔�</div>
+        <div id="chart-daily" class="chart-content"></div>
       </div>
     </div>
 
-    <!-- 绗笁琛岋細鏈湀瀵规瘮/搴撳瓨鎬婚噺 -->
+    <!-- 绗洓琛岋細浠撳簱鍒嗗竷 -->
     <div class="chart-row">
-      <div class="chart-card">
-        <div class="card-title">鏈湀鍑哄叆搴撳姣�</div>
-        <div id="chart-month" class="chart-content"></div>
-      </div>
-      <div class="chart-card">
-        <div class="card-title">褰撳墠搴撳瓨鎬婚噺</div>
-        <div class="stock-total">
-          <div class="total-number">{{ overviewData.TotalStock || 0 }}</div>
-          <div class="total-label">鎵樼洏</div>
-        </div>
-      </div>
-    </div>
-
-    <!-- 绗洓琛岋細搴撻緞鍒嗗竷/浠撳簱鍒嗗竷 -->
-    <div class="chart-row">
-      <div class="chart-card">
-        <div class="card-title">搴撳瓨搴撻緞鍒嗗竷</div>
-        <div id="chart-stock-age" class="chart-content"></div>
-      </div>
       <div class="chart-card">
         <div class="card-title">鍚勪粨搴撳簱瀛樺垎甯�</div>
         <div id="chart-warehouse" class="chart-content"></div>
@@ -57,16 +34,8 @@
   data() {
     return {
       charts: {},
-      overviewData: {
-        TodayInbound: 0,
-        TodayOutbound: 0,
-        MonthInbound: 0,
-        MonthOutbound: 0,
-        TotalStock: 0
-      },
-      weeklyData: [],
+      dailyData: [],
       monthlyData: [],
-      stockAgeData: [],
       warehouseData: []
     };
   },
@@ -86,53 +55,22 @@
 
     initCharts() {
       this.charts.monthlyTrend = echarts.init(document.getElementById("chart-monthly-trend"));
-      this.charts.today = echarts.init(document.getElementById("chart-today"));
-      this.charts.week = echarts.init(document.getElementById("chart-week"));
-      this.charts.month = echarts.init(document.getElementById("chart-month"));
-      this.charts.stockAge = echarts.init(document.getElementById("chart-stock-age"));
+      this.charts.daily = echarts.init(document.getElementById("chart-daily"));
       this.charts.warehouse = echarts.init(document.getElementById("chart-warehouse"));
     },
 
     async loadData() {
-      await this.loadOverview();
-      await this.loadWeeklyStats();
       await this.loadMonthlyStats();
-      await this.loadStockAgeDistribution();
+      await this.loadDailyStats();
       await this.loadStockByWarehouse();
-    },
-
-    async loadOverview() {
-      try {
-        const res = await this.http.get("/api/Dashboard/Overview");
-        console.log("鎬昏鏁版嵁", res.Data);
-        if (res.Status && res.Data) {
-          this.overviewData = res.Data;
-          this.updateTodayChart();
-          this.updateWeekChart();
-          this.updateMonthChart();
-        }
-      } catch (e) {
-        console.error("鍔犺浇鎬昏鏁版嵁澶辫触", e);
-      }
-    },
-
-    async loadWeeklyStats() {
-      try {
-        const res = await this.http.get("/api/Dashboard/WeeklyStats", { weeks: 12 });
-        if (res.Status && res.Data) {
-          this.weeklyData = res.Data;
-          this.updateWeekChart();
-        }
-      } catch (e) {
-        console.error("鍔犺浇姣忓懆缁熻澶辫触", e);
-      }
     },
 
     async loadMonthlyStats() {
       try {
         const res = await this.http.get("/api/Dashboard/MonthlyStats", { months: 12 });
-        if (res.Status && res.Data) {
-          this.monthlyData = res.Data;
+        if (res.status && res.data) {
+          console.log("姣忔湀缁熻鏁版嵁:", res.data);
+          this.monthlyData = res.data;
           this.updateMonthlyTrendChart();
         }
       } catch (e) {
@@ -140,110 +78,30 @@
       }
     },
 
-    async loadStockAgeDistribution() {
+    async loadDailyStats() {
       try {
-        const res = await this.http.get("/api/Dashboard/StockAgeDistribution");
-        if (res.Status && res.Data) {
-          this.stockAgeData = res.Data;
-          this.updateStockAgeChart();
+        const res = await this.http.get("/api/Dashboard/DailyStats", { days: 30 });
+        if (res.status && res.data) {
+          console.log("姣忔棩缁熻鏁版嵁:", res.data);
+          this.dailyData = res.data;
+          this.updateDailyChart();
         }
       } catch (e) {
-        console.error("鍔犺浇搴撻緞鍒嗗竷澶辫触", e);
+        console.error("鍔犺浇姣忔棩缁熻澶辫触", e);
       }
     },
 
     async loadStockByWarehouse() {
       try {
         const res = await this.http.get("/api/Dashboard/StockByWarehouse");
-        if (res.Status && res.Data) {
-          this.warehouseData = res.Data;
+        if (res.status && res.data) {
+          console.log("浠撳簱鍒嗗竷鏁版嵁:", res.data);
+          this.warehouseData = res.data.data || res.data;
           this.updateWarehouseChart();
         }
       } catch (e) {
         console.error("鍔犺浇浠撳簱鍒嗗竷澶辫触", e);
       }
-    },
-
-    updateTodayChart() {
-      const option = {
-        tooltip: { trigger: "axis" },
-        legend: { data: ["鍏ュ簱", "鍑哄簱"], textStyle: { color: "#fff" } },
-        xAxis: {
-          type: "category",
-          data: ["浠婃棩"],
-          axisLabel: { color: "#fff" }
-        },
-        yAxis: {
-          type: "value",
-          axisLabel: { color: "#fff" }
-        },
-        series: [
-          { name: "鍏ュ簱", type: "bar", data: [this.overviewData.TodayInbound], itemStyle: { color: "#5470c6" } },
-          { name: "鍑哄簱", type: "bar", data: [this.overviewData.TodayOutbound], itemStyle: { color: "#91cc75" } }
-        ]
-      };
-      this.charts.today.setOption(option, true);
-    },
-
-    updateWeekChart() {
-      const thisWeek = this.getThisWeekData(this.weeklyData);
-      const option = {
-        tooltip: { trigger: "axis" },
-        legend: { data: ["鍏ュ簱", "鍑哄簱"], textStyle: { color: "#fff" } },
-        xAxis: {
-          type: "category",
-          data: ["鏈懆"],
-          axisLabel: { color: "#fff" }
-        },
-        yAxis: {
-          type: "value",
-          axisLabel: { color: "#fff" }
-        },
-        series: [
-          { name: "鍏ュ簱", type: "bar", data: [thisWeek.Inbound], itemStyle: { color: "#5470c6" } },
-          { name: "鍑哄簱", type: "bar", data: [thisWeek.Outbound], itemStyle: { color: "#91cc75" } }
-        ]
-      };
-      this.charts.week.setOption(option, true);
-    },
-
-    getThisWeekData(weeklyData) {
-      if (!weeklyData || weeklyData.length === 0) return { Inbound: 0, Outbound: 0 };
-      const thisWeekKey = this.getCurrentWeekKey();
-      const thisWeek = weeklyData.find(w => w.Week === thisWeekKey);
-      return thisWeek || { Inbound: 0, Outbound: 0 };
-    },
-
-    getCurrentWeekKey() {
-      const now = new Date();
-      const diff = (7 + (now.getDay() - 1)) % 7;
-      const monday = new Date(now);
-      monday.setDate(now.getDate() - diff);
-      const year = monday.getFullYear();
-      const jan1 = new Date(year, 0, 1);
-      const weekNum = Math.ceil(((monday - jan1) / 86400000 + jan1.getDay() + 1) / 7);
-      return `${year}-W${String(weekNum).padStart(2, "0")}`;
-    },
-
-    updateMonthChart() {
-      const option = {
-        tooltip: { trigger: "axis" },
-        legend: { data: ["鍏ュ簱", "鍑哄簱"], textStyle: { color: "#fff" } },
-        xAxis: {
-          type: "category",
-          data: ["鏈湀"],
-          axisLabel: { color: "#fff" }
-        },
-        yAxis: {
-          type: "value",
-          axisLabel: { color: "#fff" }
-        },
-        series: [
-          { name: "鍏ュ簱", type: "bar", data: [this.overviewData.MonthInbound], itemStyle: { color: "#5470c6" } },
-          { name: "鍑哄簱", type: "bar", data: [this.overviewData.MonthOutbound], itemStyle: { color: "#91cc75" } }
-        ]
-      };
-      this.charts.month.setOption(option, true);
     },
 
     updateMonthlyTrendChart() {
@@ -252,7 +110,7 @@
         legend: { data: ["鍏ュ簱", "鍑哄簱"], textStyle: { color: "#fff" } },
         xAxis: {
           type: "category",
-          data: this.monthlyData.map(m => m.Month),
+          data: this.monthlyData.map(m => m.month),
           axisLabel: { color: "#fff", rotate: 45 }
         },
         yAxis: [
@@ -263,56 +121,144 @@
           }
         ],
         series: [
-          { name: "鍏ュ簱", type: "bar", data: this.monthlyData.map(m => m.Inbound), itemStyle: { color: "#5470c6" } },
-          { name: "鍑哄簱", type: "line", data: this.monthlyData.map(m => m.Outbound), itemStyle: { color: "#91cc75" } }
+          { name: "鍏ュ簱", type: "bar", data: this.monthlyData.map(m => m.inbound), itemStyle: { color: "#5470c6" } },
+          { name: "鍑哄簱", type: "line", data: this.monthlyData.map(m => m.outbound), itemStyle: { color: "#91cc75" } }
         ]
       };
       this.charts.monthlyTrend.setOption(option, true);
     },
 
-    updateStockAgeChart() {
+    updateDailyChart() {
       const option = {
         tooltip: { trigger: "axis" },
+        legend: { data: ["鍏ュ簱", "鍑哄簱"], textStyle: { color: "#fff" } },
         xAxis: {
           type: "category",
-          data: this.stockAgeData.map(s => s.Range),
-          axisLabel: { color: "#fff" }
+          data: this.dailyData.map(d => d.date),
+          axisLabel: { 
+            color: "#fff", 
+            interval: 0,
+            rotate: 45,
+            fontSize: 12,
+            margin: 10
+          },
+          axisTick: {
+            alignWithLabel: true
+          }
         },
         yAxis: {
           type: "value",
           axisLabel: { color: "#fff" }
         },
+        grid: {
+          left: '3%',
+          right: '4%',
+          bottom: '15%',
+          top: '10%',
+          containLabel: true
+        },
         series: [
-          {
-            type: "bar",
-            data: this.stockAgeData.map(s => s.Count),
-            itemStyle: { color: "#5470c6" }
-          }
+          { name: "鍏ュ簱", type: "bar", data: this.dailyData.map(d => d.inbound), itemStyle: { color: "#5470c6" } },
+          { name: "鍑哄簱", type: "bar", data: this.dailyData.map(d => d.outbound), itemStyle: { color: "#91cc75" } }
         ]
       };
-      this.charts.stockAge.setOption(option, true);
+      this.charts.daily.setOption(option, true);
     },
 
     updateWarehouseChart() {
+      const warehouseNames = this.warehouseData.map(w => w.warehouse);
+      const totalStocks = this.warehouseData.map(w => w.total);
+      const hasStocks = this.warehouseData.map(w => w.hasStock);
+      const noStocks = this.warehouseData.map(w => w.noStock);
+      const hasStockPercentages = this.warehouseData.map(w => w.hasStockPercentage);
+      const noStockPercentages = this.warehouseData.map(w => w.noStockPercentage);
+      
       const option = {
-        tooltip: { trigger: "axis" },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'shadow'
+          },
+          formatter: function(params) {
+            let tip = params[0].name + '<br/>';
+            params.forEach(param => {
+              const dataIndex = param.dataIndex;
+              const warehouse = window.homeComponent.warehouseData[dataIndex];
+              
+              if (param.seriesName === '宸茬敤瀹归噺') {
+                tip += `${param.marker}${param.seriesName}: ${param.value} (${warehouse.hasStockPercentage})<br/>`;
+                tip += `鏈夊簱瀛�: ${warehouse.hasStock}<br/>`;
+                tip += `鏃犲簱瀛�: ${warehouse.noStock}<br/>`;
+                tip += `鎬诲閲�: ${warehouse.total}`;
+              } else if (param.seriesName === '鍓╀綑瀹归噺') {
+                tip += `${param.marker}${param.seriesName}: ${param.value} (${warehouse.noStockPercentage})<br/>`;
+                tip += `鏈夊簱瀛�: ${warehouse.hasStock}<br/>`;
+                tip += `鏃犲簱瀛�: ${warehouse.noStock}<br/>`;
+                tip += `鎬诲閲�: ${warehouse.total}`;
+              }
+            });
+            return tip;
+          }
+        },
+        legend: {
+          data: ['宸茬敤瀹归噺', '鍓╀綑瀹归噺'],
+          textStyle: { color: '#fff' }
+        },
         xAxis: {
-          type: "category",
-          data: this.warehouseData.map(w => w.Warehouse),
-          axisLabel: { color: "#fff", rotate: 30 }
+          type: 'category',
+          data: warehouseNames,
+          axisLabel: { color: '#fff', rotate: 30 }
         },
         yAxis: {
-          type: "value",
-          axisLabel: { color: "#fff" }
+          type: 'value',
+          axisLabel: { color: '#fff' }
         },
         series: [
           {
-            type: "bar",
-            data: this.warehouseData.map(w => w.Count),
-            itemStyle: { color: "#5470c6" }
+            name: '宸茬敤瀹归噺',
+            type: 'bar',
+            data: hasStocks.map((value, index) => ({
+              value: value,
+              label: {
+                show: true,
+                position: 'top',
+                formatter: '{c} {a|' + hasStockPercentages[index] + '}',
+                rich: {
+                  a: {
+                    lineHeight: 20,
+                    borderColor: '#91cc75',
+                    color: '#91cc75'
+                  }
+                }
+              }
+            })),
+            itemStyle: { color: '#91cc75' }
+          },
+          {
+            name: '鍓╀綑瀹归噺',
+            type: 'bar',
+            data: noStocks.map((value, index) => ({
+              value: value,
+              label: {
+                show: true,
+                position: 'top',
+                formatter: '{c} {a|' + noStockPercentages[index] + '}',
+                rich: {
+                  a: {
+                    lineHeight: 20,
+                    borderColor: '#fac858',
+                    color: '#fac858'
+                  }
+                }
+              }
+            })),
+            itemStyle: { color: '#fac858' }
           }
         ]
       };
+      
+      window.homeComponent = this;
+      
       this.charts.warehouse.setOption(option, true);
     }
   }
@@ -322,8 +268,10 @@
 <style scoped>
 .dashboard-container {
   padding: 20px;
-  background-color: #0e1a2b;
+  color: #e0e0e0;
   min-height: calc(100vh - 60px);
+  background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
+  background-attachment: fixed;
 }
 
 .chart-row {
@@ -338,11 +286,25 @@
 
 .chart-card {
   flex: 1;
-  background: rgba(255, 255, 255, 0.05);
-  border: 1px solid rgba(25, 186, 139, 0.17);
-  border-radius: 4px;
+  background: rgba(10, 16, 35, 0.6);
+  backdrop-filter: blur(10px);
+  border: 1px solid rgba(64, 224, 208, 0.3);
+  border-radius: 12px;
   padding: 15px;
   position: relative;
+  box-shadow: 
+    0 0 15px rgba(0, 255, 255, 0.1),
+    inset 0 0 10px rgba(64, 224, 208, 0.1);
+  transition: all 0.3s ease;
+  overflow: hidden;
+}
+
+.chart-card:hover {
+  transform: translateY(-5px);
+  box-shadow: 
+    0 0 25px rgba(0, 255, 255, 0.3),
+    inset 0 0 15px rgba(64, 224, 208, 0.2);
+  border: 1px solid rgba(64, 224, 208, 0.6);
 }
 
 .chart-card::before {
@@ -352,8 +314,9 @@
   left: 0;
   width: 10px;
   height: 10px;
-  border-top: 2px solid #02a6b5;
-  border-left: 2px solid #02a6b5;
+  border-top: 2px solid #00ffff;
+  border-left: 2px solid #00ffff;
+  box-shadow: -2px -2px 10px #00ffff, 0 0 10px rgba(0, 255, 255, 0.7);
 }
 
 .chart-card::after {
@@ -363,41 +326,39 @@
   right: 0;
   width: 10px;
   height: 10px;
-  border-top: 2px solid #02a6b5;
-  border-right: 2px solid #02a6b5;
+  border-top: 2px solid #00ffff;
+  border-right: 2px solid #00ffff;
+  box-shadow: 2px -2px 10px #00ffff, 0 0 10px rgba(0, 255, 255, 0.7);
+}
+
+.chart-card::before,
+.chart-card::after {
+  animation: neon-flicker 2s infinite alternate;
+}
+
+@keyframes neon-flicker {
+  0%, 100% {
+    opacity: 1;
+    box-shadow: -2px -2px 10px #00ffff, 0 0 10px rgba(0, 255, 255, 0.7);
+  }
+  50% {
+    opacity: 0.8;
+    box-shadow: -2px -2px 5px #00ffff, 0 0 5px rgba(0, 255, 255, 0.5);
+  }
 }
 
 .card-title {
-  color: #fff;
+  color: #00ffff;
   font-size: 16px;
   text-align: center;
   margin-bottom: 10px;
+  text-shadow: 0 0 10px rgba(0, 255, 255, 0.7);
+  font-weight: 500;
 }
 
 .chart-content {
   height: 280px;
   width: 100%;
-}
-
-.stock-total {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  height: 280px;
-}
-
-.total-number {
-  font-size: 64px;
-  font-weight: bold;
-  color: #67caca;
-  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, PingFang SC, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif;
-}
-
-.total-label {
-  font-size: 18px;
-  color: #fcf0d8;
-  margin-top: 10px;
 }
 
 /* 鍏ㄥ鍥捐〃 */
@@ -409,4 +370,20 @@
 .full-width .chart-content {
   height: 350px;
 }
-</style>
+
+/* 娣诲姞缃戞牸绾挎晥鏋� */
+.dashboard-container::before {
+  content: "";
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-image: 
+    linear-gradient(rgba(64, 224, 208, 0.05) 1px, transparent 1px),
+    linear-gradient(90deg, rgba(64, 224, 208, 0.05) 1px, transparent 1px);
+  background-size: 30px 30px;
+  pointer-events: none;
+  z-index: -1;
+}
+</style>
\ No newline at end of file

--
Gitblit v1.9.3