wanshenmean
2026-03-19 c493779a8504fe1eb548c865ff268a7f7436ec01
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -17,25 +17,32 @@
#endregion << 版 本 注 释 >>
using AutoMapper;
using MapsterMapper;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using SqlSugar;
using System.Diagnostics.CodeAnalysis;
using WIDESEA_Core;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.Stock;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.DTO;
namespace WIDESEAWCS_TaskInfoService
{
    public class RobotTaskService : ServiceBase<Dt_RobotTask, IRobotTaskRepository>, IRobotTaskService
    {
        private readonly IMapper _mapper;
        private readonly HttpClientHelper _httpClientHelper;
        private readonly ITaskExecuteDetailService _taskExecuteDetailService;
        private Dictionary<string, OrderByType> _taskOrderBy = new()
            {
@@ -52,22 +59,52 @@
        public List<int> TaskRobotTypes => typeof(TaskOtherTypeEnum).GetEnumIndexList();
        public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper) : base(BaseDal)
        public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper, HttpClientHelper httpClientHelper, ITaskExecuteDetailService taskExecuteDetailService) : base(BaseDal)
        {
            _mapper = mapper;
            _httpClientHelper = httpClientHelper;
            _taskExecuteDetailService = taskExecuteDetailService;
        }
        //public override WebResponseContent DeleteData(object[] keys)
        //{
        //    List<int> taskKeys = new List<int>();
        //    for (int i = 0; i < keys.Length; i++)
        //    {
        //        taskKeys.Add(Convert.ToInt32(keys[i]));
        //    }
        //    List<Dt_RobotTask> tasks = BaseDal.QueryData(x => taskKeys.Contains(x.RobotTaskId));
        //    BaseDal.DeleteAndMoveIntoHty(tasks, OperateTypeEnum.人工删除);
        //    return WebResponseContent.Instance.OK($"成功删除{tasks.Count}条数据");
        //}
        public WebResponseContent ReceiveWMSTask([NotNull] WMSTaskDTO taskDTO, StockDTO stockDTO)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                if (BaseDal.QueryFirst(x => x.RobotTaskNum == taskDTO.TaskNum || x.RobotSourceAddressPalletCode == taskDTO.PalletCode) != null)
                {
                    return content.Error("任务已存在");
                }
                Dt_RobotTask task = new Dt_RobotTask
                {
                    RobotTaskNum = taskDTO.TaskNum,
                    RobotSourceAddressLineCode = stockDTO.SourceLineNo,
                    RobotTargetAddressLineCode = stockDTO.TargetLineNo,
                    RobotRoadway = stockDTO.Roadway,
                    RobotSourceAddress = stockDTO.SourceLineNo,
                    RobotTargetAddress = stockDTO.TargetLineNo,
                    RobotSourceAddressPalletCode = stockDTO.SourcePalletNo,
                    RobotTargetAddressPalletCode = stockDTO.TargetPalletNo,
                    RobotTaskType = taskDTO.TaskType,
                    RobotTaskState = taskDTO.TaskStatus,
                    RobotGrade = taskDTO.Grade,
                    Creater = "WMS",
                    RobotTaskTotalNum = 0,
                };
                BaseDal.AddData(task);
                _taskExecuteDetailService.AddTaskExecuteDetail(new List<int> { task.RobotTaskNum }, "接收WMS任务");
                content = WebResponseContent.Instance.OK("成功", task);
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error($"任务接收错误,错误信息:{ex.Message}");
            }
            return content;
        }
        public Dt_RobotTask? QueryRobotCraneTask(string deviceCode)
        {
@@ -78,5 +115,147 @@
        {
            return await BaseDal.UpdateDataAsync(robotTask);
        }
        /// <summary>
        /// 获取WMS系统机械手任务
        /// </summary>
        /// <param name="task"></param>
        /// <returns></returns>
        public 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 wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data?.ToString() ?? string.Empty);
            if (wMSTask == null)
                return WebResponseContent.Instance.Error($"获取WMS系统机械手任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【WMS未返回有效任务数据】");
            return ReceiveWMSTask(wMSTask, stock);
        }
        /// <summary>
        /// 根据输送线目标地址解析机械手任务接口。
        /// 规则:
        /// 1. 从配置读取精确地址映射(AddressMap)
        /// 2. 未命中时默认换盘
        /// </summary>
        public 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);
        }
        public int MapWarehouseIdConfigKey(string? targetAddress)
        {
            return targetAddress switch
            {
                "11068" => 1,
                "11001" => 3,
                "11010" => 3,
                "10010" => 1,
                "10030" => 1,
                _ => 1
            };
        }
        /// <summary>
        /// 将配置任务类型转换为接口配置键。
        /// 支持值:Split/Group/Change(大小写不敏感)
        /// </summary>
        public 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>
        public 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;
                    DeviceProDTO? devicePro = conveyorLine.DeviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == nameof(ConveyorLineDBNameNew.Barcode) && x.DeviceChildCode == sourceLineNo);
                    ConveyorLineTaskCommandNew command = conveyorLine.ReadCustomer<ConveyorLineTaskCommandNew>(sourceLineNo);  // 测试用
                    //var barcode = conveyorLine.GetValue<ConveyorLineDBNameNew, string>(ConveyorLineDBNameNew.Barcode, sourceLineNo);
                    stock.SourcePalletNo = string.IsNullOrEmpty(command.Barcode.Replace("\0", "").ToString()) ? string.Empty : command.Barcode.Replace("\0", "").ToString();
                }
            }
            return stock;
        }
        /// <summary>
        /// 根据目标地址按「精确 > 回退值」解析规则值。
        /// </summary>
        public 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());
        }
    }
}