From ce1292c9cf37195b6abd2699dfc5d6cb3e143c9b Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期日, 12 四月 2026 23:38:19 +0800
Subject: [PATCH] feat(MES): 添加MES接口相关实体和DTO JS扩展文件至JSX格式并更新配置

---
 Code/docs/superpowers/plans/2026-04-12-mes-integration-plan.md | 1933 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,933 insertions(+), 0 deletions(-)

diff --git a/Code/docs/superpowers/plans/2026-04-12-mes-integration-plan.md b/Code/docs/superpowers/plans/2026-04-12-mes-integration-plan.md
new file mode 100644
index 0000000..3322365
--- /dev/null
+++ b/Code/docs/superpowers/plans/2026-04-12-mes-integration-plan.md
@@ -0,0 +1,1933 @@
+# WMS搴撳瓨椤甸潰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 (`- [ ]`) syntax for tracking.
+
+**Goal:** 涓篧MS搴撳瓨淇℃伅椤甸潰鍜屽簱瀛樻槑缁嗛〉闈㈡坊鍔犳搷浣滃垪锛岃皟鐢∕ES绯荤粺鐨勮繘绔�/鍑虹珯/缁戝畾/瑙g粦/NG涓婃姤鎺ュ彛
+
+**Architecture:** 鍓嶇鍦ㄥ簱瀛樿〃鏍间腑娣诲姞鎿嶄綔鍒楋紝鐐瑰嚮鍚庡脊鍑虹‘璁ゅ璇濇锛岀‘璁ゅ悗璋冪敤鍚庣API锛涘悗绔帴鏀惰姹傦紝璋冪敤MES鏈嶅姟锛岃褰曞畬鏁存棩蹇楋紝杩斿洖缁撴灉
+
+**Tech Stack:** Vue 3, Element Plus, .NET 8, SqlSugar ORM, SQL Server, HttpClient
+
+---
+
+## 鏂囦欢缁撴瀯
+
+### 鍓嶇鏂囦欢
+
+```
+WMS/WIDESEA_WMSClient/src/
+鈹溾攢鈹� views/stock/
+鈹�   鈹溾攢鈹� stockInfo.vue                         # 淇敼锛氭坊鍔犳搷浣滃垪
+鈹�   鈹斺攢鈹� stockInfoDetail.vue                   # 淇敼锛氭坊鍔犳搷浣滃垪
+鈹溾攢鈹� components/
+鈹�   鈹斺攢鈹� MesConfirmDialog.vue                  # 鏂板锛歁ES纭瀵硅瘽妗�
+鈹斺攢鈹� api/
+    鈹斺攢鈹� mes.js                                # 鏂板锛歁ES API璋冪敤
+```
+
+### 鍚庣鏂囦欢
+
+```
+WMS/WIDESEA_WMSServer/
+鈹溾攢鈹� Controllers/
+鈹�   鈹斺攢鈹� Stock/
+鈹�       鈹溾攢鈹� StockInfoController.cs            # 淇敼锛氭坊鍔犺繘绔�/鍑虹珯鎺ュ彛
+鈹�       鈹斺攢鈹� StockInfoDetailController.cs      # 淇敼锛氭坊鍔犵粦瀹�/瑙g粦/NG涓婃姤鎺ュ彛
+鈹溾攢鈹� Services/
+鈹�   鈹斺攢鈹� Mes/
+鈹�       鈹溾攢鈹� IMesLogService.cs                 # 鏂板锛氭棩蹇楁湇鍔℃帴鍙�
+鈹�       鈹斺攢鈹� MesLogService.cs                  # 鏂板锛氭棩蹇楁湇鍔″疄鐜�
+鈹溾攢鈹� DTO/
+鈹�   鈹溾攢鈹� Mes/
+鈹�   鈹�   鈹溾攢鈹� MesApiLogDto.cs                   # 鏂板锛氭棩蹇桪TO
+鈹�   鈹�   鈹溾攢鈹� InboundInContainerRequestDto.cs   # 鏂板锛氳繘绔欒姹侱TO
+鈹�   鈹�   鈹溾攢鈹� OutboundInContainerRequestDto.cs  # 鏂板锛氬嚭绔欒姹侱TO
+鈹�   鈹�   鈹溾攢鈹� BindContainerRequestDto.cs        # 鏂板锛氱粦瀹氳姹侱TO
+鈹�   鈹�   鈹溾攢鈹� UnbindContainerRequestDto.cs      # 鏂板锛氳В缁戣姹侱TO
+鈹�   鈹�   鈹斺攢鈹� ContainerNgReportRequestDto.cs    # 鏂板锛歂G涓婃姤璇锋眰DTO
+鈹�   鈹斺攢鈹� Models/
+鈹�       鈹斺攢鈹� Mes/
+鈹�           鈹斺攢鈹� Dt_MesApiLog.cs                # 鏂板锛氭棩蹇楀疄浣�
+鈹斺攢鈹� Database/
+    鈹斺攢鈹� Scripts/
+        鈹斺攢鈹� 20260412_MesApiLog.sql             # 鏂板锛氭棩蹇楄〃鍒涘缓鑴氭湰
+```
+
+---
+
+## Task 1: 鍒涘缓鏁版嵁搴撹〃
+
+**Files:**
+- Create: `WMS/WIDESEA_WMSServer/Database/Scripts/20260412_MesApiLog.sql`
+
+- [ ] **Step 1: 鍒涘缓MES鎺ュ彛鏃ュ織琛⊿QL鑴氭湰**
+
+```sql
+-- =============================================
+-- WMS MES鎺ュ彛璋冪敤鏃ュ織琛�
+-- =============================================
+
+IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Dt_MesApiLog')
+BEGIN
+    CREATE TABLE Dt_MesApiLog (
+        Id BIGINT PRIMARY KEY IDENTITY(1,1),
+        ApiType NVARCHAR(50) NOT NULL,           -- 鎺ュ彛绫诲瀷
+        RequestJson NVARCHAR(MAX) NULL,          -- 璇锋眰JSON
+        ResponseJson NVARCHAR(MAX) NULL,         -- 鍝嶅簲JSON
+        IsSuccess BIT NOT NULL DEFAULT 0,        -- 鏄惁鎴愬姛
+        ErrorMessage NVARCHAR(500) NULL,         -- 閿欒淇℃伅
+        ElapsedMs INT NOT NULL DEFAULT 0,        -- 鑰楁椂(姣)
+        CreateDate DATETIME NOT NULL,            -- 鍒涘缓鏃堕棿
+        Creator NVARCHAR(50) NULL,               -- 鍒涘缓浜�
+        ModifyDate DATETIME NULL,                -- 淇敼鏃堕棿
+        Modifier NVARCHAR(50) NULL               -- 淇敼浜�
+    );
+
+    -- 鍒涘缓绱㈠紩
+    CREATE INDEX IX_MesApiLog_ApiType ON Dt_MesApiLog(ApiType);
+    CREATE INDEX IX_MesApiLog_CreateDate ON Dt_MesApiLog(CreateDate);
+    CREATE INDEX IX_MesApiLog_IsSuccess ON Dt_MesApiLog(IsSuccess);
+
+    PRINT 'MES鎺ュ彛鏃ュ織琛� Dt_MesApiLog 鍒涘缓鎴愬姛';
+END
+ELSE
+BEGIN
+    PRINT 'MES鎺ュ彛鏃ュ織琛� Dt_MesApiLog 宸插瓨鍦�';
+END
+
+-- 鎻掑叆MES绯荤粺閰嶇疆
+IF NOT EXISTS (SELECT * FROM Dt_SystemConfig WHERE ConfigKey = 'MES_EquipmentCode')
+BEGIN
+    INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier)
+    VALUES ('MES_EquipmentCode', 'WCS_001', 'MES璁惧缂栫爜', GETDATE(), 'System');
+
+    INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier)
+    VALUES ('MES_ResourceCode', 'RESOURCE_001', 'MES璧勬簮缂栫爜', GETDATE(), 'System');
+
+    INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier)
+    VALUES ('MES_ApiBaseUrl', 'http://mes-server/api', 'MES鎺ュ彛鍦板潃', GETDATE(), 'System');
+
+    INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier)
+    VALUES ('MES_TimeoutSeconds', '30', 'MES鎺ュ彛瓒呮椂鏃堕棿(绉�)', GETDATE(), 'System');
+
+    PRINT 'MES绯荤粺閰嶇疆鎻掑叆鎴愬姛';
+END
+```
+
+- [ ] **Step 2: 鎵цSQL鑴氭湰鍒涘缓琛�**
+
+Run: 鍦⊿QL Server Management Studio涓墽琛岃鑴氭湰
+Expected: 琛ㄥ垱寤烘垚鍔燂紝閰嶇疆鎻掑叆鎴愬姛
+
+- [ ] **Step 3: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSServer/Database/Scripts/20260412_MesApiLog.sql
+git commit -m "feat(MES): 娣诲姞MES鎺ュ彛鏃ュ織琛ㄥ拰绯荤粺閰嶇疆
+
+- 鍒涘缓 Dt_MesApiLog 琛ㄨ褰曟帴鍙h皟鐢ㄦ棩蹇�
+- 娣诲姞MES鐩稿叧绯荤粺閰嶇疆椤癸紙璁惧缂栫爜銆佽祫婧愮紪鐮併�佹帴鍙e湴鍧�绛夛級
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
+```
+
+---
+
+## Task 2: 鍒涘缓鍚庣瀹炰綋鍜孌TO
+
+**Files:**
+- Create: `WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/Mes/Dt_MesApiLog.cs`
+- Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/MesApiLogDto.cs`
+- Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/InboundInContainerRequestDto.cs`
+- Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/OutboundInContainerRequestDto.cs`
+- Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/BindContainerRequestDto.cs`
+- Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/UnbindContainerRequestDto.cs`
+- Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/ContainerNgReportRequestDto.cs`
+
+- [ ] **Step 1: 鍒涘缓MES鏃ュ織瀹炰綋**
+
+```csharp
+using SqlSugar;
+using System;
+
+namespace WIDESEA_Model.Models.Mes
+{
+    /// <summary>
+    /// MES鎺ュ彛璋冪敤鏃ュ織瀹炰綋
+    /// </summary>
+    [SugarTable("Dt_MesApiLog")]
+    public class Dt_MesApiLog
+    {
+        /// <summary>
+        /// 涓婚敭ID
+        /// </summary>
+        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+        public long Id { get; set; }
+
+        /// <summary>
+        /// 鎺ュ彛绫诲瀷锛欼nboundInContainer, OutboundInContainer, BindContainer, UnbindContainer, ContainerNgReport
+        /// </summary>
+        [SugarColumn(Length = 50, IsNullable = false)]
+        public string ApiType { get; set; }
+
+        /// <summary>
+        /// 璇锋眰JSON
+        /// </summary>
+        [SugarColumn(ColumnDataType = "nvarchar(max)", IsNullable = true)]
+        public string RequestJson { get; set; }
+
+        /// <summary>
+        /// 鍝嶅簲JSON
+        /// </summary>
+        [SugarColumn(ColumnDataType = "nvarchar(max)", IsNullable = true)]
+        public string ResponseJson { get; set; }
+
+        /// <summary>
+        /// 鏄惁鎴愬姛
+        /// </summary>
+        [SugarColumn(IsNullable = false)]
+        public bool IsSuccess { get; set; }
+
+        /// <summary>
+        /// 閿欒淇℃伅
+        /// </summary>
+        [SugarColumn(Length = 500, IsNullable = true)]
+        public string ErrorMessage { get; set; }
+
+        /// <summary>
+        /// 鑰楁椂锛堟绉掞級
+        /// </summary>
+        [SugarColumn(IsNullable = false)]
+        public int ElapsedMs { get; set; }
+
+        /// <summary>
+        /// 鍒涘缓鏃堕棿
+        /// </summary>
+        [SugarColumn(IsNullable = false)]
+        public DateTime CreateDate { get; set; }
+
+        /// <summary>
+        /// 鍒涘缓浜�
+        /// </summary>
+        [SugarColumn(Length = 50, IsNullable = true)]
+        public string Creator { get; set; }
+
+        /// <summary>
+        /// 淇敼鏃堕棿
+        /// </summary>
+        public DateTime? ModifyDate { get; set; }
+
+        /// <summary>
+        /// 淇敼浜�
+        /// </summary>
+        [SugarColumn(Length = 50, IsNullable = true)]
+        public string Modifier { get; set; }
+    }
+}
+```
+
+- [ ] **Step 2: 鍒涘缓MES鏃ュ織DTO**
+
+```csharp
+namespace WIDESEA_DTO.Mes
+{
+    /// <summary>
+    /// MES鎺ュ彛鏃ュ織DTO
+    /// </summary>
+    public class MesApiLogDto
+    {
+        /// <summary>
+        /// 鎺ュ彛绫诲瀷
+        /// </summary>
+        public string ApiType { get; set; }
+
+        /// <summary>
+        /// 璇锋眰JSON
+        /// </summary>
+        public string RequestJson { get; set; }
+
+        /// <summary>
+        /// 鍝嶅簲JSON
+        /// </summary>
+        public string ResponseJson { get; set; }
+
+        /// <summary>
+        /// 鏄惁鎴愬姛
+        /// </summary>
+        public bool IsSuccess { get; set; }
+
+        /// <summary>
+        /// 閿欒淇℃伅
+        /// </summary>
+        public string ErrorMessage { get; set; }
+
+        /// <summary>
+        /// 鑰楁椂锛堟绉掞級
+        /// </summary>
+        public int ElapsedMs { get; set; }
+
+        /// <summary>
+        /// 鍒涘缓浜�
+        /// </summary>
+        public string Creator { get; set; }
+    }
+}
+```
+
+- [ ] **Step 3: 鍒涘缓杩涚珯璇锋眰DTO**
+
+```csharp
+namespace WIDESEA_DTO.Mes
+{
+    /// <summary>
+    /// 鎵樼洏杩涚珯璇锋眰DTO
+    /// </summary>
+    public class InboundInContainerRequestDto
+    {
+        /// <summary>
+        /// 鎵樼洏缂栧彿
+        /// </summary>
+        public string PalletCode { get; set; }
+
+        /// <summary>
+        /// 搴撳瓨ID
+        /// </summary>
+        public long StockId { get; set; }
+    }
+}
+```
+
+- [ ] **Step 4: 鍒涘缓鍑虹珯璇锋眰DTO**
+
+```csharp
+using System.Collections.Generic;
+
+namespace WIDESEA_DTO.Mes
+{
+    /// <summary>
+    /// 鎵樼洏鍑虹珯璇锋眰DTO
+    /// </summary>
+    public class OutboundInContainerRequestDto
+    {
+        /// <summary>
+        /// 鎵樼洏缂栧彿
+        /// </summary>
+        public string PalletCode { get; set; }
+
+        /// <summary>
+        /// 搴撳瓨ID
+        /// </summary>
+        public long StockId { get; set; }
+
+        /// <summary>
+        /// 浜у搧鍙傛暟鍒楄〃锛堝彲閫夛級
+        /// </summary>
+        public List<ParamItemDto> ParamList { get; set; }
+
+        /// <summary>
+        /// 鍙傛暟椤笵TO
+        /// </summary>
+        public class ParamItemDto
+        {
+            /// <summary>
+            /// 鍙傛暟缂栫爜
+            /// </summary>
+            public string ParamCode { get; set; }
+
+            /// <summary>
+            /// 鍙傛暟鍊�
+            /// </summary>
+            public string ParamValue { get; set; }
+
+            /// <summary>
+            /// 閲囬泦鏃堕棿
+            /// </summary>
+            public string CollectionTime { get; set; }
+        }
+    }
+}
+```
+
+- [ ] **Step 5: 鍒涘缓缁戝畾璇锋眰DTO**
+
+```csharp
+using System.Collections.Generic;
+
+namespace WIDESEA_DTO.Mes
+{
+    /// <summary>
+    /// 鎵樼洏鐢佃姱缁戝畾璇锋眰DTO
+    /// </summary>
+    public class BindContainerRequestDto
+    {
+        /// <summary>
+        /// 鎵樼洏缂栧彿
+        /// </summary>
+        public string PalletCode { get; set; }
+
+        /// <summary>
+        /// 鐢佃姱鐮佸垪琛�
+        /// </summary>
+        public List<string> SfcList { get; set; }
+
+        /// <summary>
+        /// 浣嶇疆淇℃伅
+        /// </summary>
+        public string Location { get; set; }
+
+        /// <summary>
+        /// 鎿嶄綔绫诲瀷锛�0-榛樿 1-杩涚珯 2-鍑虹珯 3-杩涘嚭绔�
+        /// </summary>
+        public int OperationType { get; set; } = 1;
+    }
+}
+```
+
+- [ ] **Step 6: 鍒涘缓瑙g粦璇锋眰DTO**
+
+```csharp
+using System.Collections.Generic;
+
+namespace WIDESEA_DTO.Mes
+{
+    /// <summary>
+    /// 鎵樼洏鐢佃姱瑙g粦璇锋眰DTO
+    /// </summary>
+    public class UnbindContainerRequestDto
+    {
+        /// <summary>
+        /// 鎵樼洏缂栧彿
+        /// </summary>
+        public string PalletCode { get; set; }
+
+        /// <summary>
+        /// 鐢佃姱鐮佸垪琛�
+        /// </summary>
+        public List<string> SfcList { get; set; }
+    }
+}
+```
+
+- [ ] **Step 7: 鍒涘缓NG涓婃姤璇锋眰DTO**
+
+```csharp
+using System.Collections.Generic;
+
+namespace WIDESEA_DTO.Mes
+{
+    /// <summary>
+    /// 鎵樼洏NG鐢佃姱涓婃姤璇锋眰DTO
+    /// </summary>
+    public class ContainerNgReportRequestDto
+    {
+        /// <summary>
+        /// 鎵樼洏缂栧彿
+        /// </summary>
+        public string PalletCode { get; set; }
+
+        /// <summary>
+        /// NG鐢佃姱鍒楄〃
+        /// </summary>
+        public List<NgSfcItemDto> NgSfcList { get; set; }
+
+        /// <summary>
+        /// NG鐢佃姱椤笵TO
+        /// </summary>
+        public class NgSfcItemDto
+        {
+            /// <summary>
+            /// 浜у搧鏉$爜
+            /// </summary>
+            public string Sfc { get; set; }
+
+            /// <summary>
+            /// NG浠g爜
+            /// </summary>
+            public string NgCode { get; set; }
+
+            /// <summary>
+            /// NG璁惧
+            /// </summary>
+            public string NgEquipmentCode { get; set; }
+
+            /// <summary>
+            /// NG璧勬簮
+            /// </summary>
+            public string NgResourceCode { get; set; }
+        }
+    }
+}
+```
+
+- [ ] **Step 8: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/Mes/Dt_MesApiLog.cs
+git add WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/*.cs
+git commit -m "feat(MES): 娣诲姞MES鎺ュ彛鐩稿叧瀹炰綋鍜孌TO
+
+- 娣诲姞 Dt_MesApiLog 鏃ュ織瀹炰綋
+- 娣诲姞 MesApiLogDto 鍙婂悇鎺ュ彛璇锋眰DTO
+- 鏀寔杩涚珯銆佸嚭绔欍�佺粦瀹氥�佽В缁戙�丯G涓婃姤鎺ュ彛
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
+```
+
+---
+
+## Task 3: 鍒涘缓MES鏃ュ織鏈嶅姟
+
+**Files:**
+- Create: `WMS/WIDESEA_WMSServer/WIDESEA_IMesService/IMesLogService.cs`
+- Create: `WMS/WIDESEA_WMSServer/WIDESEA_MesService/MesLogService.cs`
+
+- [ ] **Step 1: 鍒涘缓MES鏃ュ織鏈嶅姟鎺ュ彛**
+
+```csharp
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using WIDESEA_Core;
+using WIDESEA_DTO.Mes;
+
+namespace WIDESEA_IMesService
+{
+    /// <summary>
+    /// MES鎺ュ彛鏃ュ織鏈嶅姟鎺ュ彛
+    /// </summary>
+    public interface IMesLogService : IDependency
+    {
+        /// <summary>
+        /// 璁板綍MES鎺ュ彛璋冪敤鏃ュ織
+        /// </summary>
+        /// <param name="log">鏃ュ織DTO</param>
+        /// <returns>鏄惁璁板綍鎴愬姛</returns>
+        Task<bool> LogAsync(MesApiLogDto log);
+
+        /// <summary>
+        /// 鑾峰彇鏈�杩戠殑MES鎺ュ彛璋冪敤璁板綍
+        /// </summary>
+        /// <param name="apiType">鎺ュ彛绫诲瀷</param>
+        /// <param name="count">璁板綍鏁伴噺</param>
+        /// <returns>鏃ュ織鍒楄〃</returns>
+        Task<List<MesApiLogDto>> GetRecentLogsAsync(string apiType, int count = 50);
+    }
+}
+```
+
+- [ ] **Step 2: 鍒涘缓MES鏃ュ織鏈嶅姟瀹炵幇**
+
+```csharp
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using WIDESEA_Core;
+using WIDESEA_DTO.Mes;
+using WIDESEA_IMesService;
+using WIDESEA_Model.Models.Mes;
+
+namespace WIDESEA_MesService
+{
+    /// <summary>
+    /// MES鎺ュ彛鏃ュ織鏈嶅姟瀹炵幇
+    /// </summary>
+    public class MesLogService : IMesLogService
+    {
+        private readonly ISqlSugarClient _db;
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        public MesLogService(ISqlSugarClient db)
+        {
+            _db = db;
+        }
+
+        /// <summary>
+        /// 璁板綍MES鎺ュ彛璋冪敤鏃ュ織
+        /// </summary>
+        public async Task<bool> LogAsync(MesApiLogDto log)
+        {
+            try
+            {
+                var entity = new Dt_MesApiLog
+                {
+                    ApiType = log.ApiType,
+                    RequestJson = log.RequestJson,
+                    ResponseJson = log.ResponseJson,
+                    IsSuccess = log.IsSuccess,
+                    ErrorMessage = log.ErrorMessage,
+                    ElapsedMs = log.ElapsedMs,
+                    CreateDate = DateTime.Now,
+                    Creator = log.Creator
+                };
+
+                var result = await _db.Insertable(entity).ExecuteCommandAsync();
+                return result > 0;
+            }
+            catch (Exception ex)
+            {
+                // 璁板綍鏃ュ織澶辫触涓嶅奖鍝嶄富娴佺▼
+                Console.WriteLine($"璁板綍MES鏃ュ織澶辫触: {ex.Message}");
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇鏈�杩戠殑MES鎺ュ彛璋冪敤璁板綍
+        /// </summary>
+        public async Task<List<MesApiLogDto>> GetRecentLogsAsync(string apiType, int count = 50)
+        {
+            try
+            {
+                var entities = await _db.Queryable<Dt_MesApiLog>()
+                    .Where(x => x.ApiType == apiType)
+                    .OrderByDescending(x => x.CreateDate)
+                    .Take(count)
+                    .ToListAsync();
+
+                return entities.Select(e => new MesApiLogDto
+                {
+                    ApiType = e.ApiType,
+                    RequestJson = e.RequestJson,
+                    ResponseJson = e.ResponseJson,
+                    IsSuccess = e.IsSuccess,
+                    ErrorMessage = e.ErrorMessage,
+                    ElapsedMs = e.ElapsedMs,
+                    Creator = e.Creator
+                }).ToList();
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"鑾峰彇MES鏃ュ織澶辫触: {ex.Message}");
+                return new List<MesApiLogDto>();
+            }
+        }
+    }
+}
+```
+
+- [ ] **Step 3: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSServer/WIDESEA_IMesService/IMesLogService.cs
+git add WMS/WIDESEA_WMSServer/WIDESEA_MesService/MesLogService.cs
+git commit -m "feat(MES): 娣诲姞MES鏃ュ織鏈嶅姟
+
+- 瀹炵幇 IMesLogService 鎺ュ彛
+- 鏀寔璁板綍鍜屾煡璇ES鎺ュ彛璋冪敤鏃ュ織
+- 寮傚父澶勭悊涓嶅奖鍝嶄富娴佺▼
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
+```
+
+---
+
+## Task 4: 鎵╁睍StockInfoController娣诲姞杩涚珯/鍑虹珯鎺ュ彛
+
+**Files:**
+- Modify: `WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoController.cs`
+
+- [ ] **Step 1: 鍦⊿tockInfoController涓坊鍔燤ES鎺ュ彛鏂规硶**
+
+鍦ㄧ幇鏈塖tockInfoController绫讳腑娣诲姞浠ヤ笅鏂规硶锛�
+
+```csharp
+/// <summary>
+/// MES鏃ュ織鏈嶅姟
+/// </summary>
+private readonly IMesLogService _mesLogService;
+
+/// <summary>
+/// MES鏈嶅姟锛堝凡鍦ㄩ」鐩腑瀹氫箟锛�
+/// </summary>
+private readonly IMesService _mesService;
+
+/// <summary>
+/// 绯荤粺閰嶇疆鏈嶅姟
+/// </summary>
+private readonly ISystemConfigService _configService;
+
+// 鍦ㄦ瀯閫犲嚱鏁颁腑娉ㄥ叆杩欎簺鏈嶅姟锛堝鏋滃皻鏈敞鍏ワ級
+```
+
+娣诲姞杩涚珯鎺ュ彛锛�
+
+```csharp
+/// <summary>
+/// 鎵樼洏杩涚珯 - 璋冪敤MES鎺ュ彛
+/// </summary>
+/// <param name="dto">杩涚珯璇锋眰DTO</param>
+/// <returns>鎿嶄綔缁撴灉</returns>
+[HttpPost("inboundInContainer")]
+[Permission("MES_INBOUND")]
+public async Task<WebResponseContent> InboundInContainer([FromBody] InboundInContainerRequestDto dto)
+{
+    var response = new WebResponseContent();
+    var stopwatch = System.Diagnostics.Stopwatch.StartNew();
+
+    try
+    {
+        // 1. 鍙傛暟楠岃瘉
+        if (string.IsNullOrWhiteSpace(dto.PalletCode))
+        {
+            return response.Error("鎵樼洏缂栧彿涓嶈兘涓虹┖");
+        }
+
+        // 2. 鏌ヨ搴撳瓨淇℃伅
+        var stockInfo = await _service.FindAsIQueryable(x => x.Id == dto.StockId)
+            .FirstAsync();
+
+        if (stockInfo == null)
+        {
+            return response.Error("搴撳瓨淇℃伅涓嶅瓨鍦�");
+        }
+
+        // 3. 楠岃瘉搴撳瓨鐘舵�侊紙浠�"寰呭叆搴�"鐘舵�佸厑璁歌繘绔欙級
+        if (stockInfo.Status != 0) // 鍋囪0=寰呭叆搴�
+        {
+            return response.Error($"褰撳墠搴撳瓨鐘舵�佷笉鍏佽杩涚珯鎿嶄綔");
+        }
+
+        // 4. 鑾峰彇绯荤粺閰嶇疆
+        var equipmentCode = await _configService.GetConfigValueAsync("MES_EquipmentCode");
+        var resourceCode = await _configService.GetConfigValueAsync("MES_ResourceCode");
+
+        if (string.IsNullOrWhiteSpace(equipmentCode) || string.IsNullOrWhiteSpace(resourceCode))
+        {
+            return response.Error("MES绯荤粺閰嶇疆涓嶅畬鏁达紝璇疯仈绯荤鐞嗗憳");
+        }
+
+        // 5. 鏋勯�燤ES璇锋眰
+        var mesRequest = new InboundInContainerRequest
+        {
+            EquipmentCode = equipmentCode,
+            ResourceCode = resourceCode,
+            LocalTime = DateTime.Now,
+            ContainerCode = dto.PalletCode
+        };
+
+        string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest);
+
+        // 6. 璋冪敤MES鎺ュ彛
+        var mesResult = await _mesService.InboundInContainer(mesRequest);
+        stopwatch.Stop();
+
+        // 7. 璁板綍鏃ュ織
+        await _mesLogService.LogAsync(new MesApiLogDto
+        {
+            ApiType = "InboundInContainer",
+            RequestJson = requestJson,
+            ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult),
+            IsSuccess = mesResult.Success,
+            ErrorMessage = mesResult.ErrorMessage,
+            ElapsedMs = (int)stopwatch.ElapsedMilliseconds,
+            Creator = UserContext.Current.UserName
+        });
+
+        // 8. 杩斿洖缁撴灉
+        if (mesResult.Success)
+        {
+            return response.OK("鎵樼洏杩涚珯鎴愬姛");
+        }
+        else
+        {
+            return response.Error($"MES鎺ュ彛璋冪敤澶辫触: {mesResult.ErrorMessage}");
+        }
+    }
+    catch (System.Exception ex)
+    {
+        stopwatch.Stop();
+
+        // 璁板綍閿欒鏃ュ織
+        await _mesLogService.LogAsync(new MesApiLogDto
+        {
+            ApiType = "InboundInContainer",
+            IsSuccess = false,
+            ErrorMessage = ex.Message,
+            ElapsedMs = (int)stopwatch.ElapsedMilliseconds,
+            Creator = UserContext.Current.UserName
+        });
+
+        return response.Error($"鎵樼洏杩涚珯澶辫触: {ex.Message}");
+    }
+}
+```
+
+娣诲姞鍑虹珯鎺ュ彛锛�
+
+```csharp
+/// <summary>
+/// 鎵樼洏鍑虹珯 - 璋冪敤MES鎺ュ彛
+/// </summary>
+/// <param name="dto">鍑虹珯璇锋眰DTO</param>
+/// <returns>鎿嶄綔缁撴灉</returns>
+[HttpPost("outboundInContainer")]
+[Permission("MES_OUTBOUND")]
+public async Task<WebResponseContent> OutboundInContainer([FromBody] OutboundInContainerRequestDto dto)
+{
+    var response = new WebResponseContent();
+    var stopwatch = System.Diagnostics.Stopwatch.StartNew();
+
+    try
+    {
+        // 1. 鍙傛暟楠岃瘉
+        if (string.IsNullOrWhiteSpace(dto.PalletCode))
+        {
+            return response.Error("鎵樼洏缂栧彿涓嶈兘涓虹┖");
+        }
+
+        // 2. 鏌ヨ搴撳瓨淇℃伅
+        var stockInfo = await _service.FindAsIQueryable(x => x.Id == dto.StockId)
+            .FirstAsync();
+
+        if (stockInfo == null)
+        {
+            return response.Error("搴撳瓨淇℃伅涓嶅瓨鍦�");
+        }
+
+        // 3. 楠岃瘉搴撳瓨鐘舵�侊紙"鍦ㄥ簱"鎴�"鍑哄簱涓�"鐘舵�佸厑璁稿嚭绔欙級
+        if (stockInfo.Status != 1 && stockInfo.Status != 2) // 鍋囪1=鍦ㄥ簱, 2=鍑哄簱涓�
+        {
+            return response.Error($"褰撳墠搴撳瓨鐘舵�佷笉鍏佽鍑虹珯鎿嶄綔");
+        }
+
+        // 4. 鑾峰彇绯荤粺閰嶇疆
+        var equipmentCode = await _configService.GetConfigValueAsync("MES_EquipmentCode");
+        var resourceCode = await _configService.GetConfigValueAsync("MES_ResourceCode");
+
+        if (string.IsNullOrWhiteSpace(equipmentCode) || string.IsNullOrWhiteSpace(resourceCode))
+        {
+            return response.Error("MES绯荤粺閰嶇疆涓嶅畬鏁达紝璇疯仈绯荤鐞嗗憳");
+        }
+
+        // 5. 鏋勯�燤ES璇锋眰
+        var mesRequest = new OutboundInContainerRequest
+        {
+            EquipmentCode = equipmentCode,
+            ResourceCode = resourceCode,
+            LocalTime = DateTime.Now,
+            ContainerCode = dto.PalletCode,
+            ParamList = dto.ParamList?.Select(p => new ParamItem
+            {
+                ParamCode = p.ParamCode,
+                ParamValue = p.ParamValue,
+                CollectionTime = DateTime.TryParse(p.CollectionTime, out var ct) ? ct : DateTime.Now
+            }).ToList()
+        };
+
+        string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest);
+
+        // 6. 璋冪敤MES鎺ュ彛
+        var mesResult = await _mesService.OutboundInContainer(mesRequest);
+        stopwatch.Stop();
+
+        // 7. 璁板綍鏃ュ織
+        await _mesLogService.LogAsync(new MesApiLogDto
+        {
+            ApiType = "OutboundInContainer",
+            RequestJson = requestJson,
+            ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult),
+            IsSuccess = mesResult.Success,
+            ErrorMessage = mesResult.ErrorMessage,
+            ElapsedMs = (int)stopwatch.ElapsedMilliseconds,
+            Creator = UserContext.Current.UserName
+        });
+
+        // 8. 杩斿洖缁撴灉
+        if (mesResult.Success)
+        {
+            return response.OK("鎵樼洏鍑虹珯鎴愬姛");
+        }
+        else
+        {
+            return response.Error($"MES鎺ュ彛璋冪敤澶辫触: {mesResult.ErrorMessage}");
+        }
+    }
+    catch (System.Exception ex)
+    {
+        stopwatch.Stop();
+
+        // 璁板綍閿欒鏃ュ織
+        await _mesLogService.LogAsync(new MesApiLogDto
+        {
+            ApiType = "OutboundInContainer",
+            IsSuccess = false,
+            ErrorMessage = ex.Message,
+            ElapsedMs = (int)stopwatch.ElapsedMilliseconds,
+            Creator = UserContext.Current.UserName
+        });
+
+        return response.Error($"鎵樼洏鍑虹珯澶辫触: {ex.Message}");
+    }
+}
+```
+
+- [ ] **Step 2: 娣诲姞蹇呰鐨剈sing璇彞**
+
+鍦ㄦ枃浠堕《閮ㄦ坊鍔狅細
+
+```csharp
+using WIDESEA_DTO.MES;
+using WIDESEA_DTO.Mes;
+using WIDESEA_IMesService;
+```
+
+- [ ] **Step 3: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoController.cs
+git commit -m "feat(MES): 搴撳瓨淇℃伅椤甸潰娣诲姞杩涚珯/鍑虹珯鎺ュ彛
+
+- POST /api/StockInfo/inboundInContainer 鎵樼洏杩涚珯
+- POST /api/StockInfo/outboundInContainer 鎵樼洏鍑虹珯
+- 娣诲姞搴撳瓨鐘舵�佹牎楠�
+- 璁板綍瀹屾暣璋冪敤鏃ュ織
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
+```
+
+---
+
+## Task 5: 鎵╁睍StockInfoDetailController娣诲姞缁戝畾/瑙g粦/NG涓婃姤鎺ュ彛
+
+**Files:**
+- Modify: `WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoDetailController.cs`
+
+- [ ] **Step 1: 鍦⊿tockInfoDetailController涓坊鍔燤ES鎺ュ彛鏂规硶**
+
+鍦ㄧ幇鏈塖tockInfoDetailController绫讳腑娣诲姞渚濊禆娉ㄥ叆鍜屾帴鍙f柟娉曪細
+
+```csharp
+/// <summary>
+/// MES鏃ュ織鏈嶅姟
+/// </summary>
+private readonly IMesLogService _mesLogService;
+
+/// <summary>
+/// MES鏈嶅姟
+/// </summary>
+private readonly IMesService _mesService;
+
+/// <summary>
+/// 绯荤粺閰嶇疆鏈嶅姟
+/// </summary>
+private readonly ISystemConfigService _configService;
+```
+
+娣诲姞缁戝畾鎺ュ彛锛�
+
+```csharp
+/// <summary>
+/// 鎵樼洏鐢佃姱缁戝畾 - 璋冪敤MES鎺ュ彛
+/// </summary>
+/// <param name="dto">缁戝畾璇锋眰DTO</param>
+/// <returns>鎿嶄綔缁撴灉</returns>
+[HttpPost("bindContainer")]
+[Permission("MES_BIND")]
+public async Task<WebResponseContent> BindContainer([FromBody] BindContainerRequestDto dto)
+{
+    var response = new WebResponseContent();
+    var stopwatch = System.Diagnostics.Stopwatch.StartNew();
+
+    try
+    {
+        // 1. 鍙傛暟楠岃瘉
+        if (string.IsNullOrWhiteSpace(dto.PalletCode))
+        {
+            return response.Error("鎵樼洏缂栧彿涓嶈兘涓虹┖");
+        }
+
+        if (dto.SfcList == null || !dto.SfcList.Any())
+        {
+            return response.Error("鐢佃姱鐮佸垪琛ㄤ笉鑳戒负绌�");
+        }
+
+        // 2. 鑾峰彇绯荤粺閰嶇疆
+        var equipmentCode = await _configService.GetConfigValueAsync("MES_EquipmentCode");
+        var resourceCode = await _configService.GetConfigValueAsync("MES_ResourceCode");
+
+        if (string.IsNullOrWhiteSpace(equipmentCode) || string.IsNullOrWhiteSpace(resourceCode))
+        {
+            return response.Error("MES绯荤粺閰嶇疆涓嶅畬鏁达紝璇疯仈绯荤鐞嗗憳");
+        }
+
+        // 3. 鏋勯�燤ES璇锋眰
+        var mesRequest = new BindContainerRequest
+        {
+            EquipmentCode = equipmentCode,
+            ResourceCode = resourceCode,
+            LocalTime = DateTime.Now,
+            ContainerCode = dto.PalletCode,
+            ContainerSfcList = dto.SfcList.Select(sfc => new ContainerSfcItem
+            {
+                Sfc = sfc,
+                Location = dto.Location ?? ""
+            }).ToList(),
+            OperationType = dto.OperationType
+        };
+
+        string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest);
+
+        // 4. 璋冪敤MES鎺ュ彛
+        var mesResult = await _mesService.BindContainer(mesRequest);
+        stopwatch.Stop();
+
+        // 5. 璁板綍鏃ュ織
+        await _mesLogService.LogAsync(new MesApiLogDto
+        {
+            ApiType = "BindContainer",
+            RequestJson = requestJson,
+            ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult),
+            IsSuccess = mesResult.Success,
+            ErrorMessage = mesResult.ErrorMessage,
+            ElapsedMs = (int)stopwatch.ElapsedMilliseconds,
+            Creator = UserContext.Current.UserName
+        });
+
+        // 6. 杩斿洖缁撴灉
+        if (mesResult.Success)
+        {
+            return response.OK($"鎴愬姛缁戝畾 {dto.SfcList.Count} 涓數鑺�");
+        }
+        else
+        {
+            return response.Error($"MES鎺ュ彛璋冪敤澶辫触: {mesResult.ErrorMessage}");
+        }
+    }
+    catch (System.Exception ex)
+    {
+        stopwatch.Stop();
+
+        await _mesLogService.LogAsync(new MesApiLogDto
+        {
+            ApiType = "BindContainer",
+            IsSuccess = false,
+            ErrorMessage = ex.Message,
+            ElapsedMs = (int)stopwatch.ElapsedMilliseconds,
+            Creator = UserContext.Current.UserName
+        });
+
+        return response.Error($"鐢佃姱缁戝畾澶辫触: {ex.Message}");
+    }
+}
+```
+
+娣诲姞瑙g粦鎺ュ彛锛�
+
+```csharp
+/// <summary>
+/// 鎵樼洏鐢佃姱瑙g粦 - 璋冪敤MES鎺ュ彛
+/// </summary>
+/// <param name="dto">瑙g粦璇锋眰DTO</param>
+/// <returns>鎿嶄綔缁撴灉</returns>
+[HttpPost("unbindContainer")]
+[Permission("MES_UNBIND")]
+public async Task<WebResponseContent> UnbindContainer([FromBody] UnbindContainerRequestDto dto)
+{
+    var response = new WebResponseContent();
+    var stopwatch = System.Diagnostics.Stopwatch.StartNew();
+
+    try
+    {
+        // 1. 鍙傛暟楠岃瘉
+        if (string.IsNullOrWhiteSpace(dto.PalletCode))
+        {
+            return response.Error("鎵樼洏缂栧彿涓嶈兘涓虹┖");
+        }
+
+        if (dto.SfcList == null || !dto.SfcList.Any())
+        {
+            return response.Error("鐢佃姱鐮佸垪琛ㄤ笉鑳戒负绌�");
+        }
+
+        // 2. 鑾峰彇绯荤粺閰嶇疆
+        var equipmentCode = await _configService.GetConfigValueAsync("MES_EquipmentCode");
+        var resourceCode = await _configService.GetConfigValueAsync("MES_ResourceCode");
+
+        if (string.IsNullOrWhiteSpace(equipmentCode) || string.IsNullOrWhiteSpace(resourceCode))
+        {
+            return response.Error("MES绯荤粺閰嶇疆涓嶅畬鏁达紝璇疯仈绯荤鐞嗗憳");
+        }
+
+        // 3. 鏋勯�燤ES璇锋眰
+        var mesRequest = new UnBindContainerRequest
+        {
+            EquipmentCode = equipmentCode,
+            ResourceCode = resourceCode,
+            LocalTime = DateTime.Now,
+            ContainCode = dto.PalletCode,
+            SfcList = dto.SfcList
+        };
+
+        string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest);
+
+        // 4. 璋冪敤MES鎺ュ彛
+        var mesResult = await _mesService.UnBindContainer(mesRequest);
+        stopwatch.Stop();
+
+        // 5. 璁板綍鏃ュ織
+        await _mesLogService.LogAsync(new MesApiLogDto
+        {
+            ApiType = "UnbindContainer",
+            RequestJson = requestJson,
+            ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult),
+            IsSuccess = mesResult.Success,
+            ErrorMessage = mesResult.ErrorMessage,
+            ElapsedMs = (int)stopwatch.ElapsedMilliseconds,
+            Creator = UserContext.Current.UserName
+        });
+
+        // 6. 杩斿洖缁撴灉
+        if (mesResult.Success)
+        {
+            return response.OK($"鎴愬姛瑙g粦 {dto.SfcList.Count} 涓數鑺�");
+        }
+        else
+        {
+            return response.Error($"MES鎺ュ彛璋冪敤澶辫触: {mesResult.ErrorMessage}");
+        }
+    }
+    catch (System.Exception ex)
+    {
+        stopwatch.Stop();
+
+        await _mesLogService.LogAsync(new MesApiLogDto
+        {
+            ApiType = "UnbindContainer",
+            IsSuccess = false,
+            ErrorMessage = ex.Message,
+            ElapsedMs = (int)stopwatch.ElapsedMilliseconds,
+            Creator = UserContext.Current.UserName
+        });
+
+        return response.Error($"鐢佃姱瑙g粦澶辫触: {ex.Message}");
+    }
+}
+```
+
+娣诲姞NG涓婃姤鎺ュ彛锛�
+
+```csharp
+/// <summary>
+/// 鎵樼洏NG鐢佃姱涓婃姤 - 璋冪敤MES鎺ュ彛
+/// </summary>
+/// <param name="dto">NG涓婃姤璇锋眰DTO</param>
+/// <returns>鎿嶄綔缁撴灉</returns>
+[HttpPost("containerNgReport")]
+[Permission("MES_NG_REPORT")]
+public async Task<WebResponseContent> ContainerNgReport([FromBody] ContainerNgReportRequestDto dto)
+{
+    var response = new WebResponseContent();
+    var stopwatch = System.Diagnostics.Stopwatch.StartNew();
+
+    try
+    {
+        // 1. 鍙傛暟楠岃瘉
+        if (string.IsNullOrWhiteSpace(dto.PalletCode))
+        {
+            return response.Error("鎵樼洏缂栧彿涓嶈兘涓虹┖");
+        }
+
+        if (dto.NgSfcList == null || !dto.NgSfcList.Any())
+        {
+            return response.Error("NG鐢佃姱鍒楄〃涓嶈兘涓虹┖");
+        }
+
+        // 2. 鑾峰彇绯荤粺閰嶇疆
+        var equipmentCode = await _configService.GetConfigValueAsync("MES_EquipmentCode");
+        var resourceCode = await _configService.GetConfigValueAsync("MES_ResourceCode");
+
+        if (string.IsNullOrWhiteSpace(equipmentCode) || string.IsNullOrWhiteSpace(resourceCode))
+        {
+            return response.Error("MES绯荤粺閰嶇疆涓嶅畬鏁达紝璇疯仈绯荤鐞嗗憳");
+        }
+
+        // 3. 鏋勯�燤ES璇锋眰
+        var mesRequest = new ContainerNgReportRequest
+        {
+            EquipmentCode = equipmentCode,
+            ResourceCode = resourceCode,
+            LocalTime = DateTime.Now,
+            ContainerCode = dto.PalletCode,
+            NgSfcList = dto.NgSfcList.Select(ng => new NgSfcItem
+            {
+                Sfc = ng.Sfc,
+                NgCode = ng.NgCode,
+                NgEquipmentCode = ng.NgEquipmentCode,
+                NgResourceCode = ng.NgResourceCode
+            }).ToList()
+        };
+
+        string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest);
+
+        // 4. 璋冪敤MES鎺ュ彛
+        var mesResult = await _mesService.ContainerNgReport(mesRequest);
+        stopwatch.Stop();
+
+        // 5. 璁板綍鏃ュ織
+        await _mesLogService.LogAsync(new MesApiLogDto
+        {
+            ApiType = "ContainerNgReport",
+            RequestJson = requestJson,
+            ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult),
+            IsSuccess = mesResult.Success,
+            ErrorMessage = mesResult.ErrorMessage,
+            ElapsedMs = (int)stopwatch.ElapsedMilliseconds,
+            Creator = UserContext.Current.UserName
+        });
+
+        // 6. 杩斿洖缁撴灉
+        if (mesResult.Success)
+        {
+            return response.OK($"鎴愬姛涓婃姤 {dto.NgSfcList.Count} 涓狽G鐢佃姱");
+        }
+        else
+        {
+            return response.Error($"MES鎺ュ彛璋冪敤澶辫触: {mesResult.ErrorMessage}");
+        }
+    }
+    catch (System.Exception ex)
+    {
+        stopwatch.Stop();
+
+        await _mesLogService.LogAsync(new MesApiLogDto
+        {
+            ApiType = "ContainerNgReport",
+            IsSuccess = false,
+            ErrorMessage = ex.Message,
+            ElapsedMs = (int)stopwatch.ElapsedMilliseconds,
+            Creator = UserContext.Current.UserName
+        });
+
+        return response.Error($"NG涓婃姤澶辫触: {ex.Message}");
+    }
+}
+```
+
+- [ ] **Step 2: 娣诲姞蹇呰鐨剈sing璇彞**
+
+鍦ㄦ枃浠堕《閮ㄦ坊鍔狅細
+
+```csharp
+using WIDESEA_DTO.MES;
+using WIDESEA_DTO.Mes;
+using WIDESEA_IMesService;
+```
+
+- [ ] **Step 3: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoDetailController.cs
+git commit -m "feat(MES): 搴撳瓨鏄庣粏椤甸潰娣诲姞缁戝畾/瑙g粦/NG涓婃姤鎺ュ彛
+
+- POST /api/StockInfoDetail/bindContainer 鎵樼洏鐢佃姱缁戝畾
+- POST /api/StockInfoDetail/unbindContainer 鎵樼洏鐢佃姱瑙g粦
+- POST /api/StockInfoDetail/containerNgReport NG鐢佃姱涓婃姤
+- 璁板綍瀹屾暣璋冪敤鏃ュ織
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
+```
+
+---
+
+## Task 6: 鍒涘缓鍓嶇MES API璋冪敤妯″潡
+
+**Files:**
+- Create: `WMS/WIDESEA_WMSClient/src/api/mes.js`
+
+- [ ] **Step 1: 鍒涘缓MES API妯″潡**
+
+```javascript
+/**
+ * MES鎺ュ彛API妯″潡
+ */
+import axios from 'axios';
+
+const baseURL = '/api';
+
+// 搴撳瓨淇℃伅鐩稿叧MES鎺ュ彛
+export const stockInfoMesApi = {
+  /**
+   * 鎵樼洏杩涚珯
+   * @param {Object} data - 璇锋眰鏁版嵁 { palletCode, stockId }
+   * @returns {Promise}
+   */
+  inboundInContainer(data) {
+    return axios.post(`${baseURL}/StockInfo/inboundInContainer`, data);
+  },
+
+  /**
+   * 鎵樼洏鍑虹珯
+   * @param {Object} data - 璇锋眰鏁版嵁 { palletCode, stockId, paramList }
+   * @returns {Promise}
+   */
+  outboundInContainer(data) {
+    return axios.post(`${baseURL}/StockInfo/outboundInContainer`, data);
+  }
+};
+
+// 搴撳瓨鏄庣粏鐩稿叧MES鎺ュ彛
+export const stockDetailMesApi = {
+  /**
+   * 鎵樼洏鐢佃姱缁戝畾
+   * @param {Object} data - 璇锋眰鏁版嵁 { palletCode, sfcList, location, operationType }
+   * @returns {Promise}
+   */
+  bindContainer(data) {
+    return axios.post(`${baseURL}/StockInfoDetail/bindContainer`, data);
+  },
+
+  /**
+   * 鎵樼洏鐢佃姱瑙g粦
+   * @param {Object} data - 璇锋眰鏁版嵁 { palletCode, sfcList }
+   * @returns {Promise}
+   */
+  unbindContainer(data) {
+    return axios.post(`${baseURL}/StockInfoDetail/unbindContainer`, data);
+  },
+
+  /**
+   * 鎵樼洏NG鐢佃姱涓婃姤
+   * @param {Object} data - 璇锋眰鏁版嵁 { palletCode, ngSfcList }
+   * @returns {Promise}
+   */
+  containerNgReport(data) {
+    return axios.post(`${baseURL}/StockInfoDetail/containerNgReport`, data);
+  }
+};
+
+export default {
+  stockInfo: stockInfoMesApi,
+  stockDetail: stockDetailMesApi
+};
+```
+
+- [ ] **Step 2: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSClient/src/api/mes.js
+git commit -m "feat(MES): 娣诲姞鍓嶇MES API璋冪敤妯″潡
+
+- 灏佽搴撳瓨淇℃伅杩涚珯/鍑虹珯鎺ュ彛
+- 灏佽搴撳瓨鏄庣粏缁戝畾/瑙g粦/NG涓婃姤鎺ュ彛
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
+```
+
+---
+
+## Task 7: 鍒涘缓MES纭瀵硅瘽妗嗙粍浠�
+
+**Files:**
+- Create: `WMS/WIDESEA_WMSClient/src/components/MesConfirmDialog.vue`
+
+- [ ] **Step 1: 鍒涘缓纭瀵硅瘽妗嗙粍浠�**
+
+```vue
+<template>
+  <el-dialog
+    v-model="visible"
+    :title="dialogTitle"
+    width="500px"
+    :close-on-click-modal="false"
+    @close="handleClose"
+  >
+    <div class="mes-confirm-content">
+      <p class="operation-text">{{ operationText }}</p>
+
+      <div class="info-section">
+        <div class="info-row" v-for="(item, index) in displayInfo" :key="index">
+          <span class="info-label">{{ item.label }}:</span>
+          <span class="info-value">{{ item.value }}</span>
+        </div>
+      </div>
+
+      <div v-if="errorMessage" class="error-message">
+        <el-icon><Warning /></el-icon>
+        <span>{{ errorMessage }}</span>
+      </div>
+    </div>
+
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="handleClose">鍙栨秷</el-button>
+        <el-button
+          type="primary"
+          :loading="loading"
+          @click="handleConfirm"
+        >
+          纭鎵ц
+        </el-button>
+      </span>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+import { ref, computed } from 'vue';
+import { Warning } from '@element-plus/icons-vue';
+import { ElMessage } from 'element-plus';
+
+export default {
+  name: 'MesConfirmDialog',
+
+  components: {
+    Warning
+  },
+
+  props: {
+    modelValue: {
+      type: Boolean,
+      default: false
+    },
+    operationType: {
+      type: String,
+      required: true
+      },
+    palletCode: {
+      type: String,
+      required: true
+    },
+    stockInfo: {
+      type: Object,
+      default: null
+    },
+    detailInfo: {
+      type: Object,
+      default: null
+    }
+  },
+
+  emits: ['update:modelValue', 'confirm'],
+
+  setup(props, { emit }) {
+    const visible = computed({
+      get: () => props.modelValue,
+      set: (val) => emit('update:modelValue', val)
+    });
+
+    const loading = ref(false);
+    const errorMessage = ref('');
+
+    const operationConfig = {
+      inbound: { title: '鎵樼洏杩涚珯', text: '鎮ㄥ嵆灏嗘墽琛屾墭鐩樿繘绔欐搷浣�' },
+      outbound: { title: '鎵樼洏鍑虹珯', text: '鎮ㄥ嵆灏嗘墽琛屾墭鐩樺嚭绔欐搷浣�' },
+      bind: { title: '鐢佃姱缁戝畾', text: '鎮ㄥ嵆灏嗘墽琛岀數鑺粦瀹氭搷浣�' },
+      unbind: { title: '鐢佃姱瑙g粦', text: '鎮ㄥ嵆灏嗘墽琛岀數鑺В缁戞搷浣�' },
+      ngReport: { title: 'NG涓婃姤', text: '鎮ㄥ嵆灏嗘墽琛孨G鐢佃姱涓婃姤鎿嶄綔' }
+    };
+
+    const dialogTitle = computed(() => {
+      return operationConfig[props.operationType]?.title || '纭鎿嶄綔';
+    });
+
+    const operationText = computed(() => {
+      return operationConfig[props.operationType]?.text || '';
+    });
+
+    const displayInfo = computed(() => {
+      const info = [
+        { label: '鎵樼洏鐮�', value: props.palletCode }
+      ];
+
+      if (props.detailInfo) {
+        info.push({ label: '鐢佃姱鏁伴噺', value: props.detailInfo.sfcCount || '-' });
+      }
+
+      return info;
+    });
+
+    const handleClose = () => {
+      visible.value = false;
+      errorMessage.value = '';
+    };
+
+    const handleConfirm = async () => {
+      loading.value = true;
+      errorMessage.value = '';
+
+      try {
+        emit('confirm', {
+          operationType: props.operationType,
+          palletCode: props.palletCode,
+          stockInfo: props.stockInfo,
+          detailInfo: props.detailInfo,
+          onSuccess: () => {
+            visible.value = false;
+            loading.value = false;
+          },
+          onError: (error) => {
+            errorMessage.value = error;
+            loading.value = false;
+          }
+        });
+      } catch (error) {
+        errorMessage.value = error.message || '鎿嶄綔澶辫触';
+        loading.value = false;
+      }
+    };
+
+    return {
+      visible,
+      loading,
+      errorMessage,
+      dialogTitle,
+      operationText,
+      displayInfo,
+      handleClose,
+      handleConfirm
+    };
+  }
+};
+</script>
+
+<style scoped>
+.mes-confirm-content {
+  padding: 10px 0;
+}
+
+.operation-text {
+  font-size: 14px;
+  color: #303133;
+  margin-bottom: 20px;
+  font-weight: 500;
+}
+
+.info-section {
+  background: #f8fafc;
+  border-radius: 8px;
+  padding: 16px;
+  margin-bottom: 16px;
+}
+
+.info-row {
+  display: flex;
+  margin-bottom: 12px;
+  font-size: 14px;
+}
+
+.info-row:last-child {
+  margin-bottom: 0;
+}
+
+.info-label {
+  color: #909399;
+  width: 80px;
+  flex-shrink: 0;
+}
+
+.info-value {
+  color: #303133;
+  font-weight: 500;
+}
+
+.error-message {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  padding: 12px;
+  background: #fef0f0;
+  border: 1px solid #fde2e2;
+  border-radius: 6px;
+  color: #f56c6c;
+  font-size: 14px;
+}
+
+.error-message .el-icon {
+  font-size: 18px;
+}
+</style>
+```
+
+- [ ] **Step 2: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSClient/src/components/MesConfirmDialog.vue
+git commit -m "feat(MES): 娣诲姞MES鎿嶄綔纭瀵硅瘽妗嗙粍浠�
+
+- 鏀寔澶氱鎿嶄綔绫诲瀷锛堣繘绔欍�佸嚭绔欍�佺粦瀹氥�佽В缁戙�丯G涓婃姤锛�
+- 鏄剧ず鍏抽敭淇℃伅锛堟墭鐩樼爜銆佺數鑺暟閲忕瓑锛�
+- 閿欒鐘舵�佸睍绀�
+- 纭/鍙栨秷鎿嶄綔
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
+```
+
+---
+
+## Task 8: 淇敼stockInfo.vue娣诲姞鎿嶄綔鍒�
+
+**Files:**
+- Modify: `WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue`
+
+- [ ] **Step 1: 鍦╯cript涓坊鍔犵粍浠跺紩鍏ュ拰鏂规硶**
+
+鍦ㄧ幇鏈夌殑script setup涓坊鍔狅細
+
+```javascript
+import MesConfirmDialog from '@/components/MesConfirmDialog.vue';
+import { stockInfoMesApi } from '@/api/mes';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import { ref } from 'vue';
+
+// MES瀵硅瘽妗嗙姸鎬�
+const mesDialogVisible = ref(false);
+const currentOperationType = ref('');
+const currentStockRow = ref(null);
+const mesLoading = ref(false);
+
+// 鎵撳紑MES纭瀵硅瘽妗�
+const openMesDialog = (operationType, row) => {
+  currentOperationType.value = operationType;
+  currentStockRow.value = row;
+  mesDialogVisible.value = true;
+};
+
+// 澶勭悊MES纭
+const handleMesConfirm = async ({ onSuccess, onError }) => {
+  const row = currentStockRow.value;
+  const operationType = currentOperationType.value;
+
+  try {
+    let result;
+
+    switch (operationType) {
+      case 'inbound':
+        result = await stockInfoMesApi.inboundInContainer({
+          palletCode: row.palletCode,
+          stockId: row.id
+        });
+        break;
+      case 'outbound':
+        result = await stockInfoMesApi.outboundInContainer({
+          palletCode: row.palletCode,
+          stockId: row.id
+        });
+        break;
+    }
+
+    if (result.data.status) {
+      ElMessage.success(result.data.message || '鎿嶄綔鎴愬姛');
+      onSuccess();
+      // 鍒锋柊鍒楄〃
+      proxy.$refs.grid.load();
+    } else {
+      onError(result.data.message || '鎿嶄綔澶辫触');
+    }
+  } catch (error) {
+    onError(error.response?.data?.message || error.message || '缃戠粶閿欒锛岃绋嶅悗閲嶈瘯');
+  }
+};
+
+// 妫�鏌ユ寜閽槸鍚﹀簲璇ユ樉绀�
+const shouldShowButton = (buttonType, row) => {
+  const status = row.status; // 0=寰呭叆搴�, 1=鍦ㄥ簱, 2=鍑哄簱涓�, 3=閿佸畾
+
+  switch (buttonType) {
+    case 'inbound':
+      return status === 0; // 浠呭緟鍏ュ簱鏄剧ず杩涚珯
+    case 'outbound':
+      return status === 1 || status === 2; // 鍦ㄥ簱鎴栧嚭搴撲腑鏄剧ず鍑虹珯
+    default:
+      return false;
+  }
+};
+```
+
+- [ ] **Step 2: 鍦╟olumns涓坊鍔犳搷浣滃垪**
+
+鍦ㄧ幇鏈夌殑columns ref瀹氫箟涓坊鍔犳搷浣滃垪锛堝湪鏈�鍚庢坊鍔狅級锛�
+
+```javascript
+const columns = ref([
+  // ... 鐜版湁鍒楀畾涔� ...
+  {
+    field: "actions",
+    title: "鎿嶄綔",
+    width: 200,
+    fixed: "right",
+    align: "center",
+    formatter: (row) => {
+      const buttons = [];
+
+      if (shouldShowButton('inbound', row)) {
+        buttons.push(
+          `<el-button type="primary" size="small" onclick="window.handleInbound(${row.id})">杩涚珯</el-button>`
+        );
+      }
+
+      if (shouldShowButton('outbound', row)) {
+        buttons.push(
+          `<el-button type="success" size="small" onclick="window.handleOutbound(${row.id})">鍑虹珯</el-button>`
+        );
+      }
+
+      return buttons.join(' ');
+    }
+  }
+]);
+```
+
+- [ ] **Step 3: 鍦ㄦā鏉夸腑娣诲姞瀵硅瘽妗嗙粍浠�**
+
+鍦╰emplate涓殑view-grid鏍囩鍚庢坊鍔狅細
+
+```vue
+<template>
+  <view-grid ... >
+  </view-grid>
+
+  <!-- MES纭瀵硅瘽妗� -->
+  <MesConfirmDialog
+    v-model="mesDialogVisible"
+    :operation-type="currentOperationType"
+    :pallet-code="currentStockRow?.palletCode"
+    :stock-info="currentStockRow"
+    @confirm="handleMesConfirm"
+  />
+</template>
+```
+
+- [ ] **Step 4: 娣诲姞鍏ㄥ眬鏂规硶鐢ㄤ簬HTML瀛楃涓蹭腑鐨刼nclick**
+
+鍦╯etup鐨勬渶鍚庢坊鍔狅細
+
+```javascript
+// 鎸傝浇鍒皐indow渚汬TML瀛楃涓蹭腑鐨刼nclick浣跨敤
+window.handleInbound = (id) => {
+  const row = proxy.$refs.grid.tableData.find(item => item.id === id);
+  if (row) openMesDialog('inbound', row);
+};
+
+window.handleOutbound = (id) => {
+  const row = proxy.$refs.grid.tableData.find(item => item.id === id);
+  if (row) openMesDialog('outbound', row);
+};
+```
+
+- [ ] **Step 5: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue
+git commit -m "feat(MES): 搴撳瓨淇℃伅椤甸潰娣诲姞杩涚珯/鍑虹珯鎿嶄綔鍒�
+
+- 娣诲姞鎿嶄綔鍒楋紝鏍规嵁搴撳瓨鐘舵�佸姩鎬佹樉绀烘寜閽�
+- 寰呭叆搴撶姸鎬佹樉绀鸿繘绔欐寜閽�
+- 鍦ㄥ簱/鍑哄簱涓姸鎬佹樉绀哄嚭绔欐寜閽�
+- 闆嗘垚MES纭瀵硅瘽妗�
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
+```
+
+---
+
+## Task 9: 淇敼stockInfoDetail.vue娣诲姞鎿嶄綔鍒�
+
+**Files:**
+- Modify: `WMS/WIDESEA_WMSClient/src/views/stock/stockInfoDetail.vue`
+
+- [ ] **Step 1: 鍦╯cript涓坊鍔犵粍浠跺紩鍏ュ拰鏂规硶**
+
+鍦ㄧ幇鏈夌殑script setup涓坊鍔狅細
+
+```javascript
+import MesConfirmDialog from '@/components/MesConfirmDialog.vue';
+import { stockDetailMesApi } from '@/api/mes';
+import { ElMessage } from 'element-plus';
+import { ref } from 'vue';
+
+// MES瀵硅瘽妗嗙姸鎬�
+const mesDialogVisible = ref(false);
+const currentOperationType = ref('');
+const currentDetailRow = ref(null);
+const mesLoading = ref(false);
+
+// 鎵撳紑MES纭瀵硅瘽妗�
+const openMesDialog = (operationType, row) => {
+  currentOperationType.value = operationType;
+  currentDetailRow.value = row;
+  mesDialogVisible.value = true;
+};
+
+// 澶勭悊MES纭
+const handleMesConfirm = async ({ onSuccess, onError }) => {
+  const row = currentDetailRow.value;
+  const operationType = currentOperationType.value;
+
+  try {
+    let result;
+
+    switch (operationType) {
+      case 'bind':
+        result = await stockDetailMesApi.bindContainer({
+          palletCode: row.palletCode || 'P001', // 闇�瑕佷粠搴撳瓨淇℃伅鑾峰彇
+          sfcList: [row.serialNumber],
+          location: row.location || '',
+          operationType: 1
+        });
+        break;
+      case 'unbind':
+        result = await stockDetailMesApi.unbindContainer({
+          palletCode: row.palletCode || 'P001',
+          sfcList: [row.serialNumber]
+        });
+        break;
+      case 'ngReport':
+        result = await stockDetailMesApi.containerNgReport({
+          palletCode: row.palletCode || 'P001',
+          ngSfcList: [{
+            sfc: row.serialNumber,
+            ngCode: 'NG001',
+            ngEquipmentCode: 'WCS_001',
+            ngResourceCode: 'RESOURCE_001'
+          }]
+        });
+        break;
+    }
+
+    if (result.data.status) {
+      ElMessage.success(result.data.message || '鎿嶄綔鎴愬姛');
+      onSuccess();
+      proxy.$refs.grid.load();
+    } else {
+      onError(result.data.message || '鎿嶄綔澶辫触');
+    }
+  } catch (error) {
+    onError(error.response?.data?.message || error.message || '缃戠粶閿欒锛岃绋嶅悗閲嶈瘯');
+  }
+};
+
+// 妫�鏌ユ寜閽槸鍚﹀簲璇ユ樉绀�
+const shouldShowButton = (row) => {
+  const status = row.status; // 1=姝e父, 2=寮傚父, 99=宸查攣瀹�
+  return status !== 99; // 闈�"宸查攣瀹�"鐘舵�佹樉绀烘墍鏈夋寜閽�
+};
+```
+
+- [ ] **Step 2: 鍦╟olumns涓坊鍔犳搷浣滃垪**
+
+鍦ㄧ幇鏈夌殑columns ref瀹氫箟涓坊鍔犳搷浣滃垪锛堝湪鏈�鍚庢坊鍔狅級锛�
+
+```javascript
+const columns = ref([
+  // ... 鐜版湁鍒楀畾涔� ...
+  {
+    field: "actions",
+    title: "鎿嶄綔",
+    width: 280,
+    fixed: "right",
+    align: "center",
+    formatter: (row) => {
+      if (!shouldShowButton(row)) {
+        return '<span class="text-muted">鏆傛棤鍙墽琛屾搷浣�</span>';
+      }
+
+      return `
+        <el-button type="primary" size="small" onclick="window.handleBind(${row.id})">缁戝畾</el-button>
+        <el-button type="warning" size="small" onclick="window.handleUnbind(${row.id})">瑙g粦</el-button>
+        <el-button type="danger" size="small" onclick="window.handleNgReport(${row.id})">NG涓婃姤</el-button>
+      `;
+    }
+  }
+]);
+```
+
+- [ ] **Step 3: 鍦ㄦā鏉夸腑娣诲姞瀵硅瘽妗嗙粍浠�**
+
+鍦╰emplate涓殑view-grid鏍囩鍚庢坊鍔狅細
+
+```vue
+<template>
+  <view-grid ... >
+  </view-grid>
+
+  <!-- MES纭瀵硅瘽妗� -->
+  <MesConfirmDialog
+    v-model="mesDialogVisible"
+    :operation-type="currentOperationType"
+    :pallet-code="currentDetailRow?.palletCode"
+    :detail-info="{ sfcCount: 1 }"
+    @confirm="handleMesConfirm"
+  />
+</template>
+```
+
+- [ ] **Step 4: 娣诲姞鍏ㄥ眬鏂规硶**
+
+鍦╯etup鐨勬渶鍚庢坊鍔狅細
+
+```javascript
+window.handleBind = (id) => {
+  const row = proxy.$refs.grid.tableData.find(item => item.id === id);
+  if (row) openMesDialog('bind', row);
+};
+
+window.handleUnbind = (id) => {
+  const row = proxy.$refs.grid.tableData.find(item => item.id === id);
+  if (row) openMesDialog('unbind', row);
+};
+
+window.handleNgReport = (id) => {
+  const row = proxy.$refs.grid.tableData.find(item => item.id === id);
+  if (row) openMesDialog('ngReport', row);
+};
+```
+
+- [ ] **Step 5: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSClient/src/views/stock/stockInfoDetail.vue
+git commit -m "feat(MES): 搴撳瓨鏄庣粏椤甸潰娣诲姞缁戝畾/瑙g粦/NG涓婃姤鎿嶄綔鍒�
+
+- 娣诲姞鎿嶄綔鍒楋紝鏍规嵁鐢佃姱鐘舵�佸姩鎬佹樉绀烘寜閽�
+- 闈為攣瀹氱姸鎬佹樉绀虹粦瀹氥�佽В缁戙�丯G涓婃姤鎸夐挳
+- 闆嗘垚MES纭瀵硅瘽妗�
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
+```
+
+---
+
+## 娴嬭瘯妫�鏌ユ竻鍗�
+
+瀹屾垚浠ヤ笂鎵�鏈変换鍔″悗锛岃繘琛屼互涓嬫祴璇曪細
+
+### 鍚庣娴嬭瘯
+
+- [ ] 楠岃瘉鏁版嵁搴撹〃 Dt_MesApiLog 宸插垱寤�
+- [ ] 楠岃瘉绯荤粺閰嶇疆宸叉彃鍏�
+- [ ] 娴嬭瘯杩涚珯鎺ュ彛锛圥ostman鎴朣wagger锛�
+- [ ] 娴嬭瘯鍑虹珯鎺ュ彛
+- [ ] 娴嬭瘯缁戝畾鎺ュ彛
+- [ ] 娴嬭瘯瑙g粦鎺ュ彛
+- [ ] 娴嬭瘯NG涓婃姤鎺ュ彛
+- [ ] 楠岃瘉鏃ュ織璁板綍姝g‘
+
+### 鍓嶇娴嬭瘯
+
+- [ ] 搴撳瓨淇℃伅椤甸潰鎿嶄綔鍒楁甯告樉绀�
+- [ ] 鎸夐挳鏍规嵁鐘舵�佹纭樉绀�/闅愯棌
+- [ ] 鐐瑰嚮鎸夐挳寮瑰嚭纭瀵硅瘽妗�
+- [ ] 纭鍚庢垚鍔熻皟鐢ㄦ帴鍙�
+- [ ] 鎴愬姛鍚庡埛鏂板垪琛�
+- [ ] 澶辫触鍚庢樉绀洪敊璇彁绀�
+- [ ] 搴撳瓨鏄庣粏椤甸潰鎿嶄綔鍒楁甯告樉绀�
+- [ ] 鎵�鏈夋寜閽姛鑳芥甯�
+
+### 闆嗘垚娴嬭瘯
+
+- [ ] 瀹屾暣娴佺▼娴嬭瘯锛堢偣鍑烩啋纭鈫掓墽琛屸啋缁撴灉锛�
+- [ ] 缃戠粶寮傚父澶勭悊
+- [ ] MES鏈嶅姟寮傚父澶勭悊
+- [ ] 鏉冮檺鎺у埗娴嬭瘯
+
+---
+
+## 澶囨敞
+
+1. **鐘舵�佸�兼槧灏�**锛氫唬鐮佷腑浣跨敤鐨勭姸鎬佸�硷紙0=寰呭叆搴�, 1=鍦ㄥ簱绛夛級闇�瑕佹牴鎹疄闄呮灇涓惧�艰皟鏁�
+2. **鎵樼洏鐮佽幏鍙�**锛氬簱瀛樻槑缁嗛〉闈腑闇�瑕侀�氳繃stockId鍏宠仈鑾峰彇鎵樼洏鐮�
+3. **鏉冮檺閰嶇疆**锛氶渶瑕佸湪绯荤粺涓坊鍔燤ES鐩稿叧鏉冮檺椤�
+4. **MES鎺ュ彛鍦板潃**锛氬湪绯荤粺閰嶇疆涓缃纭殑MES鎺ュ彛鍦板潃
+5. **閿欒澶勭悊**锛氭牴鎹疄闄匨ES杩斿洖鐨勯敊璇爜璋冩暣鎻愮ず淇℃伅

--
Gitblit v1.9.3