From 71be45c250688b0e76a59f93cd80e85ba37e3de7 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期五, 01 五月 2026 23:19:44 +0800
Subject: [PATCH] Merge branch 'dev'

---
 Code/WMS/WIDESEA_WMSClient/src/views/Home.vue                                             |  850 ++++++++++++++++++++-----
 Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js                                         |   11 
 Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotTask.vue                               |    3 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask.cs               |   14 
 Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json                             |    2 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs     |  304 ++++----
 Code/WMS/WIDESEA_WMSClient/src/extension/stock/hcstockInfo.jsx                            |  163 ++++
 Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs |  108 ++
 Code/WMS/WIDESEA_WMSClient/src/views/stock/hcstockInfo.vue                                |  505 +++++++++++++++
 Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue                                  |    7 
 10 files changed, 1,608 insertions(+), 359 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotTask.vue b/Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotTask.vue
index 8b6fec7..ca13d9c 100644
--- a/Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotTask.vue
+++ b/Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotTask.vue
@@ -42,6 +42,9 @@
       robotSourceAddressPalletCode: "",
       robotTargetAddressPalletCode: "",
       robotGrade: 2,
+      robotExceptionMessage: "",
+      robotDispatchertime: "",
+      robotRemark: "",
     });
 
     // 缂栬緫琛ㄥ崟閰嶇疆
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask.cs
index c5155db..7fcc68b 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask.cs
@@ -66,31 +66,31 @@
         /// <summary>
         /// 鏈哄櫒浜烘潵婧愬湴鍧�杈撻�佺嚎缂栧彿
         /// </summary>
-        [SugarColumn(Length = 20, ColumnDescription = "鏈哄櫒浜烘潵婧愬湴鍧�杈撻�佺嚎缂栧彿")]
+        [SugarColumn(Length = 20, ColumnDescription = "鏈哄櫒浜烘潵婧愬湴鍧�杈撻�佺嚎缂栧彿", IsNullable = true)]
         public string RobotSourceAddressLineCode { get; set; }
 
         /// <summary>
         /// 鏈哄櫒浜虹洰鏍囧湴鍧�杈撻�佺嚎缂栧彿
         /// </summary>
-        [SugarColumn(Length = 20, ColumnDescription = "鏈哄櫒浜虹洰鏍囧湴鍧�杈撻�佺嚎缂栧彿")]
+        [SugarColumn(Length = 20, ColumnDescription = "鏈哄櫒浜虹洰鏍囧湴鍧�杈撻�佺嚎缂栧彿", IsNullable = true)]
         public string RobotTargetAddressLineCode { get; set; }
 
         /// <summary>
         /// 鏈哄櫒浜烘潵婧愬湴鍧�杈撻�佺嚎鎵樼洏鍙�
         /// </summary>
-        [SugarColumn(Length = 20, ColumnDescription = "鏈哄櫒浜烘潵婧愬湴鍧�杈撻�佺嚎鎵樼洏鍙�")]
+        [SugarColumn(Length = 20, ColumnDescription = "鏈哄櫒浜烘潵婧愬湴鍧�杈撻�佺嚎鎵樼洏鍙�", IsNullable = true)]
         public string RobotSourceAddressPalletCode { get; set; }
 
         /// <summary>
         /// 鏈哄櫒浜虹洰鏍囧湴鍧�绾挎墭鐩樺彿
         /// </summary>
-        [SugarColumn(Length = 20, ColumnDescription = "鏈哄櫒浜虹洰鏍囧湴鍧�绾挎墭鐩樺彿")]
+        [SugarColumn(Length = 20, ColumnDescription = "鏈哄櫒浜虹洰鏍囧湴鍧�绾挎墭鐩樺彿", IsNullable = true)]
         public string RobotTargetAddressPalletCode { get; set; }
 
         /// <summary>
         /// 鏈哄櫒浜哄紓甯镐俊鎭�
         /// </summary>
-        [SugarColumn(ColumnDescription = "鏈哄櫒浜哄紓甯镐俊鎭�")]
+        [SugarColumn(ColumnDescription = "鏈哄櫒浜哄紓甯镐俊鎭�", IsNullable = true)]
         public string RobotExceptionMessage { get; set; }
 
         /// <summary>
@@ -102,13 +102,13 @@
         /// <summary>
         /// 鏈哄櫒浜鸿皟搴︽椂闂�
         /// </summary>
-        [SugarColumn(ColumnDescription = "鏈哄櫒浜鸿皟搴︽椂闂�")]
+        [SugarColumn(ColumnDescription = "鏈哄櫒浜鸿皟搴︽椂闂�", IsNullable = true)]
         public DateTime? RobotDispatchertime { get; set; }
 
         /// <summary>
         /// 鏈哄櫒浜哄娉�
         /// </summary>
-        [SugarColumn(Length = 50, ColumnDescription = "鏈哄櫒浜哄娉�")]
+        [SugarColumn(Length = 50, ColumnDescription = "鏈哄櫒浜哄娉�", IsNullable = true)]
         public string RobotRemark { get; set; }
     }
 }
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs
index cb689b9..5a3c6f4 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs
@@ -1,153 +1,153 @@
-锘縰sing Serilog;
-using System.Diagnostics.CodeAnalysis;
-using WIDESEA_Core;
-using WIDESEAWCS_Common.HttpEnum;
-using WIDESEAWCS_Common.TaskEnum;
-using WIDESEAWCS_Core;
-using WIDESEAWCS_Core.Enums;
-using WIDESEAWCS_Core.Helper;
-using WIDESEAWCS_DTO;
-using WIDESEAWCS_DTO.TaskInfo;
-using WIDESEAWCS_ITaskInfoRepository;
-using WIDESEAWCS_ITaskInfoService;
-using WIDESEAWCS_Model.Models;
-using WIDESEAWCS_QuartzJob.Models;
-using WIDESEAWCS_QuartzJob.Service;
-using WIDESEAWCS_Tasks;
-
-namespace WIDESEAWCS_TaskInfoService.Flows
-{
-    /// <summary>
-    /// 鍏ュ簱浠诲姟娴佺▼鏈嶅姟銆�
-    /// 璐熻矗鍏ュ簱浠诲姟鎺ユ敹鍒濆鍖栥�佺姸鎬佹帹杩涘強鍫嗗灈鏈哄畬鎴愬鐞嗐��
-    /// </summary>
-    public class InboundTaskFlowService : IInboundTaskFlowService
-    {
+锘縰sing Serilog;
+using System.Diagnostics.CodeAnalysis;
+using WIDESEA_Core;
+using WIDESEAWCS_Common.HttpEnum;
+using WIDESEAWCS_Common.TaskEnum;
+using WIDESEAWCS_Core;
+using WIDESEAWCS_Core.Enums;
+using WIDESEAWCS_Core.Helper;
+using WIDESEAWCS_DTO;
+using WIDESEAWCS_DTO.TaskInfo;
+using WIDESEAWCS_ITaskInfoRepository;
+using WIDESEAWCS_ITaskInfoService;
+using WIDESEAWCS_Model.Models;
+using WIDESEAWCS_QuartzJob.Models;
+using WIDESEAWCS_QuartzJob.Service;
+using WIDESEAWCS_Tasks;
+
+namespace WIDESEAWCS_TaskInfoService.Flows
+{
+    /// <summary>
+    /// 鍏ュ簱浠诲姟娴佺▼鏈嶅姟銆�
+    /// 璐熻矗鍏ュ簱浠诲姟鎺ユ敹鍒濆鍖栥�佺姸鎬佹帹杩涘強鍫嗗灈鏈哄畬鎴愬鐞嗐��
+    /// </summary>
+    public class InboundTaskFlowService : IInboundTaskFlowService
+    {
         private readonly IRouterService _routerService;
-        private readonly ITaskRepository _taskRepository;
-        private readonly HttpClientHelper _httpClientHelper;
-        private readonly ILogger _logger;
-
-        /// <summary>
-        /// 鍒濆鍖栧叆搴撲换鍔℃祦绋嬫湇鍔°��
-        /// </summary>
-        /// <param name="routerService">璺敱鏈嶅姟銆�</param>
-        /// <param name="httpClientHelper">WMS鎺ュ彛璋冪敤甯姪绫汇��</param>
-        public InboundTaskFlowService(IRouterService routerService, ITaskRepository taskRepository, HttpClientHelper httpClientHelper, ILogger logger)
-        {
-            _routerService = routerService;
-            _taskRepository = taskRepository;
-            _httpClientHelper = httpClientHelper;
-            _logger = logger;
-        }
-
-        /// <summary>
-        /// 鎺ユ敹WMS浠诲姟鏃跺垵濮嬪寲鍏ュ簱浠诲姟銆�
-        /// </summary>
-        /// <param name="task">浠诲姟瀹炰綋銆�</param>
-        /// <param name="source">WMS浠诲姟鍘熷鏁版嵁銆�</param>
-        public WebResponseContent InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
-        {
-            WebResponseContent content = new WebResponseContent();
-            Dt_Router routers = _routerService.QueryNextRoute(source.SourceAddress);
-            if (routers.IsNullOrEmpty())
-            {
-                return content.Error("鏈壘鍒拌矾鐢变俊鎭�");
-            }
-
-            task.TaskStatus = (int)TaskInStatusEnum.InNew;
-            task.CurrentAddress = source.SourceAddress;
-            task.NextAddress = routers.ChildPosi;
-
-            return content.OK();
-        }
-
-        /// <summary>
-        /// 鎺ㄨ繘鍏ュ簱浠诲姟鐘舵�侊紝骞跺湪鍏抽敭鐘舵�佽皟鐢╓MS鎺ュ彛銆�
-        /// </summary>
-        /// <param name="task">浠诲姟瀹炰綋銆�</param>
-        /// <returns>鎺ㄨ繘缁撴灉銆�</returns>
-        public WebResponseContent MoveToNextStatus([NotNull] Dt_Task task)
-        {
-            if (task.TaskStatus >= (int)TaskInStatusEnum.InFinish)
-                return WebResponseContent.Instance.Error($"璇ヤ换鍔$姸鎬佷笉鍙烦杞埌涓嬩竴姝�,浠诲姟鍙�:銆恵task.TaskNum}銆�,浠诲姟鐘舵��:銆恵task.TaskStatus}銆�");
-
-            task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskInStatusEnum>();
-            if (task.TaskStatus <= 0)
-                return WebResponseContent.Instance.Error($"璇ヤ换鍔$姸鎬佷笉鍙烦杞埌涓嬩竴姝�,浠诲姟鍙�:銆恵task.TaskNum}銆�,浠诲姟鐘舵��:銆恵task.TaskStatus}銆�");
-
-            if (task.TaskStatus == (int)TaskInStatusEnum.Line_InFinish)
-            {
-                return GetWMSInboundLocation(task);
-            }
-
-            return UpdateWMSTaskStatus(task);
-        }
-
-        /// <summary>
-        /// 澶勭悊鍫嗗灈鏈哄叆搴撳畬鎴愬姩浣溿��
-        /// </summary>
-        /// <param name="task">浠诲姟瀹炰綋銆�</param>
-        /// <returns>澶勭悊缁撴灉銆�</returns>
-        public WebResponseContent CompleteStackerTask([NotNull] Dt_Task task)
-        {
-            WebResponseContent content = new WebResponseContent();
-            if (task.TaskStatus != (int)TaskInStatusEnum.SC_InExecuting)
-            {
-                return WebResponseContent.Instance.OK();
-            }
-
-            int nextStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskInStatusEnum>();
-            task.TaskStatus = nextStatus;
-            task.ModifyDate = DateTime.Now;
-            task.Modifier = "System";
-
-            var result = _httpClientHelper.Post<WebResponseContent>(
-                nameof(ConfigKey.InboundFinishTaskAsync),
-                (new CreateTaskDto { PalletCode = task.PalletCode }).ToJson());
-
-            if (!result.IsSuccess || !result.Data.Status)
-            {
-                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆怚nboundFinishTaskAsync銆�,璇锋眰鍙傛暟:銆恵task.PalletCode}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "InboundTaskFlowService");
-                return content.Error($"閫氱煡WMS绯荤粺鍫嗗灈鏈哄叆搴撳畬鎴愬け璐�,浠诲姟鍙�:銆恵task.TaskNum}銆�,鎵樼洏鍙�:銆恵task.PalletCode}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�");
-            }
-
-            QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆怚nboundFinishTaskAsync銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:0ms", "InboundTaskFlowService");
-            return content.OK($"閫氱煡WMS绯荤粺鍫嗗灈鏈哄叆搴撳畬鎴愭垚鍔�,浠诲姟鍙�:銆恵task.TaskNum}銆�,鎵樼洏鍙�:銆恵task.PalletCode}銆�");
-        }
-
-        /// <summary>
-        /// 浠嶹MS鑾峰彇鍏ュ簱鐩爣鍦板潃骞跺洖鍐欎换鍔°��
-        /// </summary>
-        /// <param name="task">浠诲姟瀹炰綋銆�</param>
-        /// <returns>璋冪敤缁撴灉銆�</returns>
-        private WebResponseContent GetWMSInboundLocation(Dt_Task task)
-        {
-            string configKey = nameof(ConfigKey.GetTasksLocation);
-            string requestParam = new CreateTaskDto { PalletCode = task.PalletCode }.ToJson();
-            DateTime startTime = DateTime.Now;
-
-            var result = _httpClientHelper.Post<WebResponseContent>(
-                configKey,
-                requestParam);
-
-            if (!result.IsSuccess || !result.Data.Status)
-            {
-                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "InboundTaskFlowService");
-                return WebResponseContent.Instance.Error($"璋冪敤WMS鎺ュ彛鑾峰彇浠诲姟鐩爣鍦板潃澶辫触,浠诲姟鍙�:銆恵task.TaskNum}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�");
-            }
-
-            QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "InboundTaskFlowService");
-
-            string? nextAddress = result.Data.Data?.ToString();
-            if (string.IsNullOrEmpty(nextAddress))
-                return WebResponseContent.Instance.Error($"璋冪敤WMS鎺ュ彛鑾峰彇浠诲姟鐩爣鍦板潃澶辫触,浠诲姟鍙�:銆恵task.TaskNum}銆�,閿欒淇℃伅:銆愭湭鑾峰彇鍒版湁鏁堢殑鐩爣鍦板潃銆�");
-
-            task.CurrentAddress = task.NextAddress;
-            task.NextAddress = nextAddress;
-            task.TargetAddress = nextAddress;
-
-            return WebResponseContent.Instance.OK();
+        private readonly ITaskRepository _taskRepository;
+        private readonly HttpClientHelper _httpClientHelper;
+        private readonly ILogger _logger;
+
+        /// <summary>
+        /// 鍒濆鍖栧叆搴撲换鍔℃祦绋嬫湇鍔°��
+        /// </summary>
+        /// <param name="routerService">璺敱鏈嶅姟銆�</param>
+        /// <param name="httpClientHelper">WMS鎺ュ彛璋冪敤甯姪绫汇��</param>
+        public InboundTaskFlowService(IRouterService routerService, ITaskRepository taskRepository, HttpClientHelper httpClientHelper, ILogger logger)
+        {
+            _routerService = routerService;
+            _taskRepository = taskRepository;
+            _httpClientHelper = httpClientHelper;
+            _logger = logger;
+        }
+
+        /// <summary>
+        /// 鎺ユ敹WMS浠诲姟鏃跺垵濮嬪寲鍏ュ簱浠诲姟銆�
+        /// </summary>
+        /// <param name="task">浠诲姟瀹炰綋銆�</param>
+        /// <param name="source">WMS浠诲姟鍘熷鏁版嵁銆�</param>
+        public WebResponseContent InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
+        {
+            WebResponseContent content = new WebResponseContent();
+            Dt_Router routers = _routerService.QueryNextRoute(source.SourceAddress);
+            if (routers.IsNullOrEmpty())
+            {
+                return content.Error("鏈壘鍒拌矾鐢变俊鎭�");
+            }
+
+            task.TaskStatus = (int)TaskInStatusEnum.InNew;
+            task.CurrentAddress = source.SourceAddress;
+            task.NextAddress = routers.ChildPosi;
+
+            return content.OK();
+        }
+
+        /// <summary>
+        /// 鎺ㄨ繘鍏ュ簱浠诲姟鐘舵�侊紝骞跺湪鍏抽敭鐘舵�佽皟鐢╓MS鎺ュ彛銆�
+        /// </summary>
+        /// <param name="task">浠诲姟瀹炰綋銆�</param>
+        /// <returns>鎺ㄨ繘缁撴灉銆�</returns>
+        public WebResponseContent MoveToNextStatus([NotNull] Dt_Task task)
+        {
+            if (task.TaskStatus >= (int)TaskInStatusEnum.InFinish)
+                return WebResponseContent.Instance.Error($"璇ヤ换鍔$姸鎬佷笉鍙烦杞埌涓嬩竴姝�,浠诲姟鍙�:銆恵task.TaskNum}銆�,浠诲姟鐘舵��:銆恵task.TaskStatus}銆�");
+
+            task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskInStatusEnum>();
+            if (task.TaskStatus <= 0)
+                return WebResponseContent.Instance.Error($"璇ヤ换鍔$姸鎬佷笉鍙烦杞埌涓嬩竴姝�,浠诲姟鍙�:銆恵task.TaskNum}銆�,浠诲姟鐘舵��:銆恵task.TaskStatus}銆�");
+
+            if (task.TaskStatus == (int)TaskInStatusEnum.Line_InFinish)
+            {
+                return GetWMSInboundLocation(task);
+            }
+
+            return UpdateWMSTaskStatus(task);
+        }
+
+        /// <summary>
+        /// 澶勭悊鍫嗗灈鏈哄叆搴撳畬鎴愬姩浣溿��
+        /// </summary>
+        /// <param name="task">浠诲姟瀹炰綋銆�</param>
+        /// <returns>澶勭悊缁撴灉銆�</returns>
+        public WebResponseContent CompleteStackerTask([NotNull] Dt_Task task)
+        {
+            WebResponseContent content = new WebResponseContent();
+            if (task.TaskStatus != (int)TaskInStatusEnum.SC_InExecuting)
+            {
+                return WebResponseContent.Instance.OK();
+            }
+
+            int nextStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskInStatusEnum>();
+            task.TaskStatus = nextStatus;
+            task.ModifyDate = DateTime.Now;
+            task.Modifier = "System";
+
+            var result = _httpClientHelper.Post<WebResponseContent>(
+                nameof(ConfigKey.InboundFinishTaskAsync),
+                (new CreateTaskDto { PalletCode = task.PalletCode }).ToJson());
+
+            if (!result.IsSuccess || !result.Data.Status)
+            {
+                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆怚nboundFinishTaskAsync銆�,璇锋眰鍙傛暟:銆恵task.PalletCode}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "InboundTaskFlowService");
+                return content.Error($"閫氱煡WMS绯荤粺鍫嗗灈鏈哄叆搴撳畬鎴愬け璐�,浠诲姟鍙�:銆恵task.TaskNum}銆�,鎵樼洏鍙�:銆恵task.PalletCode}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�");
+            }
+
+            QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆怚nboundFinishTaskAsync銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:0ms", "InboundTaskFlowService");
+            return content.OK($"閫氱煡WMS绯荤粺鍫嗗灈鏈哄叆搴撳畬鎴愭垚鍔�,浠诲姟鍙�:銆恵task.TaskNum}銆�,鎵樼洏鍙�:銆恵task.PalletCode}銆�");
+        }
+
+        /// <summary>
+        /// 浠嶹MS鑾峰彇鍏ュ簱鐩爣鍦板潃骞跺洖鍐欎换鍔°��
+        /// </summary>
+        /// <param name="task">浠诲姟瀹炰綋銆�</param>
+        /// <returns>璋冪敤缁撴灉銆�</returns>
+        private WebResponseContent GetWMSInboundLocation(Dt_Task task)
+        {
+            string configKey = nameof(ConfigKey.GetTasksLocation);
+            string requestParam = new CreateTaskDto { PalletCode = task.PalletCode }.ToJson();
+            DateTime startTime = DateTime.Now;
+
+            var result = _httpClientHelper.Post<WebResponseContent>(
+                configKey,
+                requestParam);
+
+            if (!result.IsSuccess || !result.Data.Status)
+            {
+                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "InboundTaskFlowService");
+                return WebResponseContent.Instance.Error($"璋冪敤WMS鎺ュ彛鑾峰彇浠诲姟鐩爣鍦板潃澶辫触,浠诲姟鍙�:銆恵task.TaskNum}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�");
+            }
+
+            QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "InboundTaskFlowService");
+
+            string? nextAddress = result.Data.Data?.ToString();
+            if (string.IsNullOrEmpty(nextAddress))
+                return WebResponseContent.Instance.Error($"璋冪敤WMS鎺ュ彛鑾峰彇浠诲姟鐩爣鍦板潃澶辫触,浠诲姟鍙�:銆恵task.TaskNum}銆�,閿欒淇℃伅:銆愭湭鑾峰彇鍒版湁鏁堢殑鐩爣鍦板潃銆�");
+
+            task.CurrentAddress = task.NextAddress;
+            task.NextAddress = nextAddress;
+            task.TargetAddress = nextAddress;
+
+            return WebResponseContent.Instance.OK();
         }
 
         /// <summary>
@@ -200,6 +200,6 @@
 
             QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "InboundTaskFlowService");
             return WebResponseContent.Instance.OK();
-        }
-    }
-}
+        }
+    }
+}
diff --git a/Code/WMS/WIDESEA_WMSClient/src/extension/stock/hcstockInfo.jsx b/Code/WMS/WIDESEA_WMSClient/src/extension/stock/hcstockInfo.jsx
new file mode 100644
index 0000000..7bb7d44
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient/src/extension/stock/hcstockInfo.jsx
@@ -0,0 +1,163 @@
+//姝s鏂囦欢鏄敤鏉ヨ嚜瀹氫箟鎵╁睍涓氬姟浠g爜锛屽彲浠ユ墿灞曚竴浜涜嚜瀹氫箟椤甸潰鎴栬�呴噸鏂伴厤缃敓鎴愮殑浠g爜
+
+let extension = {
+  components: {
+    //鏌ヨ鐣岄潰鎵╁睍缁勪欢
+    gridHeader: "",
+    gridBody: "",
+    gridFooter: "",
+    //鏂板缓銆佺紪杈戝脊鍑烘鎵╁睍缁勪欢
+    modelHeader: "",
+    modelBody: "",
+    modelFooter: "",
+  },
+  tableAction: "",
+  buttons: { view: [], box: [], detail: [] },
+  methods: {
+    onInit() {
+      // 娣诲姞MES鎿嶄綔鍒�
+      this.columns.push({
+        title: "鎿嶄綔",
+        field: "鎿嶄綔",
+        align: "center",
+        width: 200,
+        fixed: "right",
+        render: (h, { row, column, index }) => {
+          return (
+            <div>
+              <el-button
+                type="primary"
+                size="small"
+                onClick={($e) => {
+                  this.handleInbound(row);
+                }}
+              >
+                杩涚珯
+              </el-button>
+              <el-button
+                type="success"
+                size="small"
+                style="margin-left: 8px"
+                onClick={($e) => {
+                  this.handleOutbound(row);
+                }}
+              >
+                鍑虹珯
+              </el-button>
+            </div>
+          );
+        },
+      });
+    },
+
+    // 鎵樼洏杩涚珯鎿嶄綔
+    async handleInbound(row) {
+      try {
+        await this.$confirm(
+          `纭鎵ц鎵樼洏杩涚珯鎿嶄綔锛焅n鎵樼洏缂栧彿锛�${row.palletCode}`,
+          "杩涚珯纭",
+          {
+            confirmButtonText: "纭",
+            cancelButtonText: "鍙栨秷",
+            type: "warning",
+          },
+        );
+
+        const result = await this.http.post(
+          "/api/StockInfo/inboundInContainer",
+          {
+            palletCode: row.palletCode,
+            stockId: row.id,
+          },
+          "姝e湪璋冪敤MES鎺ュ彛...",
+        );
+
+        if (result.status) {
+          this.$Message.success(result.message || "鎵樼洏杩涚珯鎴愬姛");
+          this.$refs.table.load();
+        } else {
+          this.$error(result.message || "鎵樼洏杩涚珯澶辫触");
+        }
+      } catch (error) {
+        if (error !== "cancel") {
+          this.$error(error.message || "缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+        }
+      }
+    },
+
+    // 鎵樼洏鍑虹珯鎿嶄綔
+    async handleOutbound(row) {
+      try {
+        await this.$confirm(
+          `纭鎵ц鎵樼洏鍑虹珯鎿嶄綔锛焅n鎵樼洏缂栧彿锛�${row.palletCode}`,
+          "鍑虹珯纭",
+          {
+            confirmButtonText: "纭",
+            cancelButtonText: "鍙栨秷",
+            type: "warning",
+          },
+        );
+
+        const result = await this.http.post(
+          "/api/StockInfo/outboundInContainer",
+          {
+            palletCode: row.palletCode,
+            stockId: row.id,
+          },
+          "姝e湪璋冪敤MES鎺ュ彛...",
+        );
+
+        if (result.status) {
+          this.$Message.success(result.message || "鎵樼洏鍑虹珯鎴愬姛");
+          this.$refs.table.load();
+        } else {
+          this.$error(result.message || "鎵樼洏鍑虹珯澶辫触");
+        }
+      } catch (error) {
+        if (error !== "cancel") {
+          this.$error(error.message || "缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+        }
+      }
+    },
+
+    onInited() {
+      // 妗嗘灦鍒濆鍖栭厤缃悗
+    },
+    searchBefore(param) {
+      const stockStatusFilter1 = {
+        name: "stockStatus",
+        value: "6",
+        displayType: "int"
+      };
+      const warehouseIdFilter1 = {
+        name: "warehouseId",
+        value: "3",
+        displayType: "int"
+      };
+      if (!param.wheres) {
+        param.wheres = [];
+      }
+      // 灏嗚繃婊ゆ潯浠舵坊鍔犲埌鏌ヨ鍙傛暟涓�
+      param.wheres.push(stockStatusFilter1);
+      param.wheres.push(warehouseIdFilter1);
+      return true;
+    },
+    searchAfter(result) {
+      return result;
+    },
+    addBefore(formData) {
+      return true;
+    },
+    updateBefore(formData) {
+      return true;
+    },
+    rowClick({ row, column, event }) {
+      this.$refs.table.$refs.table.toggleRowSelection(row);
+    },
+    modelOpenAfter(row) {
+      // 鐐瑰嚮缂栬緫銆佹柊寤烘寜閽脊鍑烘鍚�
+    },
+  },
+};
+
+export default extension;
diff --git a/Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js b/Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js
index ee9d66c..72f41e5 100644
--- a/Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js
+++ b/Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js
@@ -78,11 +78,18 @@
     path: '/outboundOrderDetail',
     name: 'outboundOrderDetail',
     component: () => import('@/views/outbound/outboundOrderDetail.vue')
-  }, {
+  }, 
+  {
     path: '/stockInfo',
     name: 'stockInfo',
     component: () => import('@/views/stock/stockInfo.vue')
-  }, {
+  },
+  {
+    path: '/hcstockInfo',
+    name: 'hcstockInfo',
+    component: () => import('@/views/stock/hcstockInfo.vue')
+  },
+  {
     path: '/stockInfoDetail',
     name: 'stockInfoDetail',
     component: () => import('@/views/stock/stockInfoDetail.vue')
diff --git a/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue b/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
index 9023c51..96461c7 100644
--- a/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
+++ b/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
@@ -1,10 +1,82 @@
 <template>
   <div class="dashboard-container">
-    <!-- 鍚勪粨搴撴湀搴﹀嚭鍏ュ簱瀵规瘮鍥� -->
-    <div class="chart-row full-width">
+    <!-- 椤堕儴KPI鍗$墖锛氭樉绀烘�昏揣浣嶅強鍚勪粨搴撹揣浣� -->
+    <div class="kpi-cards">
+      <div class="kpi-card">
+        <div class="kpi-icon">馃彋锔�</div>
+        <div class="kpi-info">
+          <div class="kpi-label">鎬昏揣浣�</div>
+          <div class="kpi-value">{{ totalLocation }}</div>
+        </div>
+      </div>
+      <div class="kpi-card">
+        <div class="kpi-icon">馃敟</div>
+        <div class="kpi-info">
+          <div class="kpi-label">鍖栨垚搴�</div>
+          <div class="kpi-value">{{ warehouseLocations.hc }}</div>
+        </div>
+      </div>
+      <div class="kpi-card">
+        <div class="kpi-icon">馃尅锔�</div>
+        <div class="kpi-info">
+          <div class="kpi-label">楂樻俯搴�</div>
+          <div class="kpi-value">{{ warehouseLocations.gw }}</div>
+        </div>
+      </div>
+      <div class="kpi-card">
+        <div class="kpi-icon">鉂勶笍</div>
+        <div class="kpi-info">
+          <div class="kpi-label">甯告俯搴�</div>
+          <div class="kpi-value">{{ warehouseLocations.cw }}</div>
+        </div>
+      </div>
+      <div class="kpi-card">
+        <div class="kpi-icon">馃摐</div>
+        <div class="kpi-info">
+          <div class="kpi-label">鏋佸嵎搴�</div>
+          <div class="kpi-value">{{ warehouseLocations.jj }}</div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 绗竴琛岋細4涓瘡鏃ュ嚭鍏ュ簱瓒嬪娍鍥撅紙姣忚2涓級 -->
+    <div class="chart-row daily-grid">
+      <div class="chart-card" v-for="warehouse in dailyWarehouses" :key="warehouse.code">
+        <div class="card-title">{{ warehouse.name }} - 姣忔棩瓒嬪娍</div>
+        <!-- 浠撳簱鏁板瓧鏄剧ず鍖哄煙锛氭樉绀烘瘡鏃ユ�婚噺鍜岀┖鎵樼洏鏁伴噺 -->
+        <div class="warehouse-numbers">
+          <!-- 鏋佸嵎搴撴樉绀烘湁璐ф墭鐩橈紙鐢垫睜鏁伴噺锛夊拰绌烘墭鐩� -->
+          <template v-if="warehouse.code === 'ROLL'">
+            <div class="number-item battery">
+              <span class="number-label">鐢垫睜鏁伴噺</span>
+              <span class="number-value">{{ getBatteryCount(warehouse.code) }}</span>
+            </div>
+            <div class="number-item empty-tray">
+              <span class="number-label">绌烘墭鐩樻暟閲�</span>
+              <span class="number-value">{{ getEmptyTrayCount(warehouse.code) }}</span>
+            </div>
+          </template>
+          <!-- 鍏朵粬浠撳簱鏄剧ず鐢垫睜鏁伴噺鍜岀┖鎵樼洏鏁伴噺 -->
+          <template v-else>
+            <div class="number-item inbound">
+              <span class="number-label">鐢垫睜鏁伴噺</span>
+              <span class="number-value">{{ getBatteryCount(warehouse.code) }}</span>
+            </div>
+            <div class="number-item empty-tray">
+              <span class="number-label">绌烘墭鐩樻暟閲�</span>
+              <span class="number-value">{{ getEmptyTrayCount(warehouse.code) }}</span>
+            </div>
+          </template>
+        </div>
+        <div :id="`daily-chart-${warehouse.code}`" class="chart-content"></div>
+      </div>
+    </div>
+
+    <!-- 浠撳簱鍒嗗竷锛堟煴鐘跺浘锛屾樉绀哄悇浠撳簱宸茬敤/鍓╀綑瀹归噺锛� -->
+    <div class="chart-row">
       <div class="chart-card">
-        <div class="card-title">鍚勪粨搴撴湀搴﹀嚭鍏ュ簱瀵规瘮</div>
-        <div id="chart-warehouse-monthly" class="chart-content"></div>
+        <div class="card-title">鍚勪粨搴撳簱瀛樺垎甯�</div>
+        <div id="chart-warehouse" class="chart-content"></div>
       </div>
     </div>
   </div>
@@ -18,9 +90,54 @@
   data() {
     return {
       charts: {},
-      monthlyData: [],
-      warehouseNames: ['FJSC1', 'ZJSC1', 'GWSC1', 'CWSC1', 'HCSC1']
+      // 鍥涗釜鏍稿績浠撳簱锛堝悎骞朵簡姝h礋鏋佸嵎搴撲负鏋佸嵎搴擄級
+      dailyWarehouses: [
+        { code: "HCSC1", name: "鍖栨垚搴�", type: "hc" },
+        { code: "GWSC1", name: "楂樻俯搴�", type: "gw" },
+        { code: "CWSC1", name: "甯告俯搴�", type: "cw" },
+        { code: "ROLL", name: "鏋佸嵎搴�", type: "jj" }
+      ],
+      // 鍘熷姣忔棩鏁版嵁瀛樺偍 (鍏朵腑ROLL涓哄悎骞跺悗鐨勬瀬鍗峰簱鏁版嵁)
+      dailyDataMap: {
+        GWSC1: [],
+        CWSC1: [],
+        HCSC1: [],
+        ROLL: []
+      },
+      // 瀛樺偍姣忎釜浠撳簱鐨勭數姹犳暟閲�
+      warehouseStocks: {
+        GWSC1: 0,
+        CWSC1: 0,
+        HCSC1: 0,
+        ROLL: 0
+      },
+      // 鏋佸嵎搴撶壒娈婃暟鎹�
+      rollData: {
+        batteryCount: 0,    // 鐢垫睜鏁伴噺
+        emptyTrayCount: 0   // 绌烘墭鐩樻暟閲�
+      },
+      // 鍏朵粬浠撳簱鐨勭┖鎵樼洏鏁伴噺
+      emptyTrayCounts: {
+        GWSC1: 0,
+        CWSC1: 0,
+        HCSC1: 0
+      },
+      warehouseData: [],     // 浠撳簱鍒嗗竷鍥炬暟鎹�
+      // 浠撳簱璐т綅鏁版嵁锛堝浐瀹氶厤缃級
+      warehouseLocations: {
+        hc: 35,   // 鍖栨垚搴�
+        gw: 324,  // 楂樻俯搴�
+        cw: 140,  // 甯告俯搴�
+        jj: 104   // 鏋佸嵎搴�
+      }
     };
+  },
+  computed: {
+    // 鎬昏揣浣嶈绠�
+    totalLocation() {
+      return this.warehouseLocations.hc + this.warehouseLocations.gw + 
+             this.warehouseLocations.cw + this.warehouseLocations.jj;
+    }
   },
   mounted() {
     this.initCharts();
@@ -29,198 +146,461 @@
   },
   beforeUnmount() {
     window.removeEventListener("resize", this.handleResize);
-    Object.values(this.charts).forEach(chart => chart.dispose());
+    Object.values(this.charts).forEach(chart => chart && chart.dispose());
   },
   methods: {
     handleResize() {
-      Object.values(this.charts).forEach(chart => chart.resize());
+      Object.values(this.charts).forEach(chart => chart && chart.resize());
     },
 
     initCharts() {
-      this.charts.warehouseMonthly = echarts.init(document.getElementById("chart-warehouse-monthly"));
+      // 鍒濆鍖栨瘡鏃ュ浘琛�
+      this.dailyWarehouses.forEach(warehouse => {
+        const chartId = `daily-chart-${warehouse.code}`;
+        const el = document.getElementById(chartId);
+        if (el) {
+          this.charts[`daily-${warehouse.code}`] = echarts.init(el);
+        }
+      });
+      // 鍒濆鍖栦粨搴撳垎甯冨浘琛�
+      this.charts.warehouse = echarts.init(document.getElementById("chart-warehouse"));
     },
 
     async loadData() {
-      await this.loadMonthlyStats();
-    },
-
-    async loadMonthlyStats() {
       try {
-        const promises = this.warehouseNames.map(warehouse => 
-          this.http.get("/api/Dashboard/MonthlyStats", { 
-            months: 6, 
-            Roadway: warehouse 
-          })
-        );
+        // 骞惰鍔犺浇鎵�鏈夋暟鎹�
+        await Promise.all([
+          this.loadAllDailyStats(),
+          this.loadStockAndTrayCount(),
+          this.loadStockByWarehouse()
+        ]);
         
-        const results = await Promise.all(promises);
-        
-        this.monthlyData = results.map((res, index) => ({
-          warehouse: this.warehouseNames[index],
-          warehouseName: this.getWarehouseName(this.warehouseNames[index]),
-          data: res.data || []
-        }));
-        
-        this.updateWarehouseMonthlyChart();
-      } catch (e) {
-        console.error("鍔犺浇姣忔湀缁熻澶辫触", e);
+        // 鏇存柊鎵�鏈夊浘琛�
+        this.updateAllDailyCharts();
+      } catch (error) {
+        console.error("鍔犺浇鏁版嵁澶辫触:", error);
+        this.$message?.error("鏁版嵁鍔犺浇澶辫触锛岃绋嶅悗閲嶈瘯");
       }
     },
 
-    getWarehouseName(code) {
-      const nameMap = {
-        'FJSC1': '璐熸瀬鍗�1鍙蜂粨搴�',
-        'ZJSC1': '姝f瀬鍗�1鍙蜂粨搴�',
-        'GWSC1': '楂樻俯1鍙蜂粨搴�',
-        'CWSC1': '甯告俯1鍙蜂粨搴�',
-        'HCSC1': '鍒嗗1鍙蜂粨搴�'
-      };
-      return nameMap[code] || code;
-    },
-
-    updateWarehouseMonthlyChart() {
-      // 鑾峰彇鎵�鏈夋湀浠�
-      const months = this.monthlyData[0]?.data.map(d => `${d.month}鏈坄) || [];
-      
-      // 涓烘瘡涓粨搴撶敓鎴愮郴鍒楁暟鎹�
-      const series = [];
-      
-      this.monthlyData.forEach((warehouseData, index) => {
-        const data = warehouseData.data;
+    async loadAllDailyStats() {
+      console.log("姝e湪鍔犺浇鎵�鏈変粨搴撶殑姣忔棩缁熻鏁版嵁...");
+      const res = await this.http.get("/api/Dashboard/DailyStats?days=10");
+      if (res.status && res.data) {
+        console.log("鎵�鏈変粨搴撴瘡鏃ョ粺璁℃暟鎹�:", res.data);
         
-        series.push({
-          name: warehouseData.warehouseName,
-          type: 'bar',
-          data: data.map(d => ({
-            value: (d.inbound || 0) + (d.outbound || 0),
-            inbound: d.inbound || 0,
-            outbound: d.outbound || 0,
-            label: {
-              show: true,
-              position: 'top',
-              formatter: function(params) {
-                return `鍏�:${params.data.inbound}\n鍑�:${params.data.outbound}`;
-              },
-              fontSize: 10,
-              color: '#fff',
-              lineHeight: 15
-            }
-          })),
-          barWidth: '15%',
-          barGap: '10%',
-          itemStyle: {
-            color: this.getBarColor(index),
-            borderRadius: [3, 3, 0, 0]
+        const dataArray = res.data;
+        
+        // 鎸変粨搴撳垎绫绘暟鎹�
+        dataArray.forEach(item => {
+          const roadway = item.roadway;
+          const dailyStats = item.dailyStats || [];
+          
+          switch(roadway) {
+            case "GWSC1":
+              this.dailyDataMap.GWSC1 = dailyStats;
+              break;
+            case "CWSC1":
+              this.dailyDataMap.CWSC1 = dailyStats;
+              break;
+            case "HCSC1":
+              this.dailyDataMap.HCSC1 = dailyStats;
+              break;
+            case "ZJSC1":
+            case "FJSC1":
+              // 鏋佸嵎搴撴暟鎹悎骞跺鐞�
+              this.mergeRollDailyStats(dailyStats);
+              break;
           }
         });
+        
+        console.log("GWSC1鏁版嵁:", this.dailyDataMap.GWSC1);
+        console.log("CWSC1鏁版嵁:", this.dailyDataMap.CWSC1);
+        console.log("HCSC1鏁版嵁:", this.dailyDataMap.HCSC1);
+        console.log("鏋佸嵎搴撳悎骞舵暟鎹�:", this.dailyDataMap.ROLL);
+      } else {
+        console.error("鑾峰彇姣忔棩鏁版嵁澶辫触");
+      }
+    },
+
+    mergeRollDailyStats(newData) {
+      // 鍚堝苟姝f瀬鍗峰簱鍜岃礋鏋佸嵎搴撶殑姣忔棩鏁版嵁
+      if (!this.dailyDataMap.ROLL.length) {
+        this.dailyDataMap.ROLL = [...newData];
+      } else {
+        const dateMap = new Map();
+        [...this.dailyDataMap.ROLL, ...newData].forEach(item => {
+          const date = item.date;
+          if (date) {
+            if (!dateMap.has(date)) {
+              dateMap.set(date, { date, inbound: 0, outbound: 0 });
+            }
+            const existing = dateMap.get(date);
+            existing.inbound += item.inbound || 0;
+            existing.outbound += item.outbound || 0;
+          }
+        });
+        
+        const sortedDates = Array.from(dateMap.keys()).sort();
+        const mergedData = sortedDates.map(date => dateMap.get(date));
+        this.dailyDataMap["ROLL"] = mergedData;
+      }
+    },
+
+    async loadStockAndTrayCount() {
+      // 鍔犺浇鐢垫睜鏁伴噺鍜岀┖鎵樼洏鏁伴噺
+      console.log("姝e湪鍔犺浇鐢垫睜鏁伴噺鍜岀┖鎵樼洏鏁版嵁...");
+      const res = await this.http.get("/api/Dashboard/StockAndTrayCount");
+      
+      if (res.status && res.data) {
+        console.log("鐢垫睜鍜岀┖鎵樼洏鏁版嵁:", res.data);
+        
+        // 閲嶇疆鏁版嵁
+        this.rollData.batteryCount = 0;
+        this.rollData.emptyTrayCount = 0;
+        
+        // 鏍规嵁杩斿洖鐨勬暟鎹粨鏋勮В鏋�
+        res.data.forEach(item => {
+          const warehouseName = item.warehouseName;
+          const batteryCount = item.batteryCount || 0;
+          const emptyTrayCount = item.emptyTrayCount || 0;
+          
+          // 鏍规嵁浠撳簱鍚嶇О鏄犲皠鍒板搴旂殑浠g爜
+          if (warehouseName === "楂樻俯搴�") {
+            this.emptyTrayCounts.GWSC1 = emptyTrayCount;
+            this.warehouseStocks.GWSC1 = batteryCount;
+          } else if (warehouseName === "甯告俯搴�") {
+            this.emptyTrayCounts.CWSC1 = emptyTrayCount;
+            this.warehouseStocks.CWSC1 = batteryCount;
+          } else if (warehouseName === "鍖栨垚搴�") {
+            this.emptyTrayCounts.HCSC1 = emptyTrayCount;
+            this.warehouseStocks.HCSC1 = batteryCount;
+          } else if (warehouseName === "鏋佸嵎搴�") {
+            // 鏋佸嵎搴撻渶瑕佸悎骞朵袱涓瀬鍗峰簱鐨勬暟鎹�
+            this.rollData.batteryCount += batteryCount;
+            this.rollData.emptyTrayCount += emptyTrayCount;
+          }
+        });
+        
+        // 璁剧疆鏋佸嵎搴撴�荤數姹犳暟閲�
+        this.warehouseStocks.ROLL = this.rollData.batteryCount;
+        
+        console.log("鐗规畩鏁版嵁鍔犺浇瀹屾垚:", { 
+          rollData: this.rollData, 
+          emptyTrayCounts: this.emptyTrayCounts,
+          warehouseStocks: this.warehouseStocks
+        });
+      } else {
+        console.error("鑾峰彇鐢垫睜鍜岀┖鎵樼洏鏁版嵁澶辫触");
+        throw new Error("鑾峰彇鐢垫睜鍜岀┖鎵樼洏鏁版嵁澶辫触");
+      }
+    },
+
+    async loadStockByWarehouse() {
+      console.log("姝e湪鍔犺浇浠撳簱鍒嗗竷鏁版嵁...");
+      const res = await this.http.get("/api/Dashboard/StockByWarehouse");
+      
+      if (res.status && res.data) {
+        console.log("浠撳簱鍒嗗竷鏁版嵁:", res.data);
+        const rawData = res.data.data || res.data;
+        
+        // 澶勭悊鏋佸嵎搴撳悎骞�
+        let rollHasStock = 0;
+        let rollNoStock = 0;
+        let rollTotal = 0;
+        const otherWarehouses = [];
+        
+        rawData.forEach(item => {
+          if (item.warehouse === "鏋佸嵎搴�" || item.warehouse.includes("鏋佸嵎搴�")) {
+            // 鍚堝苟鏋佸嵎搴撴暟鎹�
+            rollHasStock += item.hasStock || 0;
+            rollNoStock += item.noStock || 0;
+            rollTotal += item.total || 0;
+          } else {
+            otherWarehouses.push(item);
+          }
+        });
+        
+        // 娣诲姞鍚堝苟鍚庣殑鏋佸嵎搴�
+        if (rollTotal > 0) {
+          const hasStockPercentage = ((rollHasStock / rollTotal) * 100).toFixed(1) + "%";
+          const noStockPercentage = ((rollNoStock / rollTotal) * 100).toFixed(1) + "%";
+          
+          otherWarehouses.push({
+            warehouse: "鏋佸嵎搴�",
+            hasStock: rollHasStock,
+            noStock: rollNoStock,
+            total: rollTotal,
+            hasStockPercentage: hasStockPercentage,
+            noStockPercentage: noStockPercentage
+          });
+        }
+        
+        this.warehouseData = otherWarehouses;
+        this.updateWarehouseChart();
+      } else {
+        console.error("鑾峰彇浠撳簱鍒嗗竷鏁版嵁澶辫触");
+        throw new Error("鑾峰彇浠撳簱鍒嗗竷鏁版嵁澶辫触");
+      }
+    },
+
+    getDailyTotalInbound(warehouseCode) {
+      const data = this.dailyDataMap[warehouseCode] || [];
+      return data.reduce((sum, item) => sum + (item.inbound || 0), 0);
+    },
+
+    getDailyTotalOutbound(warehouseCode) {
+      const data = this.dailyDataMap[warehouseCode] || [];
+      return data.reduce((sum, item) => sum + (item.outbound || 0), 0);
+    },
+
+    getWarehouseStock(warehouseCode) {
+      return this.warehouseStocks[warehouseCode] || 0;
+    },
+
+    getBatteryCount(warehouseCode) {
+      if (warehouseCode === 'ROLL') {
+        return this.rollData.batteryCount;
+      } else if (warehouseCode === 'GWSC1') {
+        return this.warehouseStocks.GWSC1;
+      } else if (warehouseCode === 'CWSC1') {
+        return this.warehouseStocks.CWSC1;
+      } else if (warehouseCode === 'HCSC1') {
+        return this.warehouseStocks.HCSC1;
+      }
+      return 0;
+    },
+
+    getEmptyTrayCount(warehouseCode) {
+      if (warehouseCode === 'ROLL') {
+        return this.rollData.emptyTrayCount;
+      } else if (warehouseCode === 'GWSC1') {
+        return this.emptyTrayCounts.GWSC1;
+      } else if (warehouseCode === 'CWSC1') {
+        return this.emptyTrayCounts.CWSC1;
+      } else if (warehouseCode === 'HCSC1') {
+        return this.emptyTrayCounts.HCSC1;
+      }
+      return 0;
+    },
+
+    updateAllDailyCharts() {
+      this.dailyWarehouses.forEach(warehouse => {
+        this.updateDailyChartForWarehouse(warehouse.code);
       });
+    },
+
+    updateDailyChartForWarehouse(roadway) {
+      const chart = this.charts[`daily-${roadway}`];
+      if (!chart) return;
+
+      const data = this.dailyDataMap[roadway] || [];
+      
+      // 濡傛灉娌℃湁鏁版嵁锛屾樉绀虹┖鍥捐〃鎻愮ず
+      if (!data.length) {
+        chart.setOption({
+          title: {
+            show: true,
+            text: '鏆傛棤鏁版嵁',
+            left: 'center',
+            top: 'center',
+            textStyle: { color: '#ccc', fontSize: 14 }
+          }
+        }, true);
+        return;
+      }
+
+      const dates = data.map(d => d.date);
+      const inboundData = data.map(d => d.inbound || 0);
+      const outboundData = data.map(d => d.outbound || 0);
 
       const option = {
-        title: {
-          text: '鍚勪粨搴撴湀搴﹀嚭鍏ュ簱瀵规瘮',
-          textStyle: {
-            color: '#00ffff',
-            fontSize: 16
-          },
-          left: 'center',
-          top: 10
-        },
-        tooltip: {
-          trigger: 'axis',
-          axisPointer: {
-            type: 'shadow'
-          },
+        tooltip: { 
+          trigger: "axis",
           formatter: function(params) {
-            let tip = `<strong>${params[0].axisValue}</strong><br/>`;
+            let result = params[0].axisValue + "<br/>";
+            params.forEach(p => {
+              result += `${p.marker}${p.seriesName}: ${p.value}<br/>`;
+            });
+            return result;
+          }
+        },
+        legend: {
+          data: ["鍏ュ簱", "鍑哄簱"],
+          textStyle: { color: "#fff" },
+          top: 0,
+          right: 10,
+          itemWidth: 20,
+          itemHeight: 12
+        },
+        grid: {
+          left: "8%",
+          right: "8%",
+          top: "18%",
+          bottom: "12%",
+          containLabel: true
+        },
+        xAxis: {
+          type: "category",
+          data: dates,
+          axisLabel: {
+            color: "#ccc",
+            rotate: 45,
+            fontSize: 10,
+            interval: 0,
+            margin: 8
+          },
+          axisLine: { lineStyle: { color: "#4a5b6e" } }
+        },
+        yAxis: {
+          type: "value",
+          name: "鏁伴噺",
+          nameTextStyle: { color: "#ccc", fontSize: 11 },
+          axisLabel: { color: "#ccc" },
+          splitLine: { lineStyle: { color: "#2a3a4a", type: "dashed" } }
+        },
+        series: [
+          {
+            name: "鍏ュ簱",
+            type: "bar",
+            data: inboundData,
+            itemStyle: {
+              color: "#5470c6",
+              borderRadius: [4, 4, 0, 0]
+            },
+            barWidth: "40%",
+            label: {
+              show: true,
+              position: "top",
+              color: "#5470c6",
+              fontSize: 10,
+              formatter: (params) => params.value
+            }
+          },
+          {
+            name: "鍑哄簱",
+            type: "line",
+            data: outboundData,
+            symbol: "circle",
+            symbolSize: 6,
+            itemStyle: { color: "#91cc75" },
+            lineStyle: { width: 2, type: "solid" },
+            smooth: false,
+            label: {
+              show: true,
+              position: "top",
+              color: "#91cc75",
+              fontSize: 10,
+              formatter: (params) => params.value
+            }
+          }
+        ]
+      };
+      chart.setOption(option, true);
+    },
+
+    updateWarehouseChart() {
+      if (!this.charts.warehouse) return;
+      
+      if (!this.warehouseData.length) {
+        this.charts.warehouse.setOption({
+          title: {
+            show: true,
+            text: '鏆傛棤浠撳簱鏁版嵁',
+            left: 'center',
+            top: 'center',
+            textStyle: { color: '#ccc' }
+          }
+        });
+        return;
+      }
+      
+      const warehouseNames = this.warehouseData.map(w => w.warehouse);
+      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",
+          axisPointer: { type: "shadow" },
+          formatter: (params) => {
+            let tip = params[0].name + "<br/>";
             params.forEach(param => {
-              tip += `<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:${param.color};margin-right:5px;"></span>`;
-              tip += `${param.seriesName}: `;
-              tip += `鍏ュ簱:${param.data.inbound} | 鍑哄簱:${param.data.outbound} | 鎬昏:${param.value}<br/>`;
+              const dataIndex = param.dataIndex;
+              const warehouse = this.warehouseData[dataIndex];
+              if (warehouse) {
+                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/>`;
+                }
+              } else {
+                tip += `${param.marker}${param.seriesName}: ${param.value}<br/>`;
+              }
             });
             return tip;
           }
         },
         legend: {
-          data: this.monthlyData.map(d => d.warehouseName),
-          textStyle: { color: '#fff', fontSize: 11 },
-          top: 45,
-          left: 'center',
-          type: 'scroll'
-        },
-        grid: {
-          left: '3%',
-          right: '4%',
-          bottom: '10%',
-          top: '20%',
-          containLabel: true
+          data: ["宸茬敤瀹归噺", "鍓╀綑瀹归噺"],
+          textStyle: { color: "#fff" }
         },
         xAxis: {
-          type: 'category',
-          data: months,
-          axisLabel: {
-            color: '#fff',
-            fontSize: 11
-          },
-          axisLine: {
-            lineStyle: { color: 'rgba(255,255,255,0.3)' }
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(255,255,255,0.1)',
-              type: 'dashed'
-            }
-          }
+          type: "category",
+          data: warehouseNames,
+          axisLabel: { color: "#fff", rotate: 30, interval: 0 }
         },
         yAxis: {
-          type: 'value',
-          name: '鏁伴噺',
-          nameTextStyle: { color: '#fff' },
-          axisLabel: { color: '#fff' },
-          splitLine: {
-            lineStyle: {
-              color: 'rgba(255,255,255,0.1)',
-              type: 'dashed'
-            }
-          }
+          type: "value",
+          name: "瀹归噺",
+          axisLabel: { color: "#fff" }
         },
-        dataZoom: [
+        series: [
           {
-            type: 'inside',
-            start: 0,
-            end: 100
+            name: "宸茬敤瀹归噺",
+            type: "bar",
+            data: hasStocks.map((value, index) => ({
+              value: value,
+              label: {
+                show: true,
+                position: "top",
+                formatter: () => {
+                  const pct = hasStockPercentages[index];
+                  return `${value} (${pct})`;
+                },
+                color: "#91cc75",
+                fontSize: 11
+              }
+            })),
+            itemStyle: { color: "#91cc75" }
           },
           {
-            start: 0,
-            end: 100,
-            height: 20,
-            bottom: 0,
-            borderColor: 'rgba(255,255,255,0.3)',
-            fillerColor: 'rgba(0,255,255,0.1)',
-            handleStyle: {
-              color: '#00ffff',
-              borderColor: '#00ffff'
-            },
-            textStyle: {
-              color: '#fff'
-            }
+            name: "鍓╀綑瀹归噺",
+            type: "bar",
+            data: noStocks.map((value, index) => ({
+              value: value,
+              label: {
+                show: true,
+                position: "top",
+                formatter: () => {
+                  const pct = noStockPercentages[index];
+                  return `${value} (${pct})`;
+                },
+                color: "#fac858",
+                fontSize: 11
+              }
+            })),
+            itemStyle: { color: "#fac858" }
           }
-        ],
-        series: series
+        ]
       };
 
-      this.charts.warehouseMonthly.setOption(option, true);
-    },
-
-    getBarColor(index) {
-      const colors = [
-        '#5470c6', // 钃�
-        '#fac858', // 榛�
-        '#73c0de', // 澶╄摑
-        '#fc8452', // 姗�
-        '#ea7ccc'  // 绮�
-      ];
-      return colors[index] || '#5470c6';
+      this.charts.warehouse.setOption(option, true);
     }
   }
 };
@@ -235,36 +615,80 @@
   background-attachment: fixed;
 }
 
-.chart-row {
+/* KPI 鍗$墖鏍峰紡 - 5鍒楀竷灞� */
+.kpi-cards {
+  display: grid;
+  grid-template-columns: repeat(5, 1fr);
+  gap: 20px;
+  margin-bottom: 24px;
+}
+
+.kpi-card {
+  background: rgba(10, 16, 35, 0.7);
+  backdrop-filter: blur(10px);
+  border: 1px solid rgba(64, 224, 208, 0.3);
+  border-radius: 16px;
+  padding: 16px 20px;
   display: flex;
+  align-items: center;
+  gap: 16px;
+  transition: all 0.3s ease;
+  box-shadow: 0 0 15px rgba(0, 255, 255, 0.1);
+}
+
+.kpi-card:hover {
+  transform: translateY(-3px);
+  border-color: rgba(64, 224, 208, 0.6);
+  box-shadow: 0 0 25px rgba(0, 255, 255, 0.2);
+}
+
+.kpi-icon {
+  font-size: 32px;
+  opacity: 0.9;
+}
+
+.kpi-info {
+  flex: 1;
+}
+
+.kpi-label {
+  font-size: 13px;
+  color: #8ba0b5;
+  margin-bottom: 6px;
+  letter-spacing: 1px;
+}
+
+.kpi-value {
+  font-size: 28px;
+  font-weight: 700;
+  color: #00ffff;
+  text-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
+  line-height: 1.2;
+}
+
+/* 姣忔棩鍥捐〃甯冨眬 - 姣忚2涓� */
+.chart-row.daily-grid {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
   gap: 20px;
   margin-bottom: 20px;
 }
 
-.chart-row.full-width {
-  width: 100%;
-}
-
 .chart-card {
-  flex: 1;
   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);
+  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);
+  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);
 }
 
@@ -294,25 +718,84 @@
 
 .card-title {
   color: #00ffff;
-  font-size: 16px;
+  font-size: 15px;
   text-align: center;
-  margin-bottom: 10px;
+  margin-bottom: 12px;
   text-shadow: 0 0 10px rgba(0, 255, 255, 0.7);
   font-weight: 500;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+/* 浠撳簱鏁板瓧鏄剧ず鍖哄煙 */
+.warehouse-numbers {
+  display: flex;
+  justify-content: space-around;
+  margin-bottom: 12px;
+  padding: 8px 0;
+  background: rgba(0, 0, 0, 0.3);
+  border-radius: 8px;
+  flex-wrap: wrap;
+}
+
+.number-item {
+  text-align: center;
+  flex: 1;
+  min-width: 80px;
+}
+
+.number-label {
+  display: block;
+  font-size: 11px;
+  color: #8ba0b5;
+  margin-bottom: 4px;
+}
+
+.number-value {
+  display: block;
+  font-size: 18px;
+  font-weight: 700;
+  letter-spacing: 1px;
+}
+
+.number-item.inbound .number-value {
+  color: #5470c6;
+}
+
+.number-item.battery .number-value {
+  color: #ee6666;
+}
+
+.number-item.empty-tray .number-value {
+  color: #fc8452;
 }
 
 .chart-content {
-  height: 500px;
+  height: 280px;
   width: 100%;
 }
 
-.full-width .chart-card {
-  flex: none;
-  width: 100%;
-}
-
-.full-width .chart-content {
-  height: 500px;
+@media (max-width: 768px) {
+  .kpi-cards {
+    grid-template-columns: repeat(2, 1fr);
+  }
+  .chart-row.daily-grid {
+    grid-template-columns: 1fr;
+  }
+  .chart-content {
+    height: 240px;
+  }
+  .card-title {
+    font-size: 13px;
+    white-space: normal;
+  }
+  .number-value {
+    font-size: 14px;
+  }
+  .number-item {
+    min-width: 60px;
+  }
 }
 
 .dashboard-container::before {
@@ -322,8 +805,7 @@
   left: 0;
   right: 0;
   bottom: 0;
-  background-image: 
-    linear-gradient(rgba(64, 224, 208, 0.05) 1px, transparent 1px),
+  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;
diff --git a/Code/WMS/WIDESEA_WMSClient/src/views/stock/hcstockInfo.vue b/Code/WMS/WIDESEA_WMSClient/src/views/stock/hcstockInfo.vue
new file mode 100644
index 0000000..271cedb
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient/src/views/stock/hcstockInfo.vue
@@ -0,0 +1,505 @@
+<template>
+  <view-grid ref="grid" :columns="columns" :detail="detail" :editFormFields="editFormFields"
+    :editFormOptions="editFormOptions" :searchFormFields="searchFormFields" :searchFormOptions="searchFormOptions"
+    :table="table" :tableExpand="tableExpand" :extend="extend">
+  </view-grid>
+</template>
+
+<script>
+import extend from "@/extension/stock/hcstockInfo.jsx";
+import {
+  defineComponent,
+  getCurrentInstance,
+  h,
+  reactive,
+  ref,
+  resolveComponent,
+} from "vue";
+
+const TEXT = {
+  pageName: "搴撳瓨淇℃伅",
+  palletCode: "鎵樼洏缂栧彿",
+  stockStatus: "搴撳瓨鐘舵��",
+  locationCode: "璐т綅缂栧彿",
+  outboundDate: "鍑哄簱鏃堕棿",
+  warehouse: "浠撳簱",
+  creator: "鍒涘缓浜�",
+  createDate: "鍒涘缓鏃堕棿",
+  modifier: "淇敼浜�",
+  modifyDate: "淇敼鏃堕棿",
+  detailName: "搴撳瓨鏄庣粏",
+  materielName: "鐗╂枡鍚嶇О",
+  serialNumber: "鐢佃姱鐮�",
+  stockQuantity: "搴撳瓨鏁伴噺",
+  status: "鐘舵��",
+  inboundOrderRowNo: "閫氶亾鍙�",
+  detailLoading: "搴撳瓨鏄庣粏鍔犺浇涓�...",
+  detailLoadFailed: "搴撳瓨鏄庣粏鍔犺浇澶辫触",
+  detailEmpty: "褰撳墠搴撳瓨澶存殏鏃犳槑缁嗘暟鎹�",
+  expandPrefix: "鎵樼洏锛�",
+  expandMiddle: " / ",
+  expandLocation: "璐т綅锛�",
+};
+
+export default defineComponent({
+  setup() {
+    const { proxy } = getCurrentInstance();
+    const ElTable = resolveComponent("el-table");
+    const ElTableColumn = resolveComponent("el-table-column");
+
+    const table = ref({
+      key: "id",
+      footer: "Foots",
+      cnName: TEXT.pageName,
+      name: "stockInfo",
+      url: "/StockInfo/",
+      sortName: "id",
+    });
+
+    const editFormFields = ref({
+      palletCode: "",
+      palletType: 0,
+      warehouseId: 0,
+      mesUploadStatus: "",
+      stockStatus: "",
+      locationCode: "",
+      locationDetails: ""
+    });
+
+
+    const editFormOptions = ref([
+      [
+        { field: "palletCode", title: TEXT.palletCode, type: "string" },
+        { field: "stockStatus", title: TEXT.stockStatus, type: "select", dataKey: "stockStatusEmun", data: [] },
+        { field: "locationCode", title: TEXT.locationCode, type: "string" },
+      ],
+    ]);
+
+    const searchFormFields = ref({
+      palletCode: "",
+      warehouseId: "",
+      stockStatus: "",
+      locationCode: "",
+    });
+
+    const searchFormOptions = ref([
+      [
+        { title: TEXT.palletCode, field: "palletCode", type: "like" },
+        { title: TEXT.warehouse, field: "warehouseId", type: "selectList", dataKey: "warehouseEnum", data: []  },
+        { title: TEXT.stockStatus, field: "stockStatus", type: "selectList", dataKey: "stockStatusEmun", data: [] },
+        { title: TEXT.locationCode, field: "locationCode", type: "like" },
+      ],
+    ]);
+
+    const columns = ref([
+      {
+        field: "id",
+        title: "Id",
+        type: "int",
+        width: 90,
+        hidden: true,
+        readonly: true,
+        require: true,
+        align: "left",
+      },
+      {
+        field: "palletCode",
+        title: TEXT.palletCode,
+        type: "string",
+        width: 150,
+        align: "left",
+      },
+      {
+        field: "stockStatus",
+        title: TEXT.stockStatus,
+        type: "int",
+        width: 120,
+        align: "left",
+        bind: { key: "stockStatusEmun", data: [] },
+      },
+      {
+        field: "mesUploadStatus",
+        title: "MES鐘舵��",
+        type: "int",
+        width: 120,
+        align: "left",
+        bind: { key: "mesUploadStatusEnum", data: [] },
+      },
+      {
+        field: "outboundDate",
+        title: TEXT.outboundDate,
+        type: "string",
+        width: 150,
+        align: "left",
+      }, 
+      {
+        field: "locationCode",
+        title: TEXT.locationCode,
+        type: "string",
+        width: 120,
+        align: "left",
+      },
+      {
+        field: "warehouseId",
+        title: TEXT.warehouse,
+        type: "select",
+        width: 100,
+        align: "left",
+        bind: { key: "warehouseEnum", data: [] },
+      },
+      {
+        field: "creater",
+        title: TEXT.creator,
+        type: "string",
+        width: 90,
+        align: "left",
+      },
+      {
+        field: "createDate",
+        title: TEXT.createDate,
+        type: "datetime",
+        width: 160,
+        align: "left",
+      },
+      {
+        field: "modifier",
+        title: TEXT.modifier,
+        type: "string",
+        width: 100,
+        align: "left",
+        hidden: true,
+      },
+      {
+        field: "modifyDate",
+        title: TEXT.modifyDate,
+        type: "datetime",
+        width: 160,
+        align: "left",
+        hidden: true,
+      },
+    ]);
+
+    const detail = ref({
+      cnName: "#detailCnName",
+      table: "",
+      columns: [],
+      sortName: "",
+    });
+
+    const detailState = reactive({
+      rowsMap: {},
+      loadingMap: {},
+      errorMap: {},
+    });
+
+    const stockStatusOptions = ref([]);
+
+    const detailColumns = [
+      { field: "materielName", title: TEXT.materielName, minWidth: 160 },
+      { field: "serialNumber", title: TEXT.serialNumber, minWidth: 160 },
+      { field: "stockQuantity", title: TEXT.stockQuantity, minWidth: 120 },
+      { field: "status", title: TEXT.status, minWidth: 120 },
+      { field: "inboundOrderRowNo", title: TEXT.inboundOrderRowNo, minWidth: 120 },
+    ];
+
+    const normalizeValue = (value) => {
+      return value === null || value === undefined || value === "" ? "--" : value;
+    };
+
+    const formatStatusText = (value) => {
+      const matched = stockStatusOptions.value.find((item) => `${item.key}` === `${value}`);
+      return matched ? matched.value || matched.label : normalizeValue(value);
+    };
+
+    const getDetailRows = (stockId) => {
+      return detailState.rowsMap[stockId] || [];
+    };
+
+    const loadDetailRows = async (row) => {
+      if (!row || !row.id || detailState.loadingMap[row.id]) {
+        return;
+      }
+      if (detailState.rowsMap[row.id]) {
+        return;
+      }
+
+      detailState.loadingMap[row.id] = true;
+      detailState.errorMap[row.id] = "";
+      try {
+        const result = await proxy.http.post("/api/StockInfoDetail/getPageData", {
+          page: 1,
+          rows: 200,
+          sort: "id",
+          order: "asc",
+          wheres: JSON.stringify([
+            {
+              name: "stockId",
+              value: String(row.id),
+              displayType: "int",
+            },
+          ]),
+        });
+        detailState.rowsMap[row.id] = (result && result.rows) || [];
+      } catch (error) {
+        detailState.rowsMap[row.id] = null;
+        detailState.errorMap[row.id] = error?.message || TEXT.detailLoadFailed;
+      } finally {
+        detailState.loadingMap[row.id] = false;
+      }
+    };
+
+    const loadStockStatusOptions = async () => {
+      try {
+        const result = await proxy.http.post("/api/Sys_Dictionary/GetVueDictionary", ["stockStatusEmun", "mesUploadStatusEnum"]);
+        const matched = (result || []).find((item) => item.dicNo === "stockStatusEmun");
+        stockStatusOptions.value = matched ? matched.data || [] : [];
+      } catch (error) {
+        stockStatusOptions.value = [];
+      }
+    };
+
+    loadStockStatusOptions();
+
+    const renderStatus = (row) => {
+      if (detailState.loadingMap[row.id]) {
+        return h("div", { class: "stock-detail-status" }, TEXT.detailLoading);
+      }
+      if (detailState.errorMap[row.id]) {
+        return h(
+          "div",
+          { class: "stock-detail-status stock-detail-status--error" },
+          detailState.errorMap[row.id]
+        );
+      }
+      return null;
+    };
+
+    const renderDetailTable = (row) => {
+      const statusNode = renderStatus(row);
+      if (statusNode) {
+        return statusNode;
+      }
+
+      const rows = getDetailRows(row.id);
+      if (!rows.length) {
+        return h("div", { class: "stock-detail-status" }, TEXT.detailEmpty);
+      }
+
+      return h("div", { class: "stock-detail-table-wrapper" }, [
+        h("div", { class: "stock-detail-toolbar" }, [
+          h("div", { class: "stock-detail-toolbar__left" }, TEXT.detailName),
+          h("div", { class: "stock-detail-toolbar__right" }, [
+            h("span", { class: "stock-detail-count" }, `${rows.length} 鏉),
+          ]),
+        ]),
+        h(
+          ElTable,
+          {
+            data: rows,
+            border: true,
+            stripe: true,
+            size: "small",
+            class: "stock-detail-el-table",
+            maxHeight: 420,
+            emptyText: TEXT.detailEmpty,
+          },
+          () =>
+            detailColumns.map((column) =>
+              h(ElTableColumn, {
+                key: column.field,
+                prop: column.field,
+                label: column.title,
+                minWidth: column.minWidth,
+                showOverflowTooltip: true,
+                formatter: (detailRow) =>
+                  column.field === "status"
+                    ? formatStatusText(detailRow[column.field])
+                    : normalizeValue(detailRow[column.field]),
+              })
+            )
+        ),
+      ]);
+    };
+
+    const tableExpand = ref({
+      width: 55,
+      onChange(row, expandedRows) {
+        const isExpanded = expandedRows.some((item) => item.id === row.id);
+        if (isExpanded) {
+          loadDetailRows(row);
+        }
+      },
+      render(render, { row }) {
+        return render("div", { class: "stock-detail-panel" }, [
+          render("div", { class: "stock-detail-header" }, [
+            render("div", { class: "stock-detail-header__main" }, [
+              render("div", { class: "stock-detail-title" }, TEXT.detailName),
+              render(
+                "div",
+                { class: "stock-detail-subtitle" },
+                `${TEXT.expandPrefix}${normalizeValue(row.palletCode)}${TEXT.expandMiddle}${TEXT.expandLocation}${normalizeValue(row.locationCode)}`
+              ),
+            ]),
+            // render("div", { class: "stock-detail-tags" }, [
+            //   render("span", { class: "stock-detail-tag" }, normalizeValue(row.palletCode)),
+            //   render(
+            //     "span",
+            //     { class: "stock-detail-tag stock-detail-tag--muted" },
+            //     normalizeValue(row.locationCode)
+            //   ),
+            // ]),
+          ]),
+          renderDetailTable(row),
+        ]);
+      },
+    });
+
+    return {
+      table,
+      extend,
+      editFormFields,
+      editFormOptions,
+      searchFormFields,
+      searchFormOptions,
+      columns,
+      detail,
+      tableExpand,
+    };
+  },
+});
+</script>
+
+<style scoped>
+.stock-detail-panel {
+  margin: 4px 8px 12px;
+  padding: 14px 16px 16px;
+  background: linear-gradient(180deg, #ffffff 0%, #fafbfc 100%);
+  border: 1px solid #e8edf3;
+  border-radius: 10px;
+  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
+}
+
+.stock-detail-header {
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
+  gap: 12px;
+  margin-bottom: 12px;
+  padding-bottom: 12px;
+  border-bottom: 1px solid #edf1f5;
+}
+
+.stock-detail-header__main {
+  min-width: 0;
+}
+
+.stock-detail-title {
+  margin-bottom: 4px;
+  font-size: 15px;
+  font-weight: 700;
+  color: #303133;
+}
+
+.stock-detail-subtitle {
+  font-size: 13px;
+  color: #606266;
+  line-height: 1.6;
+}
+
+.stock-detail-tags {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: flex-end;
+  gap: 8px;
+}
+
+.stock-detail-tag {
+  display: inline-flex;
+  align-items: center;
+  height: 28px;
+  padding: 0 10px;
+  color: #1f5eff;
+  background: #edf4ff;
+  border: 1px solid #d8e6ff;
+  border-radius: 999px;
+  font-size: 12px;
+  font-weight: 600;
+}
+
+.stock-detail-tag--muted {
+  color: #4e5969;
+  background: #f4f6f8;
+  border-color: #e5e9ef;
+}
+
+.stock-detail-status {
+  padding: 14px 12px;
+  color: #606266;
+  background: #f8fafc;
+  border: 1px dashed #d9e2ec;
+  border-radius: 8px;
+}
+
+.stock-detail-status--error {
+  color: #f56c6c;
+  background: #fef0f0;
+  border-color: #fde2e2;
+}
+
+.stock-detail-table-wrapper {
+  overflow-x: auto;
+  border: 1px solid #ebeef5;
+  border-radius: 8px;
+  background: #fff;
+}
+
+.stock-detail-toolbar {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 12px;
+  padding: 12px 14px;
+  background: #f8fafc;
+  border-bottom: 1px solid #edf1f5;
+}
+
+.stock-detail-toolbar__left {
+  font-size: 13px;
+  font-weight: 600;
+  color: #303133;
+}
+
+.stock-detail-count {
+  display: inline-flex;
+  align-items: center;
+  height: 24px;
+  padding: 0 10px;
+  color: #606266;
+  background: #fff;
+  border: 1px solid #e5e9ef;
+  border-radius: 999px;
+  font-size: 12px;
+}
+
+:deep(.stock-detail-el-table) {
+  border-top: none;
+}
+
+:deep(.stock-detail-el-table .el-table__inner-wrapper::before) {
+  display: none;
+}
+
+:deep(.stock-detail-el-table th.el-table__cell) {
+  background: #f5f7fa;
+  color: #303133;
+  font-weight: 600;
+}
+
+:deep(.stock-detail-el-table td.el-table__cell) {
+  color: #606266;
+}
+
+:deep(.stock-detail-el-table .el-table__body tr:hover > td.el-table__cell) {
+  background: #f0f7ff;
+}
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue b/Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue
index 789e395..b4ab422 100644
--- a/Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue
+++ b/Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue
@@ -21,6 +21,7 @@
   palletCode: "鎵樼洏缂栧彿",
   stockStatus: "搴撳瓨鐘舵��",
   locationCode: "璐т綅缂栧彿",
+  locationId: "璐т綅id",
   outboundDate: "鍑哄簱鏃堕棿",
   warehouse: "浠撳簱",
   creator: "鍒涘缓浜�",
@@ -63,7 +64,8 @@
       mesUploadStatus: "",
       stockStatus: "",
       locationCode: "",
-      locationDetails: ""
+      locationDetails: "",
+      locationId: "",
     });
 
 
@@ -72,11 +74,13 @@
         { field: "palletCode", title: TEXT.palletCode, type: "string" },
         { field: "stockStatus", title: TEXT.stockStatus, type: "select", dataKey: "stockStatusEmun", data: [] },
         { field: "locationCode", title: TEXT.locationCode, type: "string" },
+        { field: "locationId", title: TEXT.locationId, type: "string"},
       ],
     ]);
 
     const searchFormFields = ref({
       palletCode: "",
+      warehouseId: "",
       stockStatus: "",
       locationCode: "",
     });
@@ -84,6 +88,7 @@
     const searchFormOptions = ref([
       [
         { title: TEXT.palletCode, field: "palletCode", type: "like" },
+        { title: TEXT.warehouse, field: "warehouseId", type: "selectList", dataKey: "warehouseEnum", data: []  },
         { title: TEXT.stockStatus, field: "stockStatus", type: "selectList", dataKey: "stockStatusEmun", data: [] },
         { title: TEXT.locationCode, field: "locationCode", type: "like" },
       ],
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs
index da08436..cffe42d 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs
@@ -2,6 +2,7 @@
 using Microsoft.AspNetCore.Mvc;
 using SqlSugar;
 using WIDESEA_Common.LocationEnum;
+using WIDESEA_Common.StockEnum;
 using WIDESEA_Core;
 using WIDESEA_Model.Models;
 
@@ -218,7 +219,7 @@
         /// 鎸夊勾鏈堢粺璁″叆绔欏拰鍑虹珯浠诲姟鏁伴噺
         /// </remarks>
         [HttpGet("MonthlyStats"), AllowAnonymous]
-        public async Task<WebResponseContent> MonthlyStats([FromQuery] int months = 12, string Roadway = null)
+        public async Task<WebResponseContent> MonthlyStats(int months, string roadway)
         {
             try
             {
@@ -230,11 +231,12 @@
                 // 浠撳簱鍚嶇О鏄犲皠
                 var roadwayNames = new Dictionary<string, string>
         {
-            { "FJSC1", "璐熸瀬鍗�1鍙蜂粨搴�" },
-            { "ZJSC1", "姝f瀬鍗�1鍙蜂粨搴�" },
+
             { "GWSC1", "楂樻俯1鍙蜂粨搴�" },
             { "CWSC1", "甯告俯1鍙蜂粨搴�" },
-            { "HCSC1", "鍒嗗1鍙蜂粨搴�" }
+            { "HCSC1", "鍒嗗1鍙蜂粨搴�" },
+            { "FJSC1", "璐熸瀬鍗�1鍙蜂粨搴�" },
+            { "ZJSC1", "姝f瀬鍗�1鍙蜂粨搴�" },
         };
 
                 // 鏋勫缓鏌ヨ
@@ -242,9 +244,9 @@
                     .Where(t => t.InsertTime >= startDate);
 
                 // 濡傛灉鎸囧畾浜嗛亾璺紝娣诲姞閬撹矾杩囨护鏉′欢
-                if (!string.IsNullOrEmpty(Roadway))
+                if (!string.IsNullOrEmpty(roadway))
                 {
-                    query = query.Where(t => t.Roadway == Roadway);
+                    query = query.Where(t => t.Roadway == roadway);
                 }
 
                 var monthlyStats = await query
@@ -294,9 +296,9 @@
                             Month = monthKey,
                             Inbound = stat.Inbound,
                             Outbound = stat.Outbound,
-                            Roadway = Roadway,
-                            RoadwayName = !string.IsNullOrEmpty(Roadway) && roadwayNames.ContainsKey(Roadway)
-                                ? roadwayNames[Roadway]
+                            Roadway = roadway,
+                            RoadwayName = !string.IsNullOrEmpty(roadway) && roadwayNames.ContainsKey(roadway)
+                                ? roadwayNames[roadway]
                                 : null
                         });
                     }
@@ -307,9 +309,9 @@
                             Month = monthKey,
                             Inbound = 0,
                             Outbound = 0,
-                            Roadway = Roadway,
-                            RoadwayName = !string.IsNullOrEmpty(Roadway) && roadwayNames.ContainsKey(Roadway)
-                                ? roadwayNames[Roadway]
+                            Roadway = roadway,
+                            RoadwayName = !string.IsNullOrEmpty(roadway) && roadwayNames.ContainsKey(roadway)
+                                ? roadwayNames[roadway]
                                 : null
                         });
                     }
@@ -414,5 +416,87 @@
                 return WebResponseContent.Instance.Error($"鍚勪粨搴撳簱瀛樺垎甯冭幏鍙栧け璐�: {ex.Message}");
             }
         }
+        /// <summary>
+        /// 鏌ヨ鍚勪粨搴撶數姹�/鏈夎揣鏁伴噺鍜岀┖鎵樼洏鏁伴噺
+        /// </summary>
+        /// <remarks>
+        /// 浠撳簱ID瑙勫垯锛�1=楂樻俯搴�, 2=甯告俯搴�, 3=鍖栨垚搴�, 6/7=鏋佸嵎搴�
+        /// <br/>
+        /// 缁熻瑙勫垯锛�
+        /// <br/>
+        /// - 楂樻俯/甯告俯/鍖栨垚搴擄細缁熻 鐢垫睜鏁伴噺(StockStatus=6) 鍜� 绌烘墭鐩樻暟閲�(StockStatus=22)
+        /// <br/>
+        /// - 鏋佸嵎搴�(6/7)锛氱粺璁� 鏈夎揣鏁伴噺(StockStatus鈮�22) 鍜� 绌烘墭鐩樻暟閲�(StockStatus=22)
+        /// <br/>
+        /// 閫氳繃杩斿洖鏁版嵁涓殑 StockStatus 鍜� Count 鍙互杩涗竴姝ユ煡璇㈡槑缁嗙數姹犮��
+        /// </remarks>
+        [HttpGet("StockAndTrayCount"), AllowAnonymous]
+        public async Task<WebResponseContent> StockAndTrayCount()
+        {
+            try
+            {
+                var warehouseIds = new[] { 1, 2, 3, 6, 7 };
+
+                var warehouseNames = new Dictionary<int, string>
+        {
+            { 1, "楂樻俯搴�" },
+            { 2, "甯告俯搴�" },
+            { 3, "鍖栨垚搴�" },
+            { 6, "鏋佸嵎搴�" },
+            { 7, "鏋佸嵎搴�" }
+        };
+
+                var result = new List<object>();
+
+                foreach (var warehouseId in warehouseIds)
+                {
+                    var warehouseName = warehouseNames.GetValueOrDefault(warehouseId, $"浠撳簱{warehouseId}");
+
+                    if (warehouseId == 6 || warehouseId == 7)
+                    {
+                        var totalCount = await _db.Queryable<Dt_StockInfo>()
+                            .Where(s => s.WarehouseId == warehouseId)
+                            .CountAsync();
+
+                        var emptyTrayCount = await _db.Queryable<Dt_StockInfo>()
+                            .Where(s => s.WarehouseId == warehouseId && s.StockStatus == (int)StockStatusEmun.绌烘墭鐩樺簱瀛�)
+                            .CountAsync();
+
+                        result.Add(new
+                        {
+                            WarehouseId = warehouseId,
+                            WarehouseName = warehouseName,
+                            HasGoodsCount = totalCount - emptyTrayCount,
+                            EmptyTrayCount = emptyTrayCount,
+                        });
+                    }
+                    else
+                    {
+                        var batteryCount = await _db.Queryable<Dt_StockInfo>()
+                            .Where(s => s.WarehouseId == warehouseId && s.StockStatus == (int)StockStatusEmun.鍏ュ簱瀹屾垚)
+                            .LeftJoin<Dt_StockInfoDetail>((s, d) => s.Id == d.StockId)
+                            .CountAsync();
+
+                        var emptyTrayCount = await _db.Queryable<Dt_StockInfo>()
+                            .Where(s => s.WarehouseId == warehouseId && s.StockStatus == (int)StockStatusEmun.绌烘墭鐩樺簱瀛�)
+                            .CountAsync();
+
+                        result.Add(new
+                        {
+                            WarehouseId = warehouseId,
+                            WarehouseName = warehouseName,
+                            BatteryCount = batteryCount,
+                            EmptyTrayCount = emptyTrayCount,
+                        });
+                    }
+                }
+
+                return WebResponseContent.Instance.OK(null, result);
+            }
+            catch (Exception ex)
+            {
+                return WebResponseContent.Instance.Error($"鐢垫睜鍜岀┖鎵樼洏鏁伴噺鏌ヨ澶辫触: {ex.Message}");
+            }
+        }
     }
 }
\ No newline at end of file
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
index fc7e7ae..c3cbc40 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
@@ -64,7 +64,7 @@
   "PDAVersion": "4",
   "WebSocketPort": 9296,
   "AutoOutboundTask": {
-    "Enable": true, /// 鏄惁鍚敤鑷姩鍑哄簱浠诲姟
+    "Enable": false, /// 鏄惁鍚敤鑷姩鍑哄簱浠诲姟
     "CheckIntervalSeconds": 300, /// 妫�鏌ラ棿闅旓紙绉掞級
     "TargetAddresses": { /// 鎸夊贩閬撳墠缂�閰嶇疆鐩爣鍦板潃锛堟敮鎸佸鍑哄簱鍙o級
       "GW": [ "11001", "11010", "11068" ],

--
Gitblit v1.9.3