From 34f1e65179910f3c02f0ac6813dbfefb4244d4d7 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期三, 15 四月 2026 19:23:24 +0800
Subject: [PATCH] feat(同步服务): 添加实例同步功能并优化更新逻辑

---
 Code/测试工具/WIDESEAWCS_S7Simulator/.omc/state/mission-state.json                                      |   53 +++++++++++++++++
 Code/测试工具/WIDESEAWCS_S7Simulator/.omc/state/idle-notif-cooldown.json                                |    3 +
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs                           |    6 +-
 Code/测试工具/WIDESEAWCS_S7Simulator/.omc/state/subagent-tracking.json                                  |   17 +++++
 Code/测试工具/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Application/InstanceSyncService.cs          |   22 +++++++
 Code/测试工具/WIDESEAWCS_S7Simulator/.omc/state/agent-replay-584f6639-de9a-47e8-a9e4-f92fac6305be.jsonl |    2 
 Code/测试工具/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue                  |   18 ++++++
 Code/测试工具/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts                        |   12 ++++
 8 files changed, 129 insertions(+), 4 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
index f1c12ab..5ff1ed7 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -225,9 +225,9 @@
                     CommonConveyorLine conveyorLine = (CommonConveyorLine)device;
 
                     DeviceProDTO? devicePro = conveyorLine.DeviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == nameof(ConveyorLineDBNameNew.Barcode) && x.DeviceChildCode == sourceLineNo);
-                    ConveyorLineTaskCommandNew command = conveyorLine.ReadCustomer<ConveyorLineTaskCommandNew>(sourceLineNo);  // 娴嬭瘯鐢�
-                    //var barcode = conveyorLine.GetValue<ConveyorLineDBNameNew, string>(ConveyorLineDBNameNew.Barcode, sourceLineNo);
-                    stock.SourcePalletNo = string.IsNullOrEmpty(command.Barcode.Replace("\0", "").ToString()) ? string.Empty : command.Barcode.Replace("\0", "").ToString();
+                    //ConveyorLineTaskCommandNew command = conveyorLine.ReadCustomer<ConveyorLineTaskCommandNew>(sourceLineNo);  // 娴嬭瘯鐢�
+                    var barcode = conveyorLine.GetValue<ConveyorLineDBNameNew, string>(ConveyorLineDBNameNew.Barcode, sourceLineNo);
+                    stock.SourcePalletNo = string.IsNullOrEmpty(barcode) ? string.Empty : barcode;
                 }
             }
 
diff --git "a/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/agent-replay-584f6639-de9a-47e8-a9e4-f92fac6305be.jsonl" "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/agent-replay-584f6639-de9a-47e8-a9e4-f92fac6305be.jsonl"
new file mode 100644
index 0000000..2531477
--- /dev/null
+++ "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/agent-replay-584f6639-de9a-47e8-a9e4-f92fac6305be.jsonl"
@@ -0,0 +1,2 @@
+{"t":0,"agent":"ae21cf2","agent_type":"explore","event":"agent_start","parent_mode":"none"}
+{"t":0,"agent":"ae21cf2","agent_type":"explore","event":"agent_stop","success":true,"duration_ms":129137}
diff --git "a/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/idle-notif-cooldown.json" "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/idle-notif-cooldown.json"
new file mode 100644
index 0000000..999c83a
--- /dev/null
+++ "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/idle-notif-cooldown.json"
@@ -0,0 +1,3 @@
+{
+  "lastSentAt": "2026-04-15T07:13:52.473Z"
+}
\ No newline at end of file
diff --git "a/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/mission-state.json" "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/mission-state.json"
new file mode 100644
index 0000000..3ab59d9
--- /dev/null
+++ "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/mission-state.json"
@@ -0,0 +1,53 @@
+{
+  "updatedAt": "2026-04-15T06:44:32.119Z",
+  "missions": [
+    {
+      "id": "session:584f6639-de9a-47e8-a9e4-f92fac6305be:none",
+      "source": "session",
+      "name": "none",
+      "objective": "Session mission",
+      "createdAt": "2026-04-15T06:42:22.982Z",
+      "updatedAt": "2026-04-15T06:44:32.119Z",
+      "status": "done",
+      "workerCount": 1,
+      "taskCounts": {
+        "total": 1,
+        "pending": 0,
+        "blocked": 0,
+        "inProgress": 0,
+        "completed": 1,
+        "failed": 0
+      },
+      "agents": [
+        {
+          "name": "explore:ae21cf2",
+          "role": "explore",
+          "ownership": "ae21cf28e45f297ff",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-15T06:44:32.119Z"
+        }
+      ],
+      "timeline": [
+        {
+          "id": "session-start:ae21cf28e45f297ff:2026-04-15T06:42:22.982Z",
+          "at": "2026-04-15T06:42:22.982Z",
+          "kind": "update",
+          "agent": "explore:ae21cf2",
+          "detail": "started explore:ae21cf2",
+          "sourceKey": "session-start:ae21cf28e45f297ff"
+        },
+        {
+          "id": "session-stop:ae21cf28e45f297ff:2026-04-15T06:44:32.119Z",
+          "at": "2026-04-15T06:44:32.119Z",
+          "kind": "completion",
+          "agent": "explore:ae21cf2",
+          "detail": "completed",
+          "sourceKey": "session-stop:ae21cf28e45f297ff"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git "a/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/subagent-tracking.json" "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/subagent-tracking.json"
new file mode 100644
index 0000000..36a8077
--- /dev/null
+++ "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/.omc/state/subagent-tracking.json"
@@ -0,0 +1,17 @@
+{
+  "agents": [
+    {
+      "agent_id": "ae21cf28e45f297ff",
+      "agent_type": "explore",
+      "started_at": "2026-04-15T06:42:22.982Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-15T06:44:32.119Z",
+      "duration_ms": 129137
+    }
+  ],
+  "total_spawned": 1,
+  "total_completed": 1,
+  "total_failed": 0,
+  "last_updated": "2026-04-15T06:44:32.224Z"
+}
\ No newline at end of file
diff --git "a/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Application/InstanceSyncService.cs" "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Application/InstanceSyncService.cs"
index d23bffd..3315faf 100644
--- "a/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Application/InstanceSyncService.cs"
+++ "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Application/InstanceSyncService.cs"
@@ -116,7 +116,27 @@
                 // 4.4 鍒涘缓鎴栨洿鏂板疄渚�
                 if (_instanceManager.InstanceExists(device.DeviceCode))
                 {
-                    _logger.LogInformation("瀹炰緥 {DeviceCode} 宸插瓨鍦紝璺宠繃鍒涘缓", device.DeviceCode);
+                    // 瀹炰緥宸插瓨鍦紝鏇存柊閰嶇疆
+                    var instance = _instanceManager.GetInstance(device.DeviceCode);
+                    if (instance != null)
+                    {
+                        var oldState = instance.GetState();
+                        var wasRunning = oldState.Status == InstanceStatus.Running;
+
+                        // 鍋滄鏃у疄渚�
+                        await _instanceManager.StopInstanceAsync(device.DeviceCode);
+
+                        // 鍒犻櫎鏃у疄渚嬶紙淇濈暀閰嶇疆锛�
+                        await _instanceManager.DeleteInstanceAsync(device.DeviceCode, deleteConfig: false);
+
+                        // 閲嶆柊鍒涘缓瀹炰緥
+                        var newInstance = await _instanceManager.CreateInstanceAsync(config);
+                        if (wasRunning)
+                        {
+                            await _instanceManager.StartInstanceAsync(device.DeviceCode);
+                        }
+                        _logger.LogInformation("宸叉洿鏂板疄渚� {DeviceCode} (绔彛:{Port})", device.DeviceCode, device.DevicePort);
+                    }
                 }
                 else
                 {
diff --git "a/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts" "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts"
index c45b917..c963cde 100644
--- "a/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts"
+++ "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts"
@@ -178,6 +178,18 @@
   }
 }
 
+// 閲嶆柊鍚屾瀹炰緥锛堜粠鏁版嵁搴撻噸鏂拌幏鍙栵級
+export async function syncInstances(): Promise<{ message: string; lastSyncTime: string }> {
+  const response = await api.post<{ message: string; lastSyncTime: string }>('/Sync/SyncInstances')
+  return response.data
+}
+
+// 鑾峰彇涓婃鍚屾鏃堕棿
+export async function getLastSyncTime(): Promise<{ lastSyncTime: string | null }> {
+  const response = await api.get<{ lastSyncTime: string | null }>('/Sync/LastSyncTime')
+  return response.data
+}
+
 // 鑾峰彇鏈烘鎵嬫湇鍔$杩愯鐘舵�侊紙鍖呭惈澶氬疄渚嬪拰鎺ユ敹娑堟伅鏃ュ織锛�
 export async function getRobotClientStatus(): Promise<RobotClientStatusResponse> {
   const response = await api.get<RobotClientStatusResponse>('/RobotClients/status')
diff --git "a/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue" "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue"
index 06cb505..f16afb0 100644
--- "a/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue"
+++ "b/Code/\346\265\213\350\257\225\345\267\245\345\205\267/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue"
@@ -13,6 +13,10 @@
         <p class="text-muted">绠$悊鍜岀洃鎺� S7 PLC 妯℃嫙鍣ㄥ疄渚�</p>
       </div>
       <div class="header-right">
+        <el-button type="default" @click="handleRefresh">
+          <el-icon><Refresh /></el-icon>
+          閲嶆柊鑾峰彇瀹炰緥
+        </el-button>
         <el-button type="primary" class="create-btn" @click="$router.push('/create')">
           <el-icon><Plus /></el-icon>
           鍒涘缓瀹炰緥
@@ -173,11 +177,14 @@
 import { onMounted, onUnmounted, ref } from 'vue'
 import { storeToRefs } from 'pinia'
 import { useInstancesStore } from '../stores/instances'
+import api from '../api'
+import { syncInstances } from '../api'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import {
   Cpu,
   Plus,
   Loading,
+  Refresh,
   User,
   VideoPause,
   VideoPlay,
@@ -199,6 +206,17 @@
   store.stopAutoRefresh()
 })
 
+async function handleRefresh() {
+  try {
+    await syncInstances()
+    await store.loadInstances()
+    ElMessage.success('宸查噸鏂拌幏鍙栧疄渚嬪垪琛�')
+  } catch (err) {
+    console.error('鍚屾澶辫触:', err)
+    ElMessage.error('鍚屾澶辫触锛岃鏌ョ湅鎺у埗鍙�')
+  }
+}
+
 async function handleStart(id: string) {
   try {
     await ElMessageBox.confirm(`纭畾瑕佸惎鍔ㄥ疄渚� "${id}" 鍚楋紵`, '纭', {

--
Gitblit v1.9.3