| Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Core/AutoOutboundTaskOptions.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Core/RoundRobinService.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WMS/WIDESEA_WMSServer/docs/plans/2026-03-09-multi-outbound-address-roundrobin-design.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Core/AutoOutboundTaskOptions.cs
@@ -18,13 +18,13 @@ public int CheckIntervalSeconds { get; set; } = 300; /// <summary> /// æå··éåç¼é ç½®ç®æ å°å /// æå··éåç¼é ç½®ç®æ å°åï¼æ¯æå¤åºåºå£ï¼ /// </summary> public Dictionary<string, string> TargetAddresses { get; set; } public Dictionary<string, List<string>> TargetAddresses { get; set; } = new() { { "GW", "10081" }, { "CW", "10080" } { "GW", new List<string> { "10081" } }, { "CW", new List<string> { "10080" } } }; } } Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Core/RoundRobinService.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,42 @@ using System.Collections.Concurrent; namespace WIDESEA_Core.Core { /// <summary> /// 轮询æå¡ - 线ç¨å®å ¨çå°åè½®è¯¢éæ© /// </summary> public class RoundRobinService { /// <summary> /// 轮询计æ°å¨ - key: å··éåç¼, value: å½åç´¢å¼ /// </summary> private readonly ConcurrentDictionary<string, int> _counters = new(); /// <summary> /// è·åä¸ä¸ä¸ªå°åï¼è½®è¯¢ï¼ /// </summary> /// <param name="key">å··éåç¼æ è¯</param> /// <param name="addresses">åéå°åå表</param> /// <returns>éä¸çç®æ å°å</returns> public string GetNextAddress(string key, List<string> addresses) { // 空åè¡¨æ£æ¥ if (addresses == null || addresses.Count == 0) return "10080"; // å个å°åï¼ç´æ¥è¿å if (addresses.Count == 1) return addresses[0]; // å¤ä¸ªå°åï¼ä½¿ç¨è½®è¯¢éæ© // AddOrUpdate æ¯ååæä½ï¼çº¿ç¨å®å ¨ int index = _counters.AddOrUpdate( key, 0, // 馿¬¡ä½¿ç¨ï¼ä» 0 å¼å§ (k, oldValue) => (oldValue + 1) % addresses.Count // 轮询ï¼éå¢å忍¡ ); return addresses[index]; } } } Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -8,6 +8,7 @@ using WIDESEA_Core; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.BaseServices; using WIDESEA_Core.Core; using WIDESEA_DTO; using WIDESEA_DTO.Task; using WIDESEA_IBasicService; @@ -24,6 +25,7 @@ private readonly ILocationInfoService _locationInfoService; private readonly HttpClientHelper _httpClientHelper; private readonly IConfiguration _configuration; private readonly RoundRobinService _roundRobinService; public IRepository<Dt_Task> Repository => BaseDal; @@ -42,13 +44,15 @@ IStockInfoService stockInfoService, ILocationInfoService locationInfoService, HttpClientHelper httpClientHelper, IConfiguration configuration) : base(BaseDal) IConfiguration configuration, RoundRobinService roundRobinService) : base(BaseDal) { _mapper = mapper; _stockInfoService = stockInfoService; _locationInfoService = locationInfoService; _httpClientHelper = httpClientHelper; _configuration = configuration; _roundRobinService = roundRobinService; } #region WCSé»è¾å¤ç @@ -381,20 +385,37 @@ } /// <summary> /// æ ¹æ®å··éç¡®å®ç®æ å°å /// æ ¹æ®å··éç¡®å®ç®æ å°åï¼æ¯æå¤åºåºå£è½®è¯¢ï¼ /// </summary> private string DetermineTargetAddress(string roadway, Dictionary<string, string> addressMap) private string DetermineTargetAddress(string roadway, Dictionary<string, List<string>> addressMap) { if (string.IsNullOrWhiteSpace(roadway)) return "10080"; // é»è®¤å°å return "10080"; // æ¥æ¾å¹é çå··éåç¼ string matchedPrefix = null; foreach (var kvp in addressMap) { if (roadway.Contains(kvp.Key)) return kvp.Value; { matchedPrefix = kvp.Key; break; } } return "10080"; // é»è®¤å°å if (matchedPrefix == null) return "10080"; var addresses = addressMap[matchedPrefix]; if (addresses == null || addresses.Count == 0) return "10080"; // å个å°åï¼ç´æ¥è¿å if (addresses.Count == 1) return addresses[0]; // å¤ä¸ªå°åï¼ä½¿ç¨è½®è¯¢æå¡ return _roundRobinService.GetNextAddress(matchedPrefix, addresses); } /// <summary> @@ -473,8 +494,8 @@ // 4. è·åé ç½®çç®æ å°åæ å° var targetAddressMap = _configuration.GetSection("AutoOutboundTask:TargetAddresses") .Get<Dictionary<string, string>>() ?? new Dictionary<string, string>(); .Get<Dictionary<string, List<string>>>() ?? new Dictionary<string, List<string>>(); // 5. æ¹éåå»ºä»»å¡ var taskList = new List<Dt_Task>(); Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs
@@ -42,6 +42,7 @@ // 2�����÷��� builder.Services.AddSingleton(new AppSettings(builder.Configuration));//ע�� builder.Services.AddAllOptionRegister();//��ȡ�����ļ� builder.Services.AddSingleton<RoundRobinService>(); builder.Services.Configure<AutoOutboundTaskOptions>( builder.Configuration.GetSection("AutoOutboundTask")); builder.Services.AddMemoryCacheSetup();//���� Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
@@ -34,9 +34,9 @@ "AutoOutboundTask": { "Enable": true, /// æ¯å¦å¯ç¨èªå¨åºåºä»»å¡ "CheckIntervalSeconds": 300, /// æ£æ¥é´éï¼ç§ï¼ "TargetAddresses": { /// æå··éåç¼é ç½®ç®æ å°å "GW": "10081", "CW": "10080" "TargetAddresses": { /// æå··éåç¼é ç½®ç®æ å°åï¼æ¯æå¤åºåºå£ï¼ "GW": ["10081"], "CW": ["10080"] } } } Code/WMS/WIDESEA_WMSServer/docs/plans/2026-03-09-multi-outbound-address-roundrobin-design.md
@@ -313,11 +313,15 @@ ## 宿½æ¸ å - [ ] ä¿®æ¹ `AutoOutboundTaskOptions.TargetAddresses` ç±»å - [ ] å建 `RoundRobinService` ç±» - [ ] ä¿®æ¹ `TaskService.DetermineTargetAddress` æ¹æ³ - [ ] å¨ `Program.cs` 注å `RoundRobinService` - [ ] æ´æ° `appsettings.json` é ç½®ç¤ºä¾ - [ ] ç¼è¯éªè¯ - [ ] æå¨æµè¯ - [ ] æ´æ°è®¾è®¡ææ¡£ - [x] ä¿®æ¹ `AutoOutboundTaskOptions.TargetAddresses` ç±»å - [x] å建 `RoundRobinService` ç±» - [x] ä¿®æ¹ `TaskService.DetermineTargetAddress` æ¹æ³ - [x] å¨ `Program.cs` 注å `RoundRobinService` - [x] æ´æ° `appsettings.json` é ç½®ç¤ºä¾ - [x] ç¼è¯éªè¯ - [ ] æå¨æµè¯ï¼éè¦è¿è¡ç¯å¢åæ°æ®åºï¼ - [x] æ´æ°è®¾è®¡ææ¡£ **宿½æ¥æ**: 2026-03-09 **宿½äºº**: Claude Code **ç¶æ**: 代ç å®ç°å®æï¼å¾ æå¨æµè¯