From 0f710285d9f02e3d4cea19557e17945e9ef9532b Mon Sep 17 00:00:00 2001
From: xiazhengtongxue <133085197+xiazhengtongxue@users.noreply.github.com>
Date: 星期五, 01 五月 2026 09:48:49 +0800
Subject: [PATCH] Merge branch 'dev' of http://115.159.85.185:8098/r/SuZhouGuanHong/ShanMeiXinNengYuan into dev
---
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Communicator/Siemens/SiemensS7Communicator.cs | 3
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs | 8
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/TaskAddressConstants.cs | 4
Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs | 9
Code/WMS/WIDESEA_WMSClient/src/views/system/outboundTimeConfig.vue | 109 ++++++
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/OutboundTimeConstants.cs | 10
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs | 16
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs | 29 +
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/QuartzNet/SchedulerCenterServer.cs | 5
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Connection/RedisConnectionManager.cs | 2
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs | 3
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json | 2
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs | 80 +--
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs | 22
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/outbound_time_config.json | 7
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs | 30 -
Code/docs/superpowers/plans/2026-04-29-outbound-task-flow-todo-implementation.md | 170 +++++++++
Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Core/OutboundTimeConfigOptions.cs | 28 +
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotTaskController.cs | 21
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs | 117 ++++++
Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js | 5
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs | 6
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs | 22
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Inbound.cs | 15
Code/docs/superpowers/specs/2026-04-29-outbound-task-flow-todo-design.md | 148 ++++++++
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs | 10
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/WIDESEA_WMSServer.csproj | 6
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/OutboundTimeConfigController.cs | 94 +++++
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Communicator/Siemens/SiemensDBDataType.cs | 1
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs | 12
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/HttpEnum/BaseAPI.cs | 2
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskService.cs | 16
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotSocketState.cs | 23 +
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs | 3
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs | 2
35 files changed, 888 insertions(+), 152 deletions(-)
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/HttpEnum/BaseAPI.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/HttpEnum/BaseAPI.cs
index 08a0f08..89e42b5 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/HttpEnum/BaseAPI.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/HttpEnum/BaseAPI.cs
@@ -11,7 +11,7 @@
/// <summary>
/// WMS鎺ュ彛鍩虹URL
/// </summary>
- public const string WMSBaseUrl = "http://localhost:9291/api/";
+ public const string WMSBaseUrl = "http://192.168.60.30:9291/api/";
/// <summary>
/// WCS鎺ュ彛鍩虹URL
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Communicator/Siemens/SiemensDBDataType.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Communicator/Siemens/SiemensDBDataType.cs
index 1e678f5..fc5ef00 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Communicator/Siemens/SiemensDBDataType.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Communicator/Siemens/SiemensDBDataType.cs
@@ -112,6 +112,7 @@
DataType_Char => TypeCode.Char,
DataType_UInt => TypeCode.UInt16,
DataType_UDInt => TypeCode.UInt32,
+ DataType_ByteArray => TypeCode.SByte,
_ => throw new CommunicationException($"鏁版嵁绫诲瀷閿欒:銆恵dataType}銆�", CommunicationErrorType.TypeError),
};
}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Communicator/Siemens/SiemensS7Communicator.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Communicator/Siemens/SiemensS7Communicator.cs
index c2dfc11..1d72f38 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Communicator/Siemens/SiemensS7Communicator.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Communicator/Siemens/SiemensS7Communicator.cs
@@ -358,6 +358,9 @@
return Encoding.Default.GetString((byte[])GetContent(plc.Read(address, length), address)).ToArray();
return (char)GetContent(plc.ReadByte(address), address);
+ case TypeCode.SByte:
+ return Encoding.Default.GetString((byte[])GetContent(plc.Read(address, 20), address)).ToArray();
+
default:
throw new CommunicationException(string.Format(CommunicationExceptionMessage.DataTypeErrorException, typeCode.ToString(), address), CommunicationErrorType.TypeError);
}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskService.cs
index 203bf94..87d7b3a 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskService.cs
@@ -83,12 +83,28 @@
WebResponseContent GetWMSRobotTask(Dt_Task task);
/// <summary>
+ ///
+ /// </summary>
+ /// <param name="taskType"></param>
+ /// <param name="palletCode"></param>
+ /// <returns></returns>
+ int GetRobotTaskTotalNum(int taskType, string? palletCode);
+
+ /// <summary>
/// 鍦ㄦ湰鍦扮洿鎺ュ垱寤烘満姊版墜浠诲姟锛屼笉璋冪敤WMS鎺ュ彛
/// </summary>
/// <param name="task">鍑哄簱浠诲姟</param>
/// <returns>鎿嶄綔缁撴灉</returns>
WebResponseContent CreateLocalRobotTask(Dt_Task task);
+ /// <summary>
+ /// 妫�鏌ユ簮绾夸綋鏄惁鏈夋墭鐩樺彿锛屽苟鏍规嵁缁撴灉鍒涘缓鏈烘鎵嬩换鍔°��
+ /// 鏈夋墭鐩樺彿鏃惰皟鐢� CreateLocalRobotTask锛屾棤鎵樼洏鍙锋椂浠� WMS 鑾峰彇浠诲姟銆�
+ /// </summary>
+ /// <param name="task">鍑哄簱浠诲姟瀹炰綋</param>
+ /// <returns>鎿嶄綔缁撴灉</returns>
+ WebResponseContent CheckSourceLineAndCreateRobotTask(Dt_Task task);
+
int MapWarehouseIdConfigKey(string? targetAddress);
string ResolveRobotRuleValue(string? targetAddress, string addressSectionName, string? fallback);
WebResponseContent CreateRobotTaskManually(ManualRobotTaskDto request);
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotSocketState.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotSocketState.cs
index de75b1d..4fcd16a 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotSocketState.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotSocketState.cs
@@ -127,13 +127,23 @@
public int[]? LastPutPositions { get; set; }
/// <summary>
- /// 鐢垫睜/璐т綅鏉$爜鍒楄〃
+ /// 鐢垫睜/璐т綅鏉$爜鍒楄〃锛堢疮绉墍鏈夋壒娆★紝涓嶉噸澶嶏級
/// </summary>
/// <remarks>
- /// 鍦ㄧ粍鐩樻搷浣滄椂鐢ㄤ簬璁板綍鐢熸垚鐨勬墭鐩樻潯鐮併��
+ /// 鍦ㄧ粍鐩樻搷浣滄椂鐢ㄤ簬绱Н璁板綍鎵�鏈夌數鑺潯鐮侊紝姣忔璇诲彇鏂版潯鐮佹椂杩藉姞锛堝幓閲嶏級銆�
+ /// 浠呭湪鏀跺埌 allputfinished锛堝叏閮ㄦ斁璐у畬鎴愶級鏃舵竻绌恒��
/// 姣忎釜鏉$爜鏍煎紡涓� "TRAY" + 鏃ユ湡 + 鏃堕棿 + 闅忔満鏁般��
/// </remarks>
public List<string> CellBarcode { get; set; } = new List<string>();
+
+ /// <summary>
+ /// 褰撳墠鎵规鐨勭數鑺潯鐮佸垪琛�
+ /// </summary>
+ /// <remarks>
+ /// 姣忔璇诲彇鏂版潯鐮佹椂璁剧疆涓烘湰鎵规鐨勬潯鐮侊紝浠呯敤浜� WMS 鎻愪氦鏃舵寜鎵规鎻愪氦銆�
+ /// 姣忔鏂版壒娆¤鍙栨椂瑕嗙洊锛屽湪 allputfinished 鏃舵竻绌恒��
+ /// </remarks>
+ public List<string> CurrentBatchBarcodes { get; set; } = new List<string>();
/// <summary>
/// 鏈烘鎵嬪綋鍓嶆鍦ㄦ墽琛岀殑浠诲姟
@@ -217,5 +227,14 @@
/// 鎷夊甫绾夸笂鐢佃姱鏄惁鍒颁綅銆�
/// </remarks>
public bool BatteryArrived { get; set; } = false;
+
+ /// <summary>
+ /// 褰撳墠鎵ц涓殑鏈哄櫒浜轰换鍔$紪鍙�
+ /// </summary>
+ /// <remarks>
+ /// 涓嬪彂浠诲姟鏃剁紦瀛樹换鍔$紪鍙凤紝鐢ㄤ簬 RobotJob 蹇�熸煡鎵炬墽琛屼腑鐨勪换鍔★紝
+ /// 閬垮厤姣忔杞鍏ㄨ〃鎵弿銆備换鍔″畬鎴愭椂娓呯┖涓� null銆�
+ /// </remarks>
+ public int? CurrentTaskNum { get; set; }
}
}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/QuartzNet/SchedulerCenterServer.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/QuartzNet/SchedulerCenterServer.cs
index 6be42fe..5c795e5 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/QuartzNet/SchedulerCenterServer.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/QuartzNet/SchedulerCenterServer.cs
@@ -459,11 +459,14 @@
/// <returns></returns>
private ITrigger CreateSimpleTrigger(DispatchInfoDTO sysSchedule)
{
+ // Quartz瑕佹眰闂撮殧鑷冲皯1绉掞紝闃叉鏁版嵁搴撲腑IntervalSecond涓�0鎴栬礋鍊煎鑷碅rgumentOutOfRangeException
+ var intervalSeconds = sysSchedule.IntervalSecond <= 0 ? 1 : sysSchedule.IntervalSecond;
+
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity(sysSchedule.Id.ToString(), sysSchedule.JobGroup)
.StartAt(sysSchedule.BeginTime.GetValueOrDefault())
.WithSimpleSchedule(x => x
- .WithIntervalInSeconds(sysSchedule.IntervalSecond)
+ .WithIntervalInSeconds(intervalSeconds)
.RepeatForever()
)
.EndAt(sysSchedule.EndTime.GetValueOrDefault())
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Connection/RedisConnectionManager.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Connection/RedisConnectionManager.cs
index 8b697de..0d93b8b 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Connection/RedisConnectionManager.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Connection/RedisConnectionManager.cs
@@ -82,6 +82,8 @@
public IServer GetServer()
{
var endpoints = _connection.Value.GetEndPoints();
+ if (endpoints == null || endpoints.Length == 0)
+ throw new InvalidOperationException("Redis娌℃湁鍙敤鐨勭粓缁撶偣锛岃妫�鏌ヨ繛鎺ラ厤缃�");
return _connection.Value.GetServer(endpoints[0]);
}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotTaskController.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotTaskController.cs
index ee7754c..e43311b 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotTaskController.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotTaskController.cs
@@ -1,14 +1,8 @@
-锘縰sing Autofac.Core;
-using Masuit.Tools;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using System.Threading.Tasks;
-using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseController;
-using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_DTO.TaskInfo;
-using WIDESEAWCS_ISystemServices;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
@@ -20,22 +14,29 @@
{
public RobotTaskController(IRobotTaskService service) : base(service)
{
-
}
+
[HttpGet, HttpPost, Route("DeleteRobotTask"), AllowAnonymous]
public WebResponseContent DeleteRobotTask(int id)
{
- if (Service.DeleteRobotTask(id)){
+ if (Service.DeleteRobotTask(id))
+ {
return WebResponseContent.Instance.OK();
}
return WebResponseContent.Instance.Error();
}
+ [HttpGet, HttpPost, Route("GetRobotTaskTotalNum"), AllowAnonymous]
+ public int GetRobotTaskTotalNum(int taskType, string? palletCode)
+ {
+ return Service.GetRobotTaskTotalNum(taskType, palletCode);
+ }
+
// 鎵嬪姩鏈烘鎵嬩换鍔�
[HttpGet, HttpPost, Route("CreateRobotTaskManually"), AllowAnonymous]
- public WebResponseContent CreateRobotTaskManually([FromBody] ManualRobotTaskDto request)
+ public WebResponseContent CreateRobotTaskManually([FromBody] ManualRobotTaskDto request)
{
return Service.CreateRobotTaskManually(request);
}
}
-}
+}
\ No newline at end of file
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
index 8897ce4..6847c0c 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
@@ -34,7 +34,7 @@
//5.PostgreSQL
"DBType": "SqlServer",
//杩炴帴瀛楃涓�
- "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWCS_ShanMei;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ConnectionString": "Data Source=192.168.60.30;Initial Catalog=WIDESEAWCS_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=WIDESEAWCS_ShanMei;User ID=sa;Password=123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
//璺ㄥ煙
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs
index 192b2a5..e9df2c8 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs
@@ -107,13 +107,17 @@
if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound)
{
- return WebResponseContent.Instance.OK();
+ //return WebResponseContent.Instance.OK();
+
+ //return _robotTaskService.CheckSourceLineAndCreateRobotTask(task);
+ // Todo:鑾峰彇瀵瑰悜绾夸綋鏄惁鏈夋墭鐩樺彿锛屽鏋滄湁鎵樼洏鍙风洿鎺ョ敓鎴愭満姊版墜浠诲姟
+
return GetWMSOutboundTrayTask(task);
}
if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
{
- return _robotTaskService.CreateLocalRobotTask(task);
+ return _robotTaskService.CreateLocalRobotTask(task);
//if (!content.Status)
//{
// return content;
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
index 48c1bc2..915f224 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -22,10 +22,12 @@
using Masuit.Tools;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
using Serilog;
using SqlSugar;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Text;
using WIDESEA_Core;
using WIDESEAWCS_Common;
using WIDESEAWCS_Common.HttpEnum;
@@ -75,6 +77,7 @@
_taskExecuteDetailService = taskExecuteDetailService;
_logger = logger;
}
+
public override WebResponseContent DeleteData(object[] keys)
{
List<int> taskKeys = new List<int>();
@@ -85,8 +88,8 @@
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);
@@ -135,7 +138,7 @@
public Dt_RobotTask? QueryRobotCraneTask(string deviceCode)
{
- return BaseDal.QueryFirst(x => x.RobotRoadway == deviceCode && x.RobotTaskState != (int)TaskRobotStatusEnum.RobotExecuting, TaskOrderBy);
+ return BaseDal.QueryFirst(x => x.RobotRoadway == deviceCode, TaskOrderBy);
}
public Dt_RobotTask? QueryRobotCraneExecutingTask(string deviceCode)
@@ -242,10 +245,108 @@
}
/// <summary>
+ /// 妫�鏌ユ簮绾夸綋鏄惁鏈夋墭鐩樺彿锛屽苟鏍规嵁缁撴灉鍒涘缓鏈烘鎵嬩换鍔°��
+ /// </summary>
+ /// <param name="task">鍑哄簱浠诲姟瀹炰綋</param>
+ /// <returns>
+ /// 鏈夋墭鐩樺彿鏃惰繑鍥� CreateLocalRobotTask 缁撴灉锛�
+ /// 鏃犳墭鐩樺彿鏃惰繑鍥� GetWMSOutboundTrayTask 缁撴灉銆�
+ /// </returns>
+ 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 GetWMSOutboundTrayTaskFromWMS(task);
+ }
+
+ // 2. 閫氳繃璁惧閫氫俊璇诲彇绾夸綋鎵樼洏鍙�
+ string? palletCode = ReadLineBarcode(sourceLineNo);
+
+ if (!string.IsNullOrWhiteSpace(palletCode))
+ {
+ // 鏈夋墭鐩樺彿锛屾湰鍦板垱寤烘満姊版墜浠诲姟
+ return CreateLocalRobotTask(task);
+ }
+
+ // 鏃犳墭鐩樺彿锛屼粠 WMS 鑾峰彇浠诲姟
+ return GetWMSOutboundTrayTaskFromWMS(task);
+ }
+
+ /// <summary>
+ /// 浠嶹MS鑾峰彇绌烘墭鐩樺嚭搴撲换鍔°��
+ /// </summary>
+ /// <param name="task">浠诲姟瀹炰綋銆�</param>
+ /// <returns>璋冪敤缁撴灉銆�</returns>
+ private WebResponseContent GetWMSOutboundTrayTaskFromWMS(Dt_Task task)
+ {
+ int warehouseId = MapWarehouseIdConfigKey(task.TargetAddress);
+ string sourceLineNo = ResolveRobotRuleValue(task.TargetAddress, "AddressSourceLineNoMap", task.TargetAddress);
+ string configKey = nameof(ConfigKey.GetOutBoundTrayTaskAsync);
+ string requestParam = new CreateTaskDto { WarehouseId = warehouseId, TargetAddress = sourceLineNo }.ToJson();
+ DateTime startTime = DateTime.Now;
+
+ var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
+
+ 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}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�");
+ }
+
+ QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RobotTaskService");
+
+ WMSTaskDTO? wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data?.ToString() ?? string.Empty);
+ if (wMSTask == null)
+ return WebResponseContent.Instance.Error($"鑾峰彇WMS绯荤粺绌烘墭鐩樺嚭搴撲换鍔″け璐�,浠诲姟鍙�:銆恵task.TaskNum}銆�,鎵樼洏鍙�:銆恵task.PalletCode}銆�,閿欒淇℃伅:銆怶MS鏈繑鍥炴湁鏁堜换鍔℃暟鎹��");
+
+ // 鏋勫缓StockDTO骞惰皟鐢≧eceiveWMSTask鍒涘缓鏈湴鍏ュ簱浠诲姟
+ var stockDto = new StockDTO
+ {
+ Roadway = task.Roadway,
+ SourceLineNo = sourceLineNo,
+ TargetLineNo = task.TargetAddress,
+ SourcePalletNo = string.Empty,
+ TargetPalletNo = string.Empty
+ };
+ return ReceiveWMSTask(wMSTask, stockDto);
+ }
+
+ /// <summary>
+ /// 璇诲彇鎸囧畾绾夸綋鐨勬墭鐩樺彿銆�
+ /// </summary>
+ /// <param name="sourceLineNo">婧愮嚎浣撶紪鍙�</param>
+ /// <returns>鎵樼洏鍙凤紝濡傛湁寮傚父杩斿洖 null</returns>
+ 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, string>(
+ ConveyorLineDBNameNew.Barcode, sourceLineNo);
+ }
+ catch (Exception ex)
+ {
+ _logger.Error(ex, $"璇诲彇绾夸綋[{sourceLineNo}]鎵樼洏鍙峰紓甯�");
+ return null;
+ }
+ }
+
+ /// <summary>
/// 鑾峰彇鏈烘鎵嬩换鍔℃�绘暟閲忋��
/// 缁勭洏浠诲姟鍥哄畾48锛屾崲鐩樺拰鎷嗙洏浠诲姟閫氳繃鎵樼洏鍙锋煡璇MS搴撳瓨鏄庣粏鏁伴噺銆�
/// </summary>
- private int GetRobotTaskTotalNum(int taskType, string? palletCode)
+ public int GetRobotTaskTotalNum(int taskType, string? palletCode)
{
if (taskType == (int)RobotTaskTypeEnum.GroupPallet)
return 48;
@@ -255,8 +356,10 @@
try
{
+ QuartzLogHelper.LogInfo(_logger, $"寮�濮嬭皟鐢╓MS鎺ュ彛鑾峰彇搴撳瓨鏄庣粏鏁伴噺,鎵樼洏鍙�:銆恵palletCode}銆�", "RobotTaskService");
string url = $"{BaseAPI.WMSBaseUrl}Stock/GetStockDetailCount?palletCode={Uri.EscapeDataString(palletCode)}";
var result = _httpClientHelper.Get(url);
+ QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鑾峰彇搴撳瓨鏄庣粏鏁伴噺鎺ュ彛,璇锋眰URL:銆恵url}銆�,鍝嶅簲鏁版嵁:銆恵result.Content}銆�,鑰楁椂:{result.Duration}ms", "RobotTaskService");
if (!result.IsSuccess || string.IsNullOrEmpty(result.Content))
return 1;
@@ -264,8 +367,8 @@
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;
+ var detailCount = (response.Data as JObject)?["detailCount"]?.Value<int>();
+ return detailCount.HasValue && detailCount.Value > 0 ? detailCount.Value : 1;
}
catch
{
@@ -370,8 +473,10 @@
CommonConveyorLine conveyorLine = (CommonConveyorLine)device;
DeviceProDTO? devicePro = conveyorLine.DeviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == nameof(ConveyorLineDBNameNew.Barcode) && x.DeviceChildCode == sourceLineNo);
+ //conveyorLine.Communicator.Read(devicePro.DeviceProAddress, 20);
//ConveyorLineTaskCommandNew command = conveyorLine.ReadCustomer<ConveyorLineTaskCommandNew>(sourceLineNo); // 娴嬭瘯鐢�
- var barcode = conveyorLine.GetValue<ConveyorLineDBNameNew, string>(ConveyorLineDBNameNew.Barcode, sourceLineNo);
+ var bytes = conveyorLine.Communicator.Read(devicePro.DeviceProAddress, 20);
+ var barcode = Encoding.Default.GetString(bytes).Trim();
stock.SourcePalletNo = string.IsNullOrEmpty(barcode) ? string.Empty : barcode;
}
}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs
index 7788251..fa281cd 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs
@@ -1,16 +1,11 @@
using MapsterMapper;
using Masuit.Tools;
-using Microsoft.Extensions.Configuration;
-using Newtonsoft.Json;
using Quartz;
using Serilog;
using SqlSugar;
using WIDESEA_Core;
-using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
-using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Helper;
-using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
@@ -228,7 +223,11 @@
{
// 濡傛灉 WCS_ACK 涓� 1锛屽厛娓呴櫎锛堣〃绀哄鐞嗚繃涓婁竴娆¤姹傦級
if (command.WCS_ACK == 1)
- conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)0, childDeviceCode);
+ {
+ conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (byte)0, childDeviceCode);
+ //Thread.Sleep(300);
+ //conveyorLine.SetValue(ConveyorLineDBNameNew.Target, (short)0, childDeviceCode);
+ }
// 澶勭悊鎵嬪姩鍏ュ簱浠诲姟锛堣捣鐐逛负绾夸綋鐐逛綅鐨勪换鍔★級
try
@@ -247,17 +246,36 @@
}
continue;
}
+ else
+ {
+ if (childDeviceCode == "2103" || childDeviceCode == "2101")
+ {
+ try
+ {
+ var task = _taskService.QueryManualInboundTask(childDeviceCode);
+ if (task != null)
+ {
+ QuartzLogHelper.LogInfo(_logger, $"鑾峰彇鍒拌緭閫佺嚎寮�濮嬩换鍔★紝浠诲姟鍙凤細{task.TaskNum}锛岀姸鎬�: {task.TaskStatus},褰撳墠鍦板潃锛歿conveyorLine.DeviceCode}", conveyorLine.DeviceCode);
+ var handler = new ManualInboundTaskHandler(_taskService, _logger);
+ handler.WriteTaskToPlc(conveyorLine, childDeviceCode, task);
+ }
+ }
+ catch (Exception ex)
+ {
+ QuartzLogHelper.LogError(_logger, ex, "澶勭悊鎵嬪姩鍏ュ簱浠诲姟寮傚父", $"澶勭悊鎵嬪姩鍏ュ簱浠诲姟寮傚父: {ex.Message}", "CommonConveyorLineNewJob");
+ }
+ }
+ }
- // ========== 澶勭悊鏃犳墭鐩樻潯鐮佺殑鎯呭喌 ==========
- // 鏃犳墭鐩樻潯鐮佹椂锛岃姹傚嚭搴撲换鍔�
- if (command.Barcode.IsNullOrEmpty() || command.Barcode.Replace("\0", "") == "")
+ // 濡傛灉 PLC_STB 涓� 1锛屼絾娌℃湁浠诲姟鍙凤紝鍙兘鏄柊浠诲姟鐨勫紑濮嬶紝鍏堣姹傚嚭搴撲换鍔★紙閫傜敤浜庢棤鏉$爜鐨勬儏鍐碉級
+ if (command.TaskNo == 1000)
{
_conveyorLineDispatch.RequestOutbound(conveyorLine, command, childDeviceCode);
continue;
}
// ========== 澶勭悊宸叉湁浠诲姟鍙风殑鎯呭喌 ==========
- if (command.TaskNo > 0 && !command.Barcode.IsNullOrEmpty())
+ if (command.TaskNo > 0)
{
// 鏌ヨ姝e湪鎵ц鐨勪换鍔�
Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNo, childDeviceCode);
@@ -299,48 +317,6 @@
conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
}
}
- //else if (!command.Barcode.IsNullOrEmpty() && (childDeviceCode == "11001" || childDeviceCode == "11010"))
- //{
- // var isWcsTask = _taskService.Db.Queryable<Dt_Task>().Any(x => x.PalletCode == command.Barcode && (x.TaskStatus == (int)TaskOutStatusEnum.OutNew || x.TaskStatus == (int)TaskInStatusEnum.InNew));
- // var isRobotTask = _robotTaskService.Db.Queryable<Dt_RobotTask>().Any(x => x.RobotTargetAddressPalletCode == command.Barcode);
- // if (isWcsTask || isRobotTask)
- // {
- // continue;
- // }
-
- // // 璋冪敤 WMS 鍒涘缓绌烘墭鐩樺叆搴撲换鍔�
- // string configKey = nameof(ConfigKey.CreateTaskInboundAsync);
- // string requestParam = new CreateTaskDto()
- // {
- // PalletCode = command.Barcode,
- // SourceAddress = childDeviceCode,
- // TargetAddress = "GWSC1", // 鐩爣鍦板潃
- // Roadway = "GWSC1", // 宸烽亾
- // WarehouseId = 1, // 浠撳簱 ID
- // PalletType = 1, // 鎵樼洏绫诲瀷锛堥粯璁や负1锛�
- // TaskType = TaskTypeEnum.InEmpty.GetHashCode() // 浠诲姟绫诲瀷锛堝叆搴�/绌烘墭鐩樺叆搴擄級
- // }.Serialize();
- // DateTime startTime = DateTime.Now;
-
- // var responseResult = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
-
- // if (responseResult.IsSuccess && responseResult.Data.Status)
- // {
- // QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,鍝嶅簲鏁版嵁:銆恵responseResult.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", conveyorLine.DeviceCode);
- // var wmsTask = JsonConvert.DeserializeObject<WMSTaskDTO>(responseResult?.Data?.Data?.ToString());
- // List<WMSTaskDTO> taskDTOs = new List<WMSTaskDTO> { wmsTask };
- // if (wmsTask == null) continue;
-
- // if (_taskService.ReceiveWMSTask(taskDTOs).Status)
- // {
- // conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
- // }
- // }
- // else
- // {
- // QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵responseResult.Data?.Message}銆�", conveyorLine.DeviceCode);
- // }
- //}
}
}
catch (Exception innerEx)
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
index d3555a1..1b3c8d5 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
@@ -257,21 +257,21 @@
// 纭畾鐩爣鍦板潃锛氱┖鎵樼洏浠诲姟浣跨敤 "2201"锛屽叾浠栦换鍔′娇鐢� NextAddress
var isEmptyTask = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty;
- var targetAddress = task.CurrentAddress == "2217" ? (isEmptyTask ? "2201" : task.NextAddress) : task.NextAddress;
+ var targetAddress = task.CurrentAddress == "2217" ? (isEmptyTask ? task.TargetAddress : task.NextAddress) : task.NextAddress;
// 澶勭悊鐗规畩鍦板潃 2217锛岄渶瑕佽皟鐢ㄧ洰鏍囧湴鍧�閫夋嫨鍣�
- if (task.CurrentAddress == "2217" && !_targetAddressSelector.HandleOutboundNextAddress(conveyorLine, targetAddress, childDeviceCode))
- {
- return Task.CompletedTask; ;
- }
+ //if (task.CurrentAddress == "2217" && !_targetAddressSelector.HandleOutboundNextAddress(conveyorLine, targetAddress, childDeviceCode))
+ //{
+ // return Task.CompletedTask; ;
+ //}
// 璁剧疆浠诲姟鍙枫�佹墭鐩樻潯鐮併�佺洰鏍囧湴鍧�銆乄CS_ACK
var isTaskNoSet = conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, task.TaskNum, childDeviceCode);
- Thread.Sleep(100); // 纭繚 PLC 鑳芥纭鍙栦换鍔″彿鍚庡啀鍐欏叆鏉$爜
+ Thread.Sleep(300); // 纭繚 PLC 鑳芥纭鍙栦换鍔″彿鍚庡啀鍐欏叆鏉$爜
var isPalletSet = conveyorLine.SetValue(ConveyorLineDBNameNew.Barcode, task.PalletCode, childDeviceCode);
- Thread.Sleep(100); // 纭繚 PLC 鑳芥纭鍙栦换鍔″彿鍚庡啀鍐欏叆鏉$爜
+ Thread.Sleep(300); // 纭繚 PLC 鑳芥纭鍙栦换鍔″彿鍚庡啀鍐欏叆鏉$爜
bool isTargetSet = conveyorLine.SetValue(ConveyorLineDBNameNew.Target, targetAddress, childDeviceCode);
//if (targetAddress == "2217" && !isEmptyTask)
//{
@@ -281,16 +281,16 @@
//}
//if (!isTargetSet || !isTaskNoSet || !isPalletSet)
//{
- // QuartzLogHelper.LogError(_logger, $"RequestOutbound锛氫笅鍙戝嚭搴撲换鍔″け璐ワ紝浠诲姟鍙�: {task.TaskNum}锛屽瓙璁惧: {childDeviceCode}", conveyorLine.DeviceCode);
+ // QuartzLogHelper.LogError(_logger, $"RequestOutbound锛氫笅鍙戝嚭搴撲换鍔″け璐ワ紝浠诲姟鍙�: {task.TaskNum}锛屽瓙璁惧: {childDeviceCode}", conveyorLine.DeviceCode);
// return Task.CompletedTask;
//}
bool isWmsResult = false;
// 鏇存柊浠诲姟鐘舵�佹垨浣嶇疆
- if (isEmptyTask && task.NextAddress == "2217")
+ if (isEmptyTask && (task.TargetAddress == "2103" || task.TargetAddress == "2101"))
{
task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskOutStatusEnum>();
- task.NextAddress = "2201";
+ task.NextAddress = "2103";
isWmsResult = _taskService.Repository.UpdateData(task);
}
else
@@ -298,7 +298,7 @@
isWmsResult = _taskService.UpdateTaskStatusToNext(task).Status;
}
- if(!isWmsResult)
+ if (!isWmsResult)
{
QuartzLogHelper.LogError(_logger, $"RequestOutbound锛氭洿鏂颁换鍔$姸鎬佸け璐ワ紝浠诲姟鍙�: {task.TaskNum}锛屽瓙璁惧: {childDeviceCode}", conveyorLine.DeviceCode);
return Task.CompletedTask;
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs
index e003d18..c816827 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs
@@ -68,8 +68,11 @@
var cvState = conveyorLine.GetValue<ConveyorLineDBNameNew, byte>(ConveyorLineDBNameNew.CV_State, nextAddress);
bool isAvailable = cvState == 2;
+ WriteDebug(conveyorLine, "鍑哄簱涓嬩竴鍦板潃鐘舵��", childDeviceCode, $"CV_State={cvState}锛屽彲鐢�={isAvailable}");
if (isAvailable)
{
+ WriteDebug(conveyorLine, "鍑哄簱涓嬩竴鍦板潃鍙敤锛屽啓鍏ョ洰鏍囧湴鍧�", childDeviceCode, nextAddress);
+ Thread.Sleep(300); // 鐭殏绛夊緟锛岀‘淇濊澶囩姸鎬佺ǔ瀹氬悗鍐嶅啓鍏ョ洰鏍囧湴鍧�
return conveyorLine.SetValue(ConveyorLineDBNameNew.Target, Convert.ToInt16(nextAddress), childDeviceCode);
}
return false;
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
index c97e7ed..ecb24ae 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
@@ -209,7 +209,15 @@
}
// 杞鑾峰彇璇ヨ澶囩殑寰呭鐞嗕换鍔�
- var task = _taskProcessor.GetTask(robotCrane);
+ // 浼樺厛閫氳繃鐘舵�佷腑缂撳瓨鐨勪换鍔$紪鍙锋煡鎵炬墽琛屼腑鐨勪换鍔�
+ Dt_RobotTask? task = null;
+ if (state.CurrentTaskNum.HasValue)
+ {
+ task = _taskProcessor.GetTaskByNum(state.CurrentTaskNum.Value);
+ }
+
+ // 缂撳瓨鐨勪换鍔″彿鏈壘鍒板搴斾换鍔℃椂锛屾寜璁惧缂栫爜鑾峰彇鏂颁换鍔�
+ task ??= _taskProcessor.GetTask(robotCrane);
// 濡傛灉娌℃湁鑾峰彇鍒板緟澶勭悊浠诲姟锛屼笖RobotArmObject涓�1锛堟湁鐗╂枡锛夛紝鍒欒幏鍙栬璁惧鎵ц涓殑浠诲姟
//if (task == null && state.RobotArmObject == 1)
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
index 318ed17..93fc738 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
@@ -124,6 +124,20 @@
}
/// <summary>
+ /// 鎸変换鍔$紪鍙疯幏鍙栨満鍣ㄤ汉浠诲姟
+ /// </summary>
+ /// <remarks>
+ /// 鐢ㄤ簬 RobotJob 蹇�熸煡鎵炬墽琛屼腑鐨勪换鍔★紝閬垮厤鍏ㄨ〃鎵弿銆�
+ /// 浼樺厛閫氳繃鐘舵�佷腑缂撳瓨鐨� CurrentTaskNum 瀹氫綅浠诲姟銆�
+ /// </remarks>
+ /// <param name="taskNum">鏈哄櫒浜轰换鍔$紪鍙�</param>
+ /// <returns>鍖归厤鐨勪换鍔″璞★紝濡傛灉娌℃湁鍒欒繑鍥� null</returns>
+ public Dt_RobotTask? GetTaskByNum(int taskNum)
+ {
+ return _robotTaskService.Repository.QueryFirst(x => x.RobotTaskNum == taskNum);
+ }
+
+ /// <summary>
/// 鎸夎澶囩紪鐮佽幏鍙栧綋鍓嶆満鍣ㄤ汉鐨勬墽琛屼腑浠诲姟
/// </summary>
/// <remarks>
@@ -186,6 +200,7 @@
// 灏嗕换鍔″叧鑱斿埌鐘舵�佸璞�
state.CurrentTask = task;
+ state.CurrentTaskNum = task.RobotTaskNum;
if (isScanNG)
{
@@ -276,6 +291,7 @@
// 灏嗕换鍔″叧鑱斿埌鐘舵�佸璞�
state.CurrentTask = task;
+ state.CurrentTaskNum = task.RobotTaskNum;
if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
{
@@ -346,6 +362,7 @@
task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
state.CurrentTask = task;
+ state.CurrentTaskNum = task.RobotTaskNum;
if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
{
@@ -389,6 +406,7 @@
{
task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
state.CurrentTask = task;
+ state.CurrentTaskNum = task.RobotTaskNum;
if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
{
@@ -434,6 +452,7 @@
{
task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
state.CurrentTask = task;
+ state.CurrentTaskNum = task.RobotTaskNum;
if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
{
@@ -627,6 +646,12 @@
// 瑙f瀽 WMS 杩斿洖鐨勪换鍔′俊鎭�
WMSTaskDTO taskDTO = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data.ToJson() ?? string.Empty) ?? new WMSTaskDTO();
+ var task = await _taskService.Repository.QueryFirstAsync(x => x.PalletCode == taskDTO.PalletCode);
+ if(task != null)
+ {
+ await _taskService.Repository.DeleteDataAsync(task);
+ }
+
// 璋冪敤浠诲姟鏈嶅姟鎺ユ敹 WMS 浠诲姟
var content = _taskService.ReceiveWMSTask(new List<WMSTaskDTO> { taskDTO });
if (!content.Status)
@@ -682,9 +707,9 @@
// 閫氶亾/浣嶇疆缂栧彿
Channel = x,
- // 鐢垫睜鏉$爜锛氬鏋滅姸鎬佷腑鏈夋潯鐮佸垪琛紝鍙栧搴斾綅缃殑鏉$爜锛涘惁鍒欎负绌�
+ // 鐢垫睜鏉$爜锛氫娇鐢ㄥ綋鍓嶆壒娆℃潯鐮佸垪琛紝鍙栧搴斾綅缃殑鏉$爜锛涘惁鍒欎负绌�
//CellBarcode = state.CellBarcode?.Count > 0 ? state.CellBarcode[x - 1] : ""
- CellBarcode = !state.CellBarcode.IsNullOrEmpty() ? state.CellBarcode[idx].ToString() ?? string.Empty : string.Empty
+ CellBarcode = !state.CurrentBatchBarcodes.IsNullOrEmpty() ? state.CurrentBatchBarcodes[idx].ToString() ?? string.Empty : string.Empty
})
.ToList()
};
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
index d60d160..eb8c01e 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
@@ -197,7 +197,7 @@
// 璋冪敤鎵归噺鎷嗙洏纭鎺ュ彛
var sourcePallet = state.CurrentTask.RobotSourceAddressPalletCode;
var confirmResult = _taskProcessor.PostSplitPalletConfirmAsync(sourcePallet, state.RobotCrane?.DeviceName);
- if (!confirmResult.IsSuccess)
+ if (!confirmResult.IsSuccess && !confirmResult.Data.Status)
{
QuartzLogHelper.LogError(_logger, $"鎵归噺鎷嗙洏纭澶辫触: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown");
return false;
@@ -221,8 +221,10 @@
QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
state.CurrentTask = null;
+ state.CurrentTaskNum = null;
state.RobotTaskTotalNum = 0;
state.CellBarcode = new List<string>();
+ state.CurrentBatchBarcodes = new List<string>();
state.ChangePalletPhase = 0;
state.CurrentBatchIndex = 1;
state.IsInFakeBatteryMode = false;
@@ -314,7 +316,7 @@
// 璋冪敤鎵归噺缁勭洏纭鎺ュ彛
var targetPallet = state.CurrentTask.RobotTargetAddressPalletCode;
var confirmResult = _taskProcessor.PostGroupPalletConfirmAsync(targetPallet, state.RobotCrane?.DeviceName);
- if (!confirmResult.IsSuccess)
+ if (!confirmResult.IsSuccess && !confirmResult.Data.Status)
{
QuartzLogHelper.LogError(_logger, $"鎵归噺缁勭洏纭澶辫触: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown");
return false;
@@ -335,8 +337,10 @@
}
state.CurrentTask = null;
+ state.CurrentTaskNum = null;
state.RobotTaskTotalNum = 0;
state.CellBarcode = new List<string>();
+ state.CurrentBatchBarcodes = new List<string>();
await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
@@ -371,8 +375,10 @@
}
state.CurrentTask = null;
+ state.CurrentTaskNum = null;
state.RobotTaskTotalNum = 0;
state.CellBarcode = new List<string>();
+ state.CurrentBatchBarcodes = new List<string>();
await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
@@ -411,8 +417,10 @@
// 娓呯悊鐘舵�侊紝涓轰笅涓�涓换鍔″仛鍑嗗
state.CurrentTask = null; // 娓呴櫎褰撳墠浠诲姟
+ state.CurrentTaskNum = null; // 娓呴櫎褰撳墠浠诲姟缂栧彿
state.RobotTaskTotalNum = 0; // 閲嶇疆浠诲姟璁℃暟
state.CellBarcode = new List<string>(); // 娓呯┖鏉$爜鍒楄〃
+ state.CurrentBatchBarcodes = new List<string>(); // 娓呯┖褰撳墠鎵规鏉$爜
await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
index 3d5241e..6d8f9a7 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
@@ -271,6 +271,7 @@
if (stateToUpdate != null)
{
stateToUpdate.CurrentTask = task;
+ stateToUpdate.CurrentTaskNum = task.RobotTaskNum;
if (_stateManager.TryUpdateStateSafely(ipAddress, stateToUpdate))
{
@@ -356,10 +357,16 @@
QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync锛氳鍙栫殑鐢佃姱鏉$爜鍞竴锛岀户缁墽琛岋紝浠诲姟鍙�: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
- // 灏嗘潯鐮佹坊鍔犲埌鐘舵�佷腑锛屼緵鍚庣画鏀捐揣鏃朵娇鐢�
- stateForUpdate.CellBarcode = new List<string>()
+ // 灏嗘潯鐮佺疮绉埌 CellBarcode锛堝幓閲嶏級锛屽苟璁剧疆褰撳墠鎵规鏉$爜
+ if (!stateForUpdate.CellBarcode.Contains(trayBarcode1))
+ stateForUpdate.CellBarcode.Add(trayBarcode1);
+ if (!stateForUpdate.CellBarcode.Contains(trayBarcode2))
+ stateForUpdate.CellBarcode.Add(trayBarcode2);
+
+ // 璁剧疆褰撳墠鎵规鏉$爜锛岀敤浜� WMS 鎻愪氦
+ stateForUpdate.CurrentBatchBarcodes = new List<string>()
{
- trayBarcode1,trayBarcode2
+ trayBarcode1, trayBarcode2
};
}
@@ -396,10 +403,13 @@
// 鐩爣鏁伴噺涓�48锛氱洿鎺ヨ蛋鍘熸湁閫昏緫锛屼笉杩涘叆鎵规妯″紡
if (targetNormalCount + currentCompletedCount == targetTotal)
{
+ QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync锛氱洰鏍囨暟閲忓凡杈�48锛岀洿鎺ヤ笅鍙戝彇璐ф寚浠わ紝浠诲姟鍙�: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate);
return;
}
+ QuartzLogHelper.LogDebug(_logger,$"HandlePutFinishedStateAsync锛氭崲鐩樹换鍔$洰鏍囨暟閲�: {targetNormalCount}锛屽綋鍓嶅凡瀹屾垚鏁伴噺: {currentCompletedCount}锛屾祦鍚�: {(isFlowA ? "A" : "B")}锛屼换鍔″彿: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
+
// 鍒濆鍖栨壒娆℃ā寮�
if (stateForUpdate.ChangePalletPhase == 0)
{
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
index 15fd6f2..2c7f8f4 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
@@ -3,6 +3,7 @@
using System.Text.Json;
using System.IO;
using WIDESEAWCS_Model.Models;
+using Serilog.Core;
namespace WIDESEAWCS_Tasks.SocketServer
{
@@ -64,6 +65,7 @@
//{
// if (_clientLastMessage.TryGetValue(clientId, out var prev) && message == prev)
// {
+ // QuartzLogHelper.LogInfo(Logger.None, $"鏉ヨ嚜瀹㈡埛绔� {clientId} 鐨勯噸澶嶆秷鎭紝鍐呭: {message}", clientId);
// continue;
// }
// _clientLastMessage[clientId] = message;
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs
index f24aa72..4568c72 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs
@@ -121,36 +121,6 @@
}
/// <summary>
- /// 鍔犺浇閰嶇疆鏂囦欢锛堜紭鍏堢骇锛氶厤缃枃浠� > 榛樿閰嶇疆锛�
- /// </summary>
- /// <remarks>
- /// 浠庡簲鐢ㄧ▼搴忕洰褰曚笅鐨� StackerCraneJob/stackercrane-command-config.json 璇诲彇閰嶇疆銆�
- /// 濡傛灉鏂囦欢涓嶅瓨鍦ㄦ垨瑙f瀽澶辫触锛屼娇鐢ㄩ粯璁ら厤缃��
- /// </remarks>
- /// <returns>鍫嗗灈鏈哄懡浠ら厤缃�</returns>
- private static StackerCraneCommandConfig LoadConfig()
- {
- try
- {
- // 鏋勯�犻厤缃枃浠惰矾寰�
- string configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "StackerCraneJob", "stackercrane-command-config.json");
- if (File.Exists(configPath))
- {
- // 璇诲彇骞惰В鏋� JSON 閰嶇疆
- string json = File.ReadAllText(configPath);
- return System.Text.Json.JsonSerializer.Deserialize<StackerCraneCommandConfig>(json) ?? new StackerCraneCommandConfig();
- }
- }
- catch (Exception ex)
- {
- // 閰嶇疆鍔犺浇澶辫触锛屼娇鐢ㄩ粯璁ら厤缃�
- Console.WriteLine($"閰嶇疆鍔犺浇澶辫触: {ex.Message}锛屼娇鐢ㄩ粯璁ら厤缃�");
- }
-
- return new StackerCraneCommandConfig();
- }
-
- /// <summary>
/// Quartz Job 鐨勬墽琛屽叆鍙�
/// </summary>
/// <remarks>
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs
index 712dd6c..7e4a4ea 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs
@@ -1,7 +1,6 @@
using Newtonsoft.Json;
using Serilog;
using System.Diagnostics.CodeAnalysis;
-using System.Threading.Tasks;
using WIDESEA_Core;
using WIDESEAWCS_Common.Constants;
using WIDESEAWCS_Common.HttpEnum;
@@ -10,7 +9,6 @@
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
-using WIDESEAWCS_QuartzJob.ConveyorLine.Enum;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
@@ -208,7 +206,7 @@
{
// 鍏堣繘琛屾湰鍦扮珯鍙版鏌ワ紙PLC 璇诲彇锛屽揩閫燂級锛岄伩鍏嶄笉蹇呰鐨� WMS HTTP 璋冪敤
- if (outboundTask.TaskType != (int)TaskOutboundTypeEnum.OutEmpty && outboundTask.Roadway != "GWSC1" && outboundTask.TargetAddress != "CWSC1")
+ if (outboundTask.TaskType != (int)TaskOutboundTypeEnum.OutEmpty && outboundTask.TargetAddress != "CWSC1")
{
// 鍒ゆ柇 TargetAddress 杈撻�佺嚎绔欏彴鏄惁绌洪棽
if (!IsTargetAddressConveyorStationAvailable(outboundTask))
@@ -223,18 +221,18 @@
return null;
}
- if (outboundTask.TargetAddress != "CWSC1")
+ //if (outboundTask.TargetAddress != "CWSC1")
+ //{
+ // 妫�鏌ユ槸鍚︽湁姝e湪鎵ц鐨勮緭閫佺嚎浠诲姟鍘诲線鍚屼竴 TargetAddress
+ if (_taskService.HasExecutingTaskToTarget(outboundTask.Roadway, outboundTask.TargetAddress))
{
- // 妫�鏌ユ槸鍚︽湁姝e湪鎵ц鐨勮緭閫佺嚎浠诲姟鍘诲線鍚屼竴 TargetAddress
- if (_taskService.HasExecutingTaskToTarget(outboundTask.Roadway, outboundTask.TargetAddress))
- {
- QuartzLogHelper.LogInfo(_logger, "TrySelectOutboundTask锛歍argetAddress: {TargetAddress} 宸叉湁姝e湪鎵ц鐨勮緭閫佺嚎浠诲姟锛屼换鍔″彿: {TaskNum}",
- $"TrySelectOutboundTask锛歍argetAddress: {outboundTask.TargetAddress} 宸叉湁姝e湪鎵ц鐨勮緭閫佺嚎浠诲姟", outboundTask.Roadway, outboundTask.TargetAddress, outboundTask.TaskNum);
- return null;
- }
+ QuartzLogHelper.LogInfo(_logger, "TrySelectOutboundTask锛歍argetAddress: {TargetAddress} 宸叉湁姝e湪鎵ц鐨勮緭閫佺嚎浠诲姟锛屼换鍔″彿: {TaskNum}",
+ $"TrySelectOutboundTask锛歍argetAddress: {outboundTask.TargetAddress} 宸叉湁姝e湪鎵ц鐨勮緭閫佺嚎浠诲姟", outboundTask.Roadway, outboundTask.TargetAddress, outboundTask.TaskNum);
+ return null;
}
+ //}
- if(outboundTask.Roadway != "GWSC1")
+ if (outboundTask.Roadway != "GWSC1")
{
return outboundTask;
}
diff --git a/Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js b/Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js
index 598b86e..b1f0e0f 100644
--- a/Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js
+++ b/Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js
@@ -243,6 +243,11 @@
name: 'PDA',
component: () => import('@/views/system/PDA.vue')
}
+ , {
+ path: '/outboundTimeConfig',
+ name: 'outboundTimeConfig',
+ component: () => import('@/views/system/outboundTimeConfig.vue')
+ }
]
export default viewgird
diff --git a/Code/WMS/WIDESEA_WMSClient/src/views/system/outboundTimeConfig.vue b/Code/WMS/WIDESEA_WMSClient/src/views/system/outboundTimeConfig.vue
new file mode 100644
index 0000000..e44fcc4
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient/src/views/system/outboundTimeConfig.vue
@@ -0,0 +1,109 @@
+<template>
+ <div class="config-container">
+ <el-card class="config-card">
+ <template #header>
+ <span>鍑哄簱鏃舵晥閰嶇疆</span>
+ </template>
+ <el-form :model="form" label-width="180px" v-loading="loading">
+ <el-form-item label="GW棣栨斁鍏ュ簱鏃舵晥锛堝皬鏃讹級">
+ <el-input-number
+ v-model="form.gw1FirstHours"
+ :min="0.01"
+ :max="999"
+ :precision="2"
+ :step="1"
+ />
+ </el-form-item>
+ <el-form-item label="GW浜屾斁鍏ュ簱鏃舵晥锛堝皬鏃讹級">
+ <el-input-number
+ v-model="form.gw1SecondHours"
+ :min="0.01"
+ :max="999"
+ :precision="2"
+ :step="0.01"
+ />
+ </el-form-item>
+ <el-form-item label="CW鍑哄簱鏃舵晥锛堝皬鏃讹級">
+ <el-input-number
+ v-model="form.cw1Hours"
+ :min="0.01"
+ :max="999"
+ :precision="2"
+ :step="1"
+ />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleSave" :loading="saving">
+ 淇濆瓨
+ </el-button>
+ </el-form-item>
+ </el-form>
+ </el-card>
+ </div>
+</template>
+
+<script>
+import { ref, onMounted } from "vue";
+import { ElMessage } from "element-plus";
+import http from "@/api/http";
+
+export default {
+ name: "outboundTimeConfig",
+ setup() {
+ const loading = ref(false);
+ const saving = ref(false);
+ const form = ref({
+ gw1FirstHours: 24,
+ gw1SecondHours: 0.05,
+ cw1Hours: 3,
+ });
+
+ /// 鍔犺浇褰撳墠閰嶇疆
+ const loadConfig = async () => {
+ loading.value = true;
+ try {
+ const res = await http.post("/api/OutboundTimeConfig/get", {}, false);
+ if (res.status) {
+ form.value = {
+ gw1FirstHours: res.data.gw1FirstHours,
+ gw1SecondHours: res.data.gw1SecondHours,
+ cw1Hours: res.data.cw1Hours,
+ };
+ }
+ } finally {
+ loading.value = false;
+ }
+ };
+
+ /// 淇濆瓨閰嶇疆
+ const handleSave = async () => {
+ saving.value = true;
+ try {
+ const res = await http.post("/api/OutboundTimeConfig/update", form.value, false);
+ if (res.status) {
+ ElMessage.success("淇濆瓨鎴愬姛");
+ } else {
+ ElMessage.error(res.message || "淇濆瓨澶辫触");
+ }
+ } finally {
+ saving.value = false;
+ }
+ };
+
+ onMounted(() => {
+ loadConfig();
+ });
+
+ return { form, loading, saving, handleSave };
+ },
+};
+</script>
+
+<style scoped>
+.config-container {
+ padding: 20px;
+}
+.config-card {
+ max-width: 600px;
+}
+</style>
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs
index d7aee6d..2a1433c 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs
@@ -159,9 +159,12 @@
&& x.LocationType == locationType)
.CountAsync();
- // 绌洪棽璐т綅涓嶈冻鏈�浣庝繚鐣欐暟閲忔椂杩斿洖null锛岄伩鍏嶅皢宸烽亾鍒嗛厤鑰楀敖
- const int minFreeLocationThreshold = 5;
- if (freeCount < minFreeLocationThreshold) return null;
+ if(roadwayNo != "CWSC1")
+ {
+ // 绌洪棽璐т綅涓嶈冻鏈�浣庝繚鐣欐暟閲忔椂杩斿洖null锛岄伩鍏嶅皢宸烽亾鍒嗛厤鑰楀敖
+ const int minFreeLocationThreshold = 1;
+ if (freeCount < minFreeLocationThreshold) return null;
+ }
// 鏁版嵁搴撶鎺掑簭鍙栫涓�鏉★紙鍙紶杈撳崟琛屾暟鎹級
return await BaseDal.Db.Queryable<Dt_LocationInfo>()
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/OutboundTimeConstants.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/OutboundTimeConstants.cs
index b1e0174..fdd7553 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/OutboundTimeConstants.cs
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/OutboundTimeConstants.cs
@@ -29,16 +29,16 @@
/// <summary>
/// GW_1棣栨斁鍏ュ簱鏃舵晥锛�24灏忔椂锛�
/// </summary>
- public const int OUTBOUND_HOURS_GW1_FIRST = 24;
+ public const double OUTBOUND_HOURS_GW1_FIRST = 24;
/// <summary>
- /// GW_1浜屾斁鍏ュ簱鏃舵晥锛�24灏忔椂锛�
+ /// GW_1浜屾斁鍏ュ簱鏃舵晥锛�5鍒嗛挓锛�
/// </summary>
- public const int OUTBOUND_HOURS_GW1_SECOND = 24;
+ public const double OUTBOUND_HOURS_GW1_SECOND = 0.05;
/// <summary>
- /// CW_1鍑哄簱鏃舵晥锛�12灏忔椂锛�
+ /// CW_1鍑哄簱鏃舵晥锛�3灏忔椂锛�
/// </summary>
- public const int OUTBOUND_HOURS_CW1 = 12;
+ public const double OUTBOUND_HOURS_CW1 = 3;
}
}
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/TaskAddressConstants.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/TaskAddressConstants.cs
index 21577e5..ab4ed07 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/TaskAddressConstants.cs
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/TaskAddressConstants.cs
@@ -13,7 +13,7 @@
/// <summary>
/// 楂樻俯1鍙峰嚭搴撳湴鍧�鍒楄〃锛堣疆璇級
/// </summary>
- public static readonly string[] GW1_ADDRESSES = { "11001" };
+ public static readonly string[] GW1_ADDRESSES = { "11010" };
/// <summary>
/// 楂樻俯2鍙峰嚭搴撳湴鍧�
@@ -28,7 +28,7 @@
/// <summary>
/// 鍒嗗搴撳嚭搴撳湴鍧�
/// </summary>
- public const string GRADING_OUTBOUND_ADDRESS = "2103";
+ public const string GRADING_OUTBOUND_ADDRESS = "2101";
/// <summary>
/// 鍒嗗搴撳嚭搴撳湴鍧�
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Core/OutboundTimeConfigOptions.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Core/OutboundTimeConfigOptions.cs
new file mode 100644
index 0000000..2b3c643
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Core/OutboundTimeConfigOptions.cs
@@ -0,0 +1,28 @@
+namespace WIDESEA_Core.Core
+{
+ /// <summary>
+ /// 鍑哄簱鏃舵晥閰嶇疆閫夐」锛岀粦瀹� appsettings.json 涓殑 OutboundTimeConfig 鑺�
+ /// </summary>
+ public class OutboundTimeConfigOptions
+ {
+ /// <summary>
+ /// 閰嶇疆鑺傚悕绉�
+ /// </summary>
+ public const string SectionName = "OutboundTimeConfig";
+
+ /// <summary>
+ /// GW棣栨斁鍏ュ簱鏃舵晥锛堝皬鏃讹級锛岄粯璁�24灏忔椂
+ /// </summary>
+ public double Gw1FirstHours { get; set; } = 24;
+
+ /// <summary>
+ /// GW浜屾斁鍏ュ簱鏃舵晥锛堝皬鏃讹級锛岄粯璁�0.05灏忔椂锛堢害3鍒嗛挓锛�
+ /// </summary>
+ public double Gw1SecondHours { get; set; } = 0.05;
+
+ /// <summary>
+ /// CW鍑哄簱鏃舵晥锛堝皬鏃讹級锛岄粯璁�3灏忔椂
+ /// </summary>
+ public double Cw1Hours { get; set; } = 3;
+ }
+}
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
index 77f62a8..2367be1 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -9,6 +9,7 @@
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.TaskEnum;
using WIDESEA_Common.WareHouseEnum;
+using Microsoft.Extensions.Options;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
@@ -43,6 +44,7 @@
private readonly IMesLogService _mesLogService;
private readonly IMesUploadHelper _mesUploadHelper;
private readonly ISqlSugarClient _sqlSugarClient;
+ private readonly IOptionsMonitor<OutboundTimeConfigOptions> _outboundTimeOptions;
public IRepository<Dt_Task> Repository => BaseDal;
@@ -71,7 +73,8 @@
IMESDeviceConfigService mesDeviceConfigService,
IMesLogService mesLogService,
IMesUploadHelper mesUploadHelper,
- ISqlSugarClient sqlSugarClient) : base(BaseDal)
+ ISqlSugarClient sqlSugarClient,
+ IOptionsMonitor<OutboundTimeConfigOptions> outboundTimeOptions) : base(BaseDal)
{
_mapper = mapper;
_stockInfoService = stockInfoService;
@@ -88,6 +91,7 @@
_mesLogService = mesLogService;
_mesUploadHelper = mesUploadHelper;
_sqlSugarClient = sqlSugarClient;
+ _outboundTimeOptions = outboundTimeOptions;
}
/// <summary>
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Inbound.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Inbound.cs
index f36e945..53cd86a 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Inbound.cs
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Inbound.cs
@@ -141,8 +141,10 @@
Creater = StockConstants.SYSTEM_USER,
Details = null,
LocationCode = location.LocationCode,
- LocationId = location.Id
+ LocationId = location.Id,
+ OutboundDate = DateTime.Now
};
+ location.LocationStatus = LocationStatusEnum.InStock.GetHashCode();
var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location);
var updateStockResult = await _stockInfoService.Repository.AddDataAsync(stockInfo);
return await CompleteTaskAsync(task, "鍏ュ簱瀹屾垚");
@@ -166,6 +168,8 @@
SetOutboundDateByRoadway(task, stockInfo);
stockInfo.StockStatus = StockStatusEmun.鍏ュ簱瀹屾垚.GetHashCode();
+
+ stockInfo.CreateDate = DateTime.Now;
location.LocationStatus = LocationStatusEnum.InStock.GetHashCode();
@@ -229,14 +233,15 @@
/// <param name="stockInfo">搴撳瓨淇℃伅</param>
private void SetOutboundDateByRoadway(Dt_Task task, Dt_StockInfo stockInfo)
{
+ var config = _outboundTimeOptions.CurrentValue;
var now = DateTime.Now;
if (task.Roadway.Contains("GW"))
{
stockInfo.OutboundDate = string.IsNullOrEmpty(stockInfo.Remark)
- ? now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_FIRST)
+ ? now.AddHours(config.Gw1FirstHours)
: stockInfo.Remark == StockRemarkConstants.GW1
- ? now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_SECOND)
- : now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_FIRST);
+ ? now.AddHours(config.Gw1SecondHours)
+ : now.AddHours(config.Gw1FirstHours);
stockInfo.Remark = string.IsNullOrEmpty(stockInfo.Remark)
? StockRemarkConstants.GW1
@@ -246,7 +251,7 @@
}
else if (task.Roadway.Contains("CW"))
{
- stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_CW1);
+ stockInfo.OutboundDate = now.AddHours(config.Cw1Hours);
if (stockInfo.Remark == StockRemarkConstants.GW2)
stockInfo.Remark = StockRemarkConstants.CW1;
}
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/OutboundTimeConfigController.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/OutboundTimeConfigController.cs
new file mode 100644
index 0000000..6b1804b
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/OutboundTimeConfigController.cs
@@ -0,0 +1,94 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using WIDESEA_Core;
+using WIDESEA_Core.Core;
+
+namespace WIDESEA_WMSServer.Controllers
+{
+ /// <summary>
+ /// 鍑哄簱鏃舵晥閰嶇疆鎺у埗鍣紝璇诲啓鐙珛鐨� outbound_time_config.json 閰嶇疆鏂囦欢
+ /// </summary>
+ [Route("api/[controller]")]
+ [ApiController]
+ [Authorize]
+ public class OutboundTimeConfigController : ControllerBase
+ {
+ private readonly IOptionsMonitor<OutboundTimeConfigOptions> _optionsMonitor;
+ private readonly IWebHostEnvironment _env;
+
+ /// <summary>
+ /// 閰嶇疆鏂囦欢鍚�
+ /// </summary>
+ private const string ConfigFileName = "outbound_time_config.json";
+
+ /// <summary>
+ /// 鏋勯�犲嚱鏁�
+ /// </summary>
+ /// <param name="optionsMonitor">鍑哄簱鏃舵晥閰嶇疆 Options 鐩戞帶鍣�</param>
+ /// <param name="env">Web 瀹夸富鐜锛岀敤浜庡畾浣嶉厤缃枃浠惰矾寰�</param>
+ public OutboundTimeConfigController(IOptionsMonitor<OutboundTimeConfigOptions> optionsMonitor, IWebHostEnvironment env)
+ {
+ _optionsMonitor = optionsMonitor;
+ _env = env;
+ }
+
+ /// <summary>
+ /// 鑾峰彇褰撳墠鍑哄簱鏃舵晥閰嶇疆
+ /// </summary>
+ /// <returns>褰撳墠閰嶇疆鍊�</returns>
+ [HttpPost("get")]
+ public IActionResult Get()
+ {
+ var config = _optionsMonitor.CurrentValue;
+ return Ok(WebResponseContent.Instance.OK("鑾峰彇鎴愬姛", new
+ {
+ config.Gw1FirstHours,
+ config.Gw1SecondHours,
+ config.Cw1Hours
+ }));
+ }
+
+ /// <summary>
+ /// 鏇存柊鍑哄簱鏃舵晥閰嶇疆锛屽啓鍏ョ嫭绔嬬殑 outbound_time_config.json 鏂囦欢
+ /// </summary>
+ /// <param name="config">鏂扮殑閰嶇疆鍊�</param>
+ /// <returns>鎿嶄綔缁撴灉</returns>
+ [HttpPost("update")]
+ public IActionResult Update([FromBody] OutboundTimeConfigOptions config)
+ {
+ if (config.Gw1FirstHours <= 0 || config.Gw1SecondHours <= 0 || config.Cw1Hours <= 0)
+ {
+ return Ok(WebResponseContent.Instance.Error("閰嶇疆鍊煎繀椤诲ぇ浜�0"));
+ }
+
+ try
+ {
+ var filePath = Path.Combine(_env.ContentRootPath, ConfigFileName);
+
+ // 鏋勫缓閰嶇疆 JSON锛屽寘瑁瑰湪 OutboundTimeConfig 鑺備笅浠ュ尮閰� Options 缁戝畾
+ var configSection = new JObject
+ {
+ ["Gw1FirstHours"] = config.Gw1FirstHours,
+ ["Gw1SecondHours"] = config.Gw1SecondHours,
+ ["Cw1Hours"] = config.Cw1Hours
+ };
+ var jsonObj = new JObject
+ {
+ [OutboundTimeConfigOptions.SectionName] = configSection
+ };
+
+ // 鍐欏叆鏂囦欢锛屾牸寮忓寲杈撳嚭
+ System.IO.File.WriteAllText(filePath, jsonObj.ToString(Formatting.Indented));
+
+ return Ok(WebResponseContent.Instance.OK("閰嶇疆鏇存柊鎴愬姛"));
+ }
+ catch (Exception ex)
+ {
+ return Ok(WebResponseContent.Instance.Error($"閰嶇疆鏇存柊澶辫触: {ex.Message}"));
+ }
+ }
+ }
+}
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs
index a3e0f16..43e60a1 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs
@@ -36,6 +36,7 @@
hostingContext.Configuration.ConfigureApplication();
config.Sources.Clear();
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
+ config.AddJsonFile("outbound_time_config.json", optional: true, reloadOnChange: true);
});
builder.Host.UseSerilog((context, services, loggerConfiguration) =>
@@ -75,6 +76,8 @@
builder.Services.AddSingleton<RoundRobinService>();
builder.Services.Configure<AutoOutboundTaskOptions>(
builder.Configuration.GetSection("AutoOutboundTask"));
+builder.Services.Configure<OutboundTimeConfigOptions>(
+ builder.Configuration.GetSection(OutboundTimeConfigOptions.SectionName));
builder.Services.AddMemoryCacheSetup(); // 缂撳瓨鏈嶅姟
builder.Services.AddWebSocketSetup();
builder.Services.AddSqlsugarSetup(); // SqlSugar 鏁版嵁搴撻厤缃�
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/WIDESEA_WMSServer.csproj b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/WIDESEA_WMSServer.csproj
index 234f1e2..e3f712c 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/WIDESEA_WMSServer.csproj
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/WIDESEA_WMSServer.csproj
@@ -24,6 +24,12 @@
</ItemGroup>
<ItemGroup>
+ <Content Update="outbound_time_config.json">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ </ItemGroup>
+
+ <ItemGroup>
<Content Update="wwwroot\swg-login.html">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Content>
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/outbound_time_config.json b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/outbound_time_config.json
new file mode 100644
index 0000000..bd086c3
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/outbound_time_config.json
@@ -0,0 +1,7 @@
+{
+ "OutboundTimeConfig": {
+ "Gw1FirstHours": 24.0,
+ "Gw1SecondHours": 0.05,
+ "Cw1Hours": 3.0
+ }
+}
\ No newline at end of file
diff --git a/Code/docs/superpowers/plans/2026-04-29-outbound-task-flow-todo-implementation.md b/Code/docs/superpowers/plans/2026-04-29-outbound-task-flow-todo-implementation.md
new file mode 100644
index 0000000..d3bf360
--- /dev/null
+++ b/Code/docs/superpowers/plans/2026-04-29-outbound-task-flow-todo-implementation.md
@@ -0,0 +1,170 @@
+# OutboundTaskFlowService.MoveToNextStatus TODO 瀹炵幇璁″垝
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** 琛ュ叏 `OutboundTaskFlowService.MoveToNextStatus` 鏂规硶涓殑 TODO锛屽疄鐜板湪鍑哄簱浠诲姟鍒拌揪 `Line_OutFinish` 鐘舵�佹椂妫�鏌ュ鍚戠嚎浣撴墭鐩樺彿锛屾湁鎵樼洏鍙峰垯鏈湴鍒涘缓鏈烘鎵嬩换鍔★紝鏃犳墭鐩樺彿鍒欎粠 WMS 鑾峰彇浠诲姟銆�
+
+**Architecture:** 鍦� `RobotTaskService` 涓柊澧� `CheckSourceLineAndCreateRobotTask` 鏂规硶锛屽鐢ㄥ凡鏈夌殑 `BuildRobotTaskStock` 鑾峰彇婧愮嚎浣撶紪鍙凤紝閫氳繃璁惧閫氫俊璇诲彇绾夸綋鎵樼洏鍙凤紝鏍规嵁缁撴灉鍐冲畾璋冪敤 `CreateLocalRobotTask` 鎴� `GetWMSOutboundTrayTask`銆�
+
+**Tech Stack:** C# / .NET 6, ASP.NET Core, SqlSugar ORM
+
+---
+
+## 娑夊強鏂囦欢
+
+| 鏂囦欢 | 鏀瑰姩 |
+|------|------|
+| `WIDESEAWCS_TaskInfoService/RobotTaskService.cs` | 鏂板 `CheckSourceLineAndCreateRobotTask` 鏂规硶 |
+| `WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs` | 鏇挎崲 TODO 浠g爜娈典负濮旀墭璋冪敤 |
+
+---
+
+## Task 1: 鍦� RobotTaskService 鏂板 CheckSourceLineAndCreateRobotTask 鏂规硶
+
+**Files:**
+- Modify: `WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs:241`锛堝湪 `CreateLocalRobotTask` 鏂规硶涔嬪悗锛�
+
+- [ ] **Step 1: 鍦� `CreateLocalRobotTask` 鏂规硶鍚庢坊鍔犳柊鏂规硶**
+
+鍦� `RobotTaskService.cs` 绗� 240 琛岋紙`CreateLocalRobotTask` 鏂规硶缁撴潫鍚庣殑浣嶇疆锛夋坊鍔犱互涓嬫柟娉曪細
+
+```csharp
+/// <summary>
+/// 妫�鏌ユ簮绾夸綋鏄惁鏈夋墭鐩樺彿锛屽苟鏍规嵁缁撴灉鍒涘缓鏈烘鎵嬩换鍔°��
+/// </summary>
+/// <param name="task">鍑哄簱浠诲姟瀹炰綋</param>
+/// <returns>
+/// 鏈夋墭鐩樺彿鏃惰繑鍥� CreateLocalRobotTask 缁撴灉锛�
+/// 鏃犳墭鐩樺彿鏃惰繑鍥� GetWMSOutboundTrayTask 缁撴灉銆�
+/// </returns>
+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);
+}
+
+/// <summary>
+/// 璇诲彇鎸囧畾绾夸綋鐨勬墭鐩樺彿銆�
+/// </summary>
+/// <param name="sourceLineNo">婧愮嚎浣撶紪鍙�</param>
+/// <returns>鎵樼洏鍙凤紝濡傛湁寮傚父杩斿洖 null</returns>
+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, string>(
+ ConveyorLineDBNameNew.Barcode, sourceLineNo);
+ }
+ catch (Exception ex)
+ {
+ _logger.Error(ex, $"璇诲彇绾夸綋[{sourceLineNo}]鎵樼洏鍙峰紓甯�");
+ return null;
+ }
+}
+```
+
+- [ ] **Step 2: 楠岃瘉缂栬瘧**
+
+Run: `dotnet build WIDESEAWCS_Server/WIDESEAWCS_Server.sln --no-restore`
+Expected: BUILD SUCCEEDED锛堟棤缂栬瘧閿欒锛�
+
+- [ ] **Step 3: 鎻愪氦**
+
+```bash
+git add WIDESEAWCS_TaskInfoService/RobotTaskService.cs
+git commit -m "feat(鏈烘鎵嬩换鍔�): 鏂板CheckSourceLineAndCreateRobotTask鏂规硶鏀寔妫�鏌ョ嚎浣撴墭鐩樺彿鍐崇瓥
+
+- 鏂板CheckSourceLineAndCreateRobotTask鏂规硶锛屾牴鎹簮绾夸綋鎵樼洏鍙峰喅瀹氬垱寤烘満姊版墜浠诲姟鏂瑰紡
+- 鏂板ReadLineBarcode绉佹湁鏂规硶锛岃鍙栨寚瀹氱嚎浣撶殑鎵樼洏鍙�
+- 鏈夋墭鐩樺彿鏃惰皟鐢–reateLocalRobotTask锛屾棤鎵樼洏鍙锋椂璋冪敤GetWMSOutboundTrayTask
+- 寮傚父鏃堕檷绾т负浠嶹MS鑾峰彇浠诲姟"
+```
+
+---
+
+## Task 2: 淇敼 OutboundTaskFlowService.MoveToNextStatus 璋冪敤鏂版柟娉�
+
+**Files:**
+- Modify: `WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs:107-114`
+
+- [ ] **Step 1: 鏇挎崲 TODO 浠g爜娈�**
+
+灏� `OutboundTaskFlowService.cs` 绗� 107-114 琛岋細
+
+```csharp
+if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound)
+{
+ return WebResponseContent.Instance.OK();
+
+ // Todo:鑾峰彇瀵瑰悜绾夸綋鏄惁鏈夋墭鐩樺彿锛屽鏋滄湁鎵樼洏鍙风洿鎺ョ敓鎴愭満姊版墜浠诲姟
+
+ return GetWMSOutboundTrayTask(task);
+}
+```
+
+鏇挎崲涓猴細
+
+```csharp
+if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound)
+{
+ // 鑾峰彇瀵瑰悜绾夸綋鏄惁鏈夋墭鐩樺彿锛屽鏋滄湁鎵樼洏鍙风洿鎺ョ敓鎴愭満姊版墜浠诲姟
+ return _robotTaskService.CheckSourceLineAndCreateRobotTask(task);
+}
+```
+
+- [ ] **Step 2: 楠岃瘉缂栬瘧**
+
+Run: `dotnet build WIDESEAWCS_Server/WIDESEAWCS_Server.sln --no-restore`
+Expected: BUILD SUCCEEDED锛堟棤缂栬瘧閿欒锛�
+
+- [ ] **Step 3: 鎻愪氦**
+
+```bash
+git add WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs
+git commit -m "feat(鍑哄簱浠诲姟): MoveToNextStatus璋冪敤CheckSourceLineAndCreateRobotTask鍐崇瓥鏈烘鎵嬩换鍔″垱寤烘柟寮�
+
+- 鏇挎崲TODO浠g爜娈典负_robotTaskService.CheckSourceLineAndCreateRobotTask璋冪敤
+- 鏈夋墭鐩樺彿鏃舵湰鍦板垱寤烘満姊版墜浠诲姟锛屾棤鎵樼洏鍙锋椂浠嶹MS鑾峰彇"
+```
+
+---
+
+## 楠岃瘉瑕佺偣
+
+1. 褰撹緭閫佺嚎鏈夋枡鏃讹紙瀵瑰悜绾夸綋 Barcode 鏈夊�硷級锛屾満姊版墜浠诲姟鐩存帴鏈湴鍒涘缓锛屼笉璋冪敤 WMS 鎺ュ彛
+2. 褰撹緭閫佺嚎鏃犳枡鏃讹紙瀵瑰悜绾夸綋 Barcode 涓虹┖锛夛紝闄嶇骇璋冪敤 WMS 鑾峰彇绌烘墭鐩樹换鍔�
+3. 寮傚父鍦烘櫙涓嶉樆濉炰富娴佺▼锛岄檷绾у埌 WMS 鑾峰彇
+
+---
+
+## 娉ㄦ剰浜嬮」
+
+- `ReadLineBarcode` 鏂规硶澶嶇敤浜� `BuildRobotTaskStock` 涓鍙� Barcode 鐨勮澶囨煡璇㈤�昏緫锛堣 `RobotTaskService.cs:365-374`锛�
+- 寮傚父澶勭悊杩斿洖 null锛岃Е鍙戦檷绾ч�昏緫璋冪敤 `GetWMSOutboundTrayTask`
+- 璁捐鏂囨。浣嶇疆锛歚docs/superpowers/specs/2026-04-29-outbound-task-flow-todo-design.md`
diff --git a/Code/docs/superpowers/specs/2026-04-29-outbound-task-flow-todo-design.md b/Code/docs/superpowers/specs/2026-04-29-outbound-task-flow-todo-design.md
new file mode 100644
index 0000000..47e84da
--- /dev/null
+++ b/Code/docs/superpowers/specs/2026-04-29-outbound-task-flow-todo-design.md
@@ -0,0 +1,148 @@
+# 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` 瑙f瀽婧愮嚎浣撶紪鍙凤紝骞堕�氳繃璁惧閫氫俊璇诲彇 `Barcode` 鐨勫畬鏁撮�昏緫
+- 鏂板鏂规硶鑱岃矗鍗曚竴锛氭鏌� 鈫� 鍐崇瓥锛屼粎鍋氬垽鏂笉鎵ц鍓綔鐢�
+- `OutboundTaskFlowService` 淇濇寔绠�娲侊紝鍙渶璋冪敤鍗冲彲
+
+## 瀹炵幇璁捐
+
+### 1. RobotTaskService 鏂板鏂规硶
+
+```csharp
+/// <summary>
+/// 妫�鏌ユ簮绾夸綋鏄惁鏈夋墭鐩樺彿锛屽苟鏍规嵁缁撴灉鍒涘缓鏈烘鎵嬩换鍔°��
+/// </summary>
+/// <param name="task">鍑哄簱浠诲姟瀹炰綋</param>
+/// <returns>
+/// 鏈夋墭鐩樺彿鏃惰繑鍥� CreateLocalRobotTask 缁撴灉锛�
+/// 鏃犳墭鐩樺彿鏃惰繑鍥� GetWMSOutboundTrayTask 缁撴灉銆�
+/// </returns>
+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);
+}
+
+/// <summary>
+/// 璇诲彇鎸囧畾绾夸綋鐨勬墭鐩樺彿銆�
+/// </summary>
+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, string>(
+ 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 浠g爜娈典负濮旀墭璋冪敤 |
+
+## 楠岃瘉瑕佺偣
+
+1. 褰撹緭閫佺嚎鏈夋枡鏃讹紝鏈烘鎵嬩换鍔$洿鎺ユ湰鍦板垱寤猴紝涓嶈皟鐢� WMS 鎺ュ彛
+2. 褰撹緭閫佺嚎鏃犳枡鏃讹紝闄嶇骇璋冪敤 WMS 鑾峰彇绌烘墭鐩樹换鍔�
+3. 寮傚父鍦烘櫙涓嶉樆濉炰富娴佺▼锛岄檷绾у埌 WMS 鑾峰彇
--
Gitblit v1.9.3