From 2e7937ca43b0712ddf96b29b04cc7baf34fa1305 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期六, 25 四月 2026 18:40:00 +0800
Subject: [PATCH] feat: 添加托盘库存明细查询功能并优化机械手任务处理

---
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs |  710 +++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 451 insertions(+), 259 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
index 465fcb5..3502c79 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -1,260 +1,452 @@
-锘�#region << 鐗� 鏈� 娉� 閲� >>
-
-/*----------------------------------------------------------------
- * 鍛藉悕绌洪棿锛歐IDESEAWCS_TaskInfoService
- * 鍒涘缓鑰咃細鑳$搴�
- * 鍒涘缓鏃堕棿锛�2024/8/2 16:13:36
- * 鐗堟湰锛歏1.0.0
- * 鎻忚堪锛�
- *
- * ----------------------------------------------------------------
- * 淇敼浜猴細
- * 淇敼鏃堕棿锛�
- * 鐗堟湰锛歏1.0.1
- * 淇敼璇存槑锛�
- *
- *----------------------------------------------------------------*/
-
-#endregion << 鐗� 鏈� 娉� 閲� >>
-
-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.Helper;
-using WIDESEAWCS_DTO.Stock;
-using WIDESEAWCS_DTO.TaskInfo;
-using WIDESEAWCS_ITaskInfoRepository;
-using WIDESEAWCS_ITaskInfoService;
-using WIDESEAWCS_Model.Models;
-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()
-            {
-                {nameof(Dt_RobotTask.RobotGrade),OrderByType.Desc },
-                {nameof(Dt_RobotTask.CreateDate),OrderByType.Asc},
-            };
-
-        public Dictionary<string, OrderByType> TaskOrderBy
-        { get { return _taskOrderBy; } set { _taskOrderBy = value; } }
-
-        public List<int> TaskInboundTypes => typeof(TaskInboundTypeEnum).GetEnumIndexList();
-
-        public List<int> TaskOutboundTypes => typeof(TaskOutboundTypeEnum).GetEnumIndexList();
-
-        public List<int> TaskRobotTypes => typeof(TaskOtherTypeEnum).GetEnumIndexList();
-
-        public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper, HttpClientHelper httpClientHelper, ITaskExecuteDetailService taskExecuteDetailService) : base(BaseDal)
-        {
-            _mapper = mapper;
-            _httpClientHelper = httpClientHelper;
-            _taskExecuteDetailService = taskExecuteDetailService;
-        }
-
-        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.TaskState,
-                    RobotGrade = taskDTO.Grade,
-                    Creater = "WMS"
-                };
-
-                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)
-        {
-            return BaseDal.QueryFirst(x => x.RobotRoadway == deviceCode && x.RobotTaskState != (int)TaskRobotStatusEnum.RobotExecuting, TaskOrderBy);
-        }
-
-        public async Task<bool> UpdateRobotTaskAsync(Dt_RobotTask robotTask)
-        {
-            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}銆�,閿欒淇℃伅:銆怶MS鏈繑鍥炴湁鏁堜换鍔℃暟鎹��");
-
-            return ReceiveWMSTask(wMSTask, stock);
-        }
-
-        /// <summary>
-        /// 鏍规嵁杈撻�佺嚎鐩爣鍦板潃瑙f瀽鏈烘鎵嬩换鍔℃帴鍙c��
-        /// 瑙勫垯锛�
-        /// 1. 浠庨厤缃鍙栫簿纭湴鍧�鏄犲皠锛圓ddressMap锛�
-        /// 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());
-        }
-    }
+锘�#region << 鐗� 鏈� 娉� 閲� >>
+
+/*----------------------------------------------------------------
+ * 鍛藉悕绌洪棿锛歐IDESEAWCS_TaskInfoService
+ * 鍒涘缓鑰咃細鑳$搴�
+ * 鍒涘缓鏃堕棿锛�2024/8/2 16:13:36
+ * 鐗堟湰锛歏1.0.0
+ * 鎻忚堪锛�
+ *
+ * ----------------------------------------------------------------
+ * 淇敼浜猴細
+ * 淇敼鏃堕棿锛�
+ * 鐗堟湰锛歏1.0.1
+ * 淇敼璇存槑锛�
+ *
+ *----------------------------------------------------------------*/
+
+#endregion << 鐗� 鏈� 娉� 閲� >>
+
+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;
+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_Core.Utilities;
+using WIDESEAWCS_DTO.Stock;
+using WIDESEAWCS_DTO.TaskInfo;
+using WIDESEAWCS_ITaskInfoRepository;
+using WIDESEAWCS_ITaskInfoService;
+using WIDESEAWCS_Model.Models;
+using WIDESEAWCS_QuartzJob;
+using WIDESEAWCS_QuartzJob.DTO;
+using WIDESEAWCS_Tasks;
+
+namespace WIDESEAWCS_TaskInfoService
+{
+    public class RobotTaskService : ServiceBase<Dt_RobotTask, IRobotTaskRepository>, IRobotTaskService
+    {
+        private readonly IMapper _mapper;
+        private readonly HttpClientHelper _httpClientHelper;
+        private readonly ITaskExecuteDetailService _taskExecuteDetailService;
+        private readonly ILogger _logger;
+
+        private Dictionary<string, OrderByType> _taskOrderBy = new()
+            {
+                {nameof(Dt_RobotTask.RobotGrade),OrderByType.Desc },
+                {nameof(Dt_RobotTask.CreateDate),OrderByType.Asc},
+            };
+
+        public Dictionary<string, OrderByType> TaskOrderBy
+        { get { return _taskOrderBy; } set { _taskOrderBy = value; } }
+
+        public List<int> TaskInboundTypes => typeof(TaskInboundTypeEnum).GetEnumIndexList();
+
+        public List<int> TaskOutboundTypes => typeof(TaskOutboundTypeEnum).GetEnumIndexList();
+
+        public List<int> TaskRobotTypes => typeof(TaskOtherTypeEnum).GetEnumIndexList();
+
+        public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper, HttpClientHelper httpClientHelper, ITaskExecuteDetailService taskExecuteDetailService, ILogger logger) : base(BaseDal)
+        {
+            _mapper = mapper;
+            _httpClientHelper = httpClientHelper;
+            _taskExecuteDetailService = taskExecuteDetailService;
+            _logger = logger;
+        }
+        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 bool DeleteRobotTask(int id)
+        {
+            Dt_RobotTask task = BaseDal.QueryFirst(x => x.RobotTaskId == id);
+            return BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.鑷姩瀹屾垚);
+        }
+
+        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 ?? string.Empty,
+                    RobotTargetAddressLineCode = stockDTO?.TargetLineNo ?? string.Empty,
+                    RobotRoadway = stockDTO?.Roadway ?? string.Empty,
+                    RobotSourceAddress = taskDTO.SourceAddress,
+                    RobotTargetAddress = taskDTO.TargetAddress,
+                    RobotSourceAddressPalletCode = stockDTO?.SourcePalletNo ?? string.Empty,
+                    RobotTargetAddressPalletCode = stockDTO?.TargetPalletNo ?? string.Empty,
+                    RobotTaskType = taskDTO.TaskType,
+                    RobotTaskState = taskDTO.TaskStatus,
+                    RobotGrade = taskDTO.Grade,
+                    Creater = "WMS",
+                    RobotTaskTotalNum = taskDTO.TaskQuantity,
+                };
+
+                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)
+        {
+            return BaseDal.QueryFirst(x => x.RobotRoadway == deviceCode && x.RobotTaskState != (int)TaskRobotStatusEnum.RobotExecuting, TaskOrderBy);
+        }
+
+        public Dt_RobotTask? QueryRobotCraneExecutingTask(string deviceCode)
+        {
+            return BaseDal.QueryFirst(x => x.RobotRoadway == deviceCode && x.RobotTaskState == (int)TaskRobotStatusEnum.RobotExecuting, TaskOrderBy);
+        }
+
+        public async Task<bool> UpdateRobotTaskAsync(Dt_RobotTask robotTask)
+        {
+            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);
+            string requestParam = stock.ToJson();
+            var stopwatch = Stopwatch.StartNew();
+
+            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}銆�");
+            }
+
+            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}銆�,閿欒淇℃伅:銆怶MS鏈繑鍥炴湁鏁堜换鍔℃暟鎹��");
+
+            return ReceiveWMSTask(wMSTask, stock);
+        }
+
+        /// <summary>
+        /// 鍦ㄦ湰鍦扮洿鎺ュ垱寤烘満姊版墜浠诲姟锛屼笉璋冪敤WMS鎺ュ彛銆�
+        /// 鏍规嵁鐩爣鍦板潃瑙f瀽浠诲姟绫诲瀷锛屾瀯寤轰换鍔℃暟鎹苟鍐欏叆鏁版嵁搴撱��
+        /// </summary>
+        /// <param name="task">鍑哄簱浠诲姟瀹炰綋</param>
+        /// <returns>鎿嶄綔缁撴灉</returns>
+        public WebResponseContent CreateLocalRobotTask(Dt_Task task)
+        {
+            WebResponseContent content = new();
+            try
+            {
+                // 鏍规嵁鐩爣鍦板潃瑙f瀽浠诲姟绫诲瀷閰嶇疆閿�
+                string configKey = ResolveRobotTaskConfigKey(task.TargetAddress);
+
+                // 鏋勫缓Stock鏁版嵁
+                StockDTO stock = BuildRobotTaskStock(task, configKey);
+
+                // 鑾峰彇鎶撳彇鍜屾斁缃湴鍧�鐨勭嚎浣撻厤缃紙濡傛灉鏈夛級
+                var section = App.Configuration.GetSection("RobotAddressRules").GetSection(stock?.TargetLineNo ?? string.Empty).GetChildren().Select(c => c.Value).ToArray();
+                if (section.Length < 2)
+                    return WebResponseContent.Instance.Error($"鏈壘鍒扮嚎浣揫{stock?.TargetLineNo}]鐨勫湴鍧�閰嶇疆");
+
+                int taskType = MapConfigKeyToRobotTaskType(configKey);
+                // 鍒涘缓鏈湴鏈哄櫒浜轰换鍔�
+                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?.TargetLineNo switch
+                    {
+                        "11068" => "娉ㄦ恫缁勭洏鏈烘鎵�",
+                        "1000" => "鎷嗙洏鏈烘鎵�",
+                        "2000" => "鎴愬搧缁勭洏鏈烘鎵�",
+                        _ => "鎹㈢洏鏈烘鎵�"
+                    },
+                    RobotSourceAddressPalletCode = stock?.SourcePalletNo ?? string.Empty,
+                    RobotTargetAddressPalletCode = stock?.TargetPalletNo ?? string.Empty,
+                    RobotTaskType = taskType,
+                    RobotTaskState = (int)TaskRobotStatusEnum.RobotNew,
+                    RobotGrade = task.Grade,
+                    Creater = "WCS_Local",
+                    RobotTaskTotalNum = GetRobotTaskTotalNum(taskType, stock.SourcePalletNo),
+                    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>
+        /// 鑾峰彇鏈烘鎵嬩换鍔℃�绘暟閲忋��
+        /// 缁勭洏浠诲姟鍥哄畾48锛屾崲鐩樺拰鎷嗙洏浠诲姟閫氳繃鎵樼洏鍙锋煡璇MS搴撳瓨鏄庣粏鏁伴噺銆�
+        /// </summary>
+        private int GetRobotTaskTotalNum(int taskType, string? palletCode)
+        {
+            if (taskType == (int)RobotTaskTypeEnum.GroupPallet)
+                return 48;
+
+            if (string.IsNullOrWhiteSpace(palletCode))
+                return 1;
+
+            try
+            {
+                string url = $"{BaseAPI.WMSBaseUrl}Stock/GetStockDetailCount?palletCode={Uri.EscapeDataString(palletCode)}";
+                var result = _httpClientHelper.Get(url);
+                if (!result.IsSuccess || string.IsNullOrEmpty(result.Content))
+                    return 1;
+
+                var response = JsonConvert.DeserializeObject<WebResponseContent>(result.Content);
+                if (response == null || !response.Status)
+                    return 1;
+
+                var detailCount = response.Data?.GetType().GetProperty("DetailCount")?.GetValue(response.Data);
+                return detailCount is int count and > 0 ? count : 1;
+            }
+            catch
+            {
+                return 1;
+            }
+        }
+
+        /// <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>
+        /// 鏍规嵁杈撻�佺嚎鐩爣鍦板潃瑙f瀽鏈烘鎵嬩换鍔℃帴鍙c��
+        /// 瑙勫垯锛�
+        /// 1. 浠庨厤缃鍙栫簿纭湴鍧�鏄犲皠锛圓ddressMap锛�
+        /// 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(barcode) ? string.Empty : barcode;
+                }
+            }
+
+            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>
+        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());
+        }
+    }
 }
\ No newline at end of file

--
Gitblit v1.9.3