wanshenmean
2026-03-17 94ad631d316da04c46266ddb1fc6e63e6f8f2fae
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
@@ -18,10 +18,10 @@
#endregion << 版 本 注 释 >>
using MapsterMapper;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using SqlSugar;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using WIDESEA_Core;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
@@ -29,13 +29,13 @@
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_Core.Http;
using WIDESEAWCS_DTO;
using WIDESEAWCS_DTO.Stock;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
@@ -96,9 +96,10 @@
                    task.Creater = "WMS";
                    if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
                    {
                        Dt_Router router = _routerService.QueryNextRoute(item.RoadWay, item.TargetAddress,item.TaskType);
                        var taskType = 100;
                        Dt_Router router = _routerService.QueryNextRoute(item.Roadway, item.TargetAddress, taskType);
                        //暂不考虑多路径
                        if (router !=null )
                        if (router != null)
                        {
                            task.TaskStatus = (int)TaskOutStatusEnum.OutNew;
                            task.CurrentAddress = item.SourceAddress;
@@ -147,7 +148,7 @@
                    TaskNum = Convert.ToInt32(DateTime.Now.ToString("HHmmss")),
                    Grade = 1,
                    PalletCode = palletCode,
                    RoadWay = "SC01",
                    Roadway = "SC01",
                    SourceAddress = sourceAddress,
                    TargetAddress = "SC01",
                    TaskState = (int)TaskInStatusEnum.InNew,
@@ -369,7 +370,14 @@
            // 更新任务数据
            task.ModifyDate = DateTime.Now;
            task.Modifier = "System";
            BaseDal.UpdateData(task);
            if(task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish)
            {
                BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动删除);
            }
            else
            {
                BaseDal.UpdateData(task);
            }
            // 记录任务执行详情
            string logMessage = App.User.UserId > 0
@@ -394,13 +402,18 @@
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
            // 根据状态调用不同的WMS接口
            if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish)
            if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound)
            {
                return NotifyWMSOutboundFinish(task);
                return GetWMSOutboundTrayTask(task);
            }
            else if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
            {
                return GetWMSRobotTask(task);
            }
            else
            {
                return UpdateWMSTaskStatus(task);
                // return UpdateWMSTaskStatus(task);
                return WebResponseContent.Instance.OK();
            }
        }
@@ -485,6 +498,170 @@
                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 = MapWarehouseIdConfigKey(task.TargetAddress);
            string sourceLineNo = 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());
            var tasks = new List<WMSTaskDTO>();
            tasks.Add(wMSTask);
            return ReceiveWMSTask(tasks);
        }
        /// <summary>
        /// 获取WMS系统机械手任务
        /// </summary>
        /// <param name="task"></param>
        /// <returns></returns>
        private WebResponseContent GetWMSRobotTask(Dt_Task task)
        {
            string configKey = ResolveRobotTaskConfigKey(task.TargetAddress);
            StockDTO stock = BuildRobotTaskStock(task, configKey);
            var result = _httpClientHelper.Post<WebResponseContent>(configKey, stock.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"获取WMS系统机械手任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,目标地址:【{task.TargetAddress}】,接口:【{configKey}】,错误信息:【{result.Data?.Message}】");
            var tasks = JsonConvert.DeserializeObject<List<WMSTaskDTO>>(result.Data.Data?.ToString() ?? string.Empty);
            if (tasks == null || tasks.Count == 0)
                return WebResponseContent.Instance.Error($"获取WMS系统机械手任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【WMS未返回有效任务数据】");
            return ReceiveWMSTask(tasks);
        }
        /// <summary>
        /// 根据输送线目标地址解析机械手任务接口。
        /// 规则:
        /// 1. 从配置读取精确地址映射(AddressMap)
        /// 2. 未命中时默认换盘
        /// </summary>
        private string ResolveRobotTaskConfigKey(string? targetAddress)
        {
            string address = (targetAddress ?? string.Empty).Trim();
            if (string.IsNullOrWhiteSpace(address))
                return nameof(ConfigKey.CreateRobotChangePalletTask);
            var section = App.Configuration.GetSection("RobotTaskAddressRules");
            var addressMap = ReadRobotRuleMap(section.GetSection("AddressMap"));
            if (addressMap.TryGetValue(address, out string? exactTaskType))
                return MapRobotTaskTypeToConfigKey(exactTaskType);
            return nameof(ConfigKey.CreateRobotChangePalletTask);
        }
        private int MapWarehouseIdConfigKey(string? targetAddress)
        {
            return targetAddress switch
            {
                "11068" => 1,
                "11001" => 3,
                "11010" => 3,
                "10010" => 1,
                "10030" => 1,
                _ => 1
            };
        }
        /// <summary>
        /// 将配置任务类型转换为接口配置键。
        /// 支持值:Split/Group/Change(大小写不敏感)
        /// </summary>
        private string MapRobotTaskTypeToConfigKey(string? taskType)
        {
            string type = (taskType ?? string.Empty).Trim().ToLowerInvariant();
            return type switch
            {
                "split" => nameof(ConfigKey.CreateRobotSplitPalletTask),
                "group" => nameof(ConfigKey.CreateRobotGroupPalletTask),
                _ => nameof(ConfigKey.CreateRobotChangePalletTask)
            };
        }
        /// <summary>
        /// 根据接口类型构建机械手任务入参。
        /// </summary>
        private StockDTO BuildRobotTaskStock(Dt_Task task, string configKey)
        {
            string targetAddress = task.TargetAddress ?? string.Empty;
            string roadway = ResolveRobotRuleValue(targetAddress, "AddressRoadwayMap", task.Roadway);
            string sourceLineNo = ResolveRobotRuleValue(targetAddress, "AddressSourceLineNoMap", task.SourceAddress);
            var stock = new StockDTO
            {
                Roadway = roadway,
                SourceLineNo = sourceLineNo,
                TargetLineNo = task.TargetAddress,
                SourcePalletNo = task.PalletCode,
                TargetPalletNo = task.PalletCode
            };
            if (configKey == nameof(ConfigKey.CreateRobotSplitPalletTask))
            {
                stock.TargetPalletNo = string.Empty;
            }
            else if (configKey == nameof(ConfigKey.CreateRobotGroupPalletTask))
            {
                stock.SourcePalletNo = string.Empty;
            }
            else if (configKey == nameof(ConfigKey.CreateRobotChangePalletTask))
            {
                IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceProDTOs.Any(d => d.DeviceChildCode == sourceLineNo));
                if (device != null)
                {
                    CommonConveyorLine conveyorLine = (CommonConveyorLine)device;
                    var barcode = conveyorLine.GetValue<ConveyorLineDBNameNew, string>(ConveyorLineDBNameNew.Barcode, sourceLineNo);
                    stock.SourcePalletNo = string.IsNullOrEmpty(barcode) ? string.Empty : barcode;
                }
            }
            return stock;
        }
        /// <summary>
        /// 根据目标地址按「精确 > 回退值」解析规则值。
        /// </summary>
        private string ResolveRobotRuleValue(string? targetAddress, string addressSectionName, string? fallback)
        {
            string address = (targetAddress ?? string.Empty).Trim();
            string defaultValue = fallback ?? string.Empty;
            if (string.IsNullOrWhiteSpace(address))
                return defaultValue;
            var section = App.Configuration.GetSection("RobotTaskAddressRules");
            var addressMap = ReadRobotRuleMap(section.GetSection(addressSectionName));
            if (addressMap.TryGetValue(address, out string? value))
                return value;
            return defaultValue;
        }
        /// <summary>
        /// 读取规则映射段。
        /// </summary>
        private Dictionary<string, string> ReadRobotRuleMap(IConfigurationSection section)
        {
            return section
                .GetChildren()
                .Where(x => !string.IsNullOrWhiteSpace(x.Key) && !string.IsNullOrWhiteSpace(x.Value))
                .ToDictionary(x => x.Key.Trim(), x => x.Value!.Trim());
        }
        /// <summary>
@@ -612,19 +789,28 @@
                    task.ModifyDate = DateTime.Now;
                    task.Modifier = "System";
                    var result = _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.OutboundFinishTaskAsync), (new StockInfoDTO() { PalletCode = task.PalletCode, TaskNum = task.TaskNum }).ToJson());
                    if (result.IsSuccess && result.Data.Status)
                    content = NotifyWMSOutboundFinish(task);
                    if (content.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}】");
                    }
                    //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)
                {
@@ -632,8 +818,6 @@
                    task.TaskStatus = nextStatus;
                    task.ModifyDate = DateTime.Now;
                    task.Modifier = "System";
                    var result = _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.InboundFinishTaskAsync), (new CreateTaskDto()
                    {
@@ -816,4 +1000,9 @@
            return BaseDal.QueryFirst(x => x.TaskNum == taskNum);
        }
    }
    public enum ConveyorLineDBNameNew
    {
        Barcode
    }
}