wanshenmean
21 小时以前 419159c8611dca81b94b3103cdeaeb9272aed5ea
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -20,7 +20,9 @@
using MapsterMapper;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Serilog;
using SqlSugar;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using WIDESEA_Core;
using WIDESEAWCS_Common.HttpEnum;
@@ -28,6 +30,7 @@
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_Core.Utilities;
using WIDESEAWCS_DTO.Stock;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoRepository;
@@ -35,6 +38,7 @@
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.DTO;
using WIDESEAWCS_Tasks;
namespace WIDESEAWCS_TaskInfoService
{
@@ -43,6 +47,7 @@
        private readonly IMapper _mapper;
        private readonly HttpClientHelper _httpClientHelper;
        private readonly ITaskExecuteDetailService _taskExecuteDetailService;
        private readonly ILogger _logger;
        private Dictionary<string, OrderByType> _taskOrderBy = new()
            {
@@ -59,11 +64,12 @@
        public List<int> TaskRobotTypes => typeof(TaskOtherTypeEnum).GetEnumIndexList();
        public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper, HttpClientHelper httpClientHelper, ITaskExecuteDetailService taskExecuteDetailService) : base(BaseDal)
        public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper, HttpClientHelper httpClientHelper, ITaskExecuteDetailService taskExecuteDetailService, ILogger logger) : base(BaseDal)
        {
            _mapper = mapper;
            _httpClientHelper = httpClientHelper;
            _taskExecuteDetailService = taskExecuteDetailService;
            _logger = logger;
        }
        public WebResponseContent ReceiveWMSTask([NotNull] WMSTaskDTO taskDTO, StockDTO stockDTO)
@@ -79,18 +85,18 @@
                Dt_RobotTask task = new Dt_RobotTask
                {
                    RobotTaskNum = taskDTO.TaskNum,
                    RobotSourceAddressLineCode = stockDTO.SourceLineNo,
                    RobotTargetAddressLineCode = stockDTO.TargetLineNo,
                    RobotRoadway = stockDTO.Roadway,
                    RobotSourceAddressLineCode = stockDTO?.SourceLineNo ?? string.Empty,
                    RobotTargetAddressLineCode = stockDTO?.TargetLineNo ?? string.Empty,
                    RobotRoadway = stockDTO?.Roadway ?? string.Empty,
                    RobotSourceAddress = taskDTO.SourceAddress,
                    RobotTargetAddress = taskDTO.TargetAddress,
                    RobotSourceAddressPalletCode = stockDTO.SourcePalletNo,
                    RobotTargetAddressPalletCode = stockDTO.TargetPalletNo,
                    RobotSourceAddressPalletCode = stockDTO?.SourcePalletNo ?? string.Empty,
                    RobotTargetAddressPalletCode = stockDTO?.TargetPalletNo ?? string.Empty,
                    RobotTaskType = taskDTO.TaskType,
                    RobotTaskState = taskDTO.TaskStatus,
                    RobotGrade = taskDTO.Grade,
                    Creater = "WMS",
                    RobotTaskTotalNum = 0,
                    RobotTaskTotalNum = taskDTO.TaskQuantity,
                };
                BaseDal.AddData(task);
@@ -130,17 +136,96 @@
        {
            string configKey = ResolveRobotTaskConfigKey(task.TargetAddress);
            StockDTO stock = BuildRobotTaskStock(task, configKey);
            string requestParam = stock.ToJson();
            var stopwatch = Stopwatch.StartNew();
            var result = _httpClientHelper.Post<WebResponseContent>(configKey, stock.ToJson());
            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
            stopwatch.Stop();
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "RobotTaskService");
                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);
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{stopwatch.ElapsedMilliseconds}ms", "RobotTaskService");
            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>
        /// 在本地直接创建机械手任务,不调用WMS接口。
        /// 根据目标地址解析任务类型,构建任务数据并写入数据库。
        /// </summary>
        /// <param name="task">出库任务实体</param>
        /// <returns>操作结果</returns>
        public WebResponseContent CreateLocalRobotTask(Dt_Task task)
        {
            WebResponseContent content = new();
            try
            {
                // 根据目标地址解析任务类型配置键
                string configKey = ResolveRobotTaskConfigKey(task.TargetAddress);
                // 构建Stock数据
                StockDTO stock = BuildRobotTaskStock(task, configKey);
                // 获取抓取和放置地址的线体配置(如果有)
                var section = App.Configuration.GetSection("RobotTaskAddressRules").GetSection(stock?.TargetLineNo ?? string.Empty).GetChildren().Select(c => c.Value).ToArray();
                if (section.Length < 2)
                    return WebResponseContent.Instance.Error($"未找到线体[{stock?.TargetLineNo}]的地址配置");
                // 创建本地机器人任务
                Dt_RobotTask robotTask = new()
                {
                    RobotTaskNum = Random.Shared.Next(),
                    RobotSourceAddress = section[0]!,
                    RobotTargetAddress = section[1]!,
                    RobotSourceAddressLineCode = stock?.SourceLineNo ?? string.Empty,
                    RobotTargetAddressLineCode = stock?.TargetLineNo ?? string.Empty,
                    RobotRoadway = stock?.Roadway ?? string.Empty,
                    RobotSourceAddressPalletCode = stock?.SourcePalletNo ?? string.Empty,
                    RobotTargetAddressPalletCode = stock?.TargetPalletNo ?? string.Empty,
                    RobotTaskType = MapConfigKeyToRobotTaskType(configKey),
                    RobotTaskState = (int)TaskRobotStatusEnum.RobotNew,
                    RobotGrade = task.Grade,
                    Creater = "WCS_Local",
                    RobotTaskTotalNum = 1,
                    CreateDate = DateTime.Now
                };
                BaseDal.AddData(robotTask);
                _taskExecuteDetailService.AddTaskExecuteDetail(new List<int> { robotTask.RobotTaskNum }, "本地创建机器人任务");
                QuartzLogHelper.LogInfo(_logger, $"本地创建机器人任务成功,任务号:【{robotTask.RobotTaskNum}】,源地址:【{robotTask.RobotSourceAddress}】,目标地址:【{robotTask.RobotTargetAddress}】,任务类型:【{configKey}】", "RobotTaskService");
                content = WebResponseContent.Instance.OK("本地创建机器人任务成功", robotTask);
            }
            catch (Exception ex)
            {
                QuartzLogHelper.LogError(_logger, $"本地创建机器人任务失败,任务号:【{task.TaskNum}】,错误信息:{ex.Message}", "RobotTaskService");
                content = WebResponseContent.Instance.Error($"本地创建机器人任务失败,错误信息:{ex.Message}");
            }
            return content;
        }
        /// <summary>
        /// 将配置键映射到机械手任务类型枚举值。
        /// </summary>
        /// <param name="configKey">配置键名称</param>
        /// <returns>任务类型枚举值</returns>
        public int MapConfigKeyToRobotTaskType(string? configKey)
        {
            return configKey switch
            {
                nameof(ConfigKey.CreateRobotGroupPalletTask) => (int)RobotTaskTypeEnum.GroupPallet,
                nameof(ConfigKey.CreateRobotSplitPalletTask) => (int)RobotTaskTypeEnum.SplitPallet,
                _ => (int)RobotTaskTypeEnum.ChangePallet
            };
        }
        /// <summary>
@@ -234,6 +319,49 @@
            return stock;
        }
        public override WebResponseContent AddData(SaveModel saveModel)
        {
            try
            {
                if (saveModel == null || saveModel.MainData == null || saveModel.MainData.Count == 0)
                {
                    return WebResponseContent.Instance.Error("传参错误,参数不能为空");
                }
                string validResult = typeof(Dt_RobotTask).ValidateDicInEntity(saveModel.MainData, true, TProperties);
                if (!string.IsNullOrEmpty(validResult))
                {
                    return WebResponseContent.Instance.Error(validResult);
                }
                object? taskNumObj = saveModel.MainData[nameof(Dt_RobotTask.RobotTaskNum)];
                if (taskNumObj != null)
                {
                    int taskNum = Convert.ToInt32(taskNumObj);
                    if (BaseDal.QueryFirst(x => x.RobotTaskNum == taskNum) != null)
                    {
                        return WebResponseContent.Instance.Error($"任务编号 {taskNum} 已存在");
                    }
                }
                Dt_RobotTask entity = saveModel.MainData.DicToModel<Dt_RobotTask>();
                entity.Creater = "手动创建";
                entity.CreateDate = DateTime.Now;
                if (saveModel.DetailData == null || saveModel.DetailData.Count == 0)
                {
                    BaseDal.AddData(entity);
                    return WebResponseContent.Instance.OK("新增成功", entity);
                }
                return base.AddData(saveModel);
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error($"新增失败,错误信息:{ex.Message}");
            }
        }
        /// <summary>
        /// 根据目标地址按「精确 > 回退值」解析规则值。
        /// </summary>