| Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Service/RouterService.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WCS/WIDESEAWCS_Server/docs/superpowers/plans/2026-03-27-router-cache.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WCS/WIDESEAWCS_Server/docs/superpowers/plans/2026-03-27-router-service-audit.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WCS/docs(superpowers)/specs/2026-03-27-task-logging-design.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| 项目资料/设备协议/上位系统对接/陕西顷刻能源科技MES系统对接接口.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Service/RouterService.cs
@@ -1,11 +1,5 @@ using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WIDESEAWCS_Common; using WIDESEAWCS_Common.TaskEnum; using WIDESEAWCS_Core; using WIDESEAWCS_Core.BaseServices; using WIDESEAWCS_Core.Enums; @@ -538,6 +532,7 @@ // è¿åä½ç½®å表 return positions; } /// <summary> /// è·åè·¯ç±è¡¨ä¸ææå®æ´çè·¯ç±ä¿¡æ¯(å端è°ç¨å±ç¤ºæ°æ®)ã /// </summary> Code/WCS/WIDESEAWCS_Server/docs/superpowers/plans/2026-03-27-router-cache.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,239 @@ # è·¯ç±ç¼åå®ç°è®¡å > **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:** å¨ RouterService ä¸å¼å ¥ HybridCacheService æ··åç¼åï¼ç¬¬ä¸æ¬¡æ¥è¯¢å è½½å ¨éè·¯ç±å°ç¼åï¼åç»æ¥è¯¢ç´æ¥ä»ç¼å读åï¼AddRouters åå ¥ååæ¥æ´æ°ç¼åã **Architecture:** æ InOutType åå¼ç¼å两份ï¼å ¥å£/åºå£ï¼ï¼GetOrAdd æå è½½ï¼åç©¿æ´æ°ç¼åï¼åå®ä¾é¨ç½²æ 广æéæ±ã **Tech Stack:** ASP.NET Core 6.0, HybridCacheService, SqlSugar ORM --- ## æä»¶åæ´æ¦è§ **ä¿®æ¹æä»¶ï¼** - `WIDESEAWCS_QuartzJob/Service/RouterService.cs` â å ¨é¨ç¼åé»è¾æ¹å¨ **ä¸åï¼** - `FindRoutesInMemory` â åªæ¹è°ç¨æ¹ï¼ç®æ³é»è¾ä¸å - `QueryAllPositions` â å·²æç¬ç«ç¼åï¼ä¸ä¾èµæ¬æ¹æ¡ --- ## Task 1: æ°å¢ GetAllRoutersFromCache ç§ææ¹æ³ **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` å¨ç±»æååé声æåºä¹åãç°ææ¹æ³ä¹åï¼æ°å¢ä»¥ä¸ç§ææ¹æ³ï¼ ```csharp /// <summary> /// ä»ç¼åè·åæå®ç±»åçå ¨éè·¯ç±æ°æ®ï¼ç¼åä¸å卿¶èªå¨ä»æ°æ®åºå 载并åå ¥ç¼å /// </summary> /// <param name="routeType">è·¯ç±ç±»åï¼å ¥å£/åºå£ï¼</param> /// <returns>该类åçå ¨é¨è·¯ç±å表</returns> private List<Dt_Router> GetAllRoutersFromCache(int routeType) { string cacheKey = $"Router:AllRouters:{(routeType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; return _cacheService.GetOrAdd( cacheKey, () => BaseDal.QueryData(x => x.InOutType == routeType) ); } --- ## Task 2: æ¹é QueryNextRoutes éè½½ï¼2ä¸ªæ¹æ³ï¼ **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:48-98` ### QueryNextRoutes(string, string) â 第48-69è¡ å代ç ï¼ ```csharp List<Dt_Router> allRouters = BaseDal.QueryData(x => true); routers = FindRoutesInMemory(startPosi, endPosi, allRouters, null); ``` æ¹ä¸ºï¼ ```csharp List<Dt_Router> allRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); // å ¥å£+åºå£é½å è½½ï¼FindRoutesInMemory å 鍿 routeType==null ä¸åè¿æ»¤ List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); allRouters.AddRange(outRouters); routers = FindRoutesInMemory(startPosi, endPosi, allRouters, null); ``` ### QueryNextRoutes(string, string, int) â 第78-99è¡ å代ç ï¼ ```csharp List<Dt_Router> allRouters = BaseDal.QueryData(x => x.InOutType == routeType); routers = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType); ``` æ¹ä¸ºï¼ ```csharp List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType); routers = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType); ``` --- ## Task 3: æ¹é QueryNextRoute éè½½ï¼4ä¸ªæ¹æ³ï¼ **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:189-314` ### QueryNextRoute(string) â 第189-205è¡ å代ç ï¼ ```csharp List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi, ...); return routes.FirstOrDefault(); ``` æ¹ä¸ºï¼ ```csharp List<Dt_Router> routes = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()) .Where(x => x.StartPosi == startPosi) .ToList(); routes = routes.OrderByDescending(x => x.IsEnd).ToList(); return routes.FirstOrDefault(); ``` ### QueryNextRoute(string, int) â 第213-229è¡ å代ç ï¼ ```csharp List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi && x.InOutType == routeType, ...); return routes.FirstOrDefault(); ``` æ¹ä¸ºï¼ ```csharp List<Dt_Router> routes = GetAllRoutersFromCache(routeType) .Where(x => x.StartPosi == startPosi) .ToList(); routes = routes.OrderByDescending(x => x.IsEnd).ToList(); return routes.FirstOrDefault(); ``` ### QueryNextRoute(string, string, int) â 第238-272è¡ å代ç ï¼ç¬¬255è¡ï¼ï¼ ```csharp List<Dt_Router> allRouters = BaseDal.QueryData(x => x.InOutType == routeType); ``` æ¹ä¸ºï¼ ```csharp List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType); ``` å ¶ä½ç´æ¥è·¯ç±å¤æå `FindRoutesInMemory` è°ç¨é»è¾ä¸åã ### QueryNextRoute(string, string) â 第280-314è¡ å代ç ï¼ç¬¬285è¡ï¼ï¼ ```csharp List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi, ...); ``` æ¹ä¸ºï¼åå¹¶å ¥å£+åºå£ä¸¤ä»½ç¼åï¼ä¸åæ¹æ³å ¨éæ¥è¯¢è¯ä¹ä¸è´ï¼ï¼ ```csharp List<Dt_Router> inRoutes = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); List<Dt_Router> outRoutes = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); List<Dt_Router> routes = inRoutes.Concat(outRoutes) .Where(x => x.StartPosi == startPosi) .ToList(); routes = routes.OrderByDescending(x => x.IsEnd).ToList(); ``` ç¶åå¤ç¨å·²æçç´æ¥è·¯ç±å¤æé»è¾ã --- ## Task 4: æ¹é QueryRoutePath **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:323-366` 第355è¡éè¿ï¼å代ç ä¸ `while` 循ç¯éæ¯æ¬¡è°ç¨ `QueryNextRoute` çé»è¾**ä¸éè¦æ¹å¨**ï¼å 为 `QueryNextRoute` å·²ç»å¨ Task3 䏿¹é äºï¼ãæ¬ä»»å¡çæ¹å¨ä» 确认 `QueryRoutePath` æ¹æ³æ¬èº«ä¸åç´æ¥è°ç¨ `BaseDal.QueryData`ï¼å³ä¸éè¦ä»»ä½æ¹å¨ ââ å®è°ç¨çæ¯ `QueryNextRoute`ï¼èåè 已被æ¹é ã **éªè¯ï¼** 确认 `QueryRoutePath` æ¹æ³ä½å 没æç´æ¥è°ç¨ `BaseDal.QueryData`ï¼åªæå¯¹ `QueryNextRoute` çè°ç¨ã --- ## Task 5: æ¹é GetAllWholeRouters **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:412-446` å代ç ï¼ ```csharp List<Dt_Router> allRouters = BaseDal.QueryData(x => true); ``` æ¹ä¸ºï¼ ```csharp List<Dt_Router> inRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); List<Dt_Router> allRouters = inRouters.Concat(outRouters).ToList(); ``` åç»éå `dt_Routers`ï¼å `IsEnd == true` çè·¯ç±ï¼çé»è¾ä¸åã --- ## Task 6: æ¹é AddRoutersï¼åå ¥ DB åæ´æ°ç¼å **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:511-594` å¨ç¬¬568è¡éè¿ï¼æ¾å°ï¼ ```csharp // æ¥è¯¢æ°æ®åºä¸å·²æçè·¯ç±ä¿¡æ¯ List<Dt_Router> dt_Routers = BaseDal.QueryData(x => x.InOutType == routerType); ``` è¿ä¸ª `dt_Routers` æ¯**æ·»å ä¹å**çå·²ææ°æ®ï¼ä¸å 嫿¬æ¬¡æ°å¢çè·¯ç±ãå¨ç¬¬586è¡ `BaseDal.AddData(routers)` **ä¹å**ã`content = WebResponseContent.Instance.OK()` **ä¹å**ï¼å¿ 须鿰æ¥è¯¢ä¸æ¬¡å ¨éæ°æ®ååå ¥ç¼åï¼ ```csharp // æ·»å æ°çè·¯ç±ä¿¡æ¯ BaseDal.AddData(routers); // éæ°æ¥è¯¢å ¨éè·¯ç±ï¼æ¤æ¶æå 嫿°å¢çè·¯ç±ï¼ï¼ååå ¥ç¼å List<Dt_Router> updatedRouters = BaseDal.QueryData(x => x.InOutType == routerType); string cacheKey = $"Router:AllRouters:{(routerType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; _cacheService.Set(cacheKey, updatedRouters); content = WebResponseContent.Instance.OK(); ``` --- ## Task 7: ç¼è¯éªè¯ **éªè¯å½ä»¤ï¼** ```bash dotnet build WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/WIDESEAWCS_QuartzJob.csproj ``` é¢æï¼æ ç¼è¯é误ï¼CS0103/CS0019 çç±»å/è¯æ³éè¯¯å ¨é¨ä¿®å¤åï¼ --- ## 宿½é¡ºåº 1. Task 1 â æ°å¢ `GetAllRoutersFromCache` ç§ææ¹æ³ 2. Task 2 â æ¹é `QueryNextRoutes` 两个éè½½ 3. Task 3 â æ¹é `QueryNextRoute` å个éè½½ 4. Task 4 â 确认 `QueryRoutePath` æ éæ¹å¨ï¼å®ä¾èµå·²æ¹é ç `QueryNextRoute`ï¼ 5. Task 5 â æ¹é `GetAllWholeRouters` 6. Task 6 â æ¹é `AddRouters` æ´æ°ç¼å 7. Task 7 â ç¼è¯éªè¯ Code/WCS/WIDESEAWCS_Server/docs/superpowers/plans/2026-03-27-router-service-audit.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,324 @@ # RouterService é»è¾ä¿®å¤ä¸æ°æ¹æ³å®ç°è®¡å > **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:** ä¿®å¤ RouterService ä¸ç 3 个é»è¾é®é¢ï¼æ°å¢ 7 ä¸ªè·¯ç±æ¥è¯¢/ç®¡çæ¹æ³ï¼å¹¶æ´æ°æ¥å£å±ã **Architecture:** å¨ç°æ RouterService åºç¡ä¸æ°å¢ç¼åç®¡çæ¹æ³åè·¯ç±æ¥è¯¢å¢å¼ºæ¹æ³ï¼ä¿æç°æ HybridCacheService ç¼åæ¶æä¸åã **Tech Stack:** ASP.NET Core 6.0, HybridCacheService, SqlSugar ORM --- ## æä»¶åæ´æ¦è§ **ä¿®æ¹æä»¶ï¼** - `WIDESEAWCS_QuartzJob/Service/RouterService.cs` â é»è¾ä¿®å¤ + æ°å¢æ¹æ³å®ç° - `WIDESEAWCS_QuartzJob/Service/IRouterService.cs` â æ¥å£æ°å¢æ¹æ³ç¾å + 廿å¤ä½ `public` 修饰符 --- ## Task 1: ä¿®å¤ AddRouters ç¼åä¸è´æ§é®é¢ **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:605-613` **å代ç ï¼** ```csharp BaseDal.AddData(routers); List<Dt_Router> updatedRouters = BaseDal.QueryData(x => x.InOutType == routerType); string cacheKey = $"Router:AllRouters:{(routerType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; _cacheService.AddOrUpdate(cacheKey, updatedRouters); content = WebResponseContent.Instance.OK(); ``` **æ¹ä¸ºï¼** ```csharp // æ·»å æ°çè·¯ç±ä¿¡æ¯ BaseDal.AddData(routers); // éæ°æ¥è¯¢å ¨éè·¯ç±ï¼æ¤æ¶æå 嫿°å¢çè·¯ç±ï¼ï¼ååå ¥ç¼å List<Dt_Router> updatedRouters = BaseDal.QueryData(x => x.InOutType == routerType); string cacheKey = $"Router:AllRouters:{(routerType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; try { _cacheService.AddOrUpdate(cacheKey, updatedRouters); } catch { // ç¼åæ´æ°å¤±è´¥æ¶éé»å¿½ç¥ï¼ä¸æ¬¡æ¥è¯¢ä¼ä»DBèªå¨é建ç¼å } content = WebResponseContent.Instance.OK(); ``` **说æ**ï¼ç¨ try-catch å 裹ç¼åæ´æ°æä½ï¼é²æ¢ç¼ååå ¥å¤±è´¥æ¶å¼å¸¸éé¸å°å¤å±è¢«å½ä½é误è¿åãDB å·²åå ¥æåï¼ç¼å失败ä¸å½±åä¸å¡æ£ç¡®æ§ã --- ## Task 2: ä¿®å¤ QueryAllPositions 空 catch å **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:412-415` **å代ç ï¼** ```csharp catch { } ``` **æ¹ä¸ºï¼** ```csharp catch (Exception ex) { ConsoleHelper.WriteErrorLine($"RouterService.QueryAllPositions æ¥è¯¢å¤±è´¥: {ex.Message}"); } ``` **说æ**ï¼å¢å é误æ¥å¿è®°å½ï¼ä¾¿äºææ¥é®é¢ãè¿åå¼ä»ä¸ºç©ºå表ï¼è°ç¨æ¹è¡ä¸ºä¸åã --- ## Task 3: ä¿®å¤ IRouterService æ¥å£ public 修饰符 + æ°å¢æ¹æ³ç¾å **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/IRouterService.cs` 廿以ä¸è¡ç `public` ä¿®é¥°ç¬¦ï¼ - 第40è¡ï¼`public Dt_Router QueryNextRoute(string startPosi);` â `Dt_Router QueryNextRoute(string startPosi);` - 第48è¡ - 第57è¡ - 第65è¡ - 第74è¡ åæ¶å¨æ¥å£æ«å°¾æ°å¢ä»¥ä¸æ¹æ³ç¾åï¼ ```csharp /// <summary> /// æ¸ é¤è·¯ç±ç¼å /// </summary> void ClearRouterCache(); /// <summary> /// æ ¹æ®è®¾å¤ç¼å·æ¥è¯¢ç»è¿è¯¥è®¾å¤çææè·¯ç± /// </summary> List<Dt_Router> QueryRoutersByDeviceCode(string deviceCode); /// <summary> /// 夿䏤ç¹ä¹é´æ¯å¦åå¨è·¯ç±ï¼å ¨ç±»åï¼ /// </summary> bool ExistsRouter(string startPosi, string endPosi); /// <summary> /// 夿䏤ç¹ä¹é´æ¯å¦å卿å®ç±»åçè·¯ç± /// </summary> bool ExistsRouter(string startPosi, string endPosi, int routeType); /// <summary> /// è·åå ¨éè·¯ç±æ°éï¼åå¹¶å ¥å£+åºå£ï¼ /// </summary> int GetRouterCount(); /// <summary> /// è·åæå®ç±»åè·¯ç±æ°é /// </summary> int GetRouterCount(int routeType); /// <summary> /// æ¹éå é¤è·¯ç± /// </summary> WebResponseContent DeleteRouters(List<long> routerIds); ``` --- ## Task 4: å®ç° ClearRouterCache() **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` å¨ `GetAllRoutersFromCache` æ¹æ³ä¹åæ°å¢ï¼ ```csharp /// <summary> /// æ¸ é¤ææè·¯ç±ç¼åï¼å ¥å£ååºå£ç±»åï¼ /// </summary> public void ClearRouterCache() { _cacheService.Remove("Router:AllRouters:In"); _cacheService.Remove("Router:AllRouters:Out"); } ``` --- ## Task 5: å®ç° QueryRoutersByDeviceCode **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` å¨ `ClearRouterCache` ä¹åæ°å¢ï¼ ```csharp /// <summary> /// æ ¹æ®è®¾å¤ç¼å·æ¥è¯¢ç»è¿è¯¥è®¾å¤çææè·¯ç±ï¼åå¹¶å ¥å£+åºå£ç±»åï¼ /// </summary> /// <param name="deviceCode">设å¤ç¼å·</param> /// <returns>ç»è¿è¯¥è®¾å¤çè·¯ç±å表</returns> public List<Dt_Router> QueryRoutersByDeviceCode(string deviceCode) { List<Dt_Router> inRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); return inRouters.Concat(outRouters) .Where(x => x.ChildPosiDeviceCode == deviceCode) .ToList(); } ``` --- ## Task 6: å®ç° ExistsRouterï¼ä¸¤ä¸ªéè½½ï¼ **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` å¨ `QueryRoutersByDeviceCode` ä¹åæ°å¢ï¼ ```csharp /// <summary> /// 夿䏤ç¹ä¹é´æ¯å¦åå¨è·¯ç±ï¼å ¨ç±»åï¼ /// </summary> public bool ExistsRouter(string startPosi, string endPosi) { List<Dt_Router> inRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); var allRouters = inRouters.Concat(outRouters).ToList(); var routes = FindRoutesInMemory(startPosi, endPosi, allRouters, null); return routes.Count > 0; } /// <summary> /// 夿䏤ç¹ä¹é´æ¯å¦å卿å®ç±»åçè·¯ç± /// </summary> public bool ExistsRouter(string startPosi, string endPosi, int routeType) { List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType); var routes = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType); return routes.Count > 0; } ``` --- ## Task 7: å®ç° GetRouterCountï¼ä¸¤ä¸ªéè½½ï¼ **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` å¨ `ExistsRouter` ä¹åæ°å¢ï¼ ```csharp /// <summary> /// è·åå ¨éè·¯ç±æ°éï¼å ¥å£+åºå£åè®¡ï¼ /// </summary> public int GetRouterCount() { int inCount = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()).Count; int outCount = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()).Count; return inCount + outCount; } /// <summary> /// è·åæå®ç±»åè·¯ç±æ°é /// </summary> public int GetRouterCount(int routeType) { return GetAllRoutersFromCache(routeType).Count; } ``` --- ## Task 8: å®ç° DeleteRouters **æä»¶:** - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` å¨ `AddRouters` æ¹æ³ä¹åæ°å¢ï¼ ```csharp /// <summary> /// æ¹éå 餿å®IDçè·¯ç±ï¼å é¤ååæ¥æ¸ é¤å¯¹åºç±»åçç¼å /// </summary> /// <param name="routerIds">å¾ å é¤çè·¯ç±IDå表</param> /// <returns>è¿åå¤çç»æ</returns> public WebResponseContent DeleteRouters(List<long> routerIds) { WebResponseContent content = new WebResponseContent(); try { if (routerIds == null || routerIds.Count == 0) { return content = WebResponseContent.Instance.Error("å¾ å é¤çè·¯ç±IDå表ä¸è½ä¸ºç©º"); } // æ¥è¯¢å¾ å é¤è·¯ç±çç±»åï¼ç¨äºåç»æ¸ é¤ç¼åï¼ var routersToDelete = BaseDal.QueryData(x => routerIds.Contains(x.Id)); if (routersToDelete.Count == 0) { return content = WebResponseContent.Instance.Error("æªæ¾å°å¾ å é¤çè·¯ç±"); } // è®°å½æ¶åçç±»åï¼å»éï¼ var affectedTypes = routersToDelete.Select(x => x.InOutType).Distinct().ToList(); // æ§è¡æ¹éå é¤ BaseDal.DeleteData(routersToDelete); // æ¸ é¤åå½±åç±»åçç¼å foreach (var routeType in affectedTypes) { string cacheKey = $"Router:AllRouters:{(routeType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; _cacheService.Remove(cacheKey); } content = WebResponseContent.Instance.OK(); } catch (Exception ex) { content = WebResponseContent.Instance.Error(ex.Message); } return content; } ``` --- ## Task 9: ç¼è¯éªè¯ **éªè¯å½ä»¤ï¼** ```bash dotnet build WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/WIDESEAWCS_QuartzJob.csproj ``` 颿ï¼0 errors --- ## 宿½é¡ºåº 1. Task 1 â ä¿®å¤ AddRouters ç¼åä¸è´æ§ 2. Task 2 â ä¿®å¤ QueryAllPositions 空 catch å 3. Task 3 â ä¿®å¤ IRouterService æ¥å£ï¼å»æ public + æ°å¢ç¾åï¼ 4. Task 4 â å®ç° ClearRouterCache 5. Task 5 â å®ç° QueryRoutersByDeviceCode 6. Task 6 â å®ç° ExistsRouter 两个éè½½ 7. Task 7 â å®ç° GetRouterCount 两个éè½½ 8. Task 8 â å®ç° DeleteRouters 9. Task 9 â ç¼è¯éªè¯ Code/WCS/docs(superpowers)/specs/2026-03-27-task-logging-design.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,167 @@ # 任塿¥å¿å¢å¼ºè®¾è®¡ææ¡£ ## æ¦è¿° 为 `RobotJob`ã`ConveyorLineNewJob`ã`StackerCraneJob` ä¸ä¸ªæ¨¡åæ·»å å®åçæ¥å¿è®°å½åè½ã ## æ¥å¿è§è ### æ¥å¿çº§å«å®ä¹ï¼ä¸¥æ ¼æè¯ä¹ï¼ | çº§å« | ç¨é | 示ä¾åºæ¯ | |------|------|----------| | `Info` | æ£å¸¸æµç¨èç¹ | ä»»å¡å¼å§å¤çãå½ä»¤ä¸åæåãç¶æè½¬æ¢å®æ | | `Warn` | éè¦å ³æ³¨ä½éé误 | 客æ·ç«¯æè¿éè¯ãç«å°ä¸å¯ç¨ãçæ¬å²çª | | `Error` | å¼å¸¸/失败 | WMS è°ç¨å¤±è´¥ãå½ä»¤åé失败ã任塿¥è¯¢å¤±è´¥ | | `Debug` | 详ç»ä¿¡æ¯ | 轮询æä½ãç¼å读åï¼å¯éï¼ | ### æ¥å¿è¾åºæ¹å¼ 1. **ILogger<T>** - éè¿ä¾èµæ³¨å ¥æç¶ç±»ä¼ é 2. **QuartzLogger** - 弿¥æä»¶æ¥å¿ï¼åæ¶è®°å½ ```csharp // æ 忥å¿åæ³ _logger.LogInformation("æ¶æ¯å 容"); QuartzLogger.Info("æ¶æ¯å 容", source); ``` ## ä¿®æ¹æ¸ å ### RobotJob 模å #### RobotJob.cs - ç¶æï¼å·²æ ILoggerï¼æ éä¿®æ¹ #### RobotClientManager.cs - æ·»å `ILogger<RobotClientManager>` - ä¿®æ£æè¿æ¥å¿ï¼Warn â Infoï¼å®¢æ·ç«¯æå¼æ¯æ£å¸¸æµç¨ï¼ - æ·»å EnsureClientSubscribed ä¸çéè¯/ä¸å¯ç¨æ¥å¿ #### RobotTaskProcessor.cs - æ·»å `ILogger<RobotTaskProcessor>` - ä¿®æ£ SendSocketRobotPickAsyncï¼Error â Infoï¼æåä¸ååºè®°å½ Infoï¼ - æ·»å HandleInboundTaskAsync ç WMS è°ç¨ç»ææ¥å¿ #### RobotStateManager.cs - æ·»å `ILogger<RobotStateManager>` - æé 彿°ç GetOrCreateState æ·»å Info æ¥å¿ - TryUpdateStateSafely æ·»å çæ¬å²çª Warn æ¥å¿ #### RobotMessageHandler.cs - å·²æ ILoggerï¼å·²æè¯å¥½æ¥å¿ï¼ä¿æä¸å #### RobotWorkflowOrchestrator.cs - æ·»å `ILogger<RobotWorkflowOrchestrator>` - ExecuteAsync æ·»å ç¶ææºå³çæ¥å¿ï¼æ»¡è¶³æ¡ä»¶æ¶è®°å½ Infoï¼ - HandlePickFinishedStateAsync æ·»å æ¾è´§æä»¤ä¸åæ¥å¿ - HandlePutFinishedStateAsync æ·»å åè´§æä»¤ä¸åæ¥å¿ ### ConveyorLineNewJob 模å #### CommonConveyorLineNewJob.cs - æ·»å `ILogger<CommonConveyorLineNewJob>` - Execute æ¹æ³ï¼ - åè®¾å¤æ°é为 0ï¼Info - Parallel.For å¼å§ï¼Debug - å½ä»¤ä¸ºç©ºè·³è¿ï¼Debug - WCS_ACK å¤çï¼Debug - æ£æ¥æçä½ç½®ï¼Info - PLC_STB æ£æ¥ï¼Debug - æ æ¡ç 请æ±åºåºï¼Info - æä»»å¡å·å¤çä»»å¡ï¼Info - å¼å¸¸æè·ï¼Error - ProcessTaskState æ¹æ³ï¼æ·»å åç¶æåæ¯çå ¥å£æ¥å¿ #### ConveyorLineDispatchHandler.cs - æ·»å `ILogger<ConveyorLineDispatchHandler>` - HeartBeatï¼Debug - RequestInboundï¼Infoï¼å ¥åºè¯·æ±å¼å§ï¼ - RequestInNextAddressï¼Infoï¼å ¥åºä¸ä¸å°åï¼ - ConveyorLineInFinishï¼Infoï¼å ¥åºå®æï¼ - RequestOutboundï¼Infoï¼åºåºè¯·æ±ï¼ - RequestOutNextAddressï¼Infoï¼åºåºä¸ä¸å°åï¼ - ConveyorLineOutFinishï¼Infoï¼åºåºå®æï¼ #### ConveyorLineTaskFilter.cs - æ·»å `ILogger<ConveyorLineTaskFilter>` - QueryPendingTaskï¼Debug - QueryExecutingTaskï¼Debug - RequestWmsTaskï¼Infoï¼WMS 请æ±ï¼ #### ConveyorLineTargetAddressSelector.cs - æ·»å `ILogger<ConveyorLineTargetAddressSelector>` - HandleInboundNextAddressï¼Debug - HandleOutboundNextAddressï¼Debug - HandleDeviceRequestï¼Debug - ProcessDeviceRequestï¼Debug ### StackerCraneJob 模å #### CommonStackerCraneJob.cs - æ·»å `ILogger<CommonStackerCraneJob>` - Execute æ¹æ³ï¼ - åæ°æ æï¼Warn - äºä»¶è®¢é ï¼Info - ä»»å¡å®ææ£æ¥ï¼Debug - ä¸å¯åéä»»å¡ï¼Debug - ä»»å¡éæ©ç»æï¼Infoï¼éä¸ä»»å¡å·ææ ä»»å¡ï¼ - å½ä»¤æå»ºç»æï¼Info - å½ä»¤åéç»æï¼Info - å¼å¸¸æè·ï¼Error - CommonStackerCrane_StackerCraneTaskCompletedEventHandlerï¼Info - LoadConfig 失败ï¼Warn #### StackerCraneTaskSelector.cs - æ·»å `ILogger<StackerCraneTaskSelector>` - SelectTaskï¼Infoï¼ä»»å¡éæ©å¼å§ãéæ©ç»æï¼ - TrySelectOutboundTaskï¼Debug - IsOutTaskStationAvailableï¼Infoï¼ç«å°å¯ç¨/ä¸å¯ç¨ï¼ - TryAddTaskFromWmsï¼Info #### StackerCraneCommandBuilder.cs - æ·»å `ILogger<StackerCraneCommandBuilder>` - ConvertToStackerCraneTaskCommandï¼Infoï¼å½ä»¤ç±»åãä»»å¡å·ï¼ - GetCommandTypeï¼Debug - BuildInboundCommandï¼Infoï¼å ¥åºå½ä»¤æå»ºï¼ - BuildOutboundCommandï¼Infoï¼åºåºå½ä»¤æå»ºï¼ - BuildRelocationCommandï¼Infoï¼ç§»åºå½ä»¤æå»ºï¼ - å°åè§£æå¤±è´¥ï¼Error ## ILogger ä¾èµä¼ éæ¹æ¡ å¯¹äºéè¿ `new` ç´æ¥å®ä¾åçè¾ å©ç±»ï¼éè¿ç¶ç±»æé 彿°ä¼ å ¥ ILoggerï¼ ```csharp // è¾ å©ç±»æ¥æ¶ ILogger public class RobotStateManager { private readonly ILogger _logger; public RobotStateManager(ICacheService cache, ILogger<RobotStateManager> logger) { _logger = logger; } } // Job å¨åå»ºè¾ å©ç±»æ¶ä¼ å ¥èªå·±ç logger public RobotJob(..., ILogger<RobotJob> logger) { _stateManager = new RobotStateManager(cache, logger); } ``` ## éä¿®æ£çæ¥å¿è¯ä¹é®é¢ | ä½ç½® | ååæ³ | ä¿®æ£å | |------|--------|--------| | RobotTaskProcessor.SendSocketRobotPickAsync | QuartzLogger.Error (æåæ¶) | QuartzLogger.Info | | RobotClientManager.EnsureClientSubscribed | QuartzLogger.Info (å¼å¸¸æ¶) | QuartzLogger.Error | | RobotClientManager.OnRobotReceived | QuartzLogger.Warn (æè¿) | QuartzLogger.Info | ## éªæ¶æ å 1. ææå ³é®ä¸å¡èç¹æ Info æ¥å¿ 2. å¼å¸¸æ 嵿 Error æ¥å¿å¹¶å å«å¼å¸¸ä¿¡æ¯ 3. éè¦å ³æ³¨çæ 嵿 Warn æ¥å¿ 4. æ¥å¿åæ¶è¾åºå° ILogger å QuartzLogger 5. æ¥å¿æ¶æ¯æ¸ æ°ï¼å å«å ³é®ä¸ä¸æï¼å¦ä»»å¡å·ã设å¤ç¼ç ï¼ Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs
@@ -102,6 +102,8 @@ public async Task<WebResponseContent> GroupPalletAsync(StockDTO stock) { WebResponseContent content = new WebResponseContent(); try { var now = DateTime.Now; var details = stock.Details.Select(item => new Dt_StockInfoDetail { @@ -143,6 +145,11 @@ return result ? content.OK("ç»çæå") : content.Error("ç»ç失败"); }); } catch (Exception ex) { return content.Error($"ç»ç失败: {ex.Message}"); } } /// <summary> /// æ¢ç @@ -150,6 +157,8 @@ public async Task<WebResponseContent> ChangePalletAsync(StockDTO stock) { WebResponseContent content = new WebResponseContent(); try { if (stock == null || string.IsNullOrWhiteSpace(stock.TargetPalletNo) || string.IsNullOrWhiteSpace(stock.SourcePalletNo) || @@ -200,6 +209,11 @@ return content.OK("æ¢çæå"); }); } catch (Exception ex) { return content.Error($"æ¢ç失败: {ex.Message}"); } } /// <summary> /// æç @@ -207,6 +221,8 @@ public async Task<WebResponseContent> SplitPalletAsync(StockDTO stock) { WebResponseContent content = new WebResponseContent(); try { if (stock == null || string.IsNullOrWhiteSpace(stock.SourcePalletNo)) return content.Error("æºæçå·ä¸è½ä¸ºç©º"); @@ -239,6 +255,11 @@ return content.OK("æçæå"); }); } catch (Exception ex) { return content.Error($"æç失败: {ex.Message}"); } } /// <summary> /// å åæºæ¢çåæ´æ°åºåä¿¡æ¯ï¼æ¸ 空åºä½ä¿¡æ¯ï¼ ÏîÄ¿×ÊÁÏ/É豸ÐÒé/ÉÏλϵͳ¶Ô½Ó/ÉÂÎ÷Çê¿ÌÄÜÔ´¿Æ¼¼MESϵͳ¶Ô½Ó½Ó¿Ú.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,329 @@ 好çï¼æå·²ç»å°æ¨æä¾çäºä¸ªæ¥å£ææ¡£ä¼åä¸ºæ´æ¸ æ°ãç»ææ´ç»ä¸çMarkdownæ ¼å¼ã主è¦ä¼åç¹å æ¬ï¼ 1. **ç»ä¸æ ¼å¼**ï¼å°æææ¥å£ç说æã请æ±å段ãååºå段çéç¨ä¸è´çæ é¢å±çº§åè¡¨æ ¼ç»æã 2. **ä¿®æ£é误**ï¼ä¿®æ£äºâæçåºç«âæ¥å£åç§°åâéç¨å·¥åºâä¸çææ¾ç¬è¯¯ã 3. **å¢å¼ºå¯è¯»æ§**ï¼ä½¿ç¨å ç²ã代ç åçMarkdownå ç´ ï¼ä½¿å ³é®ä¿¡æ¯åæ¥æç¤ºä¾æ´çªåºã 4. **è¡¥å 说æ**ï¼å¨æ¥æç¤ºä¾ä¸ï¼å°`body`é¨åç¨JSON代ç åé«äº®æ¾ç¤ºï¼ä¾¿äºé 读ã --- ### **1.1. æççµè¯ç»å®** #### **1.1.1. è§¦åæ¡ä»¶** 1. ç¨äºçµè¯ç ç»å®æçç ã #### **1.1.2. æ¥å£è¯´æ** | é¡¹ç® | å 容 | | :----------- | :--------------------------------------- | | **æ¥å£åç§°** | æççµè¯ç»å®ï¼å¨å¶å&容å¨ï¼ | | **æ¥å£æ¹å¼** | WebApi | | **è¯·æ±æ¹å¼** | POST | | **åéæ¹** | EQP | | **æ¥æ¶æ¹** | MES | | **æ¥å£å°å** | `/EquipmentService/api/v1/BindContainer` | | **éç¨å·¥åº** | çµè¯ç ç»å®æçç | #### **1.1.3. è¯·æ±æ¥æ** **Header åæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :-------------- | :---------- | :------- | :---------- | | 1 | `Authorization` | MES认è¯ä¿¡æ¯ | STRING | å¼ç±MESæä¾ | **Body åæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :----------------- | :----------------- | :------------------------------------- | :--------------------- | | 1 | `EquipmentCode` | 设å¤ç¼ç | STRING | | | 2 | `ResourceCode` | èµæºç¼ç | STRING | | | 3 | `LocalTime` | è°ç¨æ¬å°æ¶é´ | DATETIME | | | 4 | `ContainerCode` | æçç | STRING | | | 5 | `ContainerSfcList` | ç»å®ççµè¯æ¡ç å表 | ARRAY OBJECT | | | 6 | `OperationType` | æä½ç±»å | 0-é»è®¤<br>1-è¿ç«<br>2-åºç«<br>3-è¿åºç« | æ¢æææçä¸ä¼ 3ï¼å ¶ä½0 | **`ContainerSfcList` æ°æ®éåæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :--------- | :------- | :------- | :--- | | 1 | `Sfc` | çµè¯ç | STRING | | | 2 | `Location` | ä½ç½®ä¿¡æ¯ | STRING | | **æ¥æç¤ºä¾** ```json { "equipmentCode": "string", "resourceCode": "string", "localTime": "2024-03-01T03:12:29.265Z", "containerCode": "string", "containerSfcList": [ { "sfc": "string", "location": "string" } ] } ``` #### **1.1.4. ååºå段** | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :----- | :------- | :------- | :-------------------- | | `code` | æ§è¡ä»£ç | INT | 0: æå<br>å ¶ä»: 失败 | | `msg` | è¿åä¿¡æ¯ | STRING | å å«å ·ä½çéè¯¯ä¿¡æ¯ | --- ### **1.2. æççµè¯è§£ç»** #### **1.2.1. è§¦åæ¡ä»¶** 1. ç¨äºæçç è§£ç»çµè¯ç»ã #### **1.2.2. æ¥å£è¯´æ** | é¡¹ç® | å 容 | | :----------- | :----------------------------------------- | | **æ¥å£åç§°** | æççµè¯è§£ç»ï¼å¨å¶å&容å¨ï¼ | | **æ¥å£æ¹å¼** | WebApi | | **è¯·æ±æ¹å¼** | POST | | **åéæ¹** | EQP | | **æ¥æ¶æ¹** | MES | | **æ¥å£å°å** | `/EquipmentService/api/v1/UnBindContainer` | | **éç¨å·¥åº** | æçç è§£ç»çµè¯ç» | #### **1.2.3. è¯·æ±æ¥æ** **Header åæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :-------------- | :---------- | :------- | :---------- | | 1 | `Authorization` | MES认è¯ä¿¡æ¯ | STRING | å¼ç±MESæä¾ | **Body åæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :-------------- | :----------- | :----------- | :--- | | 1 | `EquipmentCode` | 设å¤ç¼ç | STRING | | | 2 | `ResourceCode` | èµæºç¼ç | STRING | | | 3 | `LocalTime` | è°ç¨æ¬å°æ¶é´ | DATETIME | | | 4 | `ContainCode` | æçç | STRING | | | 5 | `SfcList` | çµè¯æ¡ç ç» | ARRAY STRING | | **æ¥æç¤ºä¾** ```json { "equipmentCode": "string", "resourceCode": "string", "localTime": "2024-03-01T03:13:12.482Z", "containCode": "string", "sfcList": [ "string" ] } ``` #### **1.2.4. ååºå段** | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :----- | :------- | :------- | :-------------------- | | `code` | æ§è¡ä»£ç | INT | 0: æå<br>å ¶ä»: 失败 | | `msg` | è¿åä¿¡æ¯ | STRING | å å«å ·ä½çéè¯¯ä¿¡æ¯ | --- ### **1.3. æçNGçµè¯ä¸æ¥** #### **1.3.1. è§¦åæ¡ä»¶** 1. æçåå¨NGæ¡ç ï¼å¨æçæè OCV2, OCV3æ¶ï¼éè¦ä¸æ¥NGçµè¯ã #### **1.3.2. æ¥å£è¯´æ** | é¡¹ç® | å 容 | | :----------- | :------------------------------------------- | | **æ¥å£åç§°** | æ¡ç ç»å®ï¼å¨å¶å&容å¨ï¼ | | **æ¥å£æ¹å¼** | WebApi | | **è¯·æ±æ¹å¼** | POST | | **åéæ¹** | EQP | | **æ¥æ¶æ¹** | MES | | **æ¥å£å°å** | `/EquipmentService/api/v1/ContainerNgReport` | | **éç¨å·¥åº** | æçNGçµè¯ä¸æ¥ | #### **1.3.3. è¯·æ±æ¥æ** **Header åæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :-------------- | :---------- | :------- | :---------- | | 1 | `Authorization` | MES认è¯ä¿¡æ¯ | STRING | å¼ç±MESæä¾ | **Body åæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :-------------- | :------------------- | :----------- | :--- | | 1 | `EquipmentCode` | 设å¤ç¼ç | STRING | | | 2 | `ResourceCode` | èµæºç¼ç | STRING | | | 3 | `LocalTime` | è°ç¨æ¬å°æ¶é´ | DATETIME | | | 4 | `ContainerCode` | æçç | STRING | | | 5 | `NgSfcList` | ç»å®NGççµè¯æ¡ç å表 | ARRAY OBJECT | | **`NgSfcList` æ°æ®éåæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :---------------- | :------- | :------- | :--- | | 1 | `sfc` | äº§åæ¡ç | STRING | | | 2 | `ngCode` | NG代ç | STRING | | | 3 | `ngEquipmentCode` | NGè®¾å¤ | STRING | | | 4 | `ngResourceCode` | NGèµæº | STRING | | **æ¥æç¤ºä¾** ```json { "equipmentCode": "string", "resourceCode": "string", "localTime": "2024-03-01T03:42:55.528Z", "containerCode": "string", "ngSfcList": [ "string" ] } ``` #### **1.3.4. ååºå段** | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :----- | :------- | :------- | :-------------------- | | `code` | æ§è¡ä»£ç | INT | 0: æå<br>å ¶ä»: 失败 | | `msg` | è¿åä¿¡æ¯ | STRING | å å«å ·ä½çéè¯¯ä¿¡æ¯ | --- ### **1.4. æçè¿ç«ï¼å®¹å¨è¿ç«ï¼** #### **1.4.1. è§¦åæ¡ä»¶** 1. æçè¿ç«ã #### **1.4.2. æ¥å£è¯´æ** | é¡¹ç® | å 容 | | :----------- | :-------------------------------------------- | | **æ¥å£åç§°** | æçè¿ç«ï¼å®¹å¨è¿ç«ï¼ | | **æ¥å£æ¹å¼** | WebApi | | **è¯·æ±æ¹å¼** | POST | | **åéæ¹** | EQP | | **æ¥æ¶æ¹** | MES | | **æ¥å£å°å** | `/EquipmentService/api/v1/InboundInContainer` | | **éç¨å·¥åº** | æçè¿ç« | #### **1.4.3. è¯·æ±æ¥æ** **Header åæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :-------------- | :---------- | :------- | :---------- | | 1 | `Authorization` | MES认è¯ä¿¡æ¯ | STRING | å¼ç±MESæä¾ | **Body åæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :-------------- | :----------- | :------- | :--- | | 1 | `EquipmentCode` | 设å¤ç¼ç | STRING | | | 2 | `ResourceCode` | èµæºç¼ç | STRING | | | 3 | `LocalTime` | è°ç¨æ¬å°æ¶é´ | DATETIME | | | 4 | `ContainerCode` | æçç | STRING | | **æ¥æç¤ºä¾** ```json { "equipmentCode": "string", "resourceCode": "string", "localTime": "2024-03-01T03:43:42.144Z", "containerCode": "string" } ``` #### **1.4.4. ååºå段** | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :----- | :------- | :------- | :-------------------- | | `code` | æ§è¡ä»£ç | INT | 0: æå<br>å ¶ä»: 失败 | | `msg` | è¿åä¿¡æ¯ | STRING | å å«å ·ä½çéè¯¯ä¿¡æ¯ | --- ### **1.5. æçåºç«ï¼å®¹å¨åºç«ï¼** #### **1.5.1. è§¦åæ¡ä»¶** 1. æçåºç«ã #### **1.5.2. æ¥å£è¯´æ** | é¡¹ç® | å 容 | | :----------- | :--------------------------------------------- | | **æ¥å£åç§°** | æçåºç«ï¼å®¹å¨åºç«ï¼ | | **æ¥å£æ¹å¼** | WebApi | | **è¯·æ±æ¹å¼** | POST | | **åéæ¹** | EQP | | **æ¥æ¶æ¹** | MES | | **æ¥å£å°å** | `/EquipmentService/api/v1/OutboundInContainer` | | **éç¨å·¥åº** | æçåºç« | #### **1.5.3. è¯·æ±æ¥æ** **Header åæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :-------------- | :---------- | :------- | :---------- | | 1 | `Authorization` | MES认è¯ä¿¡æ¯ | STRING | å¼ç±MESæä¾ | **Body åæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :-------------- | :----------- | :----------- | :--- | | 1 | `EquipmentCode` | 设å¤ç¼ç | STRING | | | 2 | `ResourceCode` | èµæºç¼ç | STRING | | | 3 | `LocalTime` | è°ç¨æ¬å°æ¶é´ | DATETIME | | | 4 | `ContainerCode` | æçç | STRING | | | 5 | `ParamList` | 产ååæ°å表 | ARRAY OBJECT | | **`ParamList` æ°æ®éåæ®µ** | åºå· | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :--- | :--------------- | :------- | :------- | :------------- | | 1 | `ParamCode` | åæ°ç¼ç | STRING | å·¥èºæä¾ | | 2 | `ParamValue` | åæ°å¼ | STRING | | | 3 | `CollectionTime` | æ¶é´æ³ | DATETIME | ééåæ°çæ¶é´ | **æ¥æç¤ºä¾** ```json { "equipmentCode": "string", "resourceCode": "string", "localTime": "2024-03-01T03:43:42.144Z", "containerCode": "string", "paramList": [ { "paramCode": "string", "paramValue": "string", "collectionTime": "2024-03-01T03:43:42.144Z" } ] } ``` #### **1.5.4. ååºå段** | åæ®µ | å 容 | æ°æ®ç±»å | 夿³¨ | | :----- | :------- | :------- | :-------------------- | | `code` | æ§è¡ä»£ç | INT | 0: æå<br>å ¶ä»: 失败 | | `msg` | è¿åä¿¡æ¯ | STRING | å å«å ·ä½çéè¯¯ä¿¡æ¯ |