# OutboundTaskFlowService.MoveToNextStatus TODO 设计方案 ## 背景 `OutboundTaskFlowService.MoveToNextStatus` 方法中存在一个 TODO: ```csharp if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound) { return WebResponseContent.Instance.OK(); // Todo:获取对向线体是否有托盘号,如果有托盘号直接生成机械手任务 return GetWMSOutboundTrayTask(task); } ``` 该 TODO 需要在出库任务到达 `Line_OutFinish` 状态时,检查对向线体是否有托盘号,以决定后续机械手任务的创建方式。 ## 业务逻辑 出库任务流程中,当物料通过输送线到达目标位置后: - **对向线体有托盘号** → 托盘上有货,直接在本地创建机械手任务执行换盘/组盘/拆盘 - **对向线体无托盘号** → 需要从 WMS 获取空托盘出库任务 ## 方案选择 **采用方案 B**:在 `RobotTaskService` 中封装检查逻辑,复用已有的 `BuildRobotTaskStock` 基础设施。 ### 原因 - `RobotTaskService.BuildRobotTaskStock` 已实现通过 `AddressSourceLineNoMap` 解析源线体编号,并通过设备通信读取 `Barcode` 的完整逻辑 - 新增方法职责单一:检查 → 决策,仅做判断不执行副作用 - `OutboundTaskFlowService` 保持简洁,只需调用即可 ## 实现设计 ### 1. RobotTaskService 新增方法 ```csharp /// /// 检查源线体是否有托盘号,并根据结果创建机械手任务。 /// /// 出库任务实体 /// /// 有托盘号时返回 CreateLocalRobotTask 结果; /// 无托盘号时返回 GetWMSOutboundTrayTask 结果。 /// public WebResponseContent CheckSourceLineAndCreateRobotTask(Dt_Task task) { // 1. 获取源线体编号(复用已有逻辑) string configKey = ResolveRobotTaskConfigKey(task.TargetAddress); StockDTO stock = BuildRobotTaskStock(task, configKey); string sourceLineNo = stock.SourceLineNo; if (string.IsNullOrWhiteSpace(sourceLineNo)) { return GetWMSOutboundTrayTask(task); } // 2. 通过设备通信读取线体托盘号 string? palletCode = ReadLineBarcode(sourceLineNo); if (!string.IsNullOrWhiteSpace(palletCode)) { // 有托盘号,本地创建机械手任务 return CreateLocalRobotTask(task); } // 无托盘号,从 WMS 获取任务 return GetWMSOutboundTrayTask(task); } /// /// 读取指定线体的托盘号。 /// private string? ReadLineBarcode(string sourceLineNo) { try { IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceProDTOs.Any(d => d.DeviceChildCode == sourceLineNo)); if (device == null) return null; CommonConveyorLine conveyorLine = (CommonConveyorLine)device; return conveyorLine.GetValue( ConveyorLineDBNameNew.Barcode, sourceLineNo); } catch { return null; } } ``` ### 2. OutboundTaskFlowService 修改 ```csharp if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound) { // 获取对向线体是否有托盘号,如果有托盘号直接生成机械手任务 return _robotTaskService.CheckSourceLineAndCreateRobotTask(task); } ``` ## 数据流 ``` MoveToNextStatus (OutboundTaskFlowService) │ ▼ CheckSourceLineAndCreateRobotTask (RobotTaskService) │ ├───► BuildRobotTaskStock ──► ResolveRobotTaskConfigKey │ └──► AddressSourceLineNoMap 获取 sourceLineNo │ ▼ ReadLineBarcode(sourceLineNo) │ ├───► Storage.Devices 查找设备 └───► CommonConveyorLine.GetValue(Barcode) │ ▼ ┌───────┴───────┐ │ 托盘号有值 │ 托盘号为空 ▼ ▼ CreateLocalRobotTask GetWMSOutboundTrayTask ``` ## 错误处理 - 设备查找失败或读取异常 → 降级为调用 `GetWMSOutboundTrayTask`(从 WMS 获取任务) - 不阻塞主流程,异常仅记录日志 ## 涉及文件 | 文件 | 改动 | |------|------| | `WIDESEAWCS_TaskInfoService/RobotTaskService.cs` | 新增 `CheckSourceLineAndCreateRobotTask` 和 `ReadLineBarcode` 方法 | | `WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs` | 替换 TODO 代码段为委托调用 | ## 验证要点 1. 当输送线有料时,机械手任务直接本地创建,不调用 WMS 接口 2. 当输送线无料时,降级调用 WMS 获取空托盘任务 3. 异常场景不阻塞主流程,降级到 WMS 获取