# MES 上传状态跟踪与异步上传实现计划 > **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 (`- [x]`) syntax for tracking. **Goal:** 在库存表添加 MES 上传状态字段,通过 `Task.Run` 异步方式上传 MES 数据不干扰主逻辑,所有 MES 调用记录详细日志,前端显示状态并提供组盘/拆盘按钮,所有 MES 凭证改为动态获取。 **Architecture:** - `Dt_StockInfo.MesUploadStatus` 单字段记录最近一次 MES 操作结果状态 - 所有 MES 调用统一通过 `Task.Run` 异步执行,不阻塞主逻辑 - 上传完成后更新 `MesUploadStatus`,并通过 `IMesLogService.LogAsync` 记录详细日志 - 所有 MES 凭证(EquipmentCode、ResourceCode、Token)改为从 `Dt_MESDeviceConfig` 表动态获取 - 前端 `stockInfo.vue` 新增状态列,`stock.jsx` 新增组盘/拆盘按钮 **Tech Stack:** .NET 6/8, C#, SqlSugar ORM, ASP.NET Core WebAPI, Vue 3, Element Plus --- ## 文件变更概览 | 操作 | 文件 | |------|------| | 新增 | `WIDESEA_Common/StockEnum/MesUploadStatusEnum.cs` | | 修改 | `WIDESEA_Model/Models/Stock/Dt_StockInfo.cs` - 新增 `MesUploadStatus` 字段 | | 修改 | `WIDESEA_IStockService/IStockInfoService.cs` - 新增 `UpdateMesUploadStatusAsync` | | 修改 | `WIDESEA_StockService/StockInfoService.cs` - 实现 `UpdateMesUploadStatusAsync` | | 修改 | `WIDESEA_DTO/MES/MesApiLogDto.cs` - 新增 `PalletCode` 字段 | | 修改 | `WIDESEA_TaskInfoService/TaskService.cs` - 新增 `MesUploadAsync` + `LogMesCallAsync` | | 修改 | `WIDESEA_TaskInfoService/WCS/TaskService_Outbound.cs` - 出站 MES 改为异步 | | 修改 | `WIDESEA_TaskInfoService/WCS/TaskService_Inbound.cs` - 进站 MES 改为异步 | | 修改 | `WIDESEA_StockService/StockSerivce.cs` - 组盘/拆盘 MES 改为异步 | | 修改 | `WIDESEA_WMSServer/Controllers/Stock/StockInfoController.cs` - 进站/出站 MES 改为异步 + 动态凭证 | | 修改 | `WIDESEA_WMSServer/Controllers/Stock/StockInfoDetailController.cs` - 绑定/解绑/NG MES 改为异步 + 动态凭证 | | 修改 | `WIDESEA_WMSClient/src/views/stock/stockInfo.vue` - 新增 `mesUploadStatus` 列 | | 修改 | `WIDESEA_WMSClient/src/extension/stock/stock.jsx` - 新增组盘/拆盘按钮 | | 新增 | 数据库变更脚本 | --- ## Phase 1: 基础设施 ### Task 1: 新增 MesUploadStatusEnum 枚举 ✅ **Files:** Create `WIDESEA_Common/StockEnum/MesUploadStatusEnum.cs` - [x] 创建枚举类(11个值:0=未上传, 1/2=组盘, 3/4=拆盘, 5/6=进站, 7/8=出站, 9/10=NG上报) - [x] Commit: `b21d0f2` ### Task 2: 修改 Dt_StockInfo 实体 ✅ **Files:** Modify `WIDESEA_Model/Models/Stock/Dt_StockInfo.cs` - [x] 在 `Remark` 和 `OutboundDate` 之间新增 `MesUploadStatus` 字段(int, 默认0) - [x] Commit: `58759d4` ### Task 3: 修改 IStockInfoService 接口 ✅ **Files:** Modify `WIDESEA_IStockService/IStockInfoService.cs` - [x] 新增 `UpdateMesUploadStatusAsync(string palletCode, int status)` 方法声明 - [x] Commit: `18e0765` ### Task 4: 修改 StockInfoService 实现 ✅ **Files:** Modify `WIDESEA_StockService/StockInfoService.cs` - [x] 实现 `UpdateMesUploadStatusAsync`:按托盘号查询 → 更新 MesUploadStatus - [x] Commit: `25a246f`(后修复缺失闭合括号 → `c329a05`) ### Task 5: 修改 TaskService 新增异步方法 ✅ **Files:** Modify `WIDESEA_TaskInfoService/TaskService.cs` - [x] 添加 using: `WIDESEA_Common.StockEnum`, `System.Diagnostics`, `Newtonsoft.Json` - [x] 新增 `MesUploadAsync` 私有异步方法(Task.Run 调用 MES + 更新状态 + 日志) - [x] 新增 `LogMesCallAsync` 私有日志方法 - [x] Commit: `1330eff` ### Task 9: 数据库变更脚本 ✅ **Files:** Create `Database/Scripts/20260420_Dt_StockInfo_MesUploadStatus.sql` - [x] ALTER TABLE 新增 MesUploadStatus TINYINT NOT NULL DEFAULT 0 - [x] Commit: `eec94e8` ### 附加修复: MesApiLogDto 新增 PalletCode ✅ **Files:** Modify `WIDESEA_DTO/MES/MesApiLogDto.cs` - [x] 新增 `PalletCode` 属性支持按托盘号查询日志 - [x] Commit: `32ece02` --- ## Phase 2: 后端 MES 调用改造 ### Task 6: TaskService_Outbound 出站 MES 异步 ✅ **Files:** Modify `WIDESEA_TaskInfoService/WCS/TaskService_Outbound.cs` - [x] `OutboundInContainer` 改为 `Task.Run` 异步执行 - [x] 使用 `MesUploadStatusEnum.出站上传成功`(7)/ `出站上传失败`(8) - [x] Commit: `91e3264` ### Task 11: StockService 组盘/拆盘 MES 异步 ✅ **Files:** Modify `WIDESEA_StockService/StockSerivce.cs` - [x] `GroupPalletConfirmAsync` → `BindContainer` 改为 `Task.Run` 异步 - 成功: `MesUploadStatusEnum.组盘上传成功`(1) - 失败: `MesUploadStatusEnum.组盘上传失败`(2) - [x] `SplitPalletConfirmAsync` → `UnBindContainer` 改为 `Task.Run` 异步 - 成功: `MesUploadStatusEnum.拆盘上传成功`(3) - 失败: `MesUploadStatusEnum.拆盘上传失败`(4) - [x] 保留动态 Token 获取逻辑(`ResolveMesConfig`) - [x] Commit: `4506a1e` ### Task 12: StockInfoDetailController MES 异步 + 动态凭证 ✅ **Files:** Modify `WIDESEA_WMSServer/Controllers/Stock/StockInfoDetailController.cs` - [x] `BindContainer` 改为 `Task.Run` 异步 → `MesUploadStatusEnum.组盘上传成功/失败` - [x] `UnbindContainer` 改为 `Task.Run` 异步 → `MesUploadStatusEnum.拆盘上传成功/失败` - [x] `ContainerNgReport` 改为 `Task.Run` 异步 → `MesUploadStatusEnum.NG上报成功/失败` - [x] 硬编码 `"STK-GROUP-001"` 改为 `_mesDeviceConfigService.GetByDeviceName()` 动态获取 - [x] 注入 `IMESDeviceConfigService` - [x] Commit: `57feefd` → `c36c5c6` ### Task 13: StockInfoController MES 异步 + 动态凭证 ✅ **Files:** Modify `WIDESEA_WMSServer/Controllers/Stock/StockInfoController.cs` - [x] `InboundInContainer` 改为 `Task.Run` 异步 → `MesUploadStatusEnum.进站上传成功/失败` - [x] `OutboundInContainer` 改为 `Task.Run` 异步 → `MesUploadStatusEnum.出站上传成功/失败` - [x] 硬编码 `"STK-GROUP-001"` 改为基于 `stockInfo.Remark` 动态选择设备名查询 MES 凭证 - [x] 注入 `IMESDeviceConfigService` 和 `IStockInfoService` - [x] Commit: `343d512` → `fba665e` ### Task 14: TaskService_Inbound 进站 MES 异步 ✅ **Files:** Modify `WIDESEA_TaskInfoService/WCS/TaskService_Inbound.cs` - [x] `InboundInContainer` 改为 `Task.Run` 异步执行 - [x] 使用 `MesUploadStatusEnum.进站上传成功`(5)/ `进站上传失败`(6) - [x] 保留动态 MES 凭证获取逻辑(`_mesDeviceConfigService.GetByDeviceName`) - [x] `CompleteTaskAsync` 立即返回,不等待 MES 结果 - [x] Commit: `63ca4ac` --- ## Phase 3: 前端 ### Task 7: stockInfo.vue 新增 MES 状态列 ✅ **Files:** Modify `WIDESEA_WMSClient/src/views/stock/stockInfo.vue` - [x] columns 中 `stockStatus` 之后新增 `mesUploadStatus` 列(bind: mesUploadStatusEnum) - [x] `loadStockStatusOptions` 改为同时加载 `stockStatusEmun` + `mesUploadStatusEnum` - [x] Commit: `9a1c82a` ### Task 8: stock.jsx 新增组盘/拆盘按钮 ✅ **Files:** Modify `WIDESEA_WMSClient/src/extension/stock/stock.jsx` - [x] `onInited` 中注入 `editTableButtons`:组盘 + 拆盘 - [x] `onGroupPallet` → POST `/Stock/GroupPalletConfirm` - [x] `onSplitPallet` → POST `/Stock/SplitPalletConfirm` - [x] Commit: `0be9278` --- ## Phase 4: 构建验证 ### Task 10: 构建验证 ✅ - [x] 后端 `dotnet build WIDESEA_WMSServer.sln` → 0 错误 - [x] 前端 `npm run build` → 0 错误 --- ## MES 调用点全覆盖 | 位置 | 方法 | MES接口 | 状态枚举 | 动态凭证 | 异步 | |------|------|---------|---------|---------|------| | `StockSerivce.cs` | `GroupPalletConfirmAsync` | `BindContainer` | 1成功/2失败 | ✅ ResolveMesConfig | ✅ | | `StockSerivce.cs` | `SplitPalletConfirmAsync` | `UnBindContainer` | 3成功/4失败 | ✅ ResolveMesConfig | ✅ | | `TaskService_Inbound.cs` | `InboundFinishTaskAsync` | `InboundInContainer` | 5成功/6失败 | ✅ MESDeviceConfigService | ✅ | | `TaskService_Outbound.cs` | `OutboundFinishTaskAsync` | `OutboundInContainer` | 7成功/8失败 | ✅ MESDeviceConfigService | ✅ | | `StockInfoController.cs` | `InboundInContainer` | `InboundInContainer` | 5成功/6失败 | ✅ MESDeviceConfigService | ✅ | | `StockInfoController.cs` | `OutboundInContainer` | `OutboundInContainer` | 7成功/8失败 | ✅ MESDeviceConfigService | ✅ | | `StockInfoDetailController.cs` | `BindContainer` | `BindContainer` | 1成功/2失败 | ✅ MESDeviceConfigService | ✅ | | `StockInfoDetailController.cs` | `UnbindContainer` | `UnBindContainer` | 3成功/4失败 | ✅ MESDeviceConfigService | ✅ | | `StockInfoDetailController.cs` | `ContainerNgReport` | `ContainerNgReport` | 9成功/10失败 | ✅ MESDeviceConfigService | ✅ | --- ## 自检清单 - [x] `MesUploadStatusEnum` 枚举值奇数为成功,偶数为失败 - [x] 所有 MES 调用通过 `Task.Run` 异步执行,不阻塞主逻辑 - [x] 所有 MES 调用记录详细日志(托盘号、接口类型、请求JSON、响应JSON、耗时、状态、错误原因) - [x] 所有 MES 凭证动态获取,不再硬编码 `"STK-GROUP-001"` - [x] 前端组盘/拆盘按钮正确调用 `GroupPalletConfirmAsync` / `SplitPalletConfirmAsync` - [x] `stockInfo.vue` 正确显示 `mesUploadStatus` 字段 - [x] 所有 public 方法均有 XML 文档注释 - [x] 数据库脚本含 IF NOT EXISTS 防止重复添加 - [x] 后端和前端均可正常编译构建(0 错误)