From 1515ffa15c11e106f35e1447bc990b7867c449bb Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期四, 16 四月 2026 16:07:14 +0800
Subject: [PATCH] feat(Robot): 机械手换盘任务特殊处理

---
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs  |  126 ++
 Code/.omc/state/mission-state.json                                                          |  128 +++
 Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json                               |    6 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/FakeBatteryPositionRepository.cs   |   12 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IFakeBatteryPositionRepository.cs |    7 
 Code/.omc/state/agent-replay-358cfb75-d493-40fb-94ed-f795f943182b.jsonl                     |   17 
 Code/.omc/state/checkpoints/checkpoint-2026-04-16T05-56-05-020Z.json                        |   16 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs                            |    2 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs  |  267 ++++++-
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IFakeBatteryPositionService.cs       |    7 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs                  |  119 +++
 /dev/null                                                                                   |    0 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs                    |   22 
 Code/docs/superpowers/specs/2026-04-16-change-pallet-batch-command-design.md                |  180 +++++
 Code/.omc/state/idle-notif-cooldown.json                                                    |    2 
 Code/.omc/state/last-tool-error.json                                                        |    6 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/FakeBatteryPositionService.cs         |    6 
 Code/docs/superpowers/plans/2026-04-16-change-pallet-batch-command.md                       | 1054 +++++++++++++++++++++++++++++
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs  |   66 +
 项目资料/设备协议/机械手协议/交互流程表(1).xlsx                                                               |    0 
 Code/.omc/state/subagent-tracking.json                                                      |   72 +
 项目资料/技术协议/~$验证平台物流仓储系统技术规格书-11.24.docx                                                      |    0 
 22 files changed, 2,019 insertions(+), 96 deletions(-)

diff --git a/Code/.omc/state/agent-replay-358cfb75-d493-40fb-94ed-f795f943182b.jsonl b/Code/.omc/state/agent-replay-358cfb75-d493-40fb-94ed-f795f943182b.jsonl
new file mode 100644
index 0000000..6180175
--- /dev/null
+++ b/Code/.omc/state/agent-replay-358cfb75-d493-40fb-94ed-f795f943182b.jsonl
@@ -0,0 +1,17 @@
+{"t":0,"agent":"system","event":"skill_invoked","skill_name":"superpowers:brainstorming"}
+{"t":0,"agent":"aab4d29","agent_type":"code-reviewer","event":"agent_start","parent_mode":"none"}
+{"t":0,"agent":"aab4d29","agent_type":"code-reviewer","event":"agent_stop","success":true,"duration_ms":301448}
+{"t":0,"agent":"a3ca65d","agent_type":"code-reviewer","event":"agent_start","parent_mode":"none"}
+{"t":0,"agent":"a3ca65d","agent_type":"code-reviewer","event":"agent_stop","success":true,"duration_ms":110707}
+{"t":0,"agent":"system","event":"skill_invoked","skill_name":"superpowers:writing-plans"}
+{"t":0,"agent":"a8078d8","agent_type":"code-reviewer","event":"agent_start","parent_mode":"none"}
+{"t":0,"agent":"a8078d8","agent_type":"code-reviewer","event":"agent_stop","success":true,"duration_ms":48817}
+{"t":0,"agent":"a789651","agent_type":"code-reviewer","event":"agent_start","parent_mode":"none"}
+{"t":0,"agent":"a789651","agent_type":"code-reviewer","event":"agent_stop","success":true,"duration_ms":363405}
+{"t":0,"agent":"system","event":"skill_invoked","skill_name":"superpowers:subagent-driven-development"}
+{"t":0,"agent":"a9cfe1f","agent_type":"unknown","event":"agent_stop","success":true}
+{"t":0,"agent":"a089308","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"}
+{"t":0,"agent":"a089308","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":171986}
+{"t":0,"agent":"a4b1abc","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"}
+{"t":0,"agent":"ab8096e","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"}
+{"t":0,"agent":"adc57d5","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"}
diff --git a/Code/.omc/state/checkpoints/checkpoint-2026-04-16T05-56-05-020Z.json b/Code/.omc/state/checkpoints/checkpoint-2026-04-16T05-56-05-020Z.json
new file mode 100644
index 0000000..49ba28b
--- /dev/null
+++ b/Code/.omc/state/checkpoints/checkpoint-2026-04-16T05-56-05-020Z.json
@@ -0,0 +1,16 @@
+{
+  "created_at": "2026-04-16T05:56:05.018Z",
+  "trigger": "auto",
+  "active_modes": {},
+  "todo_summary": {
+    "pending": 0,
+    "in_progress": 0,
+    "completed": 0
+  },
+  "wisdom_exported": false,
+  "background_jobs": {
+    "active": [],
+    "recent": [],
+    "stats": null
+  }
+}
\ No newline at end of file
diff --git a/Code/.omc/state/idle-notif-cooldown.json b/Code/.omc/state/idle-notif-cooldown.json
index 83bb211..2f67d58 100644
--- a/Code/.omc/state/idle-notif-cooldown.json
+++ b/Code/.omc/state/idle-notif-cooldown.json
@@ -1,3 +1,3 @@
 {
-  "lastSentAt": "2026-04-15T14:42:46.838Z"
+  "lastSentAt": "2026-04-16T07:39:40.298Z"
 }
\ No newline at end of file
diff --git a/Code/.omc/state/last-tool-error.json b/Code/.omc/state/last-tool-error.json
index 8d171f3..d1b457d 100644
--- a/Code/.omc/state/last-tool-error.json
+++ b/Code/.omc/state/last-tool-error.json
@@ -1,7 +1,7 @@
 {
   "tool_name": "Bash",
-  "tool_input_preview": "{\"command\":\"dotnet build D:/Git/ShanMeiXinNengYuan/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server.sln\",\"timeout\":300000,\"description\":\"Build WCS solution to verify fix\"}",
-  "error": "Exit code 1\n  姝e湪纭畾瑕佽繕鍘熺殑椤圭洰鈥r\n  鎵�鏈夐」鐩潎鏄渶鏂扮殑锛屾棤娉曡繕鍘熴�俓r\n  WIDESEAWCS_Common -> D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\bin\\Debug\\net8.0\\WIDESEAWCS_Common.dll\r\nD:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Communicator\\AllenBrandly\\AllenBrandlyEtherNetCommunicator.cs(110,80): warning CS1570: XML 娉ㄩ噴鍑虹幇 XML 鏍煎紡閿欒 --鈥滅粨鏉熸爣璁扳�減aram鈥濅笌寮�濮嬫爣璁扳�淭鈥濅笉鍖归厤銆傗�� [D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Communicator\\WIDESEAWCS_Communicator.csproj]\r\nD:\\Git\\ShanM...",
-  "timestamp": "2026-04-15T14:12:47.386Z",
+  "tool_input_preview": "{\"command\":\"cd /d D:\\\\Git\\\\ShanMeiXinNengYuan\\\\Code\\\\WCS\\\\WIDESEAWCS_Server && dotnet build WIDESEAWCS_Server.sln 2>&1\",\"timeout\":120000,\"description\":\"Build WCS solution to verify changes\"}",
+  "error": "Exit code 1\n/usr/bin/bash: line 1: cd: too many arguments",
+  "timestamp": "2026-04-16T06:02:11.459Z",
   "retry_count": 1
 }
\ No newline at end of file
diff --git a/Code/.omc/state/mission-state.json b/Code/.omc/state/mission-state.json
index 46bc1bf..d5e5e41 100644
--- a/Code/.omc/state/mission-state.json
+++ b/Code/.omc/state/mission-state.json
@@ -1,5 +1,5 @@
 {
-  "updatedAt": "2026-04-15T14:16:41.286Z",
+  "updatedAt": "2026-04-16T06:05:51.361Z",
   "missions": [
     {
       "id": "session:9007b9ea-1eb6-4d24-8fe7-2c3a949eac88:none",
@@ -620,6 +620,132 @@
           "sourceKey": "session-stop:a991ee262522932f5"
         }
       ]
+    },
+    {
+      "id": "session:358cfb75-d493-40fb-94ed-f795f943182b:none",
+      "source": "session",
+      "name": "none",
+      "objective": "Session mission",
+      "createdAt": "2026-04-16T02:59:26.042Z",
+      "updatedAt": "2026-04-16T06:05:51.361Z",
+      "status": "running",
+      "workerCount": 8,
+      "taskCounts": {
+        "total": 8,
+        "pending": 0,
+        "blocked": 0,
+        "inProgress": 3,
+        "completed": 5,
+        "failed": 0
+      },
+      "agents": [
+        {
+          "name": "code-reviewer:aab4d29",
+          "role": "code-reviewer",
+          "ownership": "aab4d29faa1a3cd33",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-16T05:57:18.762Z"
+        },
+        {
+          "name": "code-reviewer:a3ca65d",
+          "role": "code-reviewer",
+          "ownership": "a3ca65d5e9e566acc",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-16T03:21:01.279Z"
+        },
+        {
+          "name": "code-reviewer:a8078d8",
+          "role": "code-reviewer",
+          "ownership": "a8078d862c25a2973",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-16T05:40:16.461Z"
+        },
+        {
+          "name": "code-reviewer:a789651",
+          "role": "code-reviewer",
+          "ownership": "a78965129a4ecaee2",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-16T05:50:59.155Z"
+        },
+        {
+          "name": "general-purpose:a089308",
+          "role": "general-purpose",
+          "ownership": "a089308fce13261b6",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-16T06:00:35.344Z"
+        },
+        {
+          "name": "general-purpose:a4b1abc",
+          "role": "general-purpose",
+          "ownership": "a4b1abcbbe45f220a",
+          "status": "running",
+          "currentStep": null,
+          "latestUpdate": null,
+          "completedSummary": null,
+          "updatedAt": "2026-04-16T06:00:51.582Z"
+        },
+        {
+          "name": "general-purpose:ab8096e",
+          "role": "general-purpose",
+          "ownership": "ab8096ee80268e720",
+          "status": "running",
+          "currentStep": null,
+          "latestUpdate": null,
+          "completedSummary": null,
+          "updatedAt": "2026-04-16T06:05:29.655Z"
+        },
+        {
+          "name": "general-purpose:adc57d5",
+          "role": "general-purpose",
+          "ownership": "adc57d5ba6bbc20c1",
+          "status": "running",
+          "currentStep": null,
+          "latestUpdate": null,
+          "completedSummary": null,
+          "updatedAt": "2026-04-16T06:05:51.361Z"
+        }
+      ],
+      "timeline": [
+        {
+          "id": "session-start:a4b1abcbbe45f220a:2026-04-16T06:00:51.582Z",
+          "at": "2026-04-16T06:00:51.582Z",
+          "kind": "update",
+          "agent": "general-purpose:a4b1abc",
+          "detail": "started general-purpose:a4b1abc",
+          "sourceKey": "session-start:a4b1abcbbe45f220a"
+        },
+        {
+          "id": "session-start:ab8096ee80268e720:2026-04-16T06:05:29.655Z",
+          "at": "2026-04-16T06:05:29.655Z",
+          "kind": "update",
+          "agent": "general-purpose:ab8096e",
+          "detail": "started general-purpose:ab8096e",
+          "sourceKey": "session-start:ab8096ee80268e720"
+        },
+        {
+          "id": "session-start:adc57d5ba6bbc20c1:2026-04-16T06:05:51.361Z",
+          "at": "2026-04-16T06:05:51.361Z",
+          "kind": "update",
+          "agent": "general-purpose:adc57d5",
+          "detail": "started general-purpose:adc57d5",
+          "sourceKey": "session-start:adc57d5ba6bbc20c1"
+        }
+      ]
     }
   ]
 }
\ No newline at end of file
diff --git a/Code/.omc/state/subagent-tracking.json b/Code/.omc/state/subagent-tracking.json
index 8ac075d..3a94e90 100644
--- a/Code/.omc/state/subagent-tracking.json
+++ b/Code/.omc/state/subagent-tracking.json
@@ -377,10 +377,76 @@
       "status": "completed",
       "completed_at": "2026-04-15T14:16:41.286Z",
       "duration_ms": 246360
+    },
+    {
+      "agent_id": "aab4d29faa1a3cd33",
+      "agent_type": "code-reviewer",
+      "started_at": "2026-04-16T02:59:26.042Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-16T03:04:27.490Z",
+      "duration_ms": 301448
+    },
+    {
+      "agent_id": "a3ca65d5e9e566acc",
+      "agent_type": "code-reviewer",
+      "started_at": "2026-04-16T03:19:10.572Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-16T03:21:01.279Z",
+      "duration_ms": 110707
+    },
+    {
+      "agent_id": "a8078d862c25a2973",
+      "agent_type": "code-reviewer",
+      "started_at": "2026-04-16T05:39:27.644Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-16T05:40:16.461Z",
+      "duration_ms": 48817
+    },
+    {
+      "agent_id": "a78965129a4ecaee2",
+      "agent_type": "code-reviewer",
+      "started_at": "2026-04-16T05:44:55.750Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-16T05:50:59.155Z",
+      "duration_ms": 363405
+    },
+    {
+      "agent_id": "a089308fce13261b6",
+      "agent_type": "general-purpose",
+      "started_at": "2026-04-16T05:57:43.358Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-16T06:00:35.344Z",
+      "duration_ms": 171986
+    },
+    {
+      "agent_id": "a4b1abcbbe45f220a",
+      "agent_type": "general-purpose",
+      "started_at": "2026-04-16T06:00:51.582Z",
+      "parent_mode": "none",
+      "status": "running"
+    },
+    {
+      "agent_id": "ab8096ee80268e720",
+      "agent_type": "general-purpose",
+      "started_at": "2026-04-16T06:05:29.655Z",
+      "parent_mode": "none",
+      "status": "running"
+    },
+    {
+      "agent_id": "adc57d5ba6bbc20c1",
+      "agent_type": "general-purpose",
+      "started_at": "2026-04-16T06:05:51.361Z",
+      "parent_mode": "none",
+      "status": "running"
     }
   ],
-  "total_spawned": 42,
-  "total_completed": 42,
+  "total_spawned": 50,
+  "total_completed": 47,
   "total_failed": 0,
-  "last_updated": "2026-04-15T14:16:41.394Z"
+  "last_updated": "2026-04-16T06:05:51.474Z"
 }
\ No newline at end of file
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IFakeBatteryPositionRepository.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IFakeBatteryPositionRepository.cs
index 72701e1..afa395d 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IFakeBatteryPositionRepository.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IFakeBatteryPositionRepository.cs
@@ -29,6 +29,13 @@
         bool MarkAsUsed(List<int> positions);
 
         /// <summary>
+        /// 鏍囪鎸囧畾鐐逛綅涓哄彲鐢紙閲婃斁鐐逛綅锛�
+        /// </summary>
+        /// <param name="positions">鐐逛綅绱㈠紩鍒楄〃</param>
+        /// <returns>鏄惁鎴愬姛</returns>
+        bool MarkAsAvailable(List<int> positions);
+
+        /// <summary>
         /// 鏍规嵁琛屽拰鍒楄幏鍙栫偣浣嶇储寮�
         /// </summary>
         /// <param name="row">琛岋紙1-3锛�</param>
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IFakeBatteryPositionService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IFakeBatteryPositionService.cs
index 11771e7..2e04e43 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IFakeBatteryPositionService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IFakeBatteryPositionService.cs
@@ -29,6 +29,13 @@
         bool MarkAsUsed(List<int> positions);
 
         /// <summary>
+        /// 鏍囪鎸囧畾鐐逛綅涓哄彲鐢紙閲婃斁鐐逛綅锛�
+        /// </summary>
+        /// <param name="positions">鐐逛綅绱㈠紩鍒楄〃</param>
+        /// <returns>鏄惁鎴愬姛</returns>
+        bool MarkAsAvailable(List<int> positions);
+
+        /// <summary>
         /// 鏍规嵁琛屽拰鍒楄幏鍙栫偣浣嶇储寮�
         /// </summary>
         /// <param name="row">琛岋紙1-3锛�</param>
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/FakeBatteryPositionRepository.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/FakeBatteryPositionRepository.cs
index f66fef7..e674dfc 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/FakeBatteryPositionRepository.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/FakeBatteryPositionRepository.cs
@@ -78,6 +78,18 @@
         }
 
         /// <inheritdoc/>
+        public bool MarkAsAvailable(List<int> positions)
+        {
+            if (positions == null || positions.Count == 0)
+                return true;
+
+            return Db.Updateable<Dt_FakeBatteryPosition>()
+                .SetColumns(x => x.IsUsed, false)
+                .Where(x => positions.Contains(x.PositionIndex))
+                .ExecuteCommand() > 0;
+        }
+
+        /// <inheritdoc/>
         public int? GetPositionIndex(int row, int col)
         {
             var entity = Db.Queryable<Dt_FakeBatteryPosition>()
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/FakeBatteryPositionService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/FakeBatteryPositionService.cs
index 7016216..83715df 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/FakeBatteryPositionService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/FakeBatteryPositionService.cs
@@ -33,6 +33,12 @@
         }
 
         /// <inheritdoc/>
+        public bool MarkAsAvailable(List<int> positions)
+        {
+            return BaseDal.MarkAsAvailable(positions);
+        }
+
+        /// <inheritdoc/>
         public int? GetPositionIndex(int row, int col)
         {
             return BaseDal.GetPositionIndex(row, col);
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
index 5d3cf9e..c4c1b41 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
@@ -125,7 +125,7 @@
             // 绠�鍗曞懡浠ゅ鐞嗗櫒锛氬鐞嗙姸鎬佹洿鏂扮瓑绠�鍗曞懡浠�
             var simpleCommandHandler = new RobotSimpleCommandHandler(_taskProcessor, socketGateway);
             // 鍓嶇紑鍛戒护澶勭悊鍣細澶勭悊 pickfinished銆乸utfinished 绛夊甫鍙傛暟鐨勫懡浠�
-            var prefixCommandHandler = new RobotPrefixCommandHandler(robotTaskService, _taskProcessor, _stateManager, socketGateway);
+            var prefixCommandHandler = new RobotPrefixCommandHandler(robotTaskService, _taskProcessor, _stateManager, socketGateway, fakeBatteryPositionService);
 
             // 鍒濆鍖栨秷鎭矾鐢卞櫒
             _messageRouter = new RobotMessageHandler(socketGateway, _stateManager, cache, simpleCommandHandler, prefixCommandHandler, logger);
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs
index 6697b01..e5981d2 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs
@@ -181,5 +181,27 @@
         /// 褰撴甯哥數鑺换鍔″畬鎴愬悗璁句负 true锛屾満鍣ㄤ汉浠庡亣鐢佃姱浣嶇疆琛ュ厖鐢佃姱鑷�48涓��
         /// </remarks>
         public bool IsInFakeBatteryMode { get; set; }
+
+        /// <summary>
+        /// 褰撳墠鎵规璧峰缂栧彿锛堢敤浜庨�掑璁$畻鍙栬揣/鏀捐揣缂栧彿锛�
+        /// </summary>
+        /// <remarks>
+        /// 鍦ㄦ壒娆℃ā寮忎笅锛屾瘡鎵瑰彇璐�/鏀捐揣鐨勮捣濮嬬紪鍙蜂粠1寮�濮嬮�掑銆�
+        /// 鐢ㄤ簬璁$畻 {start}-{end} 鏍煎紡涓殑 start 鍊笺��
+        /// </remarks>
+        public int CurrentBatchIndex { get; set; } = 1;
+
+        /// <summary>
+        /// 鎹㈢洏浠诲姟褰撳墠闃舵
+        /// </summary>
+        /// <remarks>
+        /// 闃舵瀹氫箟锛�
+        /// 0: 鏈紑濮�
+        /// 1: 鍙栨甯哥數鑺紙娴佸悜B锛� / 鍙栧亣鐢佃姱锛堟祦鍚慉锛�
+        /// 2: 鏀炬甯哥數鑺紙娴佸悜B锛� / 鏀惧亣鐢佃姱锛堟祦鍚慉锛�
+        /// 3: 鍙栧亣鐢佃姱锛堟祦鍚態 Phase2锛�
+        /// 4: 鏀惧亣鐢佃姱鍒�5鍙蜂綅锛堟祦鍚態 Phase2锛�
+        /// </remarks>
+        public int ChangePalletPhase { get; set; }
     }
 }
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
index fb5ef53..e30d316 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
@@ -268,6 +268,125 @@
         }
 
         /// <summary>
+        /// 璁$畻鎵规缂栧彿鑼冨洿
+        /// </summary>
+        /// <remarks>
+        /// 杩斿洖鏍煎紡锛�(start, end)
+        /// - remaining >= 4: (currentIndex, currentIndex + 3)
+        /// - remaining > 1: (currentIndex, currentIndex + remaining - 1)
+        /// - remaining == 1: (currentIndex, 0)  -- 鍗曚釜鐗╁搧鐢� 0 琛ㄧず end
+        /// </remarks>
+        /// <param name="currentIndex">褰撳墠鎵规璧峰缂栧彿</param>
+        /// <param name="remaining">鍓╀綑鏁伴噺</param>
+        /// <returns>(start, end) 鍏冪粍</returns>
+        public (int Start, int End) BuildBatchRange(int currentIndex, int remaining)
+        {
+            if (remaining >= 4)
+                return (currentIndex, currentIndex + 3);
+            else if (remaining > 1)
+                return (currentIndex, currentIndex + remaining - 1);
+            else  // remaining == 1
+                return (currentIndex, 0);
+        }
+
+        /// <summary>
+        /// 涓嬪彂鍙栬揣鎸囦护锛堝甫鎵规鏍煎紡鍜屾�绘暟锛�
+        /// </summary>
+        /// <remarks>
+        /// 鍙戦�侀『搴忥細
+        /// 1. PickTotalNum,{N} -- 鐪熷疄鐢佃姱鎬绘暟
+        /// 2. Pickbattery,{浣嶇疆},{start}-{end} -- 鎵规鍙栬揣鎸囦护
+        ///
+        /// 涓嬪彂鎴愬姛鍚庢洿鏂颁换鍔$姸鎬佷负"鏈哄櫒浜烘墽琛屼腑"銆�
+        /// </remarks>
+        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
+        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+        /// <param name="position">鍙栬揣浣嶇疆</param>
+        /// <param name="batchStart">鎵规璧峰缂栧彿</param>
+        /// <param name="batchEnd">鎵规缁撴潫缂栧彿</param>
+        public async Task SendPickWithBatchAsync(Dt_RobotTask task, RobotSocketState state, string position, int batchStart, int batchEnd)
+        {
+            // 鍏堝彂閫佹�绘暟鎸囦护
+            string totalNumCmd = $"PickTotalNum,{task.RobotTaskTotalNum}";
+            await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
+
+            // 鍐嶅彂閫佹壒娆″彇璐ф寚浠�
+            string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
+            string taskString = $"Pickbattery,{position},{range}";
+
+            bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
+
+            if (result)
+            {
+                _logger.LogInformation("涓嬪彂鎵规鍙栬揣鎸囦护鎴愬姛锛屾寚浠�: {TaskString}锛屾壒娆�: {Range}锛岃澶�: {DeviceName}",
+                    taskString, range, state.RobotCrane?.DeviceName);
+                QuartzLogger.Info($"涓嬪彂鎵规鍙栬揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛屾壒娆�: {range}", state.RobotCrane?.DeviceName);
+
+                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
+                state.CurrentTask = task;
+
+                if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
+                {
+                    await _robotTaskService.UpdateRobotTaskAsync(task);
+                }
+            }
+            else
+            {
+                _logger.LogError("涓嬪彂鎵规鍙栬揣鎸囦护澶辫触锛屾寚浠�: {TaskString}锛岃澶�: {DeviceName}", taskString, state.RobotCrane?.DeviceName);
+                QuartzLogger.Error($"涓嬪彂鎵规鍙栬揣鎸囦护澶辫触锛屾寚浠�: {taskString}", state.RobotCrane?.DeviceName);
+            }
+        }
+
+        /// <summary>
+        /// 涓嬪彂鏀捐揣鎸囦护锛堝甫鎵规鏍煎紡鍜屾�绘暟锛�
+        /// </summary>
+        /// <remarks>
+        /// 鍙戦�侀『搴忥細
+        /// 1. PutTotalNum,{N} -- 鐪熷疄鐢佃姱鎬绘暟
+        /// 2. Putbattery,{浣嶇疆},{start}-{end} -- 鎵规鏀捐揣鎸囦护
+        ///
+        /// 涓嬪彂鎴愬姛鍚庢洿鏂颁换鍔$姸鎬佷负"鏈哄櫒浜烘墽琛屼腑"銆�
+        /// </remarks>
+        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
+        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+        /// <param name="position">鏀捐揣浣嶇疆</param>
+        /// <param name="batchStart">鎵规璧峰缂栧彿</param>
+        /// <param name="batchEnd">鎵规缁撴潫缂栧彿</param>
+        public async Task SendPutWithBatchAsync(Dt_RobotTask task, RobotSocketState state, string position, int batchStart, int batchEnd)
+        {
+            // 鍏堝彂閫佹�绘暟鎸囦护
+            string totalNumCmd = $"PutTotalNum,{task.RobotTaskTotalNum}";
+            await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
+
+            // 鍐嶅彂閫佹壒娆℃斁璐ф寚浠�
+            string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
+            string taskString = $"Putbattery,{position},{range}";
+
+            bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
+
+            if (result)
+            {
+                _logger.LogInformation("涓嬪彂鏀捐揣鎸囦护鎴愬姛锛屾寚浠�: {TaskString}锛屾壒娆�: {Range}锛岃澶�: {DeviceName}",
+                    taskString, range, state.RobotCrane?.DeviceName);
+                QuartzLogger.Info($"涓嬪彂鏀捐揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛屾壒娆�: {range}", state.RobotCrane?.DeviceName);
+
+                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
+                state.CurrentTask = task;
+
+                if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
+                {
+                    await _robotTaskService.UpdateRobotTaskAsync(task);
+                }
+            }
+            else
+            {
+                _logger.LogError("涓嬪彂鏀捐揣鎸囦护澶辫触锛屾寚浠�: {TaskString}锛岃澶�: {DeviceName}",
+                    taskString, state.RobotCrane?.DeviceName);
+                QuartzLogger.Error($"涓嬪彂鏀捐揣鎸囦护澶辫触锛屾寚浠�: {taskString}", state.RobotCrane?.DeviceName);
+            }
+        }
+
+        /// <summary>
         /// 澶勭悊鍏ュ簱浠诲姟鍥炰紶锛堟媶鐩�/缁勭洏/鎹㈢洏鍦烘櫙锛�
         /// </summary>
         /// <remarks>
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
index f277c39..9eb7830 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
@@ -58,22 +58,33 @@
         private readonly ISocketClientGateway _socketClientGateway;
 
         /// <summary>
+        /// 鍋囩數鑺綅缃湇鍔�
+        /// </summary>
+        /// <remarks>
+        /// 鐢ㄤ簬閲婃斁鍋囩數鑺偣浣嶃��
+        /// </remarks>
+        private readonly IFakeBatteryPositionService _fakeBatteryPositionService;
+
+        /// <summary>
         /// 鏋勯�犲嚱鏁�
         /// </summary>
         /// <param name="robotTaskService">浠诲姟鏈嶅姟</param>
         /// <param name="taskProcessor">浠诲姟澶勭悊鍣�</param>
         /// <param name="stateManager">鐘舵�佺鐞嗗櫒</param>
         /// <param name="socketClientGateway">Socket 缃戝叧</param>
+        /// <param name="fakeBatteryPositionService">鍋囩數鑺綅缃湇鍔�</param>
         public RobotPrefixCommandHandler(
             IRobotTaskService robotTaskService,
             RobotTaskProcessor taskProcessor,
             RobotStateManager stateManager,
-            ISocketClientGateway socketClientGateway)
+            ISocketClientGateway socketClientGateway,
+            IFakeBatteryPositionService fakeBatteryPositionService)
         {
             _robotTaskService = robotTaskService;
             _taskProcessor = taskProcessor;
             _stateManager = stateManager;
             _socketClientGateway = socketClientGateway;
+            _fakeBatteryPositionService = fakeBatteryPositionService;
         }
 
         /// <summary>
@@ -162,24 +173,31 @@
         /// <remarks>
         /// 澶勭悊閫昏緫锛�
         /// 1. 濡傛灉鏄媶鐩樹换鍔★紝鏋勫缓搴撳瓨 DTO 骞惰皟鐢ㄦ媶鐩� API
-        /// 2. 鏇存柊褰撳墠鍔ㄤ綔涓�"鍙栬揣瀹屾垚"
-        /// 3. 璁板綍鍙栬揣瀹屾垚鐨勪綅缃�
-        /// 4. 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜哄彇璐у畬鎴�"
-        /// 5. 瀹夊叏鏇存柊鐘舵�佸埌 Redis
+        /// 2. 鎹㈢洏浠诲姟 Phase3 鍙栧亣鐢佃姱鏃朵笉璋冪敤鎷嗙洏 API
+        /// 3. 鏇存柊褰撳墠鍔ㄤ綔涓�"鍙栬揣瀹屾垚"
+        /// 4. 璁板綍鍙栬揣瀹屾垚鐨勪綅缃�
+        /// 5. 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜哄彇璐у畬鎴�"
+        /// 6. 瀹夊叏鏇存柊鐘舵�佸埌 Redis
         /// </remarks>
         /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
         /// <param name="positions">鍙栬揣瀹屾垚鐨勪綅缃紪鍙锋暟缁�</param>
         /// <param name="task">鏈哄櫒浜轰换鍔¤褰�</param>
         private async Task HandlePickFinishedAsync(RobotSocketState state, int[] positions, Dt_RobotTask? task)
         {
-            // 濡傛灉鏄媶鐩樹换鍔�
-            if (state.IsSplitPallet)
+            // 璁板綍鍙栬揣瀹屾垚鐨勪綅缃�
+            state.LastPickPositions = positions;
+
+            // 鎹㈢洏浠诲姟 Phase3 鍙栧亣鐢佃姱锛氫笉璋冪敤鎷嗙洏 API
+            if (state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()
+                && state.ChangePalletPhase == 3)
+            {
+                state.CurrentAction = "PickFinished";
+            }
+            // 鎷嗙洏浠诲姟
+            else if (state.IsSplitPallet)
             {
                 // 鏋勫缓搴撳瓨 DTO锛屽寘鍚綅缃俊鎭拰鎵樼洏鏉$爜
                 var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
-
-                // 璁板綍鍙栬揣瀹屾垚鐨勪綅缃�
-                state.LastPickPositions = positions;
 
                 // 璋冪敤鎷嗙洏 API
                 var result = _taskProcessor.PostSplitPalletAsync(stockDTO);
@@ -187,7 +205,6 @@
                 // 濡傛灉 API 璋冪敤鎴愬姛
                 if (result.Data.Status && result.IsSuccess)
                 {
-                    // 鏇存柊褰撳墠鍔ㄤ綔涓�"鍙栬揣瀹屾垚"
                     state.CurrentAction = "PickFinished";
                 }
             }
@@ -196,9 +213,6 @@
                 // 闈炴媶鐩樹换鍔★紝鐩存帴鏇存柊鍔ㄤ綔
                 state.CurrentAction = "PickFinished";
             }
-
-            // 璁板綍鍙栬揣瀹屾垚鐨勪綅缃紙鏃犺鏄惁鎷嗙洏閮借褰曪級
-            state.LastPickPositions = positions;
 
             // 濡傛灉浠诲姟瀛樺湪
             if (task != null)
@@ -220,10 +234,11 @@
         /// <remarks>
         /// 澶勭悊閫昏緫锛�
         /// 1. 濡傛灉鏄粍鐩樹换鍔★紝鏋勫缓搴撳瓨 DTO 骞惰皟鐢ㄧ粍鐩�/鎹㈢洏 API
-        /// 2. 濡傛灉缁勭洏鎴愬姛锛屽鍔犱换鍔¤鏁�
-        /// 3. 鏇存柊褰撳墠鍔ㄤ綔涓�"鏀捐揣瀹屾垚"
-        /// 4. 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘斁璐у畬鎴�"
-        /// 5. 瀹夊叏鏇存柊鐘舵�佸埌 Redis
+        /// 2. 鎹㈢洏浠诲姟鏍规嵁闃舵鍖哄垎澶勭悊锛氭祦鍚慉 Phase2 涓嶈皟鐢� API锛涙祦鍚態 Phase2 姝e父璋冪敤锛汸hase4 璋冪敤 MarkAsAvailable
+        /// 3. 濡傛灉缁勭洏鎴愬姛锛屽鍔犱换鍔¤鏁�
+        /// 4. 鏇存柊褰撳墠鍔ㄤ綔涓�"鏀捐揣瀹屾垚"
+        /// 5. 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘斁璐у畬鎴�"
+        /// 6. 瀹夊叏鏇存柊鐘舵�佸埌 Redis
         /// </remarks>
         /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
         /// <param name="positions">鏀捐揣瀹屾垚鐨勪綅缃紪鍙锋暟缁�</param>
@@ -239,20 +254,62 @@
                 // 璁板綍鏀捐揣瀹屾垚鐨勪綅缃�
                 state.LastPutPositions = positions;
 
-                // 鏋勫缓搴撳瓨 DTO
-                var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
+                // 鍒ゆ柇鏄惁涓烘崲鐩樹换鍔�
+                var isChangePallet = state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode();
+                var isFlowA = state.CurrentTask?.RobotSourceAddressLineCode is "11001" or "11010";
 
-                // 鏍规嵁浠诲姟绫诲瀷鍐冲畾璋冪敤鍝釜 API
-                // 鎹㈢洏浠诲姟璋冪敤 ChangePalletAsync锛岀粍鐩樹换鍔¤皟鐢� GroupPalletAsync
-                var configKey = state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()
-                    ? nameof(ConfigKey.ChangePalletAsync)
-                    : nameof(ConfigKey.GroupPalletAsync);
+                if (isChangePallet)
+                {
+                    // 鎹㈢洏浠诲姟锛氭牴鎹樁娈靛尯鍒嗗鐞�
+                    if (state.ChangePalletPhase == 2)
+                    {
+                        if (isFlowA)
+                        {
+                            // 娴佸悜A Phase2锛氭斁鍋囩數鑺埌鐩爣鎵樼洏锛屼笉璋冪敤 API锛屼笉閫掑璁℃暟
+                            // 浠呮洿鏂扮姸鎬�
+                        }
+                        else
+                        {
+                            // 娴佸悜B Phase2锛氭斁姝e父鐢佃姱锛岄�掑璁℃暟
+                            state.RobotTaskTotalNum += positions.Length;
+                            if (task != null)
+                                task.RobotTaskTotalNum -= positions.Length;
 
-                // 璋冪敤缁勭洏/鎹㈢洏 API
-                var result = _taskProcessor.PostGroupPalletAsync(configKey, stockDTO);
+                            // 鏋勫缓搴撳瓨 DTO 骞惰皟鐢� ChangePalletAsync API
+                            var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
+                            var result = _taskProcessor.PostGroupPalletAsync(nameof(ConfigKey.ChangePalletAsync), stockDTO);
+                            putSuccess = result.Data.Status && result.IsSuccess;
+                        }
+                    }
+                    else if (state.ChangePalletPhase == 4)
+                    {
+                        // 娴佸悜B Phase4锛氭斁鍋囩數鑺埌5鍙蜂綅锛屼笉璋冪敤 API锛屼笉閫掑璁℃暟锛岄噴鏀剧偣浣�
+                        _fakeBatteryPositionService.MarkAsAvailable(positions.ToList());
+                    }
+                    else
+                    {
+                        // 闈炴壒娆℃ā寮忥細姝e父閫掑璁℃暟骞惰皟鐢� API
+                        state.RobotTaskTotalNum += positions.Length;
+                        if (task != null)
+                            task.RobotTaskTotalNum -= positions.Length;
 
-                // 妫�鏌� API 杩斿洖鐘舵��
-                putSuccess = result.Data.Status && result.IsSuccess;
+                        var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
+                        var result = _taskProcessor.PostGroupPalletAsync(nameof(ConfigKey.GroupPalletAsync), stockDTO);
+                        putSuccess = result.Data.Status && result.IsSuccess;
+                    }
+                }
+                else
+                {
+                    // 缁勭洏浠诲姟锛氬師鏈夐�昏緫
+                    var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
+                    var result = _taskProcessor.PostGroupPalletAsync(nameof(ConfigKey.GroupPalletAsync), stockDTO);
+                    putSuccess = result.Data.Status && result.IsSuccess;
+
+                    // 澧炲姞浠诲姟璁℃暟
+                    state.RobotTaskTotalNum += positions.Length;
+                    if (task != null)
+                        task.RobotTaskTotalNum -= positions.Length;
+                }
             }
 
             // 濡傛灉鏀捐揣鎴愬姛
@@ -261,13 +318,12 @@
                 // 鏇存柊褰撳墠鍔ㄤ綔涓�"鏀捐揣瀹屾垚"
                 state.CurrentAction = "PutFinished";
 
-                // 澧炲姞浠诲姟璁℃暟锛堢疮鍔犳湰娆″畬鎴愮殑鏁伴噺锛�
-                state.RobotTaskTotalNum += positions.Length;
-
-                // 濡傛灉浠诲姟瀛樺湪锛屽悓姝ユ洿鏂颁换鍔$殑璁℃暟
-                if (task != null)
+                // 闈炵粍鐩樹换鍔℃椂澧炲姞璁℃暟锛堢粍鐩樹换鍔″凡鍦ㄤ笂闈㈤�掑锛�
+                if (!state.IsGroupPallet)
                 {
-                    task.RobotTaskTotalNum -= positions.Length;
+                    state.RobotTaskTotalNum += positions.Length;
+                    if (task != null)
+                        task.RobotTaskTotalNum -= positions.Length;
                 }
             }
 
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
index b564835..d2b057b 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
@@ -138,11 +138,33 @@
                         // 鍒ゆ柇浠诲姟绫诲瀷
                         var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType;
 
-                        // 鍙湁鎷嗙洏鎴栨崲鐩樹换鍔¢渶瑕佸鐞嗗叆搴�
-                        if (robotTaskType == RobotTaskTypeEnum.SplitPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet)
+                        // 鎹㈢洏浠诲姟锛氫粎褰撴墍鏈夐樁娈靛畬鎴愭椂鎵嶅鐞嗗叆搴�
+                        if (robotTaskType == RobotTaskTypeEnum.ChangePallet)
                         {
-                            // 澶勭悊鍏ュ簱浠诲姟鍥炰紶
-                            // useSourceAddress: true 琛ㄧず浣跨敤婧愬湴鍧�锛堟媶鐩�/鎹㈢洏鍦烘櫙锛�
+                            if (state.ChangePalletPhase == 0)
+                            {
+                                // 鎵�鏈夐樁娈靛畬鎴愶紝澶勭悊鍏ュ簱
+                                if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true))
+                                {
+                                    // 鍏ュ簱鎴愬姛锛屽垹闄や换鍔¤褰�
+                                    _taskProcessor.DeleteTask(currentTask.RobotTaskId);
+                                    await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
+                                    QuartzLogger.Info($"鍙戦�佹秷鎭細銆怱wap,diskFinished銆�", state.RobotCrane.DeviceName);
+
+                                    // 閲嶇疆鎵规鐘舵��
+                                    state.ChangePalletPhase = 0;
+                                    state.CurrentBatchIndex = 1;
+                                    state.IsInFakeBatteryMode = false;
+                                    return true;
+                                }
+                            }
+                            // 涓棿闃舵涓嶅鐞嗭紝浠呮洿鏂扮姸鎬�
+                            return true;
+                        }
+
+                        // 鎷嗙洏浠诲姟锛氱洿鎺ュ鐞嗗叆搴�
+                        if (robotTaskType == RobotTaskTypeEnum.SplitPallet)
+                        {
                             if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true))
                             {
                                 // 鍏ュ簱鎴愬姛锛屽垹闄や换鍔¤褰�
@@ -171,11 +193,41 @@
                         // 鍒ゆ柇浠诲姟绫诲瀷
                         var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType;
 
-                        // 鍙湁缁勭洏鎴栨崲鐩樹换鍔¢渶瑕佸鐞嗗叆搴�
-                        if (robotTaskType == RobotTaskTypeEnum.GroupPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet)
+                        // 鎹㈢洏浠诲姟锛氫粎褰撴墍鏈夐樁娈靛畬鎴愭椂鎵嶅鐞嗗叆搴�
+                        if (robotTaskType == RobotTaskTypeEnum.ChangePallet)
+                        {
+                            if (state.ChangePalletPhase == 0)
+                            {
+                                // 鎵�鏈夐樁娈靛畬鎴愶紝澶勭悊鍏ュ簱
+                                if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false))
+                                {
+                                    // 鍏ュ簱鎴愬姛锛屽垹闄や换鍔¤褰�
+                                    _taskProcessor.DeleteTask(currentTask.RobotTaskId);
+
+                                    // 娓呯悊鐘舵�侊紝涓轰笅涓�涓换鍔″仛鍑嗗
+                                    state.CurrentTask = null;           // 娓呴櫎褰撳墠浠诲姟
+                                    state.RobotTaskTotalNum = 0;        // 閲嶇疆浠诲姟璁℃暟
+                                    state.CellBarcode = new List<string>();  // 娓呯┖鏉$爜鍒楄〃
+
+                                    await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
+                                    QuartzLogger.Info($"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
+
+                                    // 閲嶇疆鎵规鐘舵��
+                                    state.ChangePalletPhase = 0;
+                                    state.CurrentBatchIndex = 1;
+                                    state.IsInFakeBatteryMode = false;
+                                    return true;
+                                }
+                            }
+                            // 涓棿闃舵涓嶅鐞嗭紝浠呮洿鏂扮姸鎬�
+                            return true;
+                        }
+
+                        // 缁勭洏浠诲姟锛氱洿鎺ュ鐞嗗叆搴�
+                        if (robotTaskType == RobotTaskTypeEnum.GroupPallet)
                         {
                             // 澶勭悊鍏ュ簱浠诲姟鍥炰紶
-                            // useSourceAddress: false 琛ㄧず浣跨敤鐩爣鍦板潃锛堢粍鐩�/鎹㈢洏鍦烘櫙锛�
+                            // useSourceAddress: false 琛ㄧず浣跨敤鐩爣鍦板潃锛堢粍鐩樺満鏅級
                             if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false))
                             {
                                 // 鍏ュ簱鎴愬姛锛屽垹闄や换鍔¤褰�
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
index e0211a5..4414558 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
@@ -152,7 +152,7 @@
         /// </summary>
         /// <remarks>
         /// 褰撳彇璐у畬鎴愬悗锛屽悜鏈哄櫒浜哄彂閫佹斁璐ф寚浠わ紙Putbattery锛夈��
-        /// 鏈哄櫒浜烘敹鍒版寚浠ゅ悗浼氬皢璐х墿鏀剧疆鍒扮洰鏍囧湴鍧�銆�
+        /// 鎹㈢洏浠诲姟浣跨敤鎵规鏍煎紡 SendPutWithBatchAsync銆�
         ///
         /// 鎸囦护鏍煎紡锛歅utbattery,{鐩爣鍦板潃}
         /// 渚嬪锛歅utbattery,B01 琛ㄧず灏嗚揣鐗╂斁缃埌 B01 浣嶇疆
@@ -161,38 +161,99 @@
         /// <param name="ipAddress">鏈哄櫒浜� IP 鍦板潃</param>
         private async Task HandlePickFinishedStateAsync(Dt_RobotTask task, string ipAddress)
         {
-            // 鏋勫缓鏀捐揣鎸囦护锛屾牸寮忥細Putbattery,{鐩爣鍦板潃}
-            string taskString = $"Putbattery,{task.RobotTargetAddress}";
+            string taskString;
 
-            // 閫氳繃瀹㈡埛绔鐞嗗櫒鍙戦�佹寚浠ゅ埌鏈哄櫒浜�
+            // 鎹㈢洏浠诲姟浣跨敤鎵规鏍煎紡
+            if (task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode())
+            {
+                int targetNormalCount = task.RobotTaskTotalNum;
+                var state = _stateManager.GetState(ipAddress);
+                int currentCompletedCount = state?.RobotTaskTotalNum ?? 0;
+
+                bool isFlowA = task.RobotSourceAddressLineCode is "11001" or "11010";
+
+                // 娴佸悜A Phase 2锛氭斁鍋囩數鑺埌鐩爣鎵樼洏
+                if (isFlowA && state?.ChangePalletPhase == 2)
+                {
+                    int remaining = 48 - currentCompletedCount;
+                    if (remaining <= 0) return;
+
+                    int batchStart = targetNormalCount + 1 + (state.CurrentBatchIndex - 1);
+                    int putCount = Math.Min(4, remaining);
+                    var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount);
+
+                    await _taskProcessor.SendPutWithBatchAsync(task, state, task.RobotTargetAddress, start, end);
+                    return;
+                }
+
+                // 娴佸悜B Phase 4锛氭斁鍋囩數鑺埌5鍙蜂綅
+                if (!isFlowA && state?.ChangePalletPhase == 4)
+                {
+                    int fakeCount = 48 - targetNormalCount;
+                    int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount);
+                    int remainingFake = fakeCount - completedFake;
+
+                    if (remainingFake <= 0) return;
+
+                    var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(Math.Min(4, remainingFake));
+                    if (positions.Count == 0)
+                    {
+                        _logger.LogError("HandlePickFinishedStateAsync锛氭棤鍙敤鍋囩數鑺偣浣嶏紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                        return;
+                    }
+
+                    int start = positions.Min();
+                    int end = positions.Max();
+
+                    await _taskProcessor.SendPutWithBatchAsync(task, state, "5", start, end);
+                    return;
+                }
+
+                // 娴佸悜B Phase 2锛氭斁姝e父鐢佃姱鍒扮洰鏍囨墭鐩�
+                if (!isFlowA && state?.ChangePalletPhase == 2)
+                {
+                    int remainingNormal = targetNormalCount - currentCompletedCount;
+                    if (remainingNormal <= 0) return;
+
+                    int batchStart = ((currentCompletedCount - 1) / 4) * 4 + 1;
+                    int putCount = Math.Min(4, remainingNormal);
+                    var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount);
+
+                    await _taskProcessor.SendPutWithBatchAsync(task, state, task.RobotTargetAddress, start, end);
+                    return;
+                }
+
+                // 榛樿锛氫娇鐢ㄥ師鏈夋牸寮�
+                taskString = $"Putbattery,{task.RobotTargetAddress}";
+            }
+            else
+            {
+                // 闈炴崲鐩樹换鍔★細浣跨敤鍘熸湁鏍煎紡
+                taskString = $"Putbattery,{task.RobotTargetAddress}";
+            }
+
             bool result = await _clientManager.SendToClientAsync(ipAddress, taskString);
 
             if (result)
             {
-                // 鍙戦�佹垚鍔燂紝璁板綍 Info 鏃ュ織
                 _logger.LogInformation("HandlePickFinishedStateAsync锛氫笅鍙戞斁璐ф寚浠ゆ垚鍔燂紝鎸囦护: {TaskString}锛屼换鍔″彿: {TaskNum}", taskString, task.RobotTaskNum);
                 QuartzLogger.Info($"涓嬪彂鏀捐揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}", task.RobotRoadway);
 
-                // 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘墽琛屼腑"
                 task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
 
-                // 鑾峰彇鏈�鏂扮姸鎬佸苟鏇存柊浠诲姟鍏宠仈
                 var stateToUpdate = _stateManager.GetState(ipAddress);
                 if (stateToUpdate != null)
                 {
                     stateToUpdate.CurrentTask = task;
 
-                    // 瀹夊叏鏇存柊鐘舵�佸埌 Redis
                     if (_stateManager.TryUpdateStateSafely(ipAddress, stateToUpdate))
                     {
-                        // 鐘舵�佹洿鏂版垚鍔熷悗锛屾洿鏂颁换鍔¤褰�
                         await _robotTaskService.UpdateRobotTaskAsync(task);
                     }
                 }
             }
             else
             {
-                // 鍙戦�佸け璐ワ紝璁板綍 Error 鏃ュ織
                 _logger.LogError("HandlePickFinishedStateAsync锛氫笅鍙戞斁璐ф寚浠ゅけ璐ワ紝鎸囦护: {TaskString}锛屼换鍔″彿: {TaskNum}", taskString, task.RobotTaskNum);
                 QuartzLogger.Error($"涓嬪彂鏀捐揣鎸囦护澶辫触锛屾寚浠�: {taskString}", task.RobotRoadway);
             }
@@ -284,61 +345,179 @@
             }
             else if (task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode())
             {
-                // 鎹㈢洏浠诲姟
-                // 鐩爣锛氭甯哥數鑺姄鍙栧畬鎴愬悗锛岃ˉ鍏呭亣鐢佃姱鑷�48涓�
                 const int targetTotal = 48;
-                const int fakeBatteryPickPosition = 5;  // 鍋囩數鑺姄鍙栦綅缃�
-                const int pickCountPerExecution = 4;     // 姣忔鎶撳彇鏁伴噺
+                int targetNormalCount = task.RobotTaskTotalNum;
+                int currentCompletedCount = stateForUpdate.RobotTaskTotalNum;
 
-                int targetNormalCount = task.RobotTaskTotalNum;  // 姝e父鐢佃姱鐩爣鏁伴噺
-                int currentCompletedCount = stateForUpdate.RobotTaskTotalNum;  // 宸插畬鎴愭暟閲�
+                // 鍒ゆ柇娴佸悜锛坣ull-safe锛�
+                bool isFlowA = task.RobotSourceAddressLineCode is "11001" or "11010";
 
-                // 濡傛灉鐩爣鏁伴噺涓�48锛岀洿鎺ヤ笅鍙戞甯镐换鍔�
+                // 鐩爣鏁伴噺涓�48锛氱洿鎺ヨ蛋鍘熸湁閫昏緫锛屼笉杩涘叆鎵规妯″紡
                 if (targetNormalCount == targetTotal)
                 {
                     await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate);
-                }
-                // 濡傛灉宸插畬鎴愭暟閲忓皬浜庣洰鏍囨暟閲忥紝缁х画鎶撳彇姝e父鐢佃姱
-                else if (currentCompletedCount < targetNormalCount)
-                {
-                    await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate);
-                }
-                // 姝e父鐢佃姱宸插畬鎴愶紝杩涘叆鍋囩數鑺ˉ鍏呮ā寮�
-                else if (currentCompletedCount == targetNormalCount && !stateForUpdate.IsInFakeBatteryMode)
-                {
-                    // 棣栨杩涘叆鍋囩數鑺ā寮忥紝璁剧疆鏍囧織
-                    stateForUpdate.IsInFakeBatteryMode = true;
-                    _logger.LogInformation("HandlePutFinishedStateAsync锛氭甯哥數鑺姄鍙栧畬鎴愶紝杩涘叆鍋囩數鑺ˉ鍏呮ā寮忥紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
-                    QuartzLogger.Info($"姝e父鐢佃姱鎶撳彇瀹屾垚锛岃繘鍏ュ亣鐢佃姱琛ュ厖妯″紡", stateForUpdate.RobotCrane?.DeviceName);
+                    return;
                 }
 
-                // 濡傛灉澶勪簬鍋囩數鑺ˉ鍏呮ā寮忥紝璁$畻骞朵笅鍙戣ˉ鏁颁换鍔�
-                if (stateForUpdate.IsInFakeBatteryMode)
+                // 鍒濆鍖栨壒娆℃ā寮�
+                if (stateForUpdate.ChangePalletPhase == 0)
                 {
-                    int remaining = targetTotal - currentCompletedCount;
-                    if (remaining > 0)
+                    stateForUpdate.ChangePalletPhase = 1;
+                    stateForUpdate.CurrentBatchIndex = 1;
+                    _logger.LogInformation("HandlePutFinishedStateAsync锛氭崲鐩樹换鍔¤繘鍏ユ壒娆℃ā寮忥紝浠诲姟鍙�: {TaskNum}锛屾祦鍚�: {Flow}",
+                        task.RobotTaskNum, isFlowA ? "A" : "B");
+                }
+
+                // ==================== 娴佸悜A锛氳ˉ鍋囩數鑺埌鐩爣鎵樼洏 ====================
+                if (isFlowA)
+                {
+                    // Phase 1: 鍙栧亣鐢佃姱锛堜粠5鍙蜂綅锛屼娇鐢� PositionIndex锛�
+                    if (stateForUpdate.ChangePalletPhase == 1)
                     {
-                        // 璁$畻姣忔鎶撳彇鐨勬暟閲忥紙鏈�澶�4涓級
-                        int pickCount = Math.Min(pickCountPerExecution, remaining);
+                        int remaining = targetTotal - currentCompletedCount;
+                        if (remaining <= 0)
+                        {
+                            stateForUpdate.ChangePalletPhase = 0;
+                            stateForUpdate.CurrentBatchIndex = 1;
+                            stateForUpdate.IsInFakeBatteryMode = false;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭祦鍚慉瀹屾垚锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
 
-                        // 鑾峰彇鍙敤鐨勫亣鐢佃姱骞抽潰鐐逛綅
+                        int pickCount = Math.Min(4, remaining);
                         var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(pickCount);
                         if (positions.Count == 0)
                         {
                             _logger.LogError("HandlePutFinishedStateAsync锛氭棤鍙敤鍋囩數鑺偣浣嶏紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
-                            QuartzLogger.Error($"鏃犲彲鐢ㄥ亣鐢佃姱鐐逛綅", stateForUpdate.RobotCrane?.DeviceName);
                             return;
                         }
 
-                        // 涓嬪彂鍋囩數鑺彇璐ф寚浠�
                         await _taskProcessor.SendSocketRobotFakeBatteryPickAsync(task, stateForUpdate, positions);
+                        stateForUpdate.ChangePalletPhase = 2;
                     }
-                    else
+                    // Phase 2: 鏀惧亣鐢佃姱鍒扮洰鏍囨墭鐩橈紙浠� targetNormalCount+1 寮�濮嬮�掑锛�
+                    else if (stateForUpdate.ChangePalletPhase == 2)
                     {
-                        // 鍋囩數鑺ˉ鍏呭畬鎴愶紝閲嶇疆鏍囧織
-                        stateForUpdate.IsInFakeBatteryMode = false;
-                        _logger.LogInformation("HandlePutFinishedStateAsync锛氭崲鐩樹换鍔″畬鎴愶紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
-                        QuartzLogger.Info($"鎹㈢洏浠诲姟瀹屾垚", stateForUpdate.RobotCrane?.DeviceName);
+                        int remaining = targetTotal - currentCompletedCount;
+                        if (remaining <= 0)
+                        {
+                            stateForUpdate.ChangePalletPhase = 0;
+                            stateForUpdate.CurrentBatchIndex = 1;
+                            stateForUpdate.IsInFakeBatteryMode = false;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭祦鍚慉瀹屾垚锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        // 璁$畻鏀捐揣鎵规缂栧彿锛氫粠 targetNormalCount + 1 寮�濮�
+                        int batchStart = targetNormalCount + 1 + (stateForUpdate.CurrentBatchIndex - 1);
+                        int putCount = Math.Min(4, remaining);
+                        var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount);
+
+                        await _taskProcessor.SendPutWithBatchAsync(task, stateForUpdate, task.RobotTargetAddress, start, end);
+
+                        stateForUpdate.CurrentBatchIndex += putCount;
+                        stateForUpdate.ChangePalletPhase = 1;
+                    }
+                }
+                // ==================== 娴佸悜B锛氬彇姝e父鐢佃姱 + 鍥炴敹鍋囩數鑺� ====================
+                else
+                {
+                    // Phase 1: 鍙栨甯哥數鑺紙浠庢簮鍦板潃锛屼粠1寮�濮嬮�掑锛�
+                    if (stateForUpdate.ChangePalletPhase == 1)
+                    {
+                        int remainingNormal = targetNormalCount - currentCompletedCount;
+                        if (remainingNormal <= 0)
+                        {
+                            // 姝e父鐢佃姱鍙栧畬锛屽垏鎹㈠埌 Phase 3
+                            stateForUpdate.ChangePalletPhase = 3;
+                            stateForUpdate.CurrentBatchIndex = targetNormalCount + 1;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭甯哥數鑺叏閮ㄥ彇瀹岋紝杩涘叆Phase 3鍥炴敹鍋囩數鑺紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        int pickCount = Math.Min(4, remainingNormal);
+                        var (start, end) = _taskProcessor.BuildBatchRange(stateForUpdate.CurrentBatchIndex, pickCount);
+
+                        await _taskProcessor.SendPickWithBatchAsync(task, stateForUpdate, task.RobotSourceAddress, start, end);
+
+                        stateForUpdate.CurrentBatchIndex += pickCount;
+                        stateForUpdate.ChangePalletPhase = 2;
+                    }
+                    // Phase 2: 鏀炬甯哥數鑺埌鐩爣鎵樼洏锛堟斁璐х紪鍙蜂笌鍙栬揣缂栧彿涓�鑷达級
+                    else if (stateForUpdate.ChangePalletPhase == 2)
+                    {
+                        int remainingNormal = targetNormalCount - currentCompletedCount;
+                        if (remainingNormal <= 0)
+                        {
+                            // 姝e父鐢佃姱鏀惧畬锛屽垏鎹㈠埌 Phase 3
+                            stateForUpdate.ChangePalletPhase = 3;
+                            stateForUpdate.CurrentBatchIndex = targetNormalCount + 1;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭甯哥數鑺叏閮ㄦ斁瀹岋紝杩涘叆Phase 3鍥炴敹鍋囩數鑺紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        // 璁$畻鏈壒鏀捐揣缂栧彿锛氬熀浜� currentCompletedCount 鎺ㄥ鎵规璧峰
+                        int batchStart = ((currentCompletedCount - 1) / 4) * 4 + 1;
+                        int putCount = Math.Min(4, remainingNormal);
+                        var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount);
+
+                        await _taskProcessor.SendPutWithBatchAsync(task, stateForUpdate, task.RobotTargetAddress, start, end);
+
+                        stateForUpdate.ChangePalletPhase = 1;
+                    }
+                    // Phase 3: 鍙栧亣鐢佃姱锛堜粠婧愬湴鍧�锛屼粠 targetNormalCount+1 寮�濮嬮�掑锛�
+                    else if (stateForUpdate.ChangePalletPhase == 3)
+                    {
+                        int fakeCount = targetTotal - targetNormalCount;
+                        int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount);
+                        int remainingFake = fakeCount - completedFake;
+
+                        if (remainingFake <= 0)
+                        {
+                            stateForUpdate.ChangePalletPhase = 0;
+                            stateForUpdate.CurrentBatchIndex = 1;
+                            stateForUpdate.IsInFakeBatteryMode = false;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭祦鍚態瀹屾垚锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        int pickCount = Math.Min(4, remainingFake);
+                        var (start, end) = _taskProcessor.BuildBatchRange(stateForUpdate.CurrentBatchIndex, pickCount);
+
+                        await _taskProcessor.SendPickWithBatchAsync(task, stateForUpdate, task.RobotSourceAddress, start, end);
+
+                        stateForUpdate.CurrentBatchIndex += pickCount;
+                        stateForUpdate.ChangePalletPhase = 4;
+                    }
+                    // Phase 4: 鏀惧亣鐢佃姱鍒�5鍙蜂綅锛堜娇鐢� PositionIndex锛�
+                    else if (stateForUpdate.ChangePalletPhase == 4)
+                    {
+                        int fakeCount = targetTotal - targetNormalCount;
+                        int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount);
+                        int remainingFake = fakeCount - completedFake;
+
+                        if (remainingFake <= 0)
+                        {
+                            stateForUpdate.ChangePalletPhase = 0;
+                            stateForUpdate.CurrentBatchIndex = 1;
+                            stateForUpdate.IsInFakeBatteryMode = false;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭祦鍚態瀹屾垚锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(Math.Min(4, remainingFake));
+                        if (positions.Count == 0)
+                        {
+                            _logger.LogError("HandlePutFinishedStateAsync锛氭棤鍙敤鍋囩數鑺偣浣嶏紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        int start = positions.Min();
+                        int end = positions.Max();
+
+                        await _taskProcessor.SendPutWithBatchAsync(task, stateForUpdate, "5", start, end);
+
+                        stateForUpdate.ChangePalletPhase = 3;
                     }
                 }
             }
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
index 76ee9b4..cb929b2 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
@@ -75,7 +75,11 @@
     "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjMwMTcyNzM5Mzk5NzYxOTIwIiwibmFtZSI6IlBBQ0voo4XphY3lt6XkvY0wMSIsIkZhY3RvcnlJZCI6IjEyMzQ1NiIsIlNpdGVJZCI6IjEyMzQ1NiIsIkNvZGUiOiJYWExQQUNLMDRBRTAzMiIsIm5iZiI6MTcwNDE4NzY5MCwiZXhwIjoyMTQ1NjkxNjkwLCJpc3MiOiJodHRwczovL3d3dy5oeW1zb24uY29tIiwiYXVkIjoiaHR0cHM6Ly93d3cuaHltc29uLmNvbSJ9.An1BE7UgfcSP--LtTOmmmWVE2RQFPDahLkDg1xy5KqY"
   },
   "RobotTaskAddressRules": {
-    "11068": [ "1", "2" ]
+    "11068": [ "1", "2" ],
+    "11001": [ "3", "1" ],
+    "11010": [ "4", "2" ],
+    "2101": [ "1", "3" ],
+    "2103": [ "2", "4" ]
   },
 
 
diff --git a/Code/docs/superpowers/plans/2026-04-16-change-pallet-batch-command.md b/Code/docs/superpowers/plans/2026-04-16-change-pallet-batch-command.md
new file mode 100644
index 0000000..a5c7485
--- /dev/null
+++ b/Code/docs/superpowers/plans/2026-04-16-change-pallet-batch-command.md
@@ -0,0 +1,1054 @@
+# 鎹㈢洏浠诲姟鎵规鎸囦护涓庡弻娴佸悜瀹炵幇璁″垝
+
+> **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:** 鍗囩骇鎹㈢洏浠诲姟鍙栬揣/鏀捐揣鎸囦护鏍煎紡涓烘壒娆℃ā寮忥紝鏀寔 PickTotalNum/PutTotalNum锛屽苟鏍规嵁 RobotSourceAddressLineCode 鍖哄垎涓ょ娴佸悜
+
+**Architecture:**
+- RobotSocketState 鏂板鎵规鐘舵�佸瓧娈碉紙CurrentBatchIndex, ChangePalletPhase锛�
+- RobotTaskProcessor 鏂板鎵规鎸囦护鏋勫缓鏂规硶锛圔uildBatchRange, SendPickWithBatchAsync, SendPutWithBatchAsync锛�
+- RobotWorkflowOrchestrator 閲嶅啓 HandlePutFinishedStateAsync 鍜� HandlePickFinishedStateAsync 瀹炵幇涓ょ娴佸悜鐨勭姸鎬佹満
+- RobotPrefixCommandHandler 鍜� RobotSimpleCommandHandler 鏍规嵁闃舵鍖哄垎澶勭悊閫昏緫
+- 鍋囩數鑺湇鍔″眰鏂板 MarkAsAvailable 鏂规硶鐢ㄤ簬閲婃斁鐐逛綅
+
+**Tech Stack:** C# / .NET 8, SqlSugar ORM, Redis缂撳瓨
+
+---
+
+## File Structure
+
+```
+WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/
+  = RobotSocketState.cs                # +CurrentBatchIndex, +ChangePalletPhase
+  = RobotTaskProcessor.cs              # +BuildBatchRange, +SendPickWithBatchAsync, +SendPutWithBatchAsync
+  = Workflow/RobotWorkflowOrchestrator.cs  # 閲嶅啓 HandlePutFinishedStateAsync + HandlePickFinishedStateAsync
+  = Workflow/RobotPrefixCommandHandler.cs  # putfinished/pickfinished 闃舵鍒ゆ柇
+  = Workflow/RobotSimpleCommandHandler.cs  # allpickfinished/allputfinished 闃舵瀹堝崼
+
+WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/
+  = IFakeBatteryPositionService.cs     # +MarkAsAvailable
+
+WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/
+  = FakeBatteryPositionService.cs      # +MarkAsAvailable
+
+WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/
+  = IFakeBatteryPositionRepository.cs  # +MarkAsAvailable
+
+WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/
+  = FakeBatteryPositionRepository.cs   # +MarkAsAvailable
+```
+
+---
+
+## Task 1: RobotSocketState 鏂板鎵规鐘舵�佸瓧娈�
+
+**Files:**
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs`
+
+- [ ] **Step 1: 娣诲姞 CurrentBatchIndex 鍜� ChangePalletPhase 灞炴��**
+
+鍦� `IsInFakeBatteryMode` 灞炴�у悗娣诲姞锛�
+
+```csharp
+        /// <summary>
+        /// 鏄惁澶勪簬鍋囩數鑺ˉ鍏呮ā寮�
+        /// </summary>
+        public bool IsInFakeBatteryMode { get; set; }
+
+        /// <summary>
+        /// 褰撳墠鎵规璧峰缂栧彿锛堢敤浜庨�掑璁$畻鍙栬揣/鏀捐揣缂栧彿锛�
+        /// </summary>
+        /// <remarks>
+        /// 鍦ㄦ壒娆℃ā寮忎笅锛屾瘡鎵瑰彇璐�/鏀捐揣鐨勮捣濮嬬紪鍙蜂粠1寮�濮嬮�掑銆�
+        /// 鐢ㄤ簬璁$畻 {start}-{end} 鏍煎紡涓殑 start 鍊笺��
+        /// </remarks>
+        public int CurrentBatchIndex { get; set; } = 1;
+
+        /// <summary>
+        /// 鎹㈢洏浠诲姟褰撳墠闃舵
+        /// </summary>
+        /// <remarks>
+        /// 闃舵瀹氫箟锛�
+        /// 0: 鏈紑濮�
+        /// 1: 鍙栨甯哥數鑺紙娴佸悜B锛� / 鍙栧亣鐢佃姱锛堟祦鍚慉锛�
+        /// 2: 鏀炬甯哥數鑺紙娴佸悜B锛� / 鏀惧亣鐢佃姱锛堟祦鍚慉锛�
+        /// 3: 鍙栧亣鐢佃姱锛堟祦鍚態 Phase2锛�
+        /// 4: 鏀惧亣鐢佃姱鍒�5鍙蜂綅锛堟祦鍚態 Phase2锛�
+        /// </remarks>
+        public int ChangePalletPhase { get; set; }
+```
+
+- [ ] **Step 2: 楠岃瘉缂栬瘧**
+
+```bash
+cd D:\Git\ShanMeiXinNengYuan\Code\WCS\WIDESEAWCS_Server
+dotnet build WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj
+```
+
+Expected: 0 errors
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs
+git commit -m "feat(Robot): RobotSocketState 鏂板 CurrentBatchIndex 鍜� ChangePalletPhase"
+```
+
+---
+
+## Task 2: 鍋囩數鑺粨鍌ㄥ眰鏂板 MarkAsAvailable 鏂规硶
+
+**Files:**
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IFakeBatteryPositionRepository.cs`
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/FakeBatteryPositionRepository.cs`
+
+- [ ] **Step 1: 鍦ㄦ帴鍙d腑娣诲姞 MarkAsAvailable 鏂规硶澹版槑锛堝湪 MarkAsUsed 鏂规硶鍚庯級**
+
+鍦� `IFakeBatteryPositionRepository.cs` 鐨� `MarkAsUsed` 鏂规硶鍚庢坊鍔狅細
+
+```csharp
+        /// <summary>
+        /// 鏍囪鎸囧畾鐐逛綅涓哄彲鐢紙閲婃斁鐐逛綅锛�
+        /// </summary>
+        /// <param name="positions">鐐逛綅绱㈠紩鍒楄〃</param>
+        /// <returns>鏄惁鎴愬姛</returns>
+        bool MarkAsAvailable(List<int> positions);
+```
+
+- [ ] **Step 2: 鍦ㄤ粨鍌ㄥ疄鐜颁腑娣诲姞 MarkAsAvailable 鏂规硶锛堝湪 MarkAsUsed 鏂规硶鍚庯級**
+
+鍦� `FakeBatteryPositionRepository.cs` 鐨� `MarkAsUsed` 鏂规硶鍚庢坊鍔狅細
+
+```csharp
+        /// <inheritdoc/>
+        public bool MarkAsAvailable(List<int> positions)
+        {
+            if (positions == null || positions.Count == 0)
+                return true;
+
+            return Db.Updateable<Dt_FakeBatteryPosition>()
+                .SetColumns(x => x.IsUsed, false)
+                .Where(x => positions.Contains(x.PositionIndex))
+                .ExecuteCommand() > 0;
+        }
+```
+
+- [ ] **Step 3: 楠岃瘉缂栬瘧**
+
+```bash
+dotnet build WIDESEAWCS_Server.sln
+```
+
+Expected: 0 errors
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IFakeBatteryPositionRepository.cs
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/FakeBatteryPositionRepository.cs
+git commit -m "feat(Robot): 鍋囩數鑺粨鍌ㄥ眰鏂板 MarkAsAvailable 鏂规硶"
+```
+
+---
+
+## Task 3: 鍋囩數鑺湇鍔″眰鏂板 MarkAsAvailable 鏂规硶
+
+**Files:**
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IFakeBatteryPositionService.cs`
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/FakeBatteryPositionService.cs`
+
+- [ ] **Step 1: 鍦ㄦ湇鍔℃帴鍙d腑娣诲姞 MarkAsAvailable 鏂规硶澹版槑锛堝湪 MarkAsUsed 鍚庯級**
+
+鍦� `IFakeBatteryPositionService.cs` 鐨� `MarkAsUsed` 鏂规硶鍚庢坊鍔狅細
+
+```csharp
+        /// <summary>
+        /// 鏍囪鎸囧畾鐐逛綅涓哄彲鐢紙閲婃斁鐐逛綅锛�
+        /// </summary>
+        /// <param name="positions">鐐逛綅绱㈠紩鍒楄〃</param>
+        /// <returns>鏄惁鎴愬姛</returns>
+        bool MarkAsAvailable(List<int> positions);
+```
+
+- [ ] **Step 2: 鍦ㄦ湇鍔″疄鐜颁腑娣诲姞 MarkAsAvailable 鏂规硶**
+
+```csharp
+        /// <inheritdoc/>
+        public bool MarkAsAvailable(List<int> positions)
+        {
+            return BaseDal.MarkAsAvailable(positions);
+        }
+```
+
+- [ ] **Step 3: 楠岃瘉缂栬瘧**
+
+```bash
+dotnet build WIDESEAWCS_Server.sln
+```
+
+Expected: 0 errors
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IFakeBatteryPositionService.cs
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/FakeBatteryPositionService.cs
+git commit -m "feat(Robot): 鍋囩數鑺湇鍔″眰鏂板 MarkAsAvailable 鏂规硶"
+```
+
+---
+
+## Task 4: RobotTaskProcessor 鏂板鎵规鎸囦护杈呭姪鏂规硶
+
+**娉ㄦ剰锛�** `_fakeBatteryPositionService` 瀛楁宸插湪涓婁竴杞凯浠d腑娣诲姞锛屾棤闇�閲嶅娉ㄥ叆銆�
+
+**Files:**
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs`
+
+- [ ] **Step 1: 娣诲姞 BuildBatchRange 杈呭姪鏂规硶**
+
+鍦� `GetNextAvailableFakeBatteryPositions` 鏂规硶鍚庢坊鍔狅細
+
+```csharp
+        /// <summary>
+        /// 璁$畻鎵规缂栧彿鑼冨洿
+        /// </summary>
+        /// <remarks>
+        /// 杩斿洖鏍煎紡锛�(start, end)
+        /// - remaining >= 4: (currentIndex, currentIndex + 3)
+        /// - remaining > 1: (currentIndex, currentIndex + remaining - 1)
+        /// - remaining == 1: (currentIndex, 0)  -- 鍗曚釜鐗╁搧鐢� 0 琛ㄧず end
+        /// </remarks>
+        /// <param name="currentIndex">褰撳墠鎵规璧峰缂栧彿</param>
+        /// <param name="remaining">鍓╀綑鏁伴噺</param>
+        /// <returns>(start, end) 鍏冪粍</returns>
+        public (int Start, int End) BuildBatchRange(int currentIndex, int remaining)
+        {
+            if (remaining >= 4)
+                return (currentIndex, currentIndex + 3);
+            else if (remaining > 1)
+                return (currentIndex, currentIndex + remaining - 1);
+            else  // remaining == 1
+                return (currentIndex, 0);
+        }
+```
+
+- [ ] **Step 2: 娣诲姞 SendPickWithBatchAsync 鏂规硶**
+
+```csharp
+        /// <summary>
+        /// 涓嬪彂鍙栬揣鎸囦护锛堝甫鎵规鏍煎紡鍜屾�绘暟锛�
+        /// </summary>
+        /// <remarks>
+        /// 鍙戦�侀『搴忥細
+        /// 1. PickTotalNum,{N} -- 鐪熷疄鐢佃姱鎬绘暟
+        /// 2. Pickbattery,{浣嶇疆},{start}-{end} -- 鎵规鍙栬揣鎸囦护
+        ///
+        /// 涓嬪彂鎴愬姛鍚庢洿鏂颁换鍔$姸鎬佷负"鏈哄櫒浜烘墽琛屼腑"銆�
+        /// </remarks>
+        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
+        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+        /// <param name="position">鍙栬揣浣嶇疆</param>
+        /// <param name="batchStart">鎵规璧峰缂栧彿</param>
+        /// <param name="batchEnd">鎵规缁撴潫缂栧彿</param>
+        public async Task SendPickWithBatchAsync(Dt_RobotTask task, RobotSocketState state, string position, int batchStart, int batchEnd)
+        {
+            // 鍏堝彂閫佹�绘暟鎸囦护
+            string totalNumCmd = $"PickTotalNum,{task.RobotTaskTotalNum}";
+            await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
+
+            // 鍐嶅彂閫佹壒娆″彇璐ф寚浠�
+            string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
+            string taskString = $"Pickbattery,{position},{range}";
+
+            bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
+
+            if (result)
+            {
+                _logger.LogInformation("涓嬪彂鎵规鍙栬揣鎸囦护鎴愬姛锛屾寚浠�: {TaskString}锛屾壒娆�: {Range}锛岃澶�: {DeviceName}",
+                    taskString, range, state.RobotCrane?.DeviceName);
+                QuartzLogger.Info($"涓嬪彂鎵规鍙栬揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛屾壒娆�: {range}", state.RobotCrane?.DeviceName);
+
+                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
+                state.CurrentTask = task;
+
+                if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
+                {
+                    await _robotTaskService.UpdateRobotTaskAsync(task);
+                }
+            }
+            else
+            {
+                _logger.LogError("涓嬪彂鎵规鍙栬揣鎸囦护澶辫触锛屾寚浠�: {TaskString}锛岃澶�: {DeviceName}", taskString, state.RobotCrane?.DeviceName);
+                QuartzLogger.Error($"涓嬪彂鎵规鍙栬揣鎸囦护澶辫触锛屾寚浠�: {taskString}", state.RobotCrane?.DeviceName);
+            }
+        }
+```
+
+- [ ] **Step 3: 娣诲姞 SendPutWithBatchAsync 鏂规硶**
+
+```csharp
+        /// <summary>
+        /// 涓嬪彂鏀捐揣鎸囦护锛堝甫鎵规鏍煎紡鍜屾�绘暟锛�
+        /// </summary>
+        /// <remarks>
+        /// 鍙戦�侀『搴忥細
+        /// 1. PutTotalNum,{N} -- 鐪熷疄鐢佃姱鎬绘暟
+        /// 2. Putbattery,{浣嶇疆},{start}-{end} -- 鎵规鏀捐揣鎸囦护
+        ///
+        /// 涓嬪彂鎴愬姛鍚庢洿鏂颁换鍔$姸鎬佷负"鏈哄櫒浜烘墽琛屼腑"銆�
+        /// </remarks>
+        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
+        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+        /// <param name="position">鏀捐揣浣嶇疆</param>
+        /// <param name="batchStart">鎵规璧峰缂栧彿</param>
+        /// <param name="batchEnd">鎵规缁撴潫缂栧彿</param>
+        public async Task SendPutWithBatchAsync(Dt_RobotTask task, RobotSocketState state, string position, int batchStart, int batchEnd)
+        {
+            // 鍏堝彂閫佹�绘暟鎸囦护
+            string totalNumCmd = $"PutTotalNum,{task.RobotTaskTotalNum}";
+            await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
+
+            // 鍐嶅彂閫佹壒娆℃斁璐ф寚浠�
+            string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
+            string taskString = $"Putbattery,{position},{range}";
+
+            bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
+
+            if (result)
+            {
+                _logger.LogInformation("涓嬪彂鏀捐揣鎸囦护鎴愬姛锛屾寚浠�: {TaskString}锛屾壒娆�: {Range}锛岃澶�: {DeviceName}",
+                    taskString, range, state.RobotCrane?.DeviceName);
+                QuartzLogger.Info($"涓嬪彂鏀捐揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛屾壒娆�: {range}", state.RobotCrane?.DeviceName);
+
+                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
+                state.CurrentTask = task;
+
+                if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
+                {
+                    await _robotTaskService.UpdateRobotTaskAsync(task);
+                }
+            }
+            else
+            {
+                _logger.LogError("涓嬪彂鏀捐揣鎸囦护澶辫触锛屾寚浠�: {TaskString}锛岃澶�: {DeviceName}", taskString, state.RobotCrane?.DeviceName);
+                QuartzLogger.Error($"涓嬪彂鏀捐揣鎸囦护澶辫触锛屾寚浠�: {taskString}", state.RobotCrane?.DeviceName);
+            }
+        }
+```
+
+- [ ] **Step 4: 楠岃瘉缂栬瘧**
+
+```bash
+dotnet build WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj
+```
+
+Expected: 0 errors
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
+git commit -m "feat(Robot): RobotTaskProcessor 鏂板鎵规鎸囦护杈呭姪鏂规硶"
+```
+
+---
+
+## Task 5: RobotSimpleCommandHandler 娣诲姞闃舵瀹堝崼
+
+**Files:**
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs`
+
+- [ ] **Step 1: 淇敼 allpickfinished 鍒嗘敮**
+
+鎵惧埌 `case "allpickfinished":` 鍒嗘敮锛屾浛鎹负锛�
+
+```csharp
+                // 鍏ㄩ儴鍙栬揣瀹屾垚
+                case "allpickfinished":
+                    {
+                        state.CurrentAction = "AllPickFinished";
+
+                        var currentTask = state.CurrentTask;
+                        if (currentTask == null)
+                            return false;
+
+                        var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType;
+
+                        // 鎹㈢洏浠诲姟锛氫粎褰撴墍鏈夐樁娈靛畬鎴愭椂鎵嶅鐞嗗叆搴�
+                        if (robotTaskType == RobotTaskTypeEnum.ChangePallet)
+                        {
+                            if (state.ChangePalletPhase == 0)
+                            {
+                                // 鎵�鏈夐樁娈靛畬鎴愶紝澶勭悊鍏ュ簱
+                                if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true))
+                                {
+                                    _taskProcessor.DeleteTask(currentTask.RobotTaskId);
+                                    await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
+                                    QuartzLogger.Info($"鍙戦�佹秷鎭細銆怱wap,diskFinished銆�", state.RobotCrane.DeviceName);
+
+                                    // 閲嶇疆鎵规鐘舵��
+                                    state.ChangePalletPhase = 0;
+                                    state.CurrentBatchIndex = 1;
+                                    state.IsInFakeBatteryMode = false;
+                                    return true;
+                                }
+                            }
+                            // 涓棿闃舵涓嶅鐞嗭紝浠呮洿鏂扮姸鎬�
+                            return true;
+                        }
+
+                        // 鎷嗙洏浠诲姟锛氱洿鎺ュ鐞嗗叆搴�
+                        if (robotTaskType == RobotTaskTypeEnum.SplitPallet)
+                        {
+                            if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true))
+                            {
+                                _taskProcessor.DeleteTask(currentTask.RobotTaskId);
+                                await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
+                                QuartzLogger.Info($"鍙戦�佹秷鎭細銆怱wap,diskFinished銆�", state.RobotCrane.DeviceName);
+                                return true;
+                            }
+                        }
+                        return false;
+                    }
+```
+
+- [ ] **Step 2: 淇敼 allputfinished 鍒嗘敮**
+
+鎵惧埌 `case "allputfinished":` 鍒嗘敮锛屾浛鎹负锛�
+
+```csharp
+                // 鍏ㄩ儴鏀捐揣瀹屾垚
+                case "allputfinished":
+                    {
+                        state.CurrentAction = "AllPutFinished";
+
+                        var currentTask = state.CurrentTask;
+                        if (currentTask == null)
+                            return false;
+
+                        var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType;
+
+                        // 鎹㈢洏浠诲姟锛氫粎褰撴墍鏈夐樁娈靛畬鎴愭椂鎵嶅鐞嗗叆搴�
+                        if (robotTaskType == RobotTaskTypeEnum.ChangePallet)
+                        {
+                            if (state.ChangePalletPhase == 0)
+                            {
+                                // 鎵�鏈夐樁娈靛畬鎴愶紝澶勭悊鍏ュ簱
+                                if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false))
+                                {
+                                    _taskProcessor.DeleteTask(currentTask.RobotTaskId);
+                                    state.CurrentTask = null;
+                                    state.RobotTaskTotalNum = 0;
+                                    state.CellBarcode = new List<string>();
+
+                                    await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
+                                    QuartzLogger.Info($"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
+
+                                    // 閲嶇疆鎵规鐘舵��
+                                    state.ChangePalletPhase = 0;
+                                    state.CurrentBatchIndex = 1;
+                                    state.IsInFakeBatteryMode = false;
+                                    return true;
+                                }
+                            }
+                            // 涓棿闃舵涓嶅鐞嗭紝浠呮洿鏂扮姸鎬�
+                            return true;
+                        }
+
+                        // 缁勭洏浠诲姟锛氱洿鎺ュ鐞嗗叆搴�
+                        if (robotTaskType == RobotTaskTypeEnum.GroupPallet)
+                        {
+                            if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false))
+                            {
+                                _taskProcessor.DeleteTask(currentTask.RobotTaskId);
+                                state.CurrentTask = null;
+                                state.RobotTaskTotalNum = 0;
+                                state.CellBarcode = new List<string>();
+
+                                await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
+                                QuartzLogger.Info($"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
+                                return true;
+                            }
+                        }
+                        return false;
+                    }
+```
+
+- [ ] **Step 3: 楠岃瘉缂栬瘧**
+
+```bash
+dotnet build WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj
+```
+
+Expected: 0 errors
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
+git commit -m "feat(Robot): RobotSimpleCommandHandler 鎹㈢洏浠诲姟娣诲姞 ChangePalletPhase 闃舵瀹堝崼"
+```
+
+---
+
+## Task 6: RobotPrefixCommandHandler 淇敼 putfinished/pickfinished 澶勭悊閫昏緫
+
+**Files:**
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs`
+
+- [ ] **Step 1: 娣诲姞 IFakeBatteryPositionService 渚濊禆**
+
+鍦ㄧ被椤堕儴娣诲姞瀛楁鍜屾瀯閫犲嚱鏁板弬鏁帮細
+
+```csharp
+        /// <summary>
+        /// 鍋囩數鑺綅缃湇鍔�
+        /// </summary>
+        private readonly IFakeBatteryPositionService _fakeBatteryPositionService;
+
+        public RobotPrefixCommandHandler(
+            IRobotTaskService robotTaskService,
+            RobotTaskProcessor taskProcessor,
+            RobotStateManager stateManager,
+            ISocketClientGateway socketClientGateway,
+            IFakeBatteryPositionService fakeBatteryPositionService)
+        {
+            _robotTaskService = robotTaskService;
+            _taskProcessor = taskProcessor;
+            _stateManager = stateManager;
+            _socketClientGateway = socketClientGateway;
+            _fakeBatteryPositionService = fakeBatteryPositionService;
+        }
+```
+
+- [ ] **Step 2: 淇敼 HandlePutFinishedAsync 鏂规硶涓殑鏀捐揣澶勭悊閫昏緫**
+
+鎵惧埌 `if (putSuccess)` 鍧楋紙鐜版湁浠g爜绾﹀湪绗�258琛岄檮杩戯級锛屾浛鎹㈠叾涓殑鏀捐揣鎴愬姛澶勭悊閫昏緫涓猴細
+
+```csharp
+            // 濡傛灉鏀捐揣鎴愬姛
+            if (putSuccess)
+            {
+                state.CurrentAction = "PutFinished";
+
+                // 鍒ゆ柇鏄惁涓烘崲鐩樹换鍔′笖澶勪簬鎵规妯″紡
+                var isChangePallet = state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode();
+                var isFlowA = state.CurrentTask?.RobotSourceAddressLineCode is "11001" or "11010";
+
+                if (isChangePallet)
+                {
+                    if (state.ChangePalletPhase == 2)
+                    {
+                        if (isFlowA)
+                        {
+                            // 娴佸悜A Phase 2锛氭斁鍋囩數鑺埌鐩爣鎵樼洏锛屼笉璋冪敤 API锛屼笉閫掑璁℃暟
+                            // 涓嶅仛浠讳綍棰濆澶勭悊锛屼粎鏇存柊鐘舵��
+                        }
+                        else
+                        {
+                            // 娴佸悜B Phase 2锛氭斁姝e父鐢佃姱锛岄�掑璁℃暟
+                            state.RobotTaskTotalNum += positions.Length;
+                            if (task != null)
+                                task.RobotTaskTotalNum -= positions.Length;
+                        }
+                    }
+                    else if (state.ChangePalletPhase == 4)
+                    {
+                        // 娴佸悜B Phase 4锛氭斁鍋囩數鑺埌5鍙蜂綅锛屼笉璋冪敤 API锛屼笉閫掑璁℃暟锛岄噴鏀剧偣浣�
+                        _fakeBatteryPositionService.MarkAsAvailable(positions.ToList());
+                    }
+                    else
+                    {
+                        // 闈炴壒娆℃ā寮忔垨闈炴崲鐩樹换鍔★細閫掑璁℃暟
+                        state.RobotTaskTotalNum += positions.Length;
+                        if (task != null)
+                            task.RobotTaskTotalNum -= positions.Length;
+                    }
+                }
+                else
+                {
+                    // 闈炴崲鐩樹换鍔★細鍘熸湁閫昏緫
+                    state.RobotTaskTotalNum += positions.Length;
+                    if (task != null)
+                        task.RobotTaskTotalNum -= positions.Length;
+                }
+            }
+```
+
+- [ ] **Step 3: 淇敼 HandlePickFinishedAsync 鏂规硶**
+
+鎵惧埌 `if (state.IsSplitPallet)` 鍧楋紙鐜版湁浠g爜绾﹀湪绗�173-198琛岋級锛屾浛鎹负锛�
+
+```csharp
+            // 濡傛灉鏄媶鐩樹换鍔�
+            if (state.IsSplitPallet)
+            {
+                var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
+                state.LastPickPositions = positions;
+                var result = _taskProcessor.PostSplitPalletAsync(stockDTO);
+
+                if (result.Data.Status && result.IsSuccess)
+                {
+                    state.CurrentAction = "PickFinished";
+                }
+            }
+            // 鎹㈢洏浠诲姟鍙栧亣鐢佃姱鏃讹紙Phase 3锛変笉璋冪敤鎷嗙洏 API
+            else if (state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()
+                     && state.ChangePalletPhase == 3)
+            {
+                state.CurrentAction = "PickFinished";
+                state.LastPickPositions = positions;
+            }
+            else
+            {
+                state.CurrentAction = "PickFinished";
+                state.LastPickPositions = positions;
+            }
+```
+
+- [ ] **Step 4: 楠岃瘉缂栬瘧**
+
+```bash
+dotnet build WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj
+```
+
+Expected: 0 errors
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
+git commit -m "feat(Robot): RobotPrefixCommandHandler 鎹㈢洏浠诲姟鏍规嵁闃舵鍖哄垎澶勭悊閫昏緫"
+```
+
+---
+
+## Task 7: RobotWorkflowOrchestrator 閲嶅啓 HandlePutFinishedStateAsync 鐨� ChangePallet 鍒嗘敮
+
+**Files:**
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs`
+
+- [ ] **Step 1: 鏇挎崲 ChangePallet 鍒嗘敮閫昏緫**
+
+鎵惧埌 `else if (task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode())` 鍒嗘敮锛屽皢鍏跺畬鏁存浛鎹负锛�
+
+```csharp
+            else if (task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode())
+            {
+                const int targetTotal = 48;
+                int targetNormalCount = task.RobotTaskTotalNum;
+                int currentCompletedCount = stateForUpdate.RobotTaskTotalNum;
+
+                // 鍒ゆ柇娴佸悜锛坣ull-safe锛�
+                bool isFlowA = task.RobotSourceAddressLineCode is "11001" or "11010";
+
+                // 鐩爣鏁伴噺涓�48锛氱洿鎺ヨ蛋鍘熸湁閫昏緫锛屼笉杩涘叆鎵规妯″紡
+                if (targetNormalCount == targetTotal)
+                {
+                    await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate);
+                    return;
+                }
+
+                // 鍒濆鍖栨壒娆℃ā寮�
+                if (stateForUpdate.ChangePalletPhase == 0)
+                {
+                    stateForUpdate.ChangePalletPhase = 1;
+                    stateForUpdate.CurrentBatchIndex = 1;
+                    _logger.LogInformation("HandlePutFinishedStateAsync锛氭崲鐩樹换鍔¤繘鍏ユ壒娆℃ā寮忥紝浠诲姟鍙�: {TaskNum}锛屾祦鍚�: {Flow}",
+                        task.RobotTaskNum, isFlowA ? "A" : "B");
+                }
+
+                // ==================== 娴佸悜A锛氳ˉ鍋囩數鑺埌鐩爣鎵樼洏 ====================
+                if (isFlowA)
+                {
+                    // Phase 1: 鍙栧亣鐢佃姱锛堜粠5鍙蜂綅锛屼娇鐢� PositionIndex锛�
+                    if (stateForUpdate.ChangePalletPhase == 1)
+                    {
+                        int remaining = targetTotal - currentCompletedCount;
+                        if (remaining <= 0)
+                        {
+                            stateForUpdate.ChangePalletPhase = 0;
+                            stateForUpdate.CurrentBatchIndex = 1;
+                            stateForUpdate.IsInFakeBatteryMode = false;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭祦鍚慉瀹屾垚锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        int pickCount = Math.Min(4, remaining);
+                        var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(pickCount);
+                        if (positions.Count == 0)
+                        {
+                            _logger.LogError("HandlePutFinishedStateAsync锛氭棤鍙敤鍋囩數鑺偣浣嶏紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        await _taskProcessor.SendSocketRobotFakeBatteryPickAsync(task, stateForUpdate, positions);
+                        stateForUpdate.ChangePalletPhase = 2;
+                    }
+                    // Phase 2: 鏀惧亣鐢佃姱鍒扮洰鏍囨墭鐩橈紙浠� targetNormalCount+1 寮�濮嬮�掑锛�
+                    else if (stateForUpdate.ChangePalletPhase == 2)
+                    {
+                        int remaining = targetTotal - currentCompletedCount;
+                        if (remaining <= 0)
+                        {
+                            stateForUpdate.ChangePalletPhase = 0;
+                            stateForUpdate.CurrentBatchIndex = 1;
+                            stateForUpdate.IsInFakeBatteryMode = false;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭祦鍚慉瀹屾垚锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        // 璁$畻鏀捐揣鎵规缂栧彿锛氫粠 targetNormalCount + 1 寮�濮�
+                        int batchStart = targetNormalCount + 1 + (stateForUpdate.CurrentBatchIndex - 1);
+                        int putCount = Math.Min(4, remaining);
+                        var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount);
+
+                        await _taskProcessor.SendPutWithBatchAsync(task, stateForUpdate, task.RobotTargetAddress, start, end);
+
+                        stateForUpdate.CurrentBatchIndex += putCount;
+                        stateForUpdate.ChangePalletPhase = 1;
+                    }
+                }
+                // ==================== 娴佸悜B锛氬彇姝e父鐢佃姱 + 鍥炴敹鍋囩數鑺� ====================
+                else
+                {
+                    // Phase 1: 鍙栨甯哥數鑺紙浠庢簮鍦板潃锛屼粠1寮�濮嬮�掑锛�
+                    if (stateForUpdate.ChangePalletPhase == 1)
+                    {
+                        int remainingNormal = targetNormalCount - currentCompletedCount;
+
+                        int pickCount = Math.Min(4, remainingNormal);
+                        var (start, end) = _taskProcessor.BuildBatchRange(stateForUpdate.CurrentBatchIndex, pickCount);
+
+                        await _taskProcessor.SendPickWithBatchAsync(task, stateForUpdate, task.RobotSourceAddress, start, end);
+
+                        // 閫掑鎵规绱㈠紩锛堝鏋滃垰濂藉彇瀹屾渶鍚庝竴涓紝绱㈠紩浼氳秴杩囩洰鏍囷紝浣唒utfinished鍥炴潵鏃朵細鍒囨崲闃舵锛�
+                        stateForUpdate.CurrentBatchIndex += pickCount;
+
+                        // 鍒囨崲鍒� Phase 2
+                        stateForUpdate.ChangePalletPhase = 2;
+                    }
+                    // Phase 2: 鏀炬甯哥數鑺埌鐩爣鎵樼洏锛堟斁璐х紪鍙蜂笌鍙栬揣缂栧彿涓�鑷达級
+                    else if (stateForUpdate.ChangePalletPhase == 2)
+                    {
+                        int remainingNormal = targetNormalCount - currentCompletedCount;
+                        if (remainingNormal <= 0)
+                        {
+                            // 姝e父鐢佃姱鏀惧畬锛屽垏鎹㈠埌 Phase 3
+                            stateForUpdate.ChangePalletPhase = 3;
+                            stateForUpdate.CurrentBatchIndex = targetNormalCount + 1;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭甯哥數鑺叏閮ㄦ斁瀹岋紝杩涘叆Phase 3鍥炴敹鍋囩數鑺紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        // 璁$畻鏈壒鏀捐揣缂栧彿锛氬熀浜� currentCompletedCount 鎺ㄥ鎵规璧峰锛堜笌鍙栬揣缂栧彿涓�鑷达級
+                        // batchStart = ((currentCompletedCount - 1) / 4) * 4 + 1
+                        int batchStart = ((currentCompletedCount - 1) / 4) * 4 + 1;
+                        int putCount = Math.Min(4, remainingNormal);
+                        var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount);
+
+                        await _taskProcessor.SendPutWithBatchAsync(task, stateForUpdate, task.RobotTargetAddress, start, end);
+
+                        stateForUpdate.ChangePalletPhase = 1;
+                    }
+                    // Phase 3: 鍙栧亣鐢佃姱锛堜粠婧愬湴鍧�锛屼粠 targetNormalCount+1 寮�濮嬮�掑锛�
+                    else if (stateForUpdate.ChangePalletPhase == 3)
+                    {
+                        int fakeCount = targetTotal - targetNormalCount;
+                        int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount);
+                        int remainingFake = fakeCount - completedFake;
+
+                        if (remainingFake <= 0)
+                        {
+                            stateForUpdate.ChangePalletPhase = 0;
+                            stateForUpdate.CurrentBatchIndex = 1;
+                            stateForUpdate.IsInFakeBatteryMode = false;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭祦鍚態瀹屾垚锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        int pickCount = Math.Min(4, remainingFake);
+                        var (start, end) = _taskProcessor.BuildBatchRange(stateForUpdate.CurrentBatchIndex, pickCount);
+
+                        await _taskProcessor.SendPickWithBatchAsync(task, stateForUpdate, task.RobotSourceAddress, start, end);
+
+                        stateForUpdate.CurrentBatchIndex += pickCount;
+                        stateForUpdate.ChangePalletPhase = 4;
+                    }
+                    // Phase 4: 鏀惧亣鐢佃姱鍒�5鍙蜂綅锛堜娇鐢� PositionIndex锛�
+                    else if (stateForUpdate.ChangePalletPhase == 4)
+                    {
+                        int fakeCount = targetTotal - targetNormalCount;
+                        int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount);
+                        int remainingFake = fakeCount - completedFake;
+
+                        if (remainingFake <= 0)
+                        {
+                            stateForUpdate.ChangePalletPhase = 0;
+                            stateForUpdate.CurrentBatchIndex = 1;
+                            stateForUpdate.IsInFakeBatteryMode = false;
+                            _logger.LogInformation("HandlePutFinishedStateAsync锛氭祦鍚態瀹屾垚锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(Math.Min(4, remainingFake));
+                        if (positions.Count == 0)
+                        {
+                            _logger.LogError("HandlePutFinishedStateAsync锛氭棤鍙敤鍋囩數鑺偣浣嶏紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        int start = positions.Min();
+                        int end = positions.Max();
+
+                        await _taskProcessor.SendPutWithBatchAsync(task, stateForUpdate, "5", start, end);
+
+                        stateForUpdate.ChangePalletPhase = 3;
+                    }
+                }
+            }
+```
+
+- [ ] **Step 2: 楠岃瘉缂栬瘧**
+
+```bash
+dotnet build WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj
+```
+
+Expected: 0 errors
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
+git commit -m "feat(Robot): RobotWorkflowOrchestrator 閲嶅啓 HandlePutFinishedStateAsync 瀹炵幇鎵规鎸囦护涓庡弻娴佸悜"
+```
+
+---
+
+## Task 8: RobotWorkflowOrchestrator 閲嶅啓 HandlePickFinishedStateAsync 鐨� ChangePallet 鍒嗘敮
+
+**Files:**
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs`
+
+- [ ] **Step 1: 淇敼 HandlePickFinishedStateAsync 鏂规硶**
+
+鎵惧埌 `HandlePickFinishedStateAsync` 鏂规硶锛堢幇鏈変唬鐮佺害绗�162-199琛岋級锛屽皢鏁翠釜鏂规硶鏇挎崲涓猴細
+
+```csharp
+        /// <summary>
+        /// 澶勭悊鍙栬揣瀹屾垚鍚庣殑鏀捐揣鎸囦护
+        /// </summary>
+        /// <remarks>
+        /// 鏍规嵁浠诲姟绫诲瀷鍐冲畾鏀捐揣鎸囦护鏍煎紡锛�
+        /// - 鎹㈢洏浠诲姟锛圕hangePallet锛夛細浣跨敤鎵规鏍煎紡 SendPutWithBatchAsync
+        /// - 缁勭洏浠诲姟锛圙roupPallet锛夛細浣跨敤鍘熸湁鏍煎紡 Putbattery,{鐩爣鍦板潃}
+        /// - 鍏朵粬浠诲姟锛氫娇鐢ㄥ師鏈夋牸寮�
+        /// </remarks>
+        /// <param name="task">褰撳墠浠诲姟</param>
+        /// <param name="ipAddress">鏈哄櫒浜� IP 鍦板潃</param>
+        private async Task HandlePickFinishedStateAsync(Dt_RobotTask task, string ipAddress)
+        {
+            string taskString;
+
+            // 鎹㈢洏浠诲姟浣跨敤鎵规鏍煎紡
+            if (task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode())
+            {
+                int targetNormalCount = task.RobotTaskTotalNum;
+                var state = _stateManager.GetState(ipAddress);
+                int currentCompletedCount = state?.RobotTaskTotalNum ?? 0;
+
+                bool isFlowA = task.RobotSourceAddressLineCode is "11001" or "11010";
+
+                // 娴佸悜A锛氭斁鍋囩數鑺埌鐩爣鎵樼洏锛圥hase 2锛�
+                if (isFlowA && state?.ChangePalletPhase == 2)
+                {
+                    int remaining = 48 - currentCompletedCount;
+                    if (remaining <= 0) return;
+
+                    // 璁$畻鎵规缂栧彿锛氫粠 targetNormalCount + 1 寮�濮�
+                    int batchStart = targetNormalCount + 1;
+                    int putCount = Math.Min(4, remaining);
+                    var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount);
+
+                    await _taskProcessor.SendPutWithBatchAsync(task, state, task.RobotTargetAddress, start, end);
+                    return;
+                }
+
+                // 娴佸悜B Phase 4锛氭斁鍋囩數鑺埌5鍙蜂綅
+                if (!isFlowA && state?.ChangePalletPhase == 4)
+                {
+                    int fakeCount = 48 - targetNormalCount;
+                    int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount);
+                    int remainingFake = fakeCount - completedFake;
+
+                    if (remainingFake <= 0) return;
+
+                    var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(Math.Min(4, remainingFake));
+                    if (positions.Count == 0)
+                    {
+                        _logger.LogError("HandlePickFinishedStateAsync锛氭棤鍙敤鍋囩數鑺偣浣嶏紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                        return;
+                    }
+
+                    int start = positions.Min();
+                    int end = positions.Max();
+
+                    await _taskProcessor.SendPutWithBatchAsync(task, state, "5", start, end);
+                    return;
+                }
+
+                // 娴佸悜B Phase 2锛氭斁姝e父鐢佃姱鍒扮洰鏍囨墭鐩�
+                if (!isFlowA && state?.ChangePalletPhase == 2)
+                {
+                    int remainingNormal = targetNormalCount - currentCompletedCount;
+                    if (remainingNormal <= 0) return;
+
+                    int batchStart = state.CurrentBatchIndex - (state.CurrentBatchIndex - 1) / 4 * 4;
+                    int putCount = Math.Min(4, remainingNormal);
+                    var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount);
+
+                    await _taskProcessor.SendPutWithBatchAsync(task, state, task.RobotTargetAddress, start, end);
+                    return;
+                }
+
+                // 榛樿锛氫娇鐢ㄥ師鏈夋牸寮�
+                taskString = $"Putbattery,{task.RobotTargetAddress}";
+            }
+            else
+            {
+                // 闈炴崲鐩樹换鍔★細浣跨敤鍘熸湁鏍煎紡
+                taskString = $"Putbattery,{task.RobotTargetAddress}";
+            }
+
+            bool result = await _clientManager.SendToClientAsync(ipAddress, taskString);
+
+            if (result)
+            {
+                _logger.LogInformation("HandlePickFinishedStateAsync锛氫笅鍙戞斁璐ф寚浠ゆ垚鍔燂紝鎸囦护: {TaskString}锛屼换鍔″彿: {TaskNum}", taskString, task.RobotTaskNum);
+                QuartzLogger.Info($"涓嬪彂鏀捐揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}", task.RobotRoadway);
+
+                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
+
+                var stateToUpdate = _stateManager.GetState(ipAddress);
+                if (stateToUpdate != null)
+                {
+                    stateToUpdate.CurrentTask = task;
+
+                    if (_stateManager.TryUpdateStateSafely(ipAddress, stateToUpdate))
+                    {
+                        await _robotTaskService.UpdateRobotTaskAsync(task);
+                    }
+                }
+            }
+            else
+            {
+                _logger.LogError("HandlePickFinishedStateAsync锛氫笅鍙戞斁璐ф寚浠ゅけ璐ワ紝鎸囦护: {TaskString}锛屼换鍔″彿: {TaskNum}", taskString, task.RobotTaskNum);
+                QuartzLogger.Error($"涓嬪彂鏀捐揣鎸囦护澶辫触锛屾寚浠�: {taskString}", task.RobotRoadway);
+            }
+        }
+```
+
+- [ ] **Step 2: 楠岃瘉缂栬瘧**
+
+```bash
+dotnet build WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj
+```
+
+Expected: 0 errors
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
+git commit -m "feat(Robot): RobotWorkflowOrchestrator 閲嶅啓 HandlePickFinishedStateAsync 鏀寔鎵规鎸囦护"
+```
+
+---
+
+## Task 9: 娉ㄥ唽渚濊禆娉ㄥ叆
+
+**Files:**
+- Modify: AutofacModuleRegister.cs 鎴栨鏌ョ幇鏈夋敞鍐�
+
+- [ ] **Step 1: 妫�鏌� FakeBatteryPositionService 鏄惁宸茶嚜鍔ㄦ敞鍐�**
+
+```bash
+grep -r "FakeBatteryPositionService" D:\Git\ShanMeiXinNengYuan\Code\WCS\WIDESEAWCS_Server\WIDESEAWCS_Core --include="*.cs"
+```
+
+Expected: 濡傛灉椤圭洰浣跨敤 `AsImplementedInterfaces()` 鑷姩鎵弿锛岃鏈嶅姟宸茶嚜鍔ㄦ敞鍐屻��
+
+- [ ] **Step 2: 妫�鏌� RobotPrefixCommandHandler 鏋勯�犲嚱鏁板彉鏇村悗鏄惁闇�瑕侀澶栨敞鍐�**
+
+鐢变簬浠呮柊澧炰簡渚濊禆鍙傛暟锛屽鏋滈」鐩娇鐢� Autofac 鑷姩瑁呴厤锛堝弬鏁拌嚜鍔ㄦ敞鍏ワ級锛屽垯鏃犻渶淇敼銆傚鏋滈渶瑕佹墜鍔ㄦ敞鍐岋紝娣诲姞锛�
+
+```csharp
+// 纭繚 IFakeBatteryPositionService 宸茶娉ㄥ唽锛堥�氬父閫氳繃 AsImplementedInterfaces 鑷姩瀹屾垚锛�
+// RobotPrefixCommandHandler 鐨勬柊鏋勯�犲嚱鏁板弬鏁颁細鑷姩瑁呴厤
+```
+
+- [ ] **Step 3: 楠岃瘉缂栬瘧**
+
+```bash
+dotnet build WIDESEAWCS_Server.sln
+```
+
+Expected: 0 errors
+
+- [ ] **Step 4: Commit**锛堜粎褰撴湁瀹為檯鏀瑰姩鏃舵墠鎻愪氦锛�
+
+```bash
+git add <淇敼鐨勬枃浠�>
+git commit -m "feat(Robot): 娉ㄥ唽渚濊禆娉ㄥ叆锛堝鏈夋敼鍔級"
+```
+
+---
+
+## Task 10: 楠岃瘉鏁翠綋鏋勫缓
+
+- [ ] **Step 1: 瀹屾暣鏋勫缓**
+
+```bash
+cd D:\Git\ShanMeiXinNengYuan\Code
+dotnet build WCS/WIDESEAWCS_Server/WIDESEAWCS_Server.sln
+```
+
+Expected: 0 errors, 0 warnings
+
+- [ ] **Step 2: 妫�鏌ユ祴璇�**
+
+```bash
+dotnet test WCS/WIDESEAWCS_Tests/WIDESEAWCS_Tests.csproj
+```
+
+Expected: 鐜版湁娴嬭瘯閫氳繃
+
+- [ ] **Step 3: 鎻愪氦瀹屾垚鏍囪**
+
+```bash
+git commit --allow-empty -m "feat(Robot): 鎹㈢洏浠诲姟鎵规鎸囦护涓庡弻娴佸悜瀹炵幇瀹屾垚"
+```
+
+---
+
+## 闄勫綍锛氭祴璇曢獙璇佹楠�
+
+### 鎵嬪姩楠岃瘉娴佺▼
+
+1. **娴佸悜A娴嬭瘯锛圧obotSourceAddressLineCode = 11001锛�**
+   - targetNormalCount = 11
+   - 棰勬湡锛歅hase1 鍙栧亣鐢佃姱锛圥ickbattery,5,{pos}锛夆啋 Phase2 鏀惧亣鐢佃姱锛圥utbattery,{鐩爣},12-15锛夆啋 寰幆鐩村埌48
+
+2. **娴佸悜B娴嬭瘯锛圧obotSourceAddressLineCode != 11001/11010锛�**
+   - targetNormalCount = 11
+   - 棰勬湡锛歅hase1 鍙栨甯革紙Pickbattery,{婧恾,1-4锛夆啋 Phase2 鏀炬甯革紙Putbattery,{鐩爣},1-4锛夆啋 寰幆 鈫� Phase3 鍙栧亣锛圥ickbattery,{婧恾,12-15锛夆啋 Phase4 鏀惧亣鍒�5鍙蜂綅锛圥utbattery,5,{pos}锛夆啋 寰幆鐩村埌鍥炴敹瀹�37涓亣鐢佃姱
+
+3. **杈圭晫鏉′欢**
+   - targetNormalCount = 48锛氳蛋鍘熸湁閫昏緫
+   - targetNormalCount = 1锛氭壒娆� 1-0 鏍煎紡
+
+---
+
+**Plan complete.**
diff --git a/Code/docs/superpowers/specs/2026-04-16-change-pallet-batch-command-design.md b/Code/docs/superpowers/specs/2026-04-16-change-pallet-batch-command-design.md
new file mode 100644
index 0000000..a3f0f7d
--- /dev/null
+++ b/Code/docs/superpowers/specs/2026-04-16-change-pallet-batch-command-design.md
@@ -0,0 +1,180 @@
+# 鎹㈢洏浠诲姟鎵规鎸囦护涓庡弻娴佸悜璁捐
+
+## 姒傝堪
+
+瀵规崲鐩樹换鍔★紙ChangePallet锛夌殑鍙栬揣/鏀捐揣鎸囦护鏍煎紡杩涜鍗囩骇锛屾敮鎸佹壒娆$紪鍙峰拰鎬绘暟鎸囦护锛屽苟鏍规嵁 `RobotSourceAddressLineCode` 鍖哄垎涓ょ娴佸悜銆�
+
+## 鑳屾櫙
+
+褰撳墠鎹㈢洏浠诲姟瀹炵幇锛堜笂涓�杞凯浠o級浠呭鐞嗕簡 `HandlePutFinishedStateAsync` 涓殑鍋囩數鑺ˉ鍏呴�昏緫锛屾寚浠ゆ牸寮忎负绠�鍗曠殑 `Pickbattery,{鍦板潃}` 鍜� `Pickbattery,5,{start}-{end}`銆傜幇闇�瑕侊細
+
+1. 鎵�鏈夋崲鐩樺彇璐�/鏀捐揣鎸囦护缁熶竴涓烘壒娆℃牸寮� `{Command},{浣嶇疆},{start}-{end}`
+2. 姣忔壒鍓嶅彂閫佹�绘暟鎸囦护 `PickTotalNum,{N}` / `PutTotalNum,{N}`
+3. 鏍规嵁婧愬湴鍧�绾夸綋缂栫爜鍖哄垎涓ょ瀹屽叏涓嶅悓鐨勬搷浣滄祦鍚�
+
+## 鎸囦护鏍煎紡
+
+### 鎵规鎸囦护
+
+| 鎸囦护绫诲瀷 | 鏍煎紡 | 绀轰緥 |
+|----------|------|------|
+| 鍙栬揣鎬绘暟 | `PickTotalNum,{N}` | `PickTotalNum,11` |
+| 鏀捐揣鎬绘暟 | `PutTotalNum,{N}` | `PutTotalNum,11` |
+| 鍙栬揣鎵规 | `Pickbattery,{浣嶇疆},{start}-{end}` | `Pickbattery,3,1-4` |
+| 鏀捐揣鎵规 | `Putbattery,{浣嶇疆},{start}-{end}` | `Putbattery,6,5-8` |
+| 鍙栬揣鍗曚釜 | `Pickbattery,{浣嶇疆},{n}-0` | `Pickbattery,3,11-0` |
+| 鏀捐揣鍗曚釜 | `Putbattery,{浣嶇疆},{n}-0` | `Putbattery,6,11-0` |
+
+- `PickTotalNum/PutTotalNum` 浠呮崲鐩樹换鍔″彂閫侊紝姣忔壒鍙�/鏀句箣鍓嶉兘鍙�
+- `N` = 鐪熷疄鐢佃姱鏁伴噺锛堝嵆 `task.RobotTaskTotalNum`锛夛紝鏈哄櫒浜哄浐浠剁敤姝ゅ�煎垽鏂墭鐩樹笂姝e父鐢佃姱鎬绘暟锛屼袱绉嶆祦鍚戝潎鍙戦�佺浉鍚岀殑 N 鍊�
+- 姣忔壒鏈�澶�4涓紝涓嶆弧4涓寜瀹為檯鏁板彂锛屽墿1涓椂 end=0
+
+### 鎵规缂栧彿璁$畻
+
+`BuildBatchRange(currentIndex, remaining)` 鈫� `(start, end)`:
+- `remaining >= 4` 鈫� `(currentIndex, currentIndex + 3)`
+- `remaining > 1` 鈫� `(currentIndex, currentIndex + remaining - 1)`
+- `remaining == 1` 鈫� `(currentIndex, 0)`
+
+绀轰緥锛坱argetNormalCount=11锛夛細绗�1鎵� 1-4锛岀2鎵� 5-8锛岀3鎵� 9-11
+绀轰緥锛坱argetNormalCount=9锛夛細绗�1鎵� 1-4锛岀2鎵� 5-8锛岀3鎵� 9-0锛堝崟涓紝end=0锛�
+
+## 涓ょ娴佸悜
+
+### 娴佸悜A锛氳ˉ鍋囩數鑺埌鐩爣鎵樼洏
+
+**鏉′欢锛�** `RobotSourceAddressLineCode == "11001" || "11010"`
+
+**鍦烘櫙锛�** 鐩爣鎵樼洏鏈� N 涓甯哥數鑺紙N < 48锛夛紝闇�浠�5鍙蜂綅鍋囩數鑺墭鐩樺彇鍋囩數鑺ˉ婊�48涓��
+
+**闃舵娴佽浆锛�**
+
+```
+[鍙栧亣鐢佃姱] Pickbattery,5,{positionIndex}        鈫� 浠�5鍙蜂綅鍙栵紝缂栧彿鐢ㄥ钩闈㈢偣浣嶈〃PositionIndex
+    鈫�
+[鏀惧亣鐢佃姱] Putbattery,{鐩爣鍦板潃},{N+1}-{N+4}    鈫� 鏀惧埌鐩爣鎵樼洏锛岀紪鍙蜂粠姝e父鏁�+1閫掑
+    鈫�
+閲嶅鐩村埌琛ユ弧48涓�
+```
+
+鍋囩數鑺暟閲� = `48 - task.RobotTaskTotalNum`
+
+### 娴佸悜B锛氬彇姝e父鐢佃姱 + 鍥炴敹鍋囩數鑺�
+
+**鏉′欢锛�** `RobotSourceAddressLineCode != "11001" && != "11010"`
+
+**鍦烘櫙锛�** 婧愭墭鐩樺師鏈弧48涓紙姝e父鐢佃姱 + 鍋囩數鑺贩鍚堬級锛屽厛鍙栬蛋姝e父鐢佃姱鏀惧埌鐩爣鎵樼洏锛屽啀鎶婃簮鎵樼洏涓婂墿浣欑殑鍋囩數鑺彇鍑烘斁鍥�5鍙蜂綅銆�
+
+**闃舵娴佽浆锛�**
+
+```
+Phase 1 - 鍙栨甯哥數鑺�:
+[鍙栨甯竇 Pickbattery,{婧愬湴鍧�},{1}-{4}            鈫� 缂栧彿浠�1閫掑
+    鈫�
+[鏀炬甯竇 Putbattery,{鐩爣鍦板潃},{1}-{4}           鈫� 缂栧彿浠�1閫掑
+    鈫�
+閲嶅鐩村埌 N 涓甯哥數鑺叏閮ㄥ彇瀹�
+
+Phase 2 - 鍥炴敹鍋囩數鑺�:
+[鍙栧亣鐢佃姱] Pickbattery,{婧愬湴鍧�},{N+1}-{N+4}     鈫� 缂栧彿浠庢甯告暟+1缁х画閫掑
+    鈫�
+[鏀惧亣鐢佃姱] Putbattery,5,{positionIndex}          鈫� 鏀惧洖5鍙蜂綅锛岀紪鍙风敤骞抽潰鐐逛綅琛≒ositionIndex
+    鈫�
+閲嶅鐩村埌鍋囩數鑺叏閮ㄥ洖鏀讹紙48-N 涓級
+```
+
+## 鐘舵�佺鐞�
+
+### RobotSocketState 鏂板瀛楁
+
+```csharp
+/// <summary>
+/// 褰撳墠鎵规璧峰缂栧彿锛堢敤浜庨�掑璁$畻鍙栬揣/鏀捐揣缂栧彿锛�
+/// </summary>
+public int CurrentBatchIndex { get; set; } = 1;
+
+/// <summary>
+/// 鎹㈢洏浠诲姟褰撳墠闃舵
+/// </summary>
+/// <remarks>
+/// 0: 鏈紑濮�
+/// 1: 鍙栨甯哥數鑺� / 鍙栧亣鐢佃姱锛堟祦鍚慉锛�
+/// 2: 鏀炬甯哥數鑺� / 鏀惧亣鐢佃姱锛堟祦鍚慉锛�
+/// 3: 鍙栧亣鐢佃姱锛堟祦鍚態 Phase2锛�
+/// 4: 鏀惧亣鐢佃姱鍒�5鍙蜂綅锛堟祦鍚態 Phase2锛�
+/// </remarks>
+public int ChangePalletPhase { get; set; }
+```
+
+### CurrentBatchIndex 鐢熷懡鍛ㄦ湡
+
+**娴佸悜A锛�**
+- Phase 0鈫�1锛歚CurrentBatchIndex = 1`锛堝垵濮嬪寲锛岀敤浜� PositionIndex 鏌ヨ璧风偣锛�
+- Phase 1鈫�2锛氫笉閲嶇疆锛堟斁璐х紪鍙蜂粠 `targetNormalCount + 1` 寮�濮嬶紝鐢� Orchestrator 璁$畻锛�
+- Phase 2鈫�1锛歚CurrentBatchIndex += 鏈壒鏁伴噺`锛堥�掑锛屼笅涓�鎵圭户缁級
+- 瀹屾垚鈫�0锛歚CurrentBatchIndex = 1`锛堥噸缃級
+
+**娴佸悜B锛�**
+- Phase 0鈫�1锛歚CurrentBatchIndex = 1`锛堝彇姝e父鐢佃姱浠�1寮�濮嬶級
+- Phase 1鈫�2锛氫笉閲嶇疆锛堟斁璐х紪鍙蜂笌鍙栬揣缂栧彿涓�鑷达級
+- Phase 2鈫�1锛歚CurrentBatchIndex += 鏈壒鏁伴噺`锛堥�掑锛�
+- Phase 2鈫�3锛堟甯哥數鑺彇瀹岋紝鍗� `state.RobotTaskTotalNum >= targetNormalCount` 鏃� putfinished 瀹屾垚鍚庤Е鍙戯級锛歚CurrentBatchIndex = targetNormalCount + 1`锛堝亣鐢佃姱浠庢甯告暟+1寮�濮嬶級
+- Phase 3鈫�4锛氫笉閲嶇疆锛堟斁鍋囩數鑺敤 PositionIndex锛岀敱 Orchestrator 璁$畻锛�
+- Phase 4鈫�3锛歚CurrentBatchIndex += 鏈壒鏁伴噺`锛堥�掑锛�
+- 瀹屾垚鈫�0锛歚CurrentBatchIndex = 1`锛堥噸缃級
+
+### 闃舵娴佽浆鐘舵�佹満
+
+**娴佸悜A锛�**
+```
+Phase 0 鈫� Phase 1锛堝彇鍋囩數鑺痜rom 5鍙蜂綅锛夆啋 Phase 2锛堟斁鍋囩數鑺痶o 鐩爣锛夆啋 Phase 1 鈫� ... 鈫� Phase 0锛堝畬鎴愶級
+```
+
+**娴佸悜B锛�**
+```
+Phase 0 鈫� Phase 1锛堝彇姝e父from 婧愶級鈫� Phase 2锛堟斁姝e父to 鐩爣锛夆啋 Phase 1 鈫� ... 
+        鈫� Phase 3锛堝彇鍋囩數鑺痜rom 婧愶級鈫� Phase 4锛堟斁鍋囩數鑺痶o 5鍙蜂綅锛夆啋 Phase 3 鈫� ... 鈫� Phase 0锛堝畬鎴愶級
+```
+
+## 浠g爜鏀瑰姩鑼冨洿
+
+| 鏂囦欢 | 鏀瑰姩 |
+|------|------|
+| `RobotSocketState.cs` | +`CurrentBatchIndex`, +`ChangePalletPhase` |
+| `RobotTaskProcessor.cs` | +`BuildBatchRange()`, +`SendPickWithBatchAsync()`, +`SendPutWithBatchAsync()`, 淇敼鐜版湁鍋囩數鑺柟娉� |
+| `RobotWorkflowOrchestrator.cs` | 閲嶅啓 ChangePallet 鍒嗘敮锛圚andlePutFinishedStateAsync + HandlePickFinishedStateAsync锛� |
+| `RobotPrefixCommandHandler.cs` | HandlePutFinishedAsync 涓尯鍒嗘崲鐩橀樁娈碉細鍋囩數鑺斁璐т笉璋冪敤 ChangePalletAsync API锛屼笉閫掑 `RobotTaskTotalNum`锛汬andlePickFinishedAsync 涓亣鐢佃姱鍙栬揣涓嶈皟鐢ㄦ媶鐩� API |
+| `RobotSimpleCommandHandler.cs` | allpickfinished/allputfinished 涓鍔� `ChangePalletPhase` 瀹堝崼锛氫粎褰� Phase==0锛堟墍鏈夐樁娈靛畬鎴愶級鏃舵墠瑙﹀彂鍏ュ簱鍜屽垹闄や换鍔★紝涓棿闃舵涓嶅鐞� |
+| `IFakeBatteryPositionService.cs` | +`MarkAsAvailable(List<int> positions)` 鏂规硶 |
+| `FakeBatteryPositionService.cs` | +`MarkAsAvailable` 瀹炵幇 |
+| `IFakeBatteryPositionRepository.cs` | +`MarkAsAvailable(List<int> positions)` 鏂规硶 |
+| `FakeBatteryPositionRepository.cs` | +`MarkAsAvailable` 瀹炵幇锛堝皢鎸囧畾鐐逛綅 IsUsed 璁句负 false锛� |
+
+## 鍛戒护澶勭悊鍣ㄤ氦浜�
+
+### RobotPrefixCommandHandler 鍙樻洿
+
+**pickfinished 澶勭悊锛�**
+- 褰� `ChangePalletPhase == 3`锛堟祦鍚態鍙栧亣鐢佃姱锛夋椂锛屼笉璋冪敤鎷嗙洏 API锛屼粎鏇存柊鐘舵��
+- 鍏朵粬闃舵淇濇寔鐜版湁閫昏緫
+
+**putfinished 澶勭悊锛�**
+- 鍒ゆ柇娴佸悜锛氶�氳繃 `state.CurrentTask.RobotSourceAddressLineCode` 鍒ゆ柇鏄祦鍚慉杩樻槸娴佸悜B
+- 褰� `ChangePalletPhase == 2` 涓旀祦鍚態锛堟斁姝e父鐢佃姱锛夋椂锛屾甯歌皟鐢� ChangePalletAsync API锛宍state.RobotTaskTotalNum += positions.Length`
+- 褰� `ChangePalletPhase == 4`锛堟祦鍚態鏀惧亣鐢佃姱鍒�5鍙蜂綅锛夋椂锛屼笉璋冪敤 API锛屼笉閫掑 `RobotTaskTotalNum`锛岃皟鐢� `MarkAsAvailable(positions)` 閲婃斁鐐逛綅
+- 褰� `ChangePalletPhase == 2` 涓旀祦鍚慉锛堟斁鍋囩數鑺埌鐩爣锛夋椂锛屼笉璋冪敤 API锛屼笉閫掑 `RobotTaskTotalNum`
+
+### RobotSimpleCommandHandler 鍙樻洿
+
+**allpickfinished / allputfinished锛�**
+- 澧炲姞瀹堝崼鏉′欢锛氫粎褰� `state.ChangePalletPhase == 0`锛堟墍鏈夐樁娈靛畬鎴愶級鏃讹紝鎵嶆墽琛屽叆搴撳洖浼犲拰浠诲姟鍒犻櫎
+- 涓棿闃舵鏀跺埌 allpickfinished/allputfinished 鏃讹紝浠呮洿鏂� `state.CurrentAction`锛屼笉瑙﹀彂鍏ュ簱閫昏緫
+- 浠诲姟瀹屾垚鏃堕澶栭噸缃細`state.ChangePalletPhase = 0`, `state.CurrentBatchIndex = 1`, `state.IsInFakeBatteryMode = false`
+
+## 杈圭晫鏉′欢
+
+- `task.RobotTaskTotalNum == 48`锛氱洿鎺ヨ蛋鍘熸湁閫昏緫锛屼笉杩涘叆鎵规妯″紡
+- `task.RobotTaskTotalNum == 0`锛氭祦鍚慉 琛ユ弧48涓亣鐢佃姱锛涙祦鍚態 璺宠繃 Phase 1/2锛岀洿鎺ヨ繘鍏� Phase 3/4 鍥炴敹48涓亣鐢佃姱
+- 鍋囩數鑺钩闈㈢偣浣嶄笉瓒筹細璁板綍閿欒鏃ュ織锛屼腑姝㈠綋鍓嶆壒娆�
+- 鍋囩數鑺偣浣嶇鐗囧寲锛歚GetNextAvailable` 瑕佹眰鍚岃杩炵画锛屽鏋滆姹�4涓壘涓嶅埌锛屼緷娆″皾璇�3銆�2銆�1涓�
+- 鎵规缂栧彿婧㈠嚭锛堣秴杩�48锛夛細涓嶅簲鍙戠敓锛屼絾闇�闃插尽鎬ф鏌�
diff --git "a/\351\241\271\347\233\256\350\265\204\346\226\231/\346\212\200\346\234\257\345\215\217\350\256\256/~$\351\252\214\350\257\201\345\271\263\345\217\260\347\211\251\346\265\201\344\273\223\345\202\250\347\263\273\347\273\237\346\212\200\346\234\257\350\247\204\346\240\274\344\271\246-11.24.docx" "b/\351\241\271\347\233\256\350\265\204\346\226\231/\346\212\200\346\234\257\345\215\217\350\256\256/~$\351\252\214\350\257\201\345\271\263\345\217\260\347\211\251\346\265\201\344\273\223\345\202\250\347\263\273\347\273\237\346\212\200\346\234\257\350\247\204\346\240\274\344\271\246-11.24.docx"
new file mode 100644
index 0000000..ec29c0c
--- /dev/null
+++ "b/\351\241\271\347\233\256\350\265\204\346\226\231/\346\212\200\346\234\257\345\215\217\350\256\256/~$\351\252\214\350\257\201\345\271\263\345\217\260\347\211\251\346\265\201\344\273\223\345\202\250\347\263\273\347\273\237\346\212\200\346\234\257\350\247\204\346\240\274\344\271\246-11.24.docx"
Binary files differ
diff --git "a/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\234\272\346\242\260\346\211\213\345\215\217\350\256\256/~$\344\272\244\344\272\222\346\265\201\347\250\213\350\241\250\0501\051.xlsx" "b/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\234\272\346\242\260\346\211\213\345\215\217\350\256\256/~$\344\272\244\344\272\222\346\265\201\347\250\213\350\241\250\0501\051.xlsx"
deleted file mode 100644
index 236d63d..0000000
--- "a/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\234\272\346\242\260\346\211\213\345\215\217\350\256\256/~$\344\272\244\344\272\222\346\265\201\347\250\213\350\241\250\0501\051.xlsx"
+++ /dev/null
Binary files differ
diff --git "a/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\234\272\346\242\260\346\211\213\345\215\217\350\256\256/\344\272\244\344\272\222\346\265\201\347\250\213\350\241\250\0501\051.xlsx" "b/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\234\272\346\242\260\346\211\213\345\215\217\350\256\256/\344\272\244\344\272\222\346\265\201\347\250\213\350\241\250\0501\051.xlsx"
index 5b2ba64..714fa71 100644
--- "a/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\234\272\346\242\260\346\211\213\345\215\217\350\256\256/\344\272\244\344\272\222\346\265\201\347\250\213\350\241\250\0501\051.xlsx"
+++ "b/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\234\272\346\242\260\346\211\213\345\215\217\350\256\256/\344\272\244\344\272\222\346\265\201\347\250\213\350\241\250\0501\051.xlsx"
Binary files differ

--
Gitblit v1.9.3