wanshenmean
2026-03-18 5c766d7e5c969b7530a014ded771973e242f25e0
refactor: 拆分 TaskService 任务流程并补充注释

改动清单:

1. TaskService 改为编排层:注入并按任务分组委托入库/出库/移库/机械手流程服务。

2. 抽离接收初始化逻辑:新增 InitializeTaskOnReceive,ReceiveWMSTask 不再内嵌分组初始化细节。

3. 抽离状态推进逻辑:UpdateTaskStatusToNext 改为委托流程服务,保留统一落库与执行明细记录。

4. 抽离堆垛机完成逻辑:StackCraneTaskCompleted 改为委托流程服务并统一处理完成后的落库策略。

5. 新增流程接口:IInboundTaskFlowService、IOutboundTaskFlowService、IRelocationTaskFlowService、IRobotTaskFlowService。

6. 新增流程实现:InboundTaskFlowService、OutboundTaskFlowService、RelocationTaskFlowService、RobotTaskFlowService。

7. 补充注释:为新增接口/实现及关键重构方法补充类、方法、参数、返回值说明与关键分支注释。

8. 配套调整 RobotTaskService 的可访问性(供流程服务复用规则解析/入参构建能力)。
已添加8个文件
已修改2个文件
1086 ■■■■■ 文件已修改
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IInboundTaskFlowService.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IOutboundTaskFlowService.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRelocationTaskFlowService.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskFlowService.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RelocationTaskFlowService.cs 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RobotTaskFlowService.cs 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs 416 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IInboundTaskFlowService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Core;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_ITaskInfoService
{
    /// <summary>
    /// å…¥åº“任务流程服务接口。
    /// </summary>
    public interface IInboundTaskFlowService : IDependency
    {
        /// <summary>
        /// æŽ¥æ”¶WMS任务时初始化入库任务。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        /// <summary>
        /// æŽ¨è¿›å…¥åº“任务到下一状态。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>推进结果。</returns>
        WebResponseContent MoveToNextStatus([NotNull] Dt_Task task);
        /// <summary>
        /// å¤„理堆垛机入库完成动作。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>处理结果。</returns>
        WebResponseContent CompleteStackerTask([NotNull] Dt_Task task);
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IOutboundTaskFlowService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Core;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_ITaskInfoService
{
    /// <summary>
    /// å‡ºåº“任务流程服务接口。
    /// </summary>
    public interface IOutboundTaskFlowService : IDependency
    {
        /// <summary>
        /// æŽ¥æ”¶WMS任务时初始化出库任务。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        /// <summary>
        /// æŽ¨è¿›å‡ºåº“任务到下一状态。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>推进结果。</returns>
        WebResponseContent MoveToNextStatus([NotNull] Dt_Task task);
        /// <summary>
        /// å¤„理堆垛机出库完成动作。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>处理结果。</returns>
        WebResponseContent CompleteStackerTask([NotNull] Dt_Task task);
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRelocationTaskFlowService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Core;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_ITaskInfoService
{
    /// <summary>
    /// ç§»åº“任务流程服务接口。
    /// </summary>
    public interface IRelocationTaskFlowService : IDependency
    {
        /// <summary>
        /// æŽ¥æ”¶WMS任务时初始化移库任务。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        /// <summary>
        /// æŽ¨è¿›ç§»åº“任务到下一状态。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>推进结果。</returns>
        WebResponseContent MoveToNextStatus([NotNull] Dt_Task task);
        /// <summary>
        /// å¤„理堆垛机移库完成动作。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>处理结果。</returns>
        WebResponseContent CompleteStackerTask([NotNull] Dt_Task task);
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskFlowService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Core;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_ITaskInfoService
{
    /// <summary>
    /// æœºæ¢°æ‰‹ä»»åŠ¡æµç¨‹æœåŠ¡æŽ¥å£ã€‚
    /// </summary>
    public interface IRobotTaskFlowService : IDependency
    {
        /// <summary>
        /// æŽ¥æ”¶WMS任务时初始化机械手任务。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        /// <summary>
        /// æŽ¨è¿›æœºæ¢°æ‰‹ä»»åŠ¡åˆ°ä¸‹ä¸€çŠ¶æ€ã€‚
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>推进结果。</returns>
        WebResponseContent MoveToNextStatus([NotNull] Dt_Task task);
        /// <summary>
        /// å¤„理堆垛机动作。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>处理结果。</returns>
        WebResponseContent CompleteStackerTask([NotNull] Dt_Task task);
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,148 @@
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEA_Core;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
namespace WIDESEAWCS_TaskInfoService.Flows
{
    /// <summary>
    /// å…¥åº“任务流程服务。
    /// è´Ÿè´£å…¥åº“任务接收初始化、状态推进及堆垛机完成处理。
    /// </summary>
    public class InboundTaskFlowService : IInboundTaskFlowService
    {
        private readonly IRouterService _routerService;
        private readonly HttpClientHelper _httpClientHelper;
        /// <summary>
        /// åˆå§‹åŒ–入库任务流程服务。
        /// </summary>
        /// <param name="routerService">路由服务。</param>
        /// <param name="httpClientHelper">WMS接口调用帮助类。</param>
        public InboundTaskFlowService(IRouterService routerService, HttpClientHelper httpClientHelper)
        {
            _routerService = routerService;
            _httpClientHelper = httpClientHelper;
        }
        /// <summary>
        /// æŽ¥æ”¶WMS任务时初始化入库任务。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        public void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        {
            Dt_Router routers = _routerService.QueryNextRoute(source.SourceAddress);
            if (routers.IsNullOrEmpty())
            {
                return;
            }
            task.TaskStatus = (int)TaskInStatusEnum.InNew;
            task.CurrentAddress = source.SourceAddress;
            task.NextAddress = routers.ChildPosi;
        }
        /// <summary>
        /// æŽ¨è¿›å…¥åº“任务状态,并在关键状态调用WMS接口。
        /// </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)
            {
                return content.Error($"通知WMS系统堆垛机入库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            }
            return content.Error($"通知WMS系统堆垛机入库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
        }
        /// <summary>
        /// ä»ŽWMS获取入库目标地址并回写任务。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>调用结果。</returns>
        private WebResponseContent GetWMSInboundLocation(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.GetTasksLocation),
                new CreateTaskDto { PalletCode = task.PalletCode }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"调用WMS接口获取任务目标地址失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            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>
        /// å°†ä»»åŠ¡çŠ¶æ€åŒæ­¥åˆ°WMS。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>同步结果。</returns>
        private WebResponseContent UpdateWMSTaskStatus(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.UpdateTaskByStatus),
                new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"调用WMS接口更新任务状态失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            return WebResponseContent.Instance.OK();
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,187 @@
using Newtonsoft.Json;
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEA_Core;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO;
using WIDESEAWCS_DTO.Stock;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.DTO;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
namespace WIDESEAWCS_TaskInfoService.Flows
{
    /// <summary>
    /// å‡ºåº“任务流程服务。
    /// è´Ÿè´£å‡ºåº“任务接收初始化、状态推进及堆垛机完成处理。
    /// </summary>
    public class OutboundTaskFlowService : IOutboundTaskFlowService
    {
        private readonly IRouterService _routerService;
        private readonly HttpClientHelper _httpClientHelper;
        private readonly IRobotTaskService _robotTaskService;
        /// <summary>
        /// åˆå§‹åŒ–出库任务流程服务。
        /// </summary>
        /// <param name="routerService">路由服务。</param>
        /// <param name="httpClientHelper">WMS接口调用帮助类。</param>
        /// <param name="robotTaskService">机械手任务服务。</param>
        public OutboundTaskFlowService(IRouterService routerService, HttpClientHelper httpClientHelper, IRobotTaskService robotTaskService)
        {
            _routerService = routerService;
            _httpClientHelper = httpClientHelper;
            _robotTaskService = robotTaskService;
        }
        /// <summary>
        /// æŽ¥æ”¶WMS任务时初始化出库任务。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        public void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        {
            int taskType = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty ? 100 : task.TaskType;
            Dt_Router router = _routerService.QueryNextRoute(source.Roadway, source.TargetAddress, taskType);
            if (router == null)
            {
                return;
            }
            task.TaskStatus = (int)TaskOutStatusEnum.OutNew;
            task.CurrentAddress = source.SourceAddress;
            task.NextAddress = router.ChildPosi;
        }
        /// <summary>
        /// æŽ¨è¿›å‡ºåº“任务状态,并在关键状态调用WMS接口。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>推进结果。</returns>
        public WebResponseContent MoveToNextStatus([NotNull] Dt_Task task)
        {
            if (task.TaskStatus >= (int)TaskOutStatusEnum.OutFinish)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskOutStatusEnum>();
            if (task.TaskStatus <= 0)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound)
            {
                return GetWMSOutboundTrayTask(task);
            }
            if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
            {
                return _robotTaskService.GetWMSRobotTask(task);
            }
            if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutExecuting)
            {
                return WebResponseContent.Instance.OK();
            }
            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)TaskOutStatusEnum.SC_OutExecuting)
            {
                return WebResponseContent.Instance.OK();
            }
            int taskType = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty ? 100 : task.TaskType;
            Dt_Router router = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress, taskType);
            if (router == null)
            {
                return WebResponseContent.Instance.Error("未找到设备路由信息");
            }
            int nextStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskOutStatusEnum>();
            task.TaskStatus = nextStatus;
            task.CurrentAddress = task.NextAddress;
            task.NextAddress = router.ChildPosi;
            task.ModifyDate = DateTime.Now;
            task.Modifier = "System";
            content = NotifyWMSOutboundFinish(task);
            if (!content.Status)
            {
                return content;
            }
            return content.Error($"通知WMS系统堆垛机出库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
        }
        /// <summary>
        /// é€šçŸ¥WMS出库完成。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>通知结果。</returns>
        private WebResponseContent NotifyWMSOutboundFinish(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.OutboundFinishTaskAsync),
                new StockInfoDTO { PalletCode = task.PalletCode, TaskNum = task.TaskNum }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"通知WMS系统堆垛机出库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// ä»ŽWMS获取空托盘出库任务。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>调用结果,成功时Data中包含一个WMSTaskDTO集合。</returns>
        private WebResponseContent GetWMSOutboundTrayTask(Dt_Task task)
        {
            int warehouseId = _robotTaskService.MapWarehouseIdConfigKey(task.TargetAddress);
            string sourceLineNo = _robotTaskService.ResolveRobotRuleValue(task.TargetAddress, "AddressSourceLineNoMap", task.TargetAddress);
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.GetOutBoundTrayTaskAsync),
                new CreateTaskDto { WarehouseId = warehouseId, TargetAddress = sourceLineNo }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"获取WMS系统空托盘出库任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            WMSTaskDTO? wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data?.ToString() ?? string.Empty);
            if (wMSTask == null)
                return WebResponseContent.Instance.Error($"获取WMS系统空托盘出库任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【WMS未返回有效任务数据】");
            return WebResponseContent.Instance.OK("成功", new List<WMSTaskDTO> { wMSTask });
        }
        /// <summary>
        /// å°†ä»»åŠ¡çŠ¶æ€åŒæ­¥åˆ°WMS。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>同步结果。</returns>
        private WebResponseContent UpdateWMSTaskStatus(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.UpdateTaskByStatus),
                new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"调用WMS接口更新任务状态失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            return WebResponseContent.Instance.OK();
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RelocationTaskFlowService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,137 @@
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEA_Core;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_TaskInfoService.Flows
{
    /// <summary>
    /// ç§»åº“任务流程服务。
    /// è´Ÿè´£ç§»åº“任务接收初始化、状态推进以及堆垛机完成时的WMS通知流程。
    /// </summary>
    public class RelocationTaskFlowService : IRelocationTaskFlowService
    {
        private readonly HttpClientHelper _httpClientHelper;
        /// <summary>
        /// åˆå§‹åŒ–移库任务流程服务。
        /// </summary>
        /// <param name="httpClientHelper">WMS接口调用帮助类。</param>
        public RelocationTaskFlowService(HttpClientHelper httpClientHelper)
        {
            _httpClientHelper = httpClientHelper;
        }
        /// <summary>
        /// æŽ¥æ”¶WMS任务时初始化移库任务。
        /// å½“前移库任务不做额外初始化。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        public void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        {
            // å½“前版本移库任务接收时不需要额外设置路由或状态。
        }
        /// <summary>
        /// å°†ç§»åº“任务推进到下一状态,并在关键状态调用WMS接口。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>状态推进结果。</returns>
        public WebResponseContent MoveToNextStatus([NotNull] Dt_Task task)
        {
            if (task.TaskStatus >= (int)TaskRelocationStatusEnum.RelocationFinish)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskRelocationStatusEnum>();
            if (task.TaskStatus <= 0)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            if (task.TaskStatus == (int)TaskRelocationStatusEnum.SC_RelocationExecuting)
            {
                return UpdateWMSTaskStatus(task);
            }
            if (task.TaskStatus == (int)TaskRelocationStatusEnum.RelocationFinish)
            {
                return NotifyWMSRelocationFinish(task);
            }
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// å¤„理堆垛机移库完成动作。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>处理结果。</returns>
        public WebResponseContent CompleteStackerTask([NotNull] Dt_Task task)
        {
            WebResponseContent content = new WebResponseContent();
            if (task.TaskStatus != (int)TaskRelocationStatusEnum.SC_RelocationExecuting)
            {
                return WebResponseContent.Instance.OK();
            }
            int nextStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskRelocationStatusEnum>();
            task.TaskStatus = nextStatus;
            task.ModifyDate = DateTime.Now;
            task.Modifier = "System";
            WebResponseContent result = NotifyWMSRelocationFinish(task);
            if (!result.Status)
            {
                return content.Error($"通知WMS系统堆垛机移库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Message}】");
            }
            return content.Error($"通知WMS系统堆垛机移库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
        }
        /// <summary>
        /// å°†ç§»åº“状态同步到WMS。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>同步结果。</returns>
        private WebResponseContent UpdateWMSTaskStatus(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.UpdateTaskByStatus),
                new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"调用WMS接口更新任务状态失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// é€šçŸ¥WMS移库任务已完成。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>通知结果。</returns>
        private WebResponseContent NotifyWMSRelocationFinish(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.RelocationFinishTask),
                new CreateTaskDto
                {
                    PalletCode = task.PalletCode,
                    SourceAddress = task.CurrentAddress,
                    TargetAddress = task.TargetAddress,
                    Roadway = task.Roadway,
                    TaskType = task.TaskType
                }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"通知WMS系统移库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            return WebResponseContent.Instance.OK();
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RobotTaskFlowService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_TaskInfoService.Flows
{
    /// <summary>
    /// æœºæ¢°æ‰‹ä»»åŠ¡æµç¨‹æœåŠ¡ã€‚
    /// è´Ÿè´£æœºæ¢°æ‰‹ä»»åŠ¡åœ¨ä¸»æµç¨‹ä¸­çš„çŠ¶æ€æŽ¨è¿›ä¸Žå®Œæˆå¤„ç†ã€‚
    /// </summary>
    public class RobotTaskFlowService : IRobotTaskFlowService
    {
        /// <summary>
        /// æŽ¥æ”¶WMS任务时初始化机械手任务。
        /// å½“前机械手任务不做额外初始化。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        public void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        {
            // å½“前版本机械手任务接收时不需要额外设置路由或状态。
        }
        /// <summary>
        /// æŽ¨è¿›æœºæ¢°æ‰‹ä»»åŠ¡çŠ¶æ€ã€‚
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>推进结果。</returns>
        public WebResponseContent MoveToNextStatus([NotNull] Dt_Task task)
        {
            if (task.TaskStatus >= (int)TaskRobotStatusEnum.RobotFinish)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskRobotStatusEnum>();
            if (task.TaskStatus <= 0)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// å¤„理堆垛机动作。
        /// æœºæ¢°æ‰‹ä»»åŠ¡å½“å‰æ— é¢å¤–å®Œæˆé€»è¾‘ã€‚
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>处理结果。</returns>
        public WebResponseContent CompleteStackerTask([NotNull] Dt_Task task)
        {
            return WebResponseContent.Instance.OK();
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -174,7 +174,7 @@
        /// å°†é…ç½®ä»»åŠ¡ç±»åž‹è½¬æ¢ä¸ºæŽ¥å£é…ç½®é”®ã€‚
        /// æ”¯æŒå€¼ï¼šSplit/Group/Change(大小写不敏感)
        /// </summary>
        private string MapRobotTaskTypeToConfigKey(string? taskType)
        public string MapRobotTaskTypeToConfigKey(string? taskType)
        {
            string type = (taskType ?? string.Empty).Trim().ToLowerInvariant();
            return type switch
@@ -188,7 +188,7 @@
        /// <summary>
        /// æ ¹æ®æŽ¥å£ç±»åž‹æž„建机械手任务入参。
        /// </summary>
        private StockDTO BuildRobotTaskStock(Dt_Task task, string configKey)
        public StockDTO BuildRobotTaskStock(Dt_Task task, string configKey)
        {
            string targetAddress = task.TargetAddress ?? string.Empty;
            string roadway = ResolveRobotRuleValue(targetAddress, "AddressRoadwayMap", task.Roadway);
@@ -231,7 +231,7 @@
        /// <summary>
        /// æ ¹æ®ç›®æ ‡åœ°å€æŒ‰ã€Œç²¾ç¡® > å›žé€€å€¼ã€è§£æžè§„则值。
        /// </summary>
        private string ResolveRobotRuleValue(string? targetAddress, string addressSectionName, string? fallback)
        public string ResolveRobotRuleValue(string? targetAddress, string addressSectionName, string? fallback)
        {
            string address = (targetAddress ?? string.Empty).Trim();
            string defaultValue = fallback ?? string.Empty;
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
@@ -18,14 +18,10 @@
#endregion << ç‰ˆ æœ¬ æ³¨ é‡Š >>
using MapsterMapper;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using SqlSugar;
using System.Diagnostics.CodeAnalysis;
using WIDESEA_Core;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseServices;
@@ -51,8 +47,10 @@
        private readonly ITaskExecuteDetailService _taskExecuteDetailService;
        private readonly ITaskExecuteDetailRepository _taskExecuteDetailRepository;
        private readonly IMapper _mapper;
        private readonly HttpClientHelper _httpClientHelper;
        private readonly IRobotTaskService _robotTaskService;
        private readonly IOutboundTaskFlowService _outboundTaskFlowService;
        private readonly IInboundTaskFlowService _inboundTaskFlowService;
        private readonly IRelocationTaskFlowService _relocationTaskFlowService;
        private readonly IRobotTaskFlowService _robotTaskFlowService;
        private Dictionary<string, OrderByType> _taskOrderBy = new()
            {
@@ -71,14 +69,25 @@
        public List<int> TaskRobotTypes => typeof(TaskOtherTypeEnum).GetEnumIndexList();
        public TaskService(ITaskRepository BaseDal, IRouterService routerService, ITaskExecuteDetailService taskExecuteDetailService, ITaskExecuteDetailRepository taskExecuteDetailRepository, IMapper mapper, HttpClientHelper httpClientHelper, IRobotTaskService robotTaskService) : base(BaseDal)
        public TaskService(
            ITaskRepository BaseDal,
            IRouterService routerService,
            ITaskExecuteDetailService taskExecuteDetailService,
            ITaskExecuteDetailRepository taskExecuteDetailRepository,
            IMapper mapper,
            IOutboundTaskFlowService outboundTaskFlowService,
            IInboundTaskFlowService inboundTaskFlowService,
            IRelocationTaskFlowService relocationTaskFlowService,
            IRobotTaskFlowService robotTaskFlowService) : base(BaseDal)
        {
            _routerService = routerService;
            _taskExecuteDetailService = taskExecuteDetailService;
            _taskExecuteDetailRepository = taskExecuteDetailRepository;
            _mapper = mapper;
            _httpClientHelper = httpClientHelper;
            _robotTaskService = robotTaskService;
            _outboundTaskFlowService = outboundTaskFlowService;
            _inboundTaskFlowService = inboundTaskFlowService;
            _relocationTaskFlowService = relocationTaskFlowService;
            _robotTaskFlowService = robotTaskFlowService;
        }
        /// <summary>
@@ -100,35 +109,7 @@
                    }
                    Dt_Task task = _mapper.Map<Dt_Task>(item);
                    task.Creater = "WMS";
                    if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
                    {
                        int taskType = 0;
                        if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
                        {
                            taskType = 100;
                        }
                        else
                            taskType = task.TaskType;
                        Dt_Router router = _routerService.QueryNextRoute(item.Roadway, item.TargetAddress, taskType);
                        //暂不考虑多路径
                        if (router != null)
                        {
                            task.TaskStatus = (int)TaskOutStatusEnum.OutNew;
                            task.CurrentAddress = item.SourceAddress;
                            task.NextAddress = router.ChildPosi;
                        }
                    }
                    else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup)
                    {
                        Dt_Router routers = _routerService.QueryNextRoute(item.SourceAddress);
                        //暂不考虑多路径
                        if (!routers.IsNullOrEmpty())
                        {
                            task.TaskStatus = (int)TaskInStatusEnum.InNew;
                            task.CurrentAddress = item.SourceAddress;
                            task.NextAddress = routers.ChildPosi;
                        }
                    }
                    InitializeTaskOnReceive(task, item);
                    tasks.Add(task);
                }
                BaseDal.AddData(tasks);
@@ -175,6 +156,32 @@
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// æŒ‰ä»»åŠ¡åˆ†ç»„åˆå§‹åŒ–ä»»åŠ¡æŽ¥æ”¶ä¿¡æ¯ã€‚
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS原始任务对象。</param>
        private void InitializeTaskOnReceive(Dt_Task task, WMSTaskDTO source)
        {
            switch (task.TaskType.GetTaskTypeGroup())
            {
                case TaskTypeGroup.OutbondGroup:
                    _outboundTaskFlowService.InitializeOnReceive(task, source);
                    break;
                case TaskTypeGroup.InboundGroup:
                    _inboundTaskFlowService.InitializeOnReceive(task, source);
                    break;
                case TaskTypeGroup.RelocationGroup:
                    _relocationTaskFlowService.InitializeOnReceive(task, source);
                    break;
                case TaskTypeGroup.OtherGroup:
                    _robotTaskFlowService.InitializeOnReceive(task, source);
                    break;
                default:
                    break;
            }
        }
        /// <summary>
@@ -369,15 +376,23 @@
            var result = task.TaskType.GetTaskTypeGroup() switch
            {
                TaskTypeGroup.OutbondGroup => ProcessOutboundTaskStatus(task),
                TaskTypeGroup.InboundGroup => ProcessInboundTaskStatus(task),
                TaskTypeGroup.RelocationGroup => ProcessRelocationTaskStatus(task),
                TaskTypeGroup.OtherGroup => ProcessRobotTaskStatus(task),
                TaskTypeGroup.OutbondGroup => _outboundTaskFlowService.MoveToNextStatus(task),
                TaskTypeGroup.InboundGroup => _inboundTaskFlowService.MoveToNextStatus(task),
                TaskTypeGroup.RelocationGroup => _relocationTaskFlowService.MoveToNextStatus(task),
                TaskTypeGroup.OtherGroup => _robotTaskFlowService.MoveToNextStatus(task),
                _ => WebResponseContent.Instance.Error($"任务类型错误,未找到该任务类型,任务号:【{task.TaskNum}】,任务类型:【{task.TaskType}】")
            };
            if (!result.Status)
                return result;
            // å‡ºåº“完成线体节点时,可能需要接收入库新任务。
            if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup
                && result.Data is List<WMSTaskDTO> wmsTasks
                && wmsTasks.Count > 0)
            {
                return ReceiveWMSTask(wmsTasks);
            }
            // æ›´æ–°ä»»åŠ¡æ•°æ®
            task.ModifyDate = DateTime.Now;
@@ -396,209 +411,6 @@
                ? $"人工手动将任务状态从【{oldState}】跳转到【{task.TaskStatus}】"
                : $"系统自动流程,任务状态从【{oldState}】转到【{task.TaskStatus}】";
            _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, logMessage);
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// å¤„理出库任务状态转换
        /// </summary>
        private WebResponseContent ProcessOutboundTaskStatus(Dt_Task task)
        {
            if (task.TaskStatus >= (int)TaskOutStatusEnum.OutFinish)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskOutStatusEnum>();
            if (task.TaskStatus <= 0)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            // æ ¹æ®çŠ¶æ€è°ƒç”¨ä¸åŒçš„WMS接口
            if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound)
            {
                return GetWMSOutboundTrayTask(task);
            }
            else if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
            {
                return _robotTaskService.GetWMSRobotTask(task);
            }
            else
            {
                if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutExecuting)
                    return WebResponseContent.Instance.OK();
                else
                    return UpdateWMSTaskStatus(task);
            }
        }
        /// <summary>
        /// å¤„理入库任务状态转换
        /// </summary>
        private WebResponseContent ProcessInboundTaskStatus(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}】");
            // æ ¹æ®çŠ¶æ€è°ƒç”¨ä¸åŒçš„WMS接口
            if (task.TaskStatus == (int)TaskInStatusEnum.Line_InFinish)
            {
                return GetWMSInboundLocation(task);
            }
            else
            {
                return UpdateWMSTaskStatus(task);
            }
        }
        /// <summary>
        /// å¤„理机械手任务状态转换
        /// </summary>
        private WebResponseContent ProcessRobotTaskStatus(Dt_Task task)
        {
            if (task.TaskStatus >= (int)TaskRobotStatusEnum.RobotFinish)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskRobotStatusEnum>();
            if (task.TaskStatus <= 0)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// å¤„理移库任务状态转换
        /// </summary>
        private WebResponseContent ProcessRelocationTaskStatus(Dt_Task task)
        {
            if (task.TaskStatus >= (int)TaskRelocationStatusEnum.RelocationFinish)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskRelocationStatusEnum>();
            if (task.TaskStatus <= 0)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            // ç§»åº“任务开始时,同步WMS任务状态
            if (task.TaskStatus == (int)TaskRelocationStatusEnum.SC_RelocationExecuting)
            {
                return UpdateWMSTaskStatus(task);
            }
            // ç§»åº“任务完成时,调用WMS移库完成接口
            if (task.TaskStatus == (int)TaskRelocationStatusEnum.RelocationFinish)
            {
                return NotifyWMSRelocationFinish(task);
            }
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// é€šçŸ¥WMS系统出库完成
        /// </summary>
        private WebResponseContent NotifyWMSOutboundFinish(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.OutboundFinishTaskAsync),
                new StockInfoDTO { PalletCode = task.PalletCode, TaskNum = task.TaskNum }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"通知WMS系统堆垛机出库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// èŽ·å–ç©ºæ‰˜å‡ºåº“ä»»åŠ¡
        /// </summary>
        private WebResponseContent GetWMSOutboundTrayTask(Dt_Task task)
        {
            var targetAddress = task.TargetAddress;
            var warehouseId = _robotTaskService.MapWarehouseIdConfigKey(task.TargetAddress);
            string sourceLineNo = _robotTaskService.ResolveRobotRuleValue(targetAddress, "AddressSourceLineNoMap", task.TargetAddress);
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.GetOutBoundTrayTaskAsync),
                new CreateTaskDto { WarehouseId = warehouseId, TargetAddress = sourceLineNo }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"获取WMS系统空托盘出库任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            var wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data?.ToString() ?? string.Empty);
            var tasks = new List<WMSTaskDTO>
            {
                wMSTask
            };
            return ReceiveWMSTask(tasks);
        }
        /// <summary>
        /// ä»ŽWMS系统获取入库目标地址
        /// </summary>
        private WebResponseContent GetWMSInboundLocation(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.GetTasksLocation),
                new CreateTaskDto { PalletCode = task.PalletCode }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"调用WMS接口获取任务目标地址失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            var 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>
        /// æ›´æ–°WMS系统任务状态
        /// </summary>
        private WebResponseContent UpdateWMSTaskStatus(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.UpdateTaskByStatus),
                new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"调用WMS接口更新任务状态失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// é€šçŸ¥WMS系统移库任务完成
        /// </summary>
        private WebResponseContent NotifyWMSRelocationFinish(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.RelocationFinishTask),
                new CreateTaskDto
                {
                    PalletCode = task.PalletCode,
                    SourceAddress = task.CurrentAddress,
                    TargetAddress = task.TargetAddress,
                    Roadway = task.Roadway,
                    TaskType = task.TaskType
                }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"通知WMS系统移库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            return WebResponseContent.Instance.OK();
        }
@@ -655,101 +467,41 @@
            {
                Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
                if (task == null) return WebResponseContent.Instance.Error($"未找到该任务信息,任务号:【{taskNum}】");
                if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup && task.TaskStatus == (int)TaskOutStatusEnum.SC_OutExecuting)
                TaskTypeGroup taskTypeGroup = task.TaskType.GetTaskTypeGroup();
                content = taskTypeGroup switch
                {
                    int taskType = 0;
                    if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
                    {
                        taskType = 100;
                    }
                    else
                        taskType = task.TaskType;
                    Dt_Router router = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress, taskType);
                    if (router == null) return WebResponseContent.Instance.Error($"未找到设备路由信息");
                    int nextStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskOutStatusEnum>();
                    task.TaskStatus = nextStatus;
                    task.CurrentAddress = task.NextAddress;
                    task.NextAddress = router.ChildPosi;
                    task.ModifyDate = DateTime.Now;
                    task.Modifier = "System";
                    content = NotifyWMSOutboundFinish(task);
                    if (content.Status)
                    {
                        BaseDal.UpdateData(task);
                        _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, $"堆垛机出库完成");
                        return content.Error($"通知WMS系统堆垛机出库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
                    }
                    //var result = _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.OutboundFinishTaskAsync), (new StockInfoDTO() { PalletCode = task.PalletCode, TaskNum = task.TaskNum }).ToJson());
                    //if (result.IsSuccess && result.Data.Status)
                    //{
                    //    BaseDal.UpdateData(task);
                    //    _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, $"堆垛机出库完成");
                    //    return content.Error($"通知WMS系统堆垛机出库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
                    //}
                    //else
                    //{
                    //    return content.Error($"通知WMS系统堆垛机出库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data.Message}】");
                    //}
                }
                else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup && task.TaskStatus == (int)TaskInStatusEnum.SC_InExecuting)
                    TaskTypeGroup.OutbondGroup => _outboundTaskFlowService.CompleteStackerTask(task),
                    TaskTypeGroup.InboundGroup => _inboundTaskFlowService.CompleteStackerTask(task),
                    TaskTypeGroup.RelocationGroup => _relocationTaskFlowService.CompleteStackerTask(task),
                    TaskTypeGroup.OtherGroup => _robotTaskFlowService.CompleteStackerTask(task),
                    _ => throw new Exception($"任务类型错误,未找到该任务类型,任务号:【{taskNum}】,任务类型:【{task.TaskType}】")
                };
                if (!content.Status)
                {
                    int nextStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskInStatusEnum>();
                    task.TaskStatus = nextStatus;
                    task.ModifyDate = DateTime.Now;
                    task.Modifier = "System";
                    return content;
                }
                    var result = _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.InboundFinishTaskAsync), (new CreateTaskDto()
                    {
                        PalletCode = task.PalletCode,
                    }).ToJson());
                if (taskTypeGroup == TaskTypeGroup.OutbondGroup && task.TaskStatus == (int)TaskOutStatusEnum.SC_OutFinish)
                {
                    BaseDal.UpdateData(task);
                    _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, "堆垛机出库完成");
                    return content;
                }
                    if (result.IsSuccess && result.Data.Status)
                    {
                        BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成);
                        _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, $"堆垛机入库完成");
                        return content.Error($"通知WMS系统堆垛机入库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
                    }
                    else
                    {
                        return content.Error($"通知WMS系统堆垛机入库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data.Message}】");
                    }
                }
                else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.RelocationGroup)
                if (taskTypeGroup == TaskTypeGroup.InboundGroup && task.TaskStatus == (int)TaskInStatusEnum.SC_InFinish)
                {
                    if (task.TaskStatus == (int)TaskRelocationStatusEnum.SC_RelocationExecuting)
                    {
                        int nextStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskRelocationStatusEnum>();
                        task.TaskStatus = nextStatus;
                        task.ModifyDate = DateTime.Now;
                        task.Modifier = "System";
                    BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成);
                    _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, "堆垛机入库完成");
                    return content;
                }
                        WebResponseContent result = NotifyWMSRelocationFinish(task);
                        if (result.Status)
                        {
                            BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成);
                            _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, $"堆垛机移库完成");
                            return content.Error($"通知WMS系统堆垛机移库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
                        }
                        else
                        {
                            return content.Error($"通知WMS系统堆垛机移库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Message}】");
                        }
                    }
                }
                else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OtherGroup)
                if (taskTypeGroup == TaskTypeGroup.RelocationGroup && task.TaskStatus == (int)TaskRelocationStatusEnum.RelocationFinish)
                {
                    BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成);
                    _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, "堆垛机移库完成");
                    return content;
                }
                else
                {
                    throw new Exception($"任务类型错误,未找到该任务类型,任务号:【{taskNum}】,任务类型:【{task.TaskType}】");
                }
                content = WebResponseContent.Instance.OK();
            }
            catch (Exception ex)