wanshenmean
8 小时以前 853f7a71577bd8694c848985e1eb21c74d30eba9
fix(WCS): 修复输送线任务处理逻辑并更新设备映射

修复输送线任务处理中的目标地址选择逻辑,改为直接检查CV_State状态并设置Target值
更新入库站台设备映射列表,添加新地址2125
修改RobotSelect.vue中的参数名从robotCode改为DeviceName
优化日志记录格式,移除冗余信息
更新HttpResponseResult.cs添加JsonIgnore属性避免序列化异常
修改开发环境API基础URL配置
已修改10个文件
86 ■■■■■ 文件已修改
Code/.omc/state/subagent-tracking.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Http/HTTP/HttpResponseResult.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/api/http.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/extension/stock/extend/RobotSelect.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Helper/HTTP/HttpResponseResult.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/.omc/state/subagent-tracking.json
@@ -1540,5 +1540,5 @@
  "total_spawned": 144,
  "total_completed": 166,
  "total_failed": 0,
  "last_updated": "2026-04-21T11:39:09.704Z"
  "last_updated": "2026-04-21T13:08:04.028Z"
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Http/HTTP/HttpResponseResult.cs
@@ -3,6 +3,7 @@
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace WIDESEA_Core
@@ -43,8 +44,9 @@
        public string ErrorMessage { get; set; }
        /// <summary>
        /// 异常信息
        /// 异常信息(不参与JSON序列化,因Exception.TargetSite类型无法被System.Text.Json序列化)
        /// </summary>
        [JsonIgnore]
        public Exception Exception { get; set; }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs
@@ -83,11 +83,11 @@
        private readonly ILogger _logger;
        /// <summary>
        /// 目标地址到设备类型的映射
        /// 目标地址到设备类型的映射(入库站台)
        /// </summary>
        /// <remarks>
        /// </remarks>
        private static List<string> AddressToDeviceType = new List<string> { "11020", "11028" };
        private static List<string> AddressToDeviceType = new List<string> { "11020", "11028", "2125" };
        /// <summary>
        /// 托盘检查位置的最近执行时间(用于30秒间隔限制)
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
@@ -5,6 +5,7 @@
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
namespace WIDESEAWCS_Tasks
@@ -103,7 +104,7 @@
        {
            // 清除任务号,表示当前空闲
            conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, 0, childDeviceCode);
            QuartzLogHelper.LogDebug(_logger, "HeartBeat:子设备 {ChildDeviceCode} 心跳", $"HeartBeat:子设备 {childDeviceCode} 心跳", conveyorLine.DeviceCode, childDeviceCode);
            QuartzLogHelper.LogDebug(_logger, $"HeartBeat:子设备 {childDeviceCode} 心跳", conveyorLine.DeviceCode);
        }
        /// <summary>
@@ -122,7 +123,7 @@
        /// <param name="childDeviceCode">子设备编码</param>
        public void RequestInbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommandNew command, string childDeviceCode)
        {
            QuartzLogHelper.LogInfo(_logger, "RequestInbound:子设备 {ChildDeviceCode} 请求入库", $"请求入库,子设备: {childDeviceCode}", conveyorLine.DeviceCode, childDeviceCode);
            QuartzLogHelper.LogInfo(_logger, $"请求入库,子设备: {childDeviceCode}", conveyorLine.DeviceCode);
            // 向 WMS 请求新任务(基于条码)
            if (_taskFilter.RequestWmsTask(command.Barcode, childDeviceCode))
@@ -143,7 +144,7 @@
                    // 更新任务状态到下一阶段
                    _taskService.UpdateTaskStatusToNext(task);
                    QuartzLogHelper.LogInfo(_logger, "RequestInbound:入库任务已下发,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"入库任务已下发,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
                    QuartzLogHelper.LogInfo(_logger, $"入库任务已下发,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
                }
            }
        }
@@ -164,17 +165,21 @@
            Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode);
            if (task == null)
            {
                QuartzLogHelper.LogDebug(_logger, "RequestInNextAddress:任务 {TaskNo} 不存在", $"RequestInNextAddress:任务 {command.TaskNo} 不存在", conveyorLine.DeviceCode, command.TaskNo);
                QuartzLogHelper.LogDebug(_logger, $"RequestInNextAddress:任务 {command.TaskNo} 不存在", conveyorLine.DeviceCode);
                return;
            }
            QuartzLogHelper.LogInfo(_logger, "RequestInNextAddress:入库下一地址,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"RequestInNextAddress:入库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
            QuartzLogHelper.LogInfo(_logger, $"RequestInNextAddress:入库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
            // 如果不是空托盘任务,处理目标地址(与拘束机/插拔钉机交互)
            if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty)
            {
                _targetAddressSelector.HandleInboundNextAddress(conveyorLine, task.NextAddress, childDeviceCode);
            }
            //// 如果不是空托盘任务,处理目标地址
            //if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty)
            //{
            Dt_Router routers = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress);
            if (routers == null) throw new Exception($"未找到设备路由信息");
            _targetAddressSelector.HandleInboundNextAddress(conveyorLine, routers.ChildPosi, childDeviceCode);
            //}
            // 更新任务当前位置
            _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
@@ -204,7 +209,7 @@
                {
                    // 回复 ACK 确认
                    conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                    QuartzLogHelper.LogInfo(_logger, "ConveyorLineInFinish:入库完成,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"入库完成,任务号: {task.TaskNum}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
                    QuartzLogHelper.LogInfo(_logger, $"入库完成,任务号: {task.TaskNum},子设备:{childDeviceCode}", conveyorLine.DeviceCode);
                }
            }
        }
@@ -263,17 +268,20 @@
            Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode);
            if (task == null)
            {
                QuartzLogHelper.LogDebug(_logger, "RequestOutNextAddress:任务 {TaskNo} 不存在", $"RequestOutNextAddress:任务 {command.TaskNo} 不存在", conveyorLine.DeviceCode, command.TaskNo);
                QuartzLogHelper.LogDebug(_logger, $"RequestOutNextAddress:任务 {command.TaskNo} 不存在", conveyorLine.DeviceCode);
                return;
            }
            QuartzLogHelper.LogInfo(_logger, "RequestOutNextAddress:出库下一地址,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"RequestOutNextAddress:出库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
            QuartzLogHelper.LogInfo(_logger, $"RequestOutNextAddress:出库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
            // 如果不是空托盘任务,处理目标地址
            if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty)
            {
                _targetAddressSelector.HandleOutboundNextAddress(conveyorLine, task.NextAddress, childDeviceCode);
            }
            //if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty)
            //{
            Dt_Router routers = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress);
            if (routers == null) throw new Exception($"未找到设备路由信息");
            _targetAddressSelector.HandleOutboundNextAddress(conveyorLine, routers.ChildPosi, childDeviceCode);
            //}
            // 更新任务当前位置
            _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
@@ -307,7 +315,7 @@
                    conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                }
                QuartzLogHelper.LogInfo(_logger, "ConveyorLineOutFinish:出库完成,完成结果:{Status},任务号: {TaskNum},子设备: {ChildDeviceCode},错误消息: {Message}", $"出库完成,完成结果:{content.Status},任务号: {task.TaskNum},错误消息:{content.Message}", conveyorLine.DeviceCode, content.Status, task.TaskNum, childDeviceCode, content.Message);
                QuartzLogHelper.LogInfo(_logger, $"出库完成,完成结果:{content.Status},任务号: {task.TaskNum},错误消息:{content.Message}", conveyorLine.DeviceCode);
            }
        }
    }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs
@@ -135,7 +135,14 @@
            // 记录入库场景的调试日志,包含子设备和目标地址信息
            WriteDebug(conveyorLine, "入库下一地址", childDeviceCode, nextAddress);
            // 委托通用处理方法,入库对应上层(isUpper: true)
            HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, Layer.Upper);
            //HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, Layer.Upper);
            var cvState = conveyorLine.GetValue<ConveyorLineDBNameNew, byte>(ConveyorLineDBNameNew.CV_State, nextAddress);
            bool isAvailable = cvState == 2;
            if (isAvailable)
            {
                conveyorLine.SetValue(ConveyorLineDBNameNew.Target, Convert.ToInt16(nextAddress), childDeviceCode);
            }
        }
        /// <summary>
@@ -153,7 +160,14 @@
            // 记录出库场景的调试日志,包含子设备和目标地址信息
            WriteDebug(conveyorLine, "出库下一地址", childDeviceCode, nextAddress);
            // 委托通用处理方法,出库对应下层(isUpper: false)
            HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, Layer.Lower);
            //HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, Layer.Lower);
            var cvState = conveyorLine.GetValue<ConveyorLineDBNameNew, byte>(ConveyorLineDBNameNew.CV_State, nextAddress);
            bool isAvailable = cvState == 2;
            if (isAvailable)
            {
                conveyorLine.SetValue(ConveyorLineDBNameNew.Target, Convert.ToInt16(nextAddress), childDeviceCode);
            }
        }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs
@@ -385,7 +385,7 @@
            CommonConveyorLine conveyorLine = (CommonConveyorLine)device;
            // 读取 CV_State,CV_State == 2 表示空闲
            byte cvState = conveyorLine.GetValue<ConveyorLineStatus, byte>(ConveyorLineStatus.CV_State, task.TargetAddress);
            byte cvState = conveyorLine.GetValue<ConveyorLineDBNameNew, byte>(ConveyorLineDBNameNew.CV_State, task.TargetAddress);
            bool isAvailable = cvState == 2;
            QuartzLogHelper.LogInfo(_logger, "IsTargetAddressConveyorStationAvailable:TargetAddress: {TargetAddress},CV_State: {CV_State},是否空闲: {IsAvailable},任务号: {TaskNum}",
                $"IsTargetAddressConveyorStationAvailable:TargetAddress: {task.TargetAddress},CV_State: {cvState},是否空闲: {isAvailable}", task.Roadway, task.TargetAddress, cvState, isAvailable, task.TaskNum);
Code/WMS/WIDESEA_WMSClient/src/api/http.js
@@ -12,7 +12,7 @@
let loadingInstance;
let loadingStatus = false;
if (process.env.NODE_ENV == 'development') {
    axios.defaults.baseURL = window.webConfig.webApiProduction;
    axios.defaults.baseURL = window.webConfig.webApiBaseUrl;
}
else if (process.env.NODE_ENV == 'debug') {
    axios.defaults.baseURL = window.webConfig.webApiBaseUrl;
Code/WMS/WIDESEA_WMSClient/src/extension/stock/extend/RobotSelect.vue
@@ -81,7 +81,7 @@
          const result = await this.http.post("/api/StockInfoDetail/BindContainer", {
            palletCode: this.currentRow.palletCode,
            robotCode: this.selectedRobot
            DeviceName: this.selectedRobot
          }, "正在调用MES接口...");
          if (result.status) {
@@ -104,7 +104,7 @@
          const result = await this.http.post("/api/StockInfoDetail/UnbindContainer", {
            palletCode: this.currentRow.palletCode,
            robotCode: this.selectedRobot
            DeviceName: this.selectedRobot
          }, "正在调用MES接口...");
          if (result.status) {
Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Helper/HTTP/HttpResponseResult.cs
@@ -3,6 +3,7 @@
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace WIDESEA_Core
@@ -43,8 +44,9 @@
        public string ErrorMessage { get; set; }
        /// <summary>
        /// 异常信息
        /// 异常信息(不参与JSON序列化,因Exception.TargetSite类型无法被System.Text.Json序列化)
        /// </summary>
        [JsonIgnore]
        public Exception Exception { get; set; }
        /// <summary>
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
@@ -34,7 +34,7 @@
  "MainDB": "DB_WIDESEA", //当前项目的主库,所对应的连接字符串的Enabled必须为true
  //连接字符串
  //"ConnectionString": "HTI6FB1H05Krd07mNm9yBCNhofW6edA5zLs9TY~MNthRYW3kn0qKbMIsGp~3yyPDF1YZUCPBQx8U0Jfk4PH~ajNFXVIwlH85M3F~v_qKYQ3CeAz3q1mLVDn8O5uWt1~3Ut2V3KRkEwYHvW2oMDN~QIDXPxDgXN0R2oTIhc9dNu7QNaLEknblqmHhjaNSSpERdDVZIgHnMKejU_SL49tralBkZmDNi0hmkbL~837j1NWe37u9fJKmv91QPb~16JsuI9uu0EvNZ06g6PuZfOSAeFH9GMMIZiketdcJG3tHelo=",
  "ConnectionString": "Data Source=192.168.60.30;Initial Catalog=WIDESEAWMS_ShanMei;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
  "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWMS_ShanMei;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
  //"ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWMS_ShanMei;User ID=sa;Password=123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
  //"ConnectionString": "Data Source=10.30.4.92;Initial Catalog=WMS_TC;User ID=sa;Password=duo123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
  //旧WMS数据库连接