From f288ccc545f8cc32bc922c96dfb3cab9a1f92ec6 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期一, 20 四月 2026 00:49:55 +0800
Subject: [PATCH] feat: 初始化WMS前端项目并实现基础功能

---
 Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/inbound.ts                                      |    6 
 Code/WMS/WMS_Api_Design.md                                                                      |  203 +
 Code/WMS/WIDESEA_WMSClient_Vben/src/views/outbound/outboundOrderDetail.vue                      |  106 
 Code/WMS/WIDESEA_WMSClient_Vben/src/api/auth.ts                                                 |   50 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotStateController.cs           |   20 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/ISocketClientGateway.cs       |    1 
 Code/WMS/WIDESEA_WMSClient_Vben/src/views/outbound/index.vue                                    |  267 ++
 Code/WMS/WIDESEA_WMSClient_Vben/src/layouts/MainLayout.vue                                      |  158 +
 Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotState.vue                                    |  184 +
 Code/WMS/WIDESEA_WMSClient_Vben/src/views/inbound/inboundOrderDetail.vue                        |  105 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotClientManager.cs                      |    1 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json                                   |    2 
 Code/WMS/WIDESEA_WMSClient_Vben_v2                                                              |    1 
 Code/WMS/WIDESEA_WMSClient_Vben/src/views/stock/index.vue                                       |  340 ++
 Code/WMS/WIDESEA_WMSClient_Vben/.env.development                                                |    1 
 Code/WMS/WIDESEA_WMSClient_Vben/src/utils/menuTransform.ts                                      |  143 +
 Code/.omc/state/mission-state.json                                                              |  532 ++++
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj                             |    1 
 Code/WMS/WIDESEA_WMSClient_Vben/src/main.ts                                                     |   15 
 Code/WMS/WIDESEA_WMSClient_Vben/src/store/index.ts                                              |    5 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotPrefixCommandHandler.cs |    1 
 Code/.omc/state/last-tool-error.json                                                            |    8 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/QuartzNet/QuartzNetExtension.cs                 |    1 
 Code/WMS/WIDESEA_WMSClient_Vben/pnpm-lock.yaml                                                  | 1297 ++++++++++
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/SocketClientGateway.cs                 |    1 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/Dt_RobotState.cs                  |   59 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotSimpleCommandHandler.cs |    2 
 Code/WMS/WIDESEA_WMSClient_Vben/package-lock.json                                               | 1929 ++++++++++++++++
 Code/WMS/WIDESEA_WMSClient_Vben/src/store/user.ts                                               |   43 
 Code/WMS/WIDESEA_WMSClient_Vben/src/views/login/index.vue                                       |  196 +
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotMessageRouter.cs        |    1 
 Code/WMS/WIDESEA_WMSClient_Vben/src/api/index.ts                                                |    6 
 Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/outbound.ts                                     |    6 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotStateService.cs                    |   13 
 Code/WMS/WIDESEA_WMSClient_Vben/vite.config.ts                                                  |   21 
 Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/menu.ts                                         |   28 
 Code/WMS/WIDESEA_WMSClient_Vben/tsconfig.node.json                                              |   11 
 Code/WCS/WIDESEAWCS_Client/src/router/viewGird.js                                               |    5 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs                     |    1 
 Code/.omc/state/subagent-tracking.json                                                          |  351 ++
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/WIDESEAWCS_ITaskInfoRepository.csproj |    1 
 Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/stock.ts                                        |    6 
 Code/WCS/WIDESEAWCS_Client/src/extension/taskinfo/robotState.jsx                                |   55 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotCraneDevice.cs               |   28 
 Code/WMS/WIDESEA_WMSClient_Vben/index.html                                                      |   13 
 Code/WMS/WIDESEA_WMSClient_Vben/src/store/modules/menu.ts                                       |   57 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs                     |   69 
 Code/WMS/WIDESEA_WMSClient_Vben/src/App.vue                                                     |   27 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs                                |    5 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/WIDESEAWCS_QuartzJob.csproj                     |    1 
 Code/WMS/WIDESEA_WMSClient_Vben/src/api/client.ts                                               |   56 
 /dev/null                                                                                       |   16 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/RobotStateRepository.cs                |   39 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IRobotStateRepository.cs              |   10 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotStateManager.cs                       |   34 
 Code/WMS/WIDESEA_WMSClient_Vben/src/router/index.ts                                             |   81 
 Code/WMS/WIDESEA_WMSClient_Vben/src/views/inbound/index.vue                                     |  275 ++
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotStateService.cs                      |   18 
 Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/user.ts                                         |    8 
 Code/WMS/WIDESEA_WMSClient_Vben/tsconfig.json                                                   |   21 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs      |    1 
 Code/WMS/WIDESEA_WMSClient_Vben/package.json                                                    |   25 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotSocketState.cs               |   11 
 Code/WMS/WIDESEA_WMSClient_Vben/src/views/dashboard/index.vue                                   |   47 
 Code/WMS/WIDESEA_WMSClient_Vben/src/locales/zh-CN.ts                                            |   21 
 Code/WMS/WIDESEA_WMSClient_Vben/src/views/stock/stockInfoDetail.vue                             |  119 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs           |    1 
 67 files changed, 6,997 insertions(+), 169 deletions(-)

diff --git a/Code/.omc/state/last-tool-error.json b/Code/.omc/state/last-tool-error.json
index c9a8df7..85397e0 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\":\"cd D:\\\\Git\\\\ShanMeiXinNengYuan\\\\Code\\\\WCS\\\\WIDESEAWCS_Client && npm run build 2>&1 | head -30\",\"timeout\":120000}",
-  "error": "Exit code 1\n/usr/bin/bash: line 1: cd: D:GitShanMeiXinNengYuanCodeWCSWIDESEAWCS_Client: No such file or directory",
-  "timestamp": "2026-04-19T07:15:17.022Z",
-  "retry_count": 1
+  "tool_input_preview": "{\"command\":\"cd \\\"D:/Git/ShanMeiXinNengYuan/Code/WMS\\\" && git clone --depth 1 https://ghproxy.com/https://github.com/vbenjs/vue-vben-admin.git WIDESEA_WMSClient_Vben 2>&1\",\"timeout\":300000,\"description...",
+  "error": "Exit code 128\nCloning into 'WIDESEA_WMSClient_Vben'...\nfatal: unable to access 'https://ghproxy.com/https://github.com/vbenjs/vue-vben-admin.git/': Failed to connect to ghproxy.com port 443 after 21158 ms: Could not connect to server",
+  "timestamp": "2026-04-19T13:54:19.051Z",
+  "retry_count": 4
 }
\ No newline at end of file
diff --git a/Code/.omc/state/mission-state.json b/Code/.omc/state/mission-state.json
index 67025a1..c4c05bb 100644
--- a/Code/.omc/state/mission-state.json
+++ b/Code/.omc/state/mission-state.json
@@ -1,5 +1,5 @@
 {
-  "updatedAt": "2026-04-18T08:52:24.581Z",
+  "updatedAt": "2026-04-19T13:53:57.853Z",
   "missions": [
     {
       "id": "session:9007b9ea-1eb6-4d24-8fe7-2c3a949eac88:none",
@@ -1268,6 +1268,536 @@
           "sourceKey": "session-stop:a6a0c97facebc27a6"
         }
       ]
+    },
+    {
+      "id": "session:4a7d9ed6-773a-4962-9881-9dcda1653389:none",
+      "source": "session",
+      "name": "none",
+      "objective": "Session mission",
+      "createdAt": "2026-04-19T11:24:03.847Z",
+      "updatedAt": "2026-04-19T12:58:38.564Z",
+      "status": "done",
+      "workerCount": 5,
+      "taskCounts": {
+        "total": 5,
+        "pending": 0,
+        "blocked": 0,
+        "inProgress": 0,
+        "completed": 5,
+        "failed": 0
+      },
+      "agents": [
+        {
+          "name": "general-purpose:af12f69",
+          "role": "general-purpose",
+          "ownership": "af12f692dd4a3fb28",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T12:58:38.564Z"
+        },
+        {
+          "name": "general-purpose:aa2a37e",
+          "role": "general-purpose",
+          "ownership": "aa2a37e07afb9d479",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T11:24:36.379Z"
+        },
+        {
+          "name": "general-purpose:a6eb9a9",
+          "role": "general-purpose",
+          "ownership": "a6eb9a903c850f24a",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T11:24:47.161Z"
+        },
+        {
+          "name": "general-purpose:a9803cf",
+          "role": "general-purpose",
+          "ownership": "a9803cf811cccaa24",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T11:25:43.000Z"
+        },
+        {
+          "name": "general-purpose:a9e37be",
+          "role": "general-purpose",
+          "ownership": "a9e37bec52fcbdaa5",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T11:26:55.341Z"
+        }
+      ],
+      "timeline": [
+        {
+          "id": "session-start:a9803cf811cccaa24:2026-04-19T11:25:09.331Z",
+          "at": "2026-04-19T11:25:09.331Z",
+          "kind": "update",
+          "agent": "general-purpose:a9803cf",
+          "detail": "started general-purpose:a9803cf",
+          "sourceKey": "session-start:a9803cf811cccaa24"
+        },
+        {
+          "id": "session-stop:a9803cf811cccaa24:2026-04-19T11:25:43.000Z",
+          "at": "2026-04-19T11:25:43.000Z",
+          "kind": "completion",
+          "agent": "general-purpose:a9803cf",
+          "detail": "completed",
+          "sourceKey": "session-stop:a9803cf811cccaa24"
+        },
+        {
+          "id": "session-start:a9e37bec52fcbdaa5:2026-04-19T11:25:51.811Z",
+          "at": "2026-04-19T11:25:51.811Z",
+          "kind": "update",
+          "agent": "general-purpose:a9e37be",
+          "detail": "started general-purpose:a9e37be",
+          "sourceKey": "session-start:a9e37bec52fcbdaa5"
+        },
+        {
+          "id": "session-stop:a9e37bec52fcbdaa5:2026-04-19T11:26:55.341Z",
+          "at": "2026-04-19T11:26:55.341Z",
+          "kind": "completion",
+          "agent": "general-purpose:a9e37be",
+          "detail": "completed",
+          "sourceKey": "session-stop:a9e37bec52fcbdaa5"
+        },
+        {
+          "id": "session-stop:a4f2a4a86620e67ac:2026-04-19T12:58:38.564Z",
+          "at": "2026-04-19T12:58:38.564Z",
+          "kind": "completion",
+          "agent": "general-purpose:af12f69",
+          "detail": "completed",
+          "sourceKey": "session-stop:a4f2a4a86620e67ac"
+        }
+      ]
+    },
+    {
+      "id": "session:d619041b-8d2b-4d40-ac1a-9c570d800e7d:none",
+      "source": "session",
+      "name": "none",
+      "objective": "Session mission",
+      "createdAt": "2026-04-19T13:39:55.243Z",
+      "updatedAt": "2026-04-19T13:53:57.853Z",
+      "status": "running",
+      "workerCount": 34,
+      "taskCounts": {
+        "total": 34,
+        "pending": 0,
+        "blocked": 0,
+        "inProgress": 3,
+        "completed": 31,
+        "failed": 0
+      },
+      "agents": [
+        {
+          "name": "agent-menu:a9260b4",
+          "role": "agent-menu",
+          "ownership": "a9260b44a0c26528b",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:41:04.664Z"
+        },
+        {
+          "name": "agent-auth:a6f1e5c",
+          "role": "agent-auth",
+          "ownership": "a6f1e5c50a57e0d5d",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:40:20.808Z"
+        },
+        {
+          "name": "agent-pages:a5a2a89",
+          "role": "agent-pages",
+          "ownership": "a5a2a89d2fb5f17ff",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:41:01.814Z"
+        },
+        {
+          "name": "agent-scaffold:a1a6151",
+          "role": "agent-scaffold",
+          "ownership": "a1a6151ba7f364cfb",
+          "status": "running",
+          "currentStep": null,
+          "latestUpdate": null,
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:39:55.484Z"
+        },
+        {
+          "name": "agent-api:a4ce4ef",
+          "role": "agent-api",
+          "ownership": "a4ce4ef36b3693f58",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:40:12.096Z"
+        },
+        {
+          "name": "agent-layout:af02a89",
+          "role": "agent-layout",
+          "ownership": "af02a89022a18c649",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:40:15.829Z"
+        },
+        {
+          "name": "agent-api:ad03467",
+          "role": "agent-api",
+          "ownership": "ad03467a75e8afc0a",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:44:15.841Z"
+        },
+        {
+          "name": "agent-auth:a3cc9be",
+          "role": "agent-auth",
+          "ownership": "a3cc9be047c9352e5",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:44:29.101Z"
+        },
+        {
+          "name": "agent-menu:a77fb32",
+          "role": "agent-menu",
+          "ownership": "a77fb323ad44a6284",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:43:03.806Z"
+        },
+        {
+          "name": "agent-layout:a81ba9f",
+          "role": "agent-layout",
+          "ownership": "a81ba9fdad4456dfd",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:42:27.425Z"
+        },
+        {
+          "name": "agent-pages:a94adb2",
+          "role": "agent-pages",
+          "ownership": "a94adb2a88c1eb29c",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:42:26.922Z"
+        },
+        {
+          "name": "agent-pages:a211822",
+          "role": "agent-pages",
+          "ownership": "a2118226e3813727c",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:42:56.060Z"
+        },
+        {
+          "name": "agent-layout:ab75021",
+          "role": "agent-layout",
+          "ownership": "ab750215093131b28",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:42:55.376Z"
+        },
+        {
+          "name": "agent-menu:ae9ed78",
+          "role": "agent-menu",
+          "ownership": "ae9ed78222ecc6cad",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:52:27.389Z"
+        },
+        {
+          "name": "agent-api:ae5c327",
+          "role": "agent-api",
+          "ownership": "ae5c327157aec2fb1",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:46:52.233Z"
+        },
+        {
+          "name": "agent-auth:adc223f",
+          "role": "agent-auth",
+          "ownership": "adc223f651f1328bd",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:44:53.789Z"
+        },
+        {
+          "name": "agent-pages:a756617",
+          "role": "agent-pages",
+          "ownership": "a756617ca874ac3c1",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:51:43.427Z"
+        },
+        {
+          "name": "agent-layout:a4c96b8",
+          "role": "agent-layout",
+          "ownership": "a4c96b89f113f809d",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:47:11.646Z"
+        },
+        {
+          "name": "agent-auth:a8a57aa",
+          "role": "agent-auth",
+          "ownership": "a8a57aa22517c31f5",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:49:10.620Z"
+        },
+        {
+          "name": "agent-api:ab1d288",
+          "role": "agent-api",
+          "ownership": "ab1d2884ac7a493bd",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:47:18.573Z"
+        },
+        {
+          "name": "agent-layout:a0cbc46",
+          "role": "agent-layout",
+          "ownership": "a0cbc46d413ef4196",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:47:31.885Z"
+        },
+        {
+          "name": "agent-api:a8d6281",
+          "role": "agent-api",
+          "ownership": "a8d6281531b04991f",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:47:38.716Z"
+        },
+        {
+          "name": "writer:a8c91fb",
+          "role": "writer",
+          "ownership": "a8c91fb2cf222b293",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:50:25.144Z"
+        },
+        {
+          "name": "agent-auth:ade32f8",
+          "role": "agent-auth",
+          "ownership": "ade32f8bf35b26757",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:52:13.860Z"
+        },
+        {
+          "name": "agent-pages:ac557d7",
+          "role": "agent-pages",
+          "ownership": "ac557d7e2a1b5f729",
+          "status": "running",
+          "currentStep": null,
+          "latestUpdate": null,
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:51:43.789Z"
+        },
+        {
+          "name": "agent-layout:a9c6179",
+          "role": "agent-layout",
+          "ownership": "a9c6179a801e0e434",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:52:12.657Z"
+        },
+        {
+          "name": "writer:a7627b0",
+          "role": "writer",
+          "ownership": "a7627b0b0e0b60be2",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:52:01.512Z"
+        },
+        {
+          "name": "agent-api:aba045f",
+          "role": "agent-api",
+          "ownership": "aba045f68cd9f61d0",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:52:03.192Z"
+        },
+        {
+          "name": "agent-auth:aeed34c",
+          "role": "agent-auth",
+          "ownership": "aeed34c94d463a92c",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:52:27.391Z"
+        },
+        {
+          "name": "agent-menu:a9271b2",
+          "role": "agent-menu",
+          "ownership": "a9271b2a5525f053a",
+          "status": "running",
+          "currentStep": null,
+          "latestUpdate": null,
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:53:39.468Z"
+        },
+        {
+          "name": "agent-api:ae5d5fc",
+          "role": "agent-api",
+          "ownership": "ae5d5fcffcb393b67",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:53:47.265Z"
+        },
+        {
+          "name": "agent-auth:ad92b78",
+          "role": "agent-auth",
+          "ownership": "ad92b7876bc72bf7e",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:53:57.853Z"
+        },
+        {
+          "name": "agent-layout:affcaab",
+          "role": "agent-layout",
+          "ownership": "affcaabcac0234d22",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:53:49.029Z"
+        },
+        {
+          "name": "writer:ac6c4a2",
+          "role": "writer",
+          "ownership": "ac6c4a28a6422e89d",
+          "status": "done",
+          "currentStep": null,
+          "latestUpdate": "completed",
+          "completedSummary": null,
+          "updatedAt": "2026-04-19T13:53:49.217Z"
+        }
+      ],
+      "timeline": [
+        {
+          "id": "session-start:ad92b7876bc72bf7e:2026-04-19T13:53:42.036Z",
+          "at": "2026-04-19T13:53:42.036Z",
+          "kind": "update",
+          "agent": "agent-auth:ad92b78",
+          "detail": "started agent-auth:ad92b78",
+          "sourceKey": "session-start:ad92b7876bc72bf7e"
+        },
+        {
+          "id": "session-start:affcaabcac0234d22:2026-04-19T13:53:42.701Z",
+          "at": "2026-04-19T13:53:42.701Z",
+          "kind": "update",
+          "agent": "agent-layout:affcaab",
+          "detail": "started agent-layout:affcaab",
+          "sourceKey": "session-start:affcaabcac0234d22"
+        },
+        {
+          "id": "session-start:ac6c4a28a6422e89d:2026-04-19T13:53:43.519Z",
+          "at": "2026-04-19T13:53:43.519Z",
+          "kind": "update",
+          "agent": "writer:ac6c4a2",
+          "detail": "started writer:ac6c4a2",
+          "sourceKey": "session-start:ac6c4a28a6422e89d"
+        },
+        {
+          "id": "session-stop:ae5d5fcffcb393b67:2026-04-19T13:53:47.265Z",
+          "at": "2026-04-19T13:53:47.265Z",
+          "kind": "completion",
+          "agent": "agent-api:ae5d5fc",
+          "detail": "completed",
+          "sourceKey": "session-stop:ae5d5fcffcb393b67"
+        },
+        {
+          "id": "session-stop:affcaabcac0234d22:2026-04-19T13:53:49.029Z",
+          "at": "2026-04-19T13:53:49.029Z",
+          "kind": "completion",
+          "agent": "agent-layout:affcaab",
+          "detail": "completed",
+          "sourceKey": "session-stop:affcaabcac0234d22"
+        },
+        {
+          "id": "session-stop:ac6c4a28a6422e89d:2026-04-19T13:53:49.217Z",
+          "at": "2026-04-19T13:53:49.217Z",
+          "kind": "completion",
+          "agent": "writer:ac6c4a2",
+          "detail": "completed",
+          "sourceKey": "session-stop:ac6c4a28a6422e89d"
+        },
+        {
+          "id": "session-stop:ad92b7876bc72bf7e:2026-04-19T13:53:57.853Z",
+          "at": "2026-04-19T13:53:57.853Z",
+          "kind": "completion",
+          "agent": "agent-auth:ad92b78",
+          "detail": "completed",
+          "sourceKey": "session-stop:ad92b7876bc72bf7e"
+        }
+      ]
     }
   ]
 }
\ No newline at end of file
diff --git a/Code/.omc/state/subagent-tracking.json b/Code/.omc/state/subagent-tracking.json
index 27a37ae..1b42f04 100644
--- a/Code/.omc/state/subagent-tracking.json
+++ b/Code/.omc/state/subagent-tracking.json
@@ -767,10 +767,355 @@
       "status": "completed",
       "completed_at": "2026-04-18T08:52:24.581Z",
       "duration_ms": 1093052
+    },
+    {
+      "agent_id": "af12f692dd4a3fb28",
+      "agent_type": "general-purpose",
+      "started_at": "2026-04-19T11:24:03.847Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T11:24:57.433Z",
+      "duration_ms": 53586
+    },
+    {
+      "agent_id": "aa2a37e07afb9d479",
+      "agent_type": "general-purpose",
+      "started_at": "2026-04-19T11:24:03.863Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T11:24:36.379Z",
+      "duration_ms": 32516
+    },
+    {
+      "agent_id": "a6eb9a903c850f24a",
+      "agent_type": "general-purpose",
+      "started_at": "2026-04-19T11:24:03.887Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T11:24:47.161Z",
+      "duration_ms": 43274
+    },
+    {
+      "agent_id": "a9803cf811cccaa24",
+      "agent_type": "general-purpose",
+      "started_at": "2026-04-19T11:25:09.331Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T11:25:43.000Z",
+      "duration_ms": 33669
+    },
+    {
+      "agent_id": "a9e37bec52fcbdaa5",
+      "agent_type": "general-purpose",
+      "started_at": "2026-04-19T11:25:51.811Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T11:26:55.341Z",
+      "duration_ms": 63530
+    },
+    {
+      "agent_id": "a9260b44a0c26528b",
+      "agent_type": "agent-menu",
+      "started_at": "2026-04-19T13:39:55.243Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:41:04.664Z",
+      "duration_ms": 69421
+    },
+    {
+      "agent_id": "a6f1e5c50a57e0d5d",
+      "agent_type": "agent-auth",
+      "started_at": "2026-04-19T13:39:55.328Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:40:20.808Z",
+      "duration_ms": 25480
+    },
+    {
+      "agent_id": "a5a2a89d2fb5f17ff",
+      "agent_type": "agent-pages",
+      "started_at": "2026-04-19T13:39:55.416Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:41:01.814Z",
+      "duration_ms": 66398
+    },
+    {
+      "agent_id": "a1a6151ba7f364cfb",
+      "agent_type": "agent-scaffold",
+      "started_at": "2026-04-19T13:39:55.484Z",
+      "parent_mode": "none",
+      "status": "running"
+    },
+    {
+      "agent_id": "a4ce4ef36b3693f58",
+      "agent_type": "agent-api",
+      "started_at": "2026-04-19T13:39:55.588Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:40:12.096Z",
+      "duration_ms": 16508
+    },
+    {
+      "agent_id": "af02a89022a18c649",
+      "agent_type": "agent-layout",
+      "started_at": "2026-04-19T13:39:55.655Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:40:15.829Z",
+      "duration_ms": 20174
+    },
+    {
+      "agent_id": "ad03467a75e8afc0a",
+      "agent_type": "agent-api",
+      "started_at": "2026-04-19T13:41:42.785Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:44:15.841Z",
+      "duration_ms": 153056
+    },
+    {
+      "agent_id": "a3cc9be047c9352e5",
+      "agent_type": "agent-auth",
+      "started_at": "2026-04-19T13:41:43.216Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:44:29.101Z",
+      "duration_ms": 165885
+    },
+    {
+      "agent_id": "a77fb323ad44a6284",
+      "agent_type": "agent-menu",
+      "started_at": "2026-04-19T13:41:43.564Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:43:03.806Z",
+      "duration_ms": 80242
+    },
+    {
+      "agent_id": "a81ba9fdad4456dfd",
+      "agent_type": "agent-layout",
+      "started_at": "2026-04-19T13:41:43.726Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:42:27.425Z",
+      "duration_ms": 43699
+    },
+    {
+      "agent_id": "a94adb2a88c1eb29c",
+      "agent_type": "agent-pages",
+      "started_at": "2026-04-19T13:41:44.247Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:42:26.922Z",
+      "duration_ms": 42675
+    },
+    {
+      "agent_id": "a2118226e3813727c",
+      "agent_type": "agent-pages",
+      "started_at": "2026-04-19T13:42:27.222Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:42:56.060Z",
+      "duration_ms": 28838
+    },
+    {
+      "agent_id": "ab750215093131b28",
+      "agent_type": "agent-layout",
+      "started_at": "2026-04-19T13:42:27.736Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:42:55.376Z",
+      "duration_ms": 27640
+    },
+    {
+      "agent_id": "ae9ed78222ecc6cad",
+      "agent_type": "agent-menu",
+      "started_at": "2026-04-19T13:43:04.113Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:53:39.187Z",
+      "duration_ms": 635074
+    },
+    {
+      "agent_id": "ae5c327157aec2fb1",
+      "agent_type": "agent-api",
+      "started_at": "2026-04-19T13:44:16.103Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:46:52.232Z",
+      "duration_ms": 156129
+    },
+    {
+      "agent_id": "adc223f651f1328bd",
+      "agent_type": "agent-auth",
+      "started_at": "2026-04-19T13:44:29.361Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:44:53.787Z",
+      "duration_ms": 24426
+    },
+    {
+      "agent_id": "a756617ca874ac3c1",
+      "agent_type": "agent-pages",
+      "started_at": "2026-04-19T13:44:31.425Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:51:43.425Z",
+      "duration_ms": 432000
+    },
+    {
+      "agent_id": "a4c96b89f113f809d",
+      "agent_type": "agent-layout",
+      "started_at": "2026-04-19T13:44:31.949Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:47:11.645Z",
+      "duration_ms": 159696
+    },
+    {
+      "agent_id": "a8a57aa22517c31f5",
+      "agent_type": "agent-auth",
+      "started_at": "2026-04-19T13:44:54.061Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:49:10.619Z",
+      "duration_ms": 256558
+    },
+    {
+      "agent_id": "ab1d2884ac7a493bd",
+      "agent_type": "agent-api",
+      "started_at": "2026-04-19T13:46:52.504Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:47:18.572Z",
+      "duration_ms": 26068
+    },
+    {
+      "agent_id": "a0cbc46d413ef4196",
+      "agent_type": "agent-layout",
+      "started_at": "2026-04-19T13:47:11.911Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:47:31.883Z",
+      "duration_ms": 19972
+    },
+    {
+      "agent_id": "a8d6281531b04991f",
+      "agent_type": "agent-api",
+      "started_at": "2026-04-19T13:47:18.855Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:47:38.715Z",
+      "duration_ms": 19860
+    },
+    {
+      "agent_id": "a8c91fb2cf222b293",
+      "agent_type": "writer",
+      "started_at": "2026-04-19T13:48:10.651Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:50:25.143Z",
+      "duration_ms": 134492
+    },
+    {
+      "agent_id": "ade32f8bf35b26757",
+      "agent_type": "agent-auth",
+      "started_at": "2026-04-19T13:49:10.886Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:52:13.858Z",
+      "duration_ms": 182972
+    },
+    {
+      "agent_id": "ac557d7e2a1b5f729",
+      "agent_type": "agent-pages",
+      "started_at": "2026-04-19T13:51:43.789Z",
+      "parent_mode": "none",
+      "status": "running"
+    },
+    {
+      "agent_id": "a9c6179a801e0e434",
+      "agent_type": "agent-layout",
+      "started_at": "2026-04-19T13:51:48.859Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:52:12.656Z",
+      "duration_ms": 23797
+    },
+    {
+      "agent_id": "a7627b0b0e0b60be2",
+      "agent_type": "writer",
+      "started_at": "2026-04-19T13:51:48.925Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:52:01.510Z",
+      "duration_ms": 12585
+    },
+    {
+      "agent_id": "aba045f68cd9f61d0",
+      "agent_type": "agent-api",
+      "started_at": "2026-04-19T13:51:48.986Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:52:03.190Z",
+      "duration_ms": 14204
+    },
+    {
+      "agent_id": "aeed34c94d463a92c",
+      "agent_type": "agent-auth",
+      "started_at": "2026-04-19T13:52:14.179Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:52:27.389Z",
+      "duration_ms": 13210
+    },
+    {
+      "agent_id": "a9271b2a5525f053a",
+      "agent_type": "agent-menu",
+      "started_at": "2026-04-19T13:53:39.468Z",
+      "parent_mode": "none",
+      "status": "running"
+    },
+    {
+      "agent_id": "ae5d5fcffcb393b67",
+      "agent_type": "agent-api",
+      "started_at": "2026-04-19T13:53:41.992Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:53:47.263Z",
+      "duration_ms": 5271
+    },
+    {
+      "agent_id": "ad92b7876bc72bf7e",
+      "agent_type": "agent-auth",
+      "started_at": "2026-04-19T13:53:42.036Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:53:57.851Z",
+      "duration_ms": 15815
+    },
+    {
+      "agent_id": "affcaabcac0234d22",
+      "agent_type": "agent-layout",
+      "started_at": "2026-04-19T13:53:42.701Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:53:49.028Z",
+      "duration_ms": 6327
+    },
+    {
+      "agent_id": "ac6c4a28a6422e89d",
+      "agent_type": "writer",
+      "started_at": "2026-04-19T13:53:43.519Z",
+      "parent_mode": "none",
+      "status": "completed",
+      "completed_at": "2026-04-19T13:53:49.216Z",
+      "duration_ms": 5697
     }
   ],
-  "total_spawned": 83,
-  "total_completed": 83,
+  "total_spawned": 115,
+  "total_completed": 119,
   "total_failed": 0,
-  "last_updated": "2026-04-18T14:41:25.052Z"
+  "last_updated": "2026-04-19T13:53:57.967Z"
 }
\ No newline at end of file
diff --git a/Code/WCS/WIDESEAWCS_Client/src/extension/taskinfo/robotState.jsx b/Code/WCS/WIDESEAWCS_Client/src/extension/taskinfo/robotState.jsx
new file mode 100644
index 0000000..0dfb0c9
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_Client/src/extension/taskinfo/robotState.jsx
@@ -0,0 +1,55 @@
+// 璇ユ墿灞曟枃浠剁敤浜庢満姊版墜鐘舵�佺鐞嗛〉闈㈢殑涓氬姟鎵╁睍銆�
+
+let extension = {
+  components: {
+    gridHeader: "",
+    gridBody: "",
+    gridFooter: "",
+    modelHeader: "",
+    modelBody: "",
+    modelFooter: "",
+  },
+  tableAction: "",
+  buttons: { view: [], box: [], detail: [] },
+  methods: {
+    onInit() {},
+
+    onInited() {},
+
+    searchBefore(param) {
+      return true;
+    },
+
+    searchAfter(result) {
+      return true;
+    },
+
+    addBefore(formData) {
+      return true;
+    },
+
+    addAfter(result) {
+      return true;
+    },
+
+    updateBefore(formData) {
+      return true;
+    },
+
+    updateAfter(result) {
+      return true;
+    },
+
+    deleteBefore(ids) {
+      return true;
+    },
+
+    deleteAfter(ids) {
+      return true;
+    },
+
+    modelOpenAfter(row) {},
+  },
+};
+
+export default extension;
diff --git a/Code/WCS/WIDESEAWCS_Client/src/router/viewGird.js b/Code/WCS/WIDESEAWCS_Client/src/router/viewGird.js
index 584bb6c..9915346 100644
--- a/Code/WCS/WIDESEAWCS_Client/src/router/viewGird.js
+++ b/Code/WCS/WIDESEAWCS_Client/src/router/viewGird.js
@@ -69,6 +69,11 @@
     component: () => import('@/views/taskinfo/robotTask.vue')
   },
   {
+    path: '/robotState',
+    name: 'robotState',
+    component: () => import('@/views/taskinfo/robotState.vue')
+  },
+  {
     path: '/task',
     name: 'task',
     component: () => import('@/views/taskinfo/task.vue')
diff --git a/Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotState.vue b/Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotState.vue
new file mode 100644
index 0000000..462827e
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotState.vue
@@ -0,0 +1,184 @@
+<template>
+  <view-grid
+    ref="grid"
+    :columns="columns"
+    :detail="detail"
+    :editFormFields="editFormFields"
+    :editFormOptions="editFormOptions"
+    :searchFormFields="searchFormFields"
+    :searchFormOptions="searchFormOptions"
+    :table="table"
+    :extend="extend"
+  >
+  </view-grid>
+</template>
+
+<script>
+import extend from "@/extension/taskinfo/robotState.jsx";
+import { ref, defineComponent } from "vue";
+
+export default defineComponent({
+  setup() {
+    const table = ref({
+      key: "Id",
+      footer: "Foots",
+      cnName: "鏈烘鎵嬬姸鎬佺鐞�",
+      name: "robotState",
+      url: "/robotState/",
+      sortName: "IPAddress",
+    });
+
+    // 缂栬緫琛ㄥ崟瀛楁
+    const editFormFields = ref({
+      IPAddress: "",
+      Version: "",
+      IsEventSubscribed: false,
+      RobotRunMode: "",
+      RobotControlMode: "",
+      RobotArmObject: "",
+      Homed: "",
+      CurrentAction: "",
+      OperStatus: "",
+      RobotTaskTotalNum: 0,
+      IsSplitPallet: false,
+      IsGroupPallet: false,
+      IsInFakeBatteryMode: false,
+      CurrentBatchIndex: 1,
+      ChangePalletPhase: 0,
+      IsScanNG: false,
+      BatteryArrived: false,
+    });
+
+    // 缂栬緫琛ㄥ崟閰嶇疆
+    const editFormOptions = ref([
+      [
+        { title: "IP鍦板潃", field: "IPAddress", type: "string", readonly: true },
+        { title: "鐗堟湰鍙�", field: "Version", type: "int", readonly: true },
+      ],
+      [
+        {
+          title: "杩愯妯″紡",
+          field: "RobotRunMode",
+          type: "select",
+          data: [
+            { key: 1, value: "鎵嬪姩妯″紡" },
+            { key: 2, value: "鑷姩妯″紡" },
+          ],
+        },
+        {
+          title: "鎺у埗妯″紡",
+          field: "RobotControlMode",
+          type: "select",
+          data: [
+            { key: 1, value: "瀹㈡埛绔帶鍒�" },
+            { key: 2, value: "鍏朵粬" },
+          ],
+        },
+        {
+          title: "鎵嬭噦鐘舵��",
+          field: "RobotArmObject",
+          type: "select",
+          data: [
+            { key: 0, value: "绌洪棽" },
+            { key: 1, value: "鏈夌墿鏂�" },
+          ],
+        },
+      ],
+      [
+        { title: "鍥為浂鐘舵��", field: "Homed", type: "string" },
+        { title: "褰撳墠鍔ㄤ綔", field: "CurrentAction", type: "string" },
+        { title: "杩愯鐘舵��", field: "OperStatus", type: "string" },
+      ],
+      [
+        { title: "浠诲姟鎬绘暟", field: "RobotTaskTotalNum", type: "int" },
+        { title: "褰撳墠鎵规", field: "CurrentBatchIndex", type: "int" },
+        { title: "鎹㈢洏闃舵", field: "ChangePalletPhase", type: "int" },
+      ],
+      [
+        {
+          title: "鏄惁鎷嗙洏",
+          field: "IsSplitPallet",
+          type: "checkbox",
+        },
+        {
+          title: "鏄惁缁勭洏",
+          field: "IsGroupPallet",
+          type: "checkbox",
+        },
+        {
+          title: "鍋囩數鑺ā寮�",
+          field: "IsInFakeBatteryMode",
+          type: "checkbox",
+        },
+      ],
+      [
+        {
+          title: "鏄惁鎵爜NG",
+          field: "IsScanNG",
+          type: "checkbox",
+        },
+        {
+          title: "鐢佃姱鏄惁鍒颁綅",
+          field: "BatteryArrived",
+          type: "checkbox",
+        },
+        {
+          title: "娑堟伅宸茶闃�",
+          field: "IsEventSubscribed",
+          type: "checkbox",
+        },
+      ],
+    ]);
+
+    // 鎼滅储琛ㄥ崟瀛楁
+    const searchFormFields = ref({
+      IPAddress: "",
+      CurrentAction: "",
+      OperStatus: "",
+    });
+
+    // 鎼滅储琛ㄥ崟閰嶇疆
+    const searchFormOptions = ref([
+      [
+        { title: "IP鍦板潃", field: "IPAddress", type: "string" },
+        { title: "褰撳墠鍔ㄤ綔", field: "CurrentAction", type: "string" },
+        { title: "杩愯鐘舵��", field: "OperStatus", type: "string" },
+      ],
+    ]);
+
+    // 鍒楀畾涔�
+    const columns = ref([
+      { field: "IPAddress", title: "IP鍦板潃", type: "string", width: 140, align: "left" },
+      { field: "Version", title: "鐗堟湰", type: "int", width: 80, align: "left" },
+      { field: "RobotRunMode", title: "杩愯妯″紡", type: "int", width: 100, bind: { key: "robotRunMode", data: [] }, align: "center" },
+      { field: "RobotControlMode", title: "鎺у埗妯″紡", type: "int", width: 100, bind: { key: "robotControlMode", data: [] }, align: "center" },
+      { field: "RobotArmObject", title: "鎵嬭噦鐘舵��", type: "int", width: 90, bind: { key: "robotArmObject", data: [] }, align: "center" },
+      { field: "Homed", title: "鍥為浂鐘舵��", type: "string", width: 100, align: "center" },
+      { field: "CurrentAction", title: "褰撳墠鍔ㄤ綔", type: "string", width: 100, align: "center" },
+      { field: "OperStatus", title: "杩愯鐘舵��", type: "string", width: 100, align: "center" },
+      { field: "RobotTaskTotalNum", title: "浠诲姟鎬绘暟", type: "int", width: 90, align: "center" },
+      { field: "IsSplitPallet", title: "鎷嗙洏", type: "byte", width: 60, align: "center" },
+      { field: "IsGroupPallet", title: "缁勭洏", type: "byte", width: 60, align: "center" },
+      { field: "IsInFakeBatteryMode", title: "鍋囩數鑺�", type: "byte", width: 70, align: "center" },
+      { field: "CurrentBatchIndex", title: "鎵规", type: "int", width: 60, align: "center" },
+      { field: "ChangePalletPhase", title: "鎹㈢洏闃舵", type: "int", width: 80, align: "center" },
+      { field: "IsScanNG", title: "鎵爜NG", type: "byte", width: 80, align: "center" },
+      { field: "BatteryArrived", title: "鐢佃姱鍒颁綅", type: "byte", width: 80, align: "center" },
+      { field: "IsEventSubscribed", title: "宸茶闃�", type: "byte", width: 70, align: "center" },
+    ]);
+
+    const detail = ref({});
+
+    return {
+      table,
+      columns,
+      detail,
+      editFormFields,
+      editFormOptions,
+      searchFormFields,
+      searchFormOptions,
+      extend,
+    };
+  },
+});
+</script>
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IRobotStateRepository.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IRobotStateRepository.cs
index 2ee6a06..60a7100 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IRobotStateRepository.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IRobotStateRepository.cs
@@ -1,3 +1,5 @@
+using WIDESEAWCS_Core;
+using WIDESEAWCS_Core.BaseRepository;
 using WIDESEAWCS_Model.Models;
 
 namespace WIDESEAWCS_ITaskInfoRepository
@@ -10,7 +12,7 @@
     /// 澶嶆潅瀵硅薄锛圧obotCrane銆丆urrentTask銆佹暟缁勭瓑锛夊湪璋冪敤鏂逛娇鐢ㄥ己绫诲瀷锛�
     /// 鍦ㄦ鎺ュ彛灞傞潰浠� Dt_RobotState 瀹炰綋涓烘搷浣滃崟浣嶃��
     /// </remarks>
-    public interface IRobotStateRepository
+    public interface IRobotStateRepository : IRepository<Dt_RobotState>
     {
         /// <summary>
         /// 鏍规嵁 IP 鍦板潃鑾峰彇鏈烘鎵嬬姸鎬�
@@ -31,10 +33,10 @@
         /// 瀹夊叏鏇存柊鏈烘鎵嬬姸鎬侊紙涔愯閿侊級
         /// </summary>
         /// <param name="ipAddress">璁惧 IP 鍦板潃</param>
-        /// <param name="newState">鏂扮姸鎬佸疄浣擄紙RowVersion 浼氳鏇存柊锛�</param>
-        /// <param name="expectedRowVersion">鏈熸湜鐨勮鐗堟湰鍙凤紙鏇存柊鍓嶇殑鐗堟湰锛�</param>
+        /// <param name="newState">鏂扮姸鎬佸疄浣擄紙Version 浼氳嚜澧烇級</param>
+        /// <param name="expectedVersion">鏈熸湜鐨勭増鏈彿锛堟洿鏂板墠鐨勭増鏈級</param>
         /// <returns>鏄惁鏇存柊鎴愬姛锛沠alse 琛ㄧず鐗堟湰鍐茬獊鎴栬褰曚笉瀛樺湪</returns>
-        bool TryUpdate(string ipAddress, Dt_RobotState newState, byte[] expectedRowVersion);
+        bool TryUpdate(string ipAddress, Dt_RobotState newState, long expectedVersion);
 
         /// <summary>
         /// 灏� Dt_RobotState 瀹炰綋杞崲涓� RobotSocketState 鍐呭瓨瀵硅薄
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/WIDESEAWCS_ITaskInfoRepository.csproj b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/WIDESEAWCS_ITaskInfoRepository.csproj
index b81dff8..34104db 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/WIDESEAWCS_ITaskInfoRepository.csproj
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/WIDESEAWCS_ITaskInfoRepository.csproj
@@ -8,6 +8,7 @@
 
 	<ItemGroup>
 	  <ProjectReference Include="..\WIDESEAWCS_DTO\WIDESEAWCS_DTO.csproj" />
+	  <ProjectReference Include="..\WIDESEAWCS_Model\WIDESEAWCS_Model.csproj" />
 	</ItemGroup>
 
 </Project>
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotStateService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotStateService.cs
new file mode 100644
index 0000000..b8dd92c
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotStateService.cs
@@ -0,0 +1,13 @@
+using WIDESEAWCS_Core;
+using WIDESEAWCS_Core.BaseServices;
+using WIDESEAWCS_Model.Models;
+
+namespace WIDESEAWCS_ITaskInfoService
+{
+    /// <summary>
+    /// 鏈烘鎵嬬姸鎬佹湇鍔℃帴鍙�
+    /// </summary>
+    public interface IRobotStateService : IService<Dt_RobotState>
+    {
+    }
+}
\ No newline at end of file
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/Dt_RobotState.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/Dt_RobotState.cs
index efcaac0..8477545 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/Dt_RobotState.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/Dt_RobotState.cs
@@ -1,4 +1,3 @@
-using Newtonsoft.Json;
 using SqlSugar;
 using WIDESEAWCS_Core.DB.Models;
 
@@ -8,7 +7,7 @@
     /// 鏈烘鎵嬬姸鎬佹暟鎹簱瀹炰綋
     /// </summary>
     /// <remarks>
-    /// 瀵瑰簲鏁版嵁搴撹〃 Dt_RobotState锛屼娇鐢� RowVersion 瀹炵幇涔愯骞跺彂鎺у埗銆�
+    /// 瀵瑰簲鏁版嵁搴撹〃 Dt_RobotState锛屼娇鐢� Version 瀛楁瀹炵幇涔愯骞跺彂鎺у埗銆�
     /// 澶嶆潅瀵硅薄锛圧obotCrane銆丆urrentTask銆佹暟缁勭瓑锛変互 JSON 瀛楃涓插瓨鍌ㄣ��
     /// </remarks>
     [SugarTable(nameof(Dt_RobotState), "鏈烘鎵嬬姸鎬佽〃")]
@@ -23,141 +22,141 @@
         /// <summary>
         /// 鏈烘鎵� IP 鍦板潃锛屽敮涓�绱㈠紩
         /// </summary>
-        [SugarColumn(Length = 50, ColumnDescription = "鏈烘鎵婭P鍦板潃", IsJsonKey = true)]
+        [SugarColumn(Length = 50, ColumnDescription = "鏈烘鎵婭P鍦板潃")]
         public string IPAddress { get; set; } = string.Empty;
 
         /// <summary>
-        /// 琛岀増鏈紝鐢ㄤ簬涔愯骞跺彂鎺у埗
+        /// 鐗堟湰鍙凤紝鐢ㄤ簬涔愯骞跺彂鎺у埗
         /// </summary>
         /// <remarks>
-        /// SqlSugar 浼氳嚜鍔ㄧ鐞嗘瀛楁锛屾瘡娆℃洿鏂版椂鏁版嵁搴撹嚜鍔ㄩ�掑銆�
-        /// 鏇存柊鏃� WHERE RowVersion = @expectedRowVersion锛屾鏌ュ奖鍝嶈鏁板垽鏂槸鍚﹀啿绐併��
+        /// 姣忔鏇存柊鏃惰嚜澧炪�傛洿鏂版椂 WHERE IPAddress = @ip AND Version = @expectedVersion銆�
+        /// 濡傛灉褰卞搷琛屾暟涓� 0锛岃鏄庣増鏈笉鍖归厤锛岃繑鍥� false銆�
         /// </remarks>
-        [SugarColumn(ColumnDescription = "琛岀増鏈紙涔愯閿侊級", IsJsonKey = true)]
-        public byte[] RowVersion { get; set; } = Array.Empty<byte>();
+        [SugarColumn(ColumnDescription = "鐗堟湰鍙凤紙涔愯閿侊級")]
+        public long Version { get; set; }
 
         /// <summary>
         /// 鏄惁宸茶闃呮秷鎭簨浠�
         /// </summary>
-        [SugarColumn(ColumnDescription = "鏄惁宸茶闃呮秷鎭簨浠�", IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "鏄惁宸茶闃呮秷鎭簨浠�")]
         public bool IsEventSubscribed { get; set; }
 
         /// <summary>
         /// 鏈烘鎵嬭繍琛屾ā寮�
         /// </summary>
         /// <remarks>1: 鎵嬪姩妯″紡, 2: 鑷姩妯″紡</remarks>
-        [SugarColumn(ColumnDescription = "杩愯妯″紡", IsNullable = true, IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "杩愯妯″紡", IsNullable = true)]
         public int? RobotRunMode { get; set; }
 
         /// <summary>
         /// 鏈烘鎵嬫帶鍒舵ā寮�
         /// </summary>
         /// <remarks>1: 瀹㈡埛绔帶鍒�, 2: 鍏朵粬</remarks>
-        [SugarColumn(ColumnDescription = "鎺у埗妯″紡", IsNullable = true, IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "鎺у埗妯″紡", IsNullable = true)]
         public int? RobotControlMode { get; set; }
 
         /// <summary>
         /// 鏈烘鎵嬫墜鑷傛姄鍙栧璞$姸鎬�
         /// </summary>
         /// <remarks>0: 鏃犵墿鏂欙紙鎵嬭噦绌洪棽锛�, 1: 鏈夌墿鏂欙紙宸叉姄鍙栬揣鐗╋級</remarks>
-        [SugarColumn(ColumnDescription = "鎵嬭噦鎶撳彇鐘舵��", IsNullable = true, IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "鎵嬭噦鎶撳彇鐘舵��", IsNullable = true)]
         public int? RobotArmObject { get; set; }
 
         /// <summary>
         /// 鏈烘鎵嬭澶囧熀纭�淇℃伅锛圝SON 搴忓垪鍖栵級
         /// </summary>
-        [SugarColumn(Length = 2000, ColumnDescription = "璁惧淇℃伅JSON", IsJsonKey = true)]
-        public string RobotCraneJson { get; set; } = string.Empty;
+        [SugarColumn(Length = 2000, ColumnDescription = "璁惧淇℃伅JSON", IsNullable = true)]
+        public string? RobotCraneJson { get; set; }
 
         /// <summary>
         /// 鏈烘鎵嬪垵濮嬪寲瀹屾垚鍥炲埌寰呮満浣嶇姸鎬�
         /// </summary>
         /// <remarks>Possible values: "Homed", "Homing"</remarks>
-        [SugarColumn(Length = 50, ColumnDescription = "鍥為浂鐘舵��", IsNullable = true, IsJsonKey = true)]
+        [SugarColumn(Length = 50, ColumnDescription = "鍥為浂鐘舵��", IsNullable = true)]
         public string? Homed { get; set; }
 
         /// <summary>
         /// 鏈烘鎵嬪綋鍓嶆鍦ㄦ墽琛岀殑鍔ㄤ綔
         /// </summary>
-        [SugarColumn(Length = 50, ColumnDescription = "褰撳墠鍔ㄤ綔", IsNullable = true, IsJsonKey = true)]
+        [SugarColumn(Length = 50, ColumnDescription = "褰撳墠鍔ㄤ綔", IsNullable = true)]
         public string? CurrentAction { get; set; }
 
         /// <summary>
         /// 鏈烘鎵嬪綋鍓嶈繍琛岀姸鎬�
         /// </summary>
-        [SugarColumn(Length = 50, ColumnDescription = "杩愯鐘舵��", IsNullable = true, IsJsonKey = true)]
+        [SugarColumn(Length = 50, ColumnDescription = "杩愯鐘舵��", IsNullable = true)]
         public string? OperStatus { get; set; }
 
         /// <summary>
         /// 鏈�杩戜竴娆″彇璐у畬鎴愮殑浣嶇疆鏁扮粍锛圝SON锛�
         /// </summary>
-        [SugarColumn(Length = 500, ColumnDescription = "鍙栬揣浣嶇疆鏁扮粍JSON", IsNullable = true, IsJsonKey = true)]
+        [SugarColumn(Length = 500, ColumnDescription = "鍙栬揣浣嶇疆鏁扮粍JSON", IsNullable = true)]
         public string? LastPickPositionsJson { get; set; }
 
         /// <summary>
         /// 鏈�杩戜竴娆℃斁璐у畬鎴愮殑浣嶇疆鏁扮粍锛圝SON锛�
         /// </summary>
-        [SugarColumn(Length = 500, ColumnDescription = "鏀捐揣浣嶇疆鏁扮粍JSON", IsNullable = true, IsJsonKey = true)]
+        [SugarColumn(Length = 500, ColumnDescription = "鏀捐揣浣嶇疆鏁扮粍JSON", IsNullable = true)]
         public string? LastPutPositionsJson { get; set; }
 
         /// <summary>
         /// 鐢垫睜/璐т綅鏉$爜鍒楄〃锛圝SON锛�
         /// </summary>
-        [SugarColumn(Length = 2000, ColumnDescription = "鐢佃姱鏉$爜鍒楄〃JSON", IsNullable = true, IsJsonKey = true)]
+        [SugarColumn(Length = 2000, ColumnDescription = "鐢佃姱鏉$爜鍒楄〃JSON", IsNullable = true)]
         public string? CellBarcodeJson { get; set; }
 
         /// <summary>
         /// 鏈烘鎵嬪綋鍓嶆鍦ㄦ墽琛岀殑浠诲姟锛圝SON 搴忓垪鍖栵級
         /// </summary>
-        [SugarColumn(Length = 2000, ColumnDescription = "褰撳墠浠诲姟JSON", IsNullable = true, IsJsonKey = true)]
+        [SugarColumn(Length = 2000, ColumnDescription = "褰撳墠浠诲姟JSON", IsNullable = true)]
         public string? CurrentTaskJson { get; set; }
 
         /// <summary>
         /// 鏄惁闇�瑕佹墽琛屾媶鐩樹换鍔�
         /// </summary>
-        [SugarColumn(ColumnDescription = "鏄惁鎷嗙洏浠诲姟", IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "鏄惁鎷嗙洏浠诲姟")]
         public bool IsSplitPallet { get; set; }
 
         /// <summary>
         /// 鏄惁闇�瑕佹墽琛岀粍鐩樹换鍔�
         /// </summary>
-        [SugarColumn(ColumnDescription = "鏄惁缁勭洏浠诲姟", IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "鏄惁缁勭洏浠诲姟")]
         public bool IsGroupPallet { get; set; }
 
         /// <summary>
         /// 鏈哄櫒浜哄凡澶勭悊鐨勪换鍔℃�绘暟
         /// </summary>
-        [SugarColumn(ColumnDescription = "宸插鐞嗕换鍔℃�绘暟", IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "宸插鐞嗕换鍔℃�绘暟")]
         public int RobotTaskTotalNum { get; set; }
 
         /// <summary>
         /// 鏄惁澶勪簬鍋囩數鑺ˉ鍏呮ā寮�
         /// </summary>
-        [SugarColumn(ColumnDescription = "鏄惁鍋囩數鑺ā寮�", IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "鏄惁鍋囩數鑺ā寮�")]
         public bool IsInFakeBatteryMode { get; set; }
 
         /// <summary>
         /// 褰撳墠鎵规璧峰缂栧彿
         /// </summary>
-        [SugarColumn(ColumnDescription = "褰撳墠鎵规缂栧彿", IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "褰撳墠鎵规缂栧彿")]
         public int CurrentBatchIndex { get; set; } = 1;
 
         /// <summary>
         /// 鎹㈢洏浠诲姟褰撳墠闃舵
         /// </summary>
-        [SugarColumn(ColumnDescription = "鎹㈢洏闃舵", IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "鎹㈢洏闃舵")]
         public int ChangePalletPhase { get; set; }
 
         /// <summary>
         /// 鏄惁鎵爜NG
         /// </summary>
-        [SugarColumn(ColumnDescription = "鏄惁鎵爜NG", IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "鏄惁鎵爜NG")]
         public bool IsScanNG { get; set; }
 
         /// <summary>
         /// 鏄惁鐢佃姱鍒颁綅
         /// </summary>
-        [SugarColumn(ColumnDescription = "鐢佃姱鏄惁鍒颁綅", IsJsonKey = true)]
+        [SugarColumn(ColumnDescription = "鐢佃姱鏄惁鍒颁綅")]
         public bool BatteryArrived { get; set; }
     }
-}
\ No newline at end of file
+}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotCraneDevice.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotCraneDevice.cs
new file mode 100644
index 0000000..5e77ab3
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotCraneDevice.cs
@@ -0,0 +1,28 @@
+namespace WIDESEAWCS_Model.Models
+{
+    /// <summary>
+    /// 鏈哄櫒浜鸿澶囧熀纭�淇℃伅
+    /// </summary>
+    public class RobotCraneDevice
+    {
+        /// <summary>
+        /// 璁惧鏍囪瘑
+        /// </summary>
+        public string Device { get; set; } = string.Empty;
+
+        /// <summary>
+        /// 璁惧缂栫爜
+        /// </summary>
+        public string DeviceCode { get; set; } = string.Empty;
+
+        /// <summary>
+        /// 璁惧鍚嶇О
+        /// </summary>
+        public string DeviceName { get; set; } = string.Empty;
+
+        /// <summary>
+        /// IP 鍦板潃
+        /// </summary>
+        public string IPAddress { get; set; } = string.Empty;
+    }
+}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotSocketState.cs
similarity index 96%
rename from Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs
rename to Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotSocketState.cs
index 06c8d92..de75b1d 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/RobotSocketState.cs
@@ -1,13 +1,10 @@
-using WIDESEAWCS_Model.Models;
-using WIDESEAWCS_QuartzJob;
-
-namespace WIDESEAWCS_Tasks
+namespace WIDESEAWCS_Model.Models
 {
     /// <summary>
     /// 鏈烘鎵� Socket 閫氫俊鐘舵�佹暟鎹被
     /// </summary>
     /// <remarks>
-    /// 璇ョ被鐢ㄤ簬鍦� Redis 缂撳瓨涓瓨鍌ㄦ満姊版墜鐨勫疄鏃剁姸鎬侊紝鍖呮嫭浣嶇疆銆佷换鍔°�佹墜鑷傚璞$瓑淇℃伅銆�
+    /// 璇ョ被鐢ㄤ簬鍦ㄦ暟鎹簱涓瓨鍌ㄦ満姊版墜鐨勫疄鏃剁姸鎬侊紝鍖呮嫭浣嶇疆銆佷换鍔°�佹墜鑷傚璞$瓑淇℃伅銆�
     /// 鎵�鏈夊睘鎬у潎璁捐涓虹嚎绋嬪畨鍏ㄦ洿鏂帮紝閫氳繃 <see cref="RobotStateManager"/> 鐨勭増鏈帶鍒舵満鍒舵潵闃叉骞跺彂瑕嗙洊銆�
     /// </remarks>
     public class RobotSocketState
@@ -21,7 +18,7 @@
         /// 鐗堟湰鍙凤紝鐢ㄤ簬涔愯骞跺彂鎺у埗
         /// </summary>
         /// <remarks>
-        /// 姣忔淇敼鐘舵�佹椂鏇存柊涓� DateTime.UtcNow.Ticks銆�
+        /// 姣忔淇敼鐘舵�佹椂鑷銆�
         /// <see cref="RobotStateManager"/> 浣跨敤姝ゅ瓧娈靛疄鐜颁箰瑙傞攣锛岄槻姝㈠苟鍙戞洿鏂版椂鏃у�艰鐩栨柊鍊笺��
         /// </remarks>
         public long Version { get; set; } = DateTime.UtcNow.Ticks;
@@ -212,8 +209,6 @@
         /// 鎷夊甫绾夸笂鐢佃姱鎵爜鏄惁NG銆�
         /// </remarks>
         public bool IsScanNG { get; set; } = false;
-
-
 
         /// <summary>
         /// 鏄惁鐢佃姱鍒颁綅
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/QuartzNet/QuartzNetExtension.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/QuartzNet/QuartzNetExtension.cs
index 3225212..41e3e7e 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/QuartzNet/QuartzNetExtension.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/QuartzNet/QuartzNetExtension.cs
@@ -4,6 +4,7 @@
 using WIDESEAWCS_Core.Caches;
 using WIDESEAWCS_Core.Helper;
 using WIDESEAWCS_Core.LogHelper;
+using WIDESEAWCS_Model.Models;
 using WIDESEAWCS_QuartzJob.DTO;
 using WIDESEAWCS_QuartzJob.Service;
 
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Robot/RobotCraneDevice.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Robot/RobotCraneDevice.cs
deleted file mode 100644
index d251e27..0000000
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Robot/RobotCraneDevice.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-锘縰sing System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace WIDESEAWCS_QuartzJob
-{
-    public class RobotCraneDevice
-    {
-        public string Device { get; set; }
-        public string DeviceCode { get; set; }
-        public string DeviceName { get; set; }
-        public string IPAddress { get; set; }
-    }
-}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/WIDESEAWCS_QuartzJob.csproj b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/WIDESEAWCS_QuartzJob.csproj
index 9c20899..9d66919 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/WIDESEAWCS_QuartzJob.csproj
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/WIDESEAWCS_QuartzJob.csproj
@@ -43,6 +43,7 @@
 		<ProjectReference Include="..\WIDESEAWCS_Common\WIDESEAWCS_Common.csproj" />
 		<ProjectReference Include="..\WIDESEAWCS_Communicator\WIDESEAWCS_Communicator.csproj" />
 		<ProjectReference Include="..\WIDESEAWCS_Core\WIDESEAWCS_Core.csproj" />
+		<ProjectReference Include="..\WIDESEAWCS_Model\WIDESEAWCS_Model.csproj" />
 	</ItemGroup>
 
 </Project>
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotStateController.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotStateController.cs
new file mode 100644
index 0000000..4f20f11
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotStateController.cs
@@ -0,0 +1,20 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using WIDESEAWCS_Core.BaseController;
+using WIDESEAWCS_ITaskInfoService;
+using WIDESEAWCS_Model.Models;
+
+namespace WIDESEAWCS_WCSServer.Controllers.Task
+{
+    /// <summary>
+    /// 鏈烘鎵嬬姸鎬佺鐞嗘帶鍒跺櫒
+    /// </summary>
+    [Route("api/RobotState")]
+    [ApiController]
+    public class RobotStateController : ApiBaseController<IRobotStateService, Dt_RobotState>
+    {
+        public RobotStateController(IRobotStateService service) : base(service)
+        {
+        }
+    }
+}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
index 2907e3e..f2d2bbf 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
@@ -54,7 +54,7 @@
   "ApiName": "WIDESEAWCS",
   "ExpMinutes": 120,
   "QuartzJobAutoStart": true,
-  "DBSeedEnable": false,
+  "DBSeedEnable": true,
   "QuartzDBSeedEnable": false,
   "LogDeubgEnable": false, //鏄惁璁板綍璋冭瘯鏃ュ織
   "PrintSql": false, //鎵撳嵃SQL璇彞
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/RobotStateRepository.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/RobotStateRepository.cs
index d282af4..012d9ad 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/RobotStateRepository.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/RobotStateRepository.cs
@@ -1,7 +1,6 @@
 using Newtonsoft.Json;
 using SqlSugar;
 using WIDESEAWCS_Core.BaseRepository;
-using WIDESEAWCS_Core.UnitOfWork;
 using WIDESEAWCS_ITaskInfoRepository;
 using WIDESEAWCS_Model.Models;
 
@@ -10,20 +9,15 @@
     /// <summary>
     /// 鏈烘鎵嬬姸鎬� SqlSugar 浠撳偍瀹炵幇
     /// </summary>
-    public class RobotStateRepository : IUnitOfWork, IRobotStateRepository
+    public class RobotStateRepository : RepositoryBase<Dt_RobotState>, IRobotStateRepository
     {
-        private readonly IUnitOfWorkManage _unitOfWork;
-        private readonly SqlSugarClient _db;
-
-        public RobotStateRepository(IUnitOfWorkManage unitOfWork)
+        public RobotStateRepository(IUnitOfWorkManage unitOfWork) : base(unitOfWork)
         {
-            _unitOfWork = unitOfWork;
-            _db = unitOfWork.GetDbClient();
         }
 
         public Dt_RobotState? GetByIp(string ipAddress)
         {
-            return _db.Queryable<Dt_RobotState>()
+            return Db.Queryable<Dt_RobotState>()
                 .Where(x => x.IPAddress == ipAddress)
                 .First();
         }
@@ -39,22 +33,23 @@
             var newState = new Dt_RobotState
             {
                 IPAddress = ipAddress,
+                Version = DateTime.UtcNow.Ticks,
                 RobotCraneJson = JsonConvert.SerializeObject(robotCrane),
-                CreateTime = DateTime.Now,
-                UpdateTime = DateTime.Now
+                CreateDate = DateTime.Now,
+                ModifyDate = DateTime.Now
             };
 
-            _db.Insertable(newState).ExecuteCommand();
+            Db.Insertable(newState).ExecuteCommand();
             return newState;
         }
 
-        public bool TryUpdate(string ipAddress, Dt_RobotState newState, byte[] expectedRowVersion)
+        public bool TryUpdate(string ipAddress, Dt_RobotState newState, long expectedVersion)
         {
-            newState.UpdateTime = DateTime.Now;
+            newState.ModifyDate = DateTime.Now;
 
-            var affectedRows = _db.Updateable<Dt_RobotState>(newState)
-                .Where(x => x.IPAddress == ipAddress)
-                .WhereRowVersion(x => x.RowVersion, expectedRowVersion)
+            // 涔愯閿侊細WHERE IPAddress = @ip AND Version = @expectedVersion锛岀増鏈尮閰嶆墠鏇存柊
+            var affectedRows = Db.Updateable<Dt_RobotState>(newState)
+                .Where(x => x.IPAddress == ipAddress && x.Version == expectedVersion)
                 .ExecuteCommand();
 
             return affectedRows > 0;
@@ -65,7 +60,7 @@
             var state = new RobotSocketState
             {
                 IPAddress = entity.IPAddress,
-                Version = BitConverter.ToInt64(entity.RowVersion.Length >= 8 ? entity.RowVersion.Take(8).ToArray() : new byte[8], 0),
+                Version = entity.Version,
                 IsEventSubscribed = entity.IsEventSubscribed,
                 RobotRunMode = entity.RobotRunMode,
                 RobotControlMode = entity.RobotControlMode,
@@ -162,13 +157,5 @@
 
             return entity;
         }
-
-        public SqlSugarClient GetDbClient() => _db;
-
-        public void BeginTran() => _unitOfWork.BeginTran();
-
-        public void CommitTran() => _unitOfWork.CommitTran();
-
-        public void RollbackTran() => _unitOfWork.RollbackTran();
     }
 }
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotStateService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotStateService.cs
new file mode 100644
index 0000000..d836367
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotStateService.cs
@@ -0,0 +1,18 @@
+using WIDESEA_Core;
+using WIDESEAWCS_Core.BaseServices;
+using WIDESEAWCS_ITaskInfoRepository;
+using WIDESEAWCS_ITaskInfoService;
+using WIDESEAWCS_Model.Models;
+
+namespace WIDESEAWCS_TaskInfoService
+{
+    /// <summary>
+    /// 鏈烘鎵嬬姸鎬佹湇鍔″疄鐜�
+    /// </summary>
+    public class RobotStateService : ServiceBase<Dt_RobotState, IRobotStateRepository>, IRobotStateService
+    {
+        public RobotStateService(IRobotStateRepository repository) : base(repository)
+        {
+        }
+    }
+}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotMessageRouter.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotMessageRouter.cs
index 7a2731a..d5fe523 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotMessageRouter.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotMessageRouter.cs
@@ -1,4 +1,5 @@
 using System.Net.Sockets;
+using WIDESEAWCS_Model.Models;
 
 namespace WIDESEAWCS_Tasks.Workflow.Abstractions
 {
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotPrefixCommandHandler.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotPrefixCommandHandler.cs
index a2ee74b..25cf6f7 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotPrefixCommandHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotPrefixCommandHandler.cs
@@ -1,4 +1,5 @@
 using System.Net.Sockets;
+using WIDESEAWCS_Model.Models;
 
 namespace WIDESEAWCS_Tasks.Workflow.Abstractions
 {
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotSimpleCommandHandler.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotSimpleCommandHandler.cs
index af6e6a2..477137a 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotSimpleCommandHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/IRobotSimpleCommandHandler.cs
@@ -1,3 +1,5 @@
+using WIDESEAWCS_Model.Models;
+
 namespace WIDESEAWCS_Tasks.Workflow.Abstractions
 {
     /// <summary>
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/ISocketClientGateway.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/ISocketClientGateway.cs
index b238bb0..0d56122 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/ISocketClientGateway.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Abstractions/ISocketClientGateway.cs
@@ -1,4 +1,5 @@
 using System.Net.Sockets;
+using WIDESEAWCS_Model.Models;
 using WIDESEAWCS_QuartzJob;
 
 namespace WIDESEAWCS_Tasks.Workflow.Abstractions
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotClientManager.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotClientManager.cs
index 942a8d3..1d952e3 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotClientManager.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotClientManager.cs
@@ -2,6 +2,7 @@
 using System.Net.Sockets;
 using Microsoft.Extensions.Logging;
 using WIDESEAWCS_Core.LogHelper;
+using WIDESEAWCS_Model.Models;
 using WIDESEAWCS_QuartzJob;
 using WIDESEAWCS_Tasks.SocketServer;
 
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
index f472356..ead2ab1 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
@@ -7,7 +7,8 @@
 using WIDESEAWCS_Core.LogHelper;
 using WIDESEAWCS_ITaskInfoService;
 using WIDESEAWCS_QuartzJob;
-using WIDESEAWCS_RedisService;
+using WIDESEAWCS_ITaskInfoRepository;
+using WIDESEAWCS_Model.Models;
 using WIDESEAWCS_Tasks.SocketServer;
 using WIDESEAWCS_Tasks.Workflow;
 using WIDESEAWCS_Tasks.Workflow.Abstractions;
@@ -129,7 +130,7 @@
             var prefixCommandHandler = new RobotPrefixCommandHandler(robotTaskService, _taskProcessor, _stateManager, socketGateway, fakeBatteryPositionService);
 
             // 鍒濆鍖栨秷鎭矾鐢卞櫒
-            _messageRouter = new RobotMessageHandler(socketGateway, _stateManager, cache, simpleCommandHandler, prefixCommandHandler, logger);
+            _messageRouter = new RobotMessageHandler(socketGateway, _stateManager, simpleCommandHandler, prefixCommandHandler, logger);
 
             // 鍒濆鍖栧伐浣滄祦缂栨帓鍣�
             _workflowOrchestrator = new RobotWorkflowOrchestrator(_stateManager, _clientManager, _taskProcessor, robotTaskService, _logger);
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs
index f8155cc..9bcf06b 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs
@@ -1,8 +1,8 @@
 using Microsoft.Extensions.Logging;
 using System.Net.Sockets;
 using WIDESEAWCS_Common;
-using WIDESEAWCS_Core.Caches;
 using WIDESEAWCS_Core.LogHelper;
+using WIDESEAWCS_Model.Models;
 using WIDESEAWCS_Tasks.Workflow.Abstractions;
 
 namespace WIDESEAWCS_Tasks
@@ -12,7 +12,7 @@
     /// </summary>
     /// <remarks>
     /// 鏍稿績鑱岃矗锛�
-    /// 1. 缂撳瓨鐘舵�佽鍙栵細浠� Redis 涓幏鍙栨満鍣ㄤ汉鏈�鏂扮殑鐘舵��
+    /// 1. 鐘舵�佹帴鏀讹細浠庤皟鐢ㄦ柟鑾峰彇鏈哄櫒浜烘渶鏂扮殑鐘舵��
     /// 2. 鍛戒护鍒嗗彂锛氭牴鎹秷鎭被鍨嬪垎鍙戠粰涓嶅悓鐨勫鐞嗗櫒
     ///    - 绠�鍗曞懡浠わ紙濡� homing銆乺unning锛夛細鐢� <see cref="IRobotSimpleCommandHandler"/> 澶勭悊
     ///    - 鍓嶇紑鍛戒护锛堝 pickfinished銆乸utfinished锛夛細鐢� <see cref="IRobotPrefixCommandHandler"/> 澶勭悊
@@ -25,41 +25,21 @@
         /// <summary>
         /// Socket 瀹㈡埛绔綉鍏虫帴鍙�
         /// </summary>
-        /// <remarks>
-        /// 鐢ㄤ簬鍚戝鎴风鍙戦�佸搷搴旀秷鎭��
-        /// </remarks>
         private readonly ISocketClientGateway _socketClientGateway;
 
         /// <summary>
         /// 鏈烘鎵嬬姸鎬佺鐞嗗櫒
         /// </summary>
-        /// <remarks>
-        /// 鐢ㄤ簬璇诲彇鍜屾洿鏂版満鍣ㄤ汉鐨勭姸鎬併��
-        /// </remarks>
         private readonly RobotStateManager _stateManager;
-
-        /// <summary>
-        /// 缂撳瓨鏈嶅姟
-        /// </summary>
-        /// <remarks>
-        /// 鐩存帴浣跨敤缂撳瓨鏈嶅姟妫�鏌ョ姸鎬佹槸鍚﹀瓨鍦ㄣ��
-        /// </remarks>
-        private readonly ICacheService _cache;
 
         /// <summary>
         /// 绠�鍗曞懡浠ゅ鐞嗗櫒
         /// </summary>
-        /// <remarks>
-        /// 澶勭悊绠�鍗曠殑鐘舵�佹洿鏂板懡浠わ紝濡傝繍琛岀姸鎬併�佹ā寮忓垏鎹㈢瓑銆�
-        /// </remarks>
         private readonly IRobotSimpleCommandHandler _simpleCommandHandler;
 
         /// <summary>
         /// 鍓嶇紑鍛戒护澶勭悊鍣�
         /// </summary>
-        /// <remarks>
-        /// 澶勭悊甯﹀弬鏁扮殑鍓嶇紑鍛戒护锛屽 pickfinished锛堝彇璐у畬鎴愶級銆乸utfinished锛堟斁璐у畬鎴愶級銆�
-        /// </remarks>
         private readonly IRobotPrefixCommandHandler _prefixCommandHandler;
 
         /// <summary>
@@ -72,21 +52,18 @@
         /// </summary>
         /// <param name="socketClientGateway">Socket 缃戝叧</param>
         /// <param name="stateManager">鐘舵�佺鐞嗗櫒</param>
-        /// <param name="cache">缂撳瓨鏈嶅姟</param>
         /// <param name="simpleCommandHandler">绠�鍗曞懡浠ゅ鐞嗗櫒</param>
         /// <param name="prefixCommandHandler">鍓嶇紑鍛戒护澶勭悊鍣�</param>
         /// <param name="logger">鏃ュ織璁板綍鍣�</param>
         public RobotMessageHandler(
             ISocketClientGateway socketClientGateway,
             RobotStateManager stateManager,
-            ICacheService cache,
             IRobotSimpleCommandHandler simpleCommandHandler,
             IRobotPrefixCommandHandler prefixCommandHandler,
             ILogger<RobotJob> logger)
         {
             _socketClientGateway = socketClientGateway;
             _stateManager = stateManager;
-            _cache = cache;
             _simpleCommandHandler = simpleCommandHandler;
             _prefixCommandHandler = prefixCommandHandler;
             _logger = logger;
@@ -98,12 +75,11 @@
         /// <remarks>
         /// 澶勭悊娴佺▼锛�
         /// 1. 璁板綍鏃ュ織锛堣褰曞師濮嬫秷鎭唴瀹癸級
-        /// 2. 楠岃瘉缂撳瓨涓槸鍚﹀瓨鍦ㄨ璁惧鐨勭姸鎬�
-        /// 3. 灏濊瘯鐢ㄧ畝鍗曞懡浠ゅ鐞嗗櫒澶勭悊锛堢姸鎬佹洿鏂扮被鍛戒护锛�
+        /// 2. 灏濊瘯鐢ㄧ畝鍗曞懡浠ゅ鐞嗗櫒澶勭悊锛堢姸鎬佹洿鏂扮被鍛戒护锛�
         ///    - 濡傛灉澶勭悊鎴愬姛锛屽洖鍐欏師娑堟伅骞舵洿鏂扮姸鎬�
-        /// 4. 濡傛灉涓嶆槸绠�鍗曞懡浠わ紝妫�鏌ユ槸鍚︽槸鍓嶇紑鍛戒护锛坧ickfinished/putfinished锛�
+        /// 3. 濡傛灉涓嶆槸绠�鍗曞懡浠わ紝妫�鏌ユ槸鍚︽槸鍓嶇紑鍛戒护锛坧ickfinished/putfinished锛�
         ///    - 濡傛灉鏄紝璋冪敤鍓嶇紑鍛戒护澶勭悊鍣ㄥ鐞�
-        /// 5. 淇濇寔鍘熸湁琛屼负锛氱畝鍗曞懡浠ゅ拰鍓嶇紑鍛戒护閮藉洖鍐欏師娑堟伅
+        /// 4. 淇濇寔鍘熸湁琛屼负锛氱畝鍗曞懡浠ゅ拰鍓嶇紑鍛戒护閮藉洖鍐欏師娑堟伅
         ///
         /// 娉ㄦ剰锛氭鏂规硶鍙兘鍦� TCP 娑堟伅鎺ユ敹鐨勪笂涓嬫枃涓棰戠箒璋冪敤锛岄渶娉ㄦ剰鎬ц兘銆�
         /// </remarks>
@@ -115,46 +91,31 @@
         public async Task<string?> HandleMessageReceivedAsync(string message, bool isJson, TcpClient client, RobotSocketState state)
         {
             // 璁板綍鎺ユ敹鍒扮殑娑堟伅鏃ュ織
-            _logger.LogInformation($"鎺ユ敹鍒板鎴风銆恵state.RobotCrane.DeviceName}銆戝彂閫佹秷鎭�恵message}銆�");
-            QuartzLogger.Info($"鎺ユ敹鍒板鎴风娑堟伅銆恵message}銆�", state.RobotCrane.DeviceName);
+            _logger.LogInformation($"鎺ユ敹鍒板鎴风銆恵state.RobotCrane?.DeviceName}銆戝彂閫佹秷鎭�恵message}銆�");
+            QuartzLogger.Info($"鎺ユ敹鍒板鎴风娑堟伅銆恵message}銆�", state.RobotCrane?.DeviceName);
 
             // 妫�鏌ヤ换鍔℃�绘暟鏄惁鏈揪鍒颁笂闄�
             if (state.RobotTaskTotalNum > RobotConst.MaxTaskTotalNum)
             {
-                // 璁板綍鎺ユ敹鍒扮殑娑堟伅鏃ュ織
-                _logger.LogInformation($"鎺ユ敹鍒板鎴风銆恵state.RobotCrane.DeviceName}銆戝彂閫佹秷鎭�恵message}銆�");
-                QuartzLogger.Info($"鎺ユ敹鍒板鎴风娑堟伅銆恵message}銆�", state.RobotCrane.DeviceName);
-                // 澶勭悊鎴愬姛鍚庯紝灏嗗師娑堟伅鍥炲啓鍒板鎴风锛堜繚鎸佸師鏈夎涓猴級
+                _logger.LogInformation($"鎺ユ敹鍒板鎴风銆恵state.RobotCrane?.DeviceName}銆戝彂閫佹秷鎭�恵message}銆�");
+                QuartzLogger.Info($"鎺ユ敹鍒板鎴风娑堟伅銆恵message}銆�", state.RobotCrane?.DeviceName);
                 await _socketClientGateway.SendMessageAsync(client, message);
                 return null;
             }
-
-            // 鏋勫缓缂撳瓨閿紝妫�鏌� Redis 涓槸鍚﹀瓨鍦ㄨ璁惧鐨勭姸鎬�
-            var cacheKey = $"{RedisPrefix.Code}:{RedisName.SocketDevices}:{client.Client.RemoteEndPoint}";
-
-            // 濡傛灉缂撳瓨涓笉瀛樺湪鎴栫姸鎬佷负 null锛屽拷鐣ユ娑堟伅
-            if (!_cache.TryGetValue(cacheKey, out RobotSocketState? cachedState) || cachedState == null)
-            {
-                _logger.LogInformation($"缂撳瓨涓笉瀛樺湪鎴栫姸鎬佷负 null锛屽拷鐣ユ娑堟伅");
-                return null;
-            }
-
-            // 浣跨敤缂撳瓨涓幏鍙栫殑鐘舵��
-            var activeState = cachedState;
 
             // 灏嗘秷鎭浆鎹负灏忓啓锛堢敤浜庣畝鍗曞懡浠ゅ尮閰嶏級
             string messageLower = message.ToLowerInvariant();
 
             // 灏濊瘯鐢ㄧ畝鍗曞懡浠ゅ鐞嗗櫒澶勭悊
             // 绠�鍗曞懡浠ゅ寘鎷細homing銆乭omed銆乺unning銆乸ausing銆乺unmode銆乧ontrolmode 绛�
-            if (await _simpleCommandHandler.HandleAsync(messageLower, activeState))
+            if (await _simpleCommandHandler.HandleAsync(messageLower, state))
             {
                 // 澶勭悊鎴愬姛鍚庯紝灏嗗師娑堟伅鍥炲啓鍒板鎴风锛堜繚鎸佸師鏈夎涓猴級
                 await _socketClientGateway.SendMessageAsync(client, message);
-                QuartzLogger.Info($"鍙戦�佹秷鎭細銆恵message}銆�", state.RobotCrane.DeviceName);
+                QuartzLogger.Info($"鍙戦�佹秷鎭細銆恵message}銆�", state.RobotCrane?.DeviceName);
 
-                // 瀹夊叏鏇存柊鐘舵�佸埌 Redis
-                _stateManager.TryUpdateStateSafely(activeState.IPAddress, activeState);
+                // 瀹夊叏鏇存柊鐘舵�佸埌鏁版嵁搴�
+                _stateManager.TryUpdateStateSafely(state.IPAddress, state);
                 return null;
             }
 
@@ -163,11 +124,9 @@
             if (_prefixCommandHandler.IsPrefixCommand(messageLower))
             {
                 // 璋冪敤鍓嶇紑鍛戒护澶勭悊鍣�
-                // 鍓嶇紑鍛戒护澶勭悊鍣ㄤ細瑙f瀽浣嶇疆鍙傛暟骞舵洿鏂扮姸鎬�
-                await _prefixCommandHandler.HandleAsync(message, activeState, client);
+                await _prefixCommandHandler.HandleAsync(message, state, client);
             }
 
-            // 榛樿杩斿洖 null锛屼笉浜х敓鍝嶅簲娑堟伅
             return null;
         }
     }
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotStateManager.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotStateManager.cs
index 028305d..4aaae62 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotStateManager.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotStateManager.cs
@@ -1,6 +1,5 @@
 using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;
-using WIDESEAWCS_Common;
 using WIDESEAWCS_Core.LogHelper;
 using WIDESEAWCS_ITaskInfoRepository;
 using WIDESEAWCS_Model.Models;
@@ -12,7 +11,7 @@
     /// </summary>
     /// <remarks>
     /// 鏍稿績鍔熻兘鏄�氳繃 IRobotStateRepository 绠$悊鏁版嵁搴撲腑鐨勬満姊版墜鐘舵�併��
-    /// 鎻愪緵涔愯骞跺彂鎺у埗锛岄�氳繃 RowVersion 闃叉骞跺彂鏇存柊鏃剁殑鏁版嵁瑕嗙洊闂銆�
+    /// 鎻愪緵涔愯骞跺彂鎺у埗锛岄�氳繃 Version 瀛楁闃叉骞跺彂鏇存柊鏃剁殑鏁版嵁瑕嗙洊闂銆�
     /// </remarks>
     public class RobotStateManager
     {
@@ -38,11 +37,11 @@
         }
 
         /// <summary>
-        /// 瀹夊叏鏇存柊 RobotSocketState 缂撳瓨锛岄槻姝㈠苟鍙戣鐩�
+        /// 瀹夊叏鏇存柊 RobotSocketState锛岄槻姝㈠苟鍙戣鐩�
         /// </summary>
         /// <remarks>
-        /// 浣跨敤涔愯骞跺彂妯″紡锛氬厛璇诲彇褰撳墠 RowVersion锛屾墽琛屾洿鏂版椂妫�鏌ョ増鏈槸鍚︿竴鑷淬��
-        /// 濡傛灉 RowVersion 涓嶅尮閰嶏紙璇存槑鏈夊叾浠栫嚎绋嬪凡鏇存柊锛夛紝鍒欐洿鏂板け璐ヨ繑鍥� false銆�
+        /// 浣跨敤涔愯骞跺彂妯″紡锛氬厛璇诲彇褰撳墠 Version锛屾墽琛屾洿鏂版椂妫�鏌ョ増鏈槸鍚︿竴鑷淬��
+        /// 濡傛灉 Version 涓嶅尮閰嶏紙璇存槑鏈夊叾浠栫嚎绋嬪凡鏇存柊锛夛紝鍒欐洿鏂板け璐ヨ繑鍥� false銆�
         /// </remarks>
         /// <param name="ipAddress">璁惧 IP 鍦板潃</param>
         /// <param name="updateAction">鏇存柊鐘舵�佺殑濮旀墭鍑芥暟锛屼紶鍏ュ綋鍓嶇姸鎬佸壇鏈紝杩斿洖淇敼鍚庣殑鏂扮姸鎬�</param>
@@ -57,8 +56,8 @@
                 return false;
             }
 
-            // 璁板綍褰撳墠瀛樺偍鐨� RowVersion锛屼綔涓烘洿鏂版椂鐨勬湡鏈涚増鏈�
-            var expectedRowVersion = currentEntity.RowVersion;
+            // 璁板綍褰撳墠瀛樺偍鐨� Version锛屼綔涓烘洿鏂版椂鐨勬湡鏈涚増鏈�
+            var expectedVersion = currentEntity.Version;
 
             // 鍒涘缓鐘舵�佺殑娣辨嫹璐濆壇鏈紙浣跨敤 JSON 搴忓垪鍖栧疄鐜帮級
             var stateCopy = CloneState(_repository.ToSocketState(currentEntity));
@@ -68,12 +67,12 @@
 
             // 灏嗘柊鐘舵�佽浆鎹负鏁版嵁搴撳疄浣�
             var newEntity = _repository.ToEntity(newState);
-            newEntity.RowVersion = Array.Empty<byte>(); // SqlSugar 浼氳嚜鍔ㄧ鐞�
             newEntity.Id = currentEntity.Id;
+            newEntity.Version = expectedVersion + 1; // 鐗堟湰鑷
 
-            // 璋冪敤浠撳偍鐨勫畨鍏ㄦ洿鏂版柟娉曪紝浼犲叆鏈熸湜 RowVersion
-            // 濡傛灉 RowVersion 涓嶄竴鑷达紙宸茶鍏朵粬绾跨▼鏇存柊锛夛紝鍒欐洿鏂板け璐�
-            return _repository.TryUpdate(ipAddress, newEntity, expectedRowVersion);
+            // 璋冪敤浠撳偍鐨勫畨鍏ㄦ洿鏂版柟娉曪紝浼犲叆鏈熸湜 Version
+            // 濡傛灉 Version 涓嶄竴鑷达紙宸茶鍏朵粬绾跨▼鏇存柊锛夛紝鍒欐洿鏂板け璐�
+            return _repository.TryUpdate(ipAddress, newEntity, expectedVersion);
         }
 
         /// <summary>
@@ -94,29 +93,26 @@
             // 濡傛灉褰撳墠涓嶅瓨鍦ㄨ璁惧鐨勭姸鎬侊紝鍒涘缓鏂拌褰�
             if (currentEntity == null)
             {
-                var entity = _repository.ToEntity(newState);
-                entity.CreateTime = DateTime.Now;
-                entity.UpdateTime = DateTime.Now;
                 _repository.GetOrCreate(newState.IPAddress, newState.RobotCrane ?? new RobotCraneDevice());
                 _logger.LogDebug("TryUpdateStateSafely锛氬垱寤烘柊鐘舵�侊紝IP: {IpAddress}", ipAddress);
                 QuartzLogger.Debug($"鍒涘缓鏂扮姸鎬侊紝IP: {ipAddress}", ipAddress);
                 return true;
             }
 
-            // 褰撳墠瀛樺湪鐘舵�侊紝璁板綍鏈熸湜 RowVersion 鐢ㄤ簬涔愯閿佹鏌�
-            var expectedRowVersion = currentEntity.RowVersion;
+            // 褰撳墠瀛樺湪鐘舵�侊紝璁板綍鏈熸湜 Version 鐢ㄤ簬涔愯閿佹鏌�
+            var expectedVersion = currentEntity.Version;
 
             // 灏嗘柊鐘舵�佽浆鎹负鏁版嵁搴撳疄浣�
             var newEntity = _repository.ToEntity(newState);
             newEntity.Id = currentEntity.Id;
-            newEntity.RowVersion = Array.Empty<byte>();
+            newEntity.Version = expectedVersion + 1; // 鐗堟湰鑷
 
             // 灏濊瘯瀹夊叏鏇存柊锛屽鏋滅増鏈啿绐佸垯杩斿洖 false
-            bool success = _repository.TryUpdate(ipAddress, newEntity, expectedRowVersion);
+            bool success = _repository.TryUpdate(ipAddress, newEntity, expectedVersion);
 
             if (!success)
             {
-                _logger.LogWarning("TryUpdateStateSafely锛氱増鏈啿绐侊紝鏇存柊澶辫触锛孖P: {IpAddress}锛屾湡鏈涚増鏈瓧鑺傞暱搴�: {ExpectedLength}", ipAddress, expectedRowVersion.Length);
+                _logger.LogWarning("TryUpdateStateSafely锛氱増鏈啿绐侊紝鏇存柊澶辫触锛孖P: {IpAddress}锛屾湡鏈涚増鏈�: {ExpectedVersion}", ipAddress, expectedVersion);
                 QuartzLogger.Warn($"鐗堟湰鍐茬獊锛屾洿鏂板け璐ワ紝IP: {ipAddress}", ipAddress);
             }
 
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 6f7515c..f623791 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
@@ -1,5 +1,6 @@
 using WIDESEAWCS_Common.TaskEnum;
 using WIDESEAWCS_Core.LogHelper;
+using WIDESEAWCS_Model.Models;
 using WIDESEAWCS_Tasks.Workflow.Abstractions;
 
 namespace WIDESEAWCS_Tasks.Workflow
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/SocketClientGateway.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/SocketClientGateway.cs
index feef4f1..7142a7b 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/SocketClientGateway.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/SocketClientGateway.cs
@@ -1,4 +1,5 @@
 using System.Net.Sockets;
+using WIDESEAWCS_Model.Models;
 using WIDESEAWCS_QuartzJob;
 using WIDESEAWCS_Tasks.Workflow.Abstractions;
 
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
index 5b0ba27..6a5fca3 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
@@ -2,6 +2,7 @@
 using System.Text;
 using System.Text.Json;
 using System.IO;
+using WIDESEAWCS_Model.Models;
 
 namespace WIDESEAWCS_Tasks.SocketServer
 {
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs
index 1999ffd..723464b 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs
@@ -6,6 +6,7 @@
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
+using WIDESEAWCS_Model.Models;
 using WIDESEAWCS_QuartzJob;
 
 namespace WIDESEAWCS_Tasks.SocketServer
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj
index a5bcd6d..cba6df7 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/WIDESEAWCS_Tasks.csproj
@@ -7,6 +7,7 @@
 	</PropertyGroup>
 
 	<ItemGroup>
+		<ProjectReference Include="..\WIDESEAWCS_Model\WIDESEAWCS_Model.csproj" />
 		<ProjectReference Include="..\WIDESEAWCS_QuartzJob\WIDESEAWCS_QuartzJob.csproj" />
 		<ProjectReference Include="..\WIDESEAWCS_TaskInfoService\WIDESEAWCS_TaskInfoService.csproj" />
 	</ItemGroup>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/.env.development b/Code/WMS/WIDESEA_WMSClient_Vben/.env.development
new file mode 100644
index 0000000..0b322fb
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/.env.development
@@ -0,0 +1 @@
+VITE_API_BASE_URL=http://localhost:9291
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/index.html b/Code/WMS/WIDESEA_WMSClient_Vben/index.html
new file mode 100644
index 0000000..d4c7c50
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/index.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="/favicon.ico" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>WMS绠$悊绯荤粺</title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.ts"></script>
+  </body>
+</html>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/package-lock.json b/Code/WMS/WIDESEA_WMSClient_Vben/package-lock.json
new file mode 100644
index 0000000..99c69ac
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/package-lock.json
@@ -0,0 +1,1929 @@
+{
+  "name": "widesea-wms-client-vben",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "widesea-wms-client-vben",
+      "version": "1.0.0",
+      "dependencies": {
+        "@element-plus/icons-vue": "^2.3.1",
+        "axios": "^1.6.7",
+        "element-plus": "^2.5.6",
+        "pinia": "^2.1.7",
+        "vue": "^3.4.21",
+        "vue-router": "^4.3.0"
+      },
+      "devDependencies": {
+        "@vitejs/plugin-vue": "^5.0.4",
+        "typescript": "^5.4.2",
+        "vite": "^5.1.6",
+        "vue-tsc": "^2.0.6"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.28.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+      "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.29.2",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
+      "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.29.0"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+      "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.28.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@ctrl/tinycolor": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz",
+      "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/@element-plus/icons-vue": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
+      "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==",
+      "license": "MIT",
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+      "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+      "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+      "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+      "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+      "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+      "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+      "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+      "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+      "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+      "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+      "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+      "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+      "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+      "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+      "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+      "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+      "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+      "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+      "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+      "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+      "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+      "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+      "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@floating-ui/core": {
+      "version": "1.7.5",
+      "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
+      "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@floating-ui/utils": "^0.2.11"
+      }
+    },
+    "node_modules/@floating-ui/dom": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
+      "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@floating-ui/core": "^1.7.5",
+        "@floating-ui/utils": "^0.2.11"
+      }
+    },
+    "node_modules/@floating-ui/utils": {
+      "version": "0.2.11",
+      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
+      "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
+      "license": "MIT"
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+      "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+      "license": "MIT"
+    },
+    "node_modules/@popperjs/core": {
+      "name": "@sxzz/popperjs-es",
+      "version": "2.11.8",
+      "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz",
+      "integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==",
+      "license": "MIT",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/popperjs"
+      }
+    },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz",
+      "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz",
+      "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz",
+      "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz",
+      "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-arm64": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz",
+      "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-x64": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz",
+      "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz",
+      "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz",
+      "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz",
+      "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz",
+      "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-gnu": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz",
+      "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-musl": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz",
+      "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz",
+      "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-musl": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz",
+      "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz",
+      "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-musl": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz",
+      "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz",
+      "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz",
+      "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz",
+      "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-openbsd-x64": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz",
+      "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-openharmony-arm64": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz",
+      "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openharmony"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz",
+      "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz",
+      "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-gnu": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz",
+      "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz",
+      "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/lodash": {
+      "version": "4.17.24",
+      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz",
+      "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
+      "license": "MIT"
+    },
+    "node_modules/@types/lodash-es": {
+      "version": "4.17.12",
+      "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz",
+      "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/lodash": "*"
+      }
+    },
+    "node_modules/@types/web-bluetooth": {
+      "version": "0.0.20",
+      "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
+      "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==",
+      "license": "MIT"
+    },
+    "node_modules/@vitejs/plugin-vue": {
+      "version": "5.2.4",
+      "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+      "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "peerDependencies": {
+        "vite": "^5.0.0 || ^6.0.0",
+        "vue": "^3.2.25"
+      }
+    },
+    "node_modules/@volar/language-core": {
+      "version": "2.4.15",
+      "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.15.tgz",
+      "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/source-map": "2.4.15"
+      }
+    },
+    "node_modules/@volar/source-map": {
+      "version": "2.4.15",
+      "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.15.tgz",
+      "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@volar/typescript": {
+      "version": "2.4.15",
+      "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.15.tgz",
+      "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/language-core": "2.4.15",
+        "path-browserify": "^1.0.1",
+        "vscode-uri": "^3.0.8"
+      }
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.5.32",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.32.tgz",
+      "integrity": "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.2",
+        "@vue/shared": "3.5.32",
+        "entities": "^7.0.1",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.5.32",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.32.tgz",
+      "integrity": "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-core": "3.5.32",
+        "@vue/shared": "3.5.32"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.5.32",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz",
+      "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.2",
+        "@vue/compiler-core": "3.5.32",
+        "@vue/compiler-dom": "3.5.32",
+        "@vue/compiler-ssr": "3.5.32",
+        "@vue/shared": "3.5.32",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.21",
+        "postcss": "^8.5.8",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.5.32",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.32.tgz",
+      "integrity": "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.32",
+        "@vue/shared": "3.5.32"
+      }
+    },
+    "node_modules/@vue/compiler-vue2": {
+      "version": "2.7.16",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz",
+      "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "de-indent": "^1.0.2",
+        "he": "^1.2.0"
+      }
+    },
+    "node_modules/@vue/devtools-api": {
+      "version": "6.6.4",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
+      "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
+      "license": "MIT"
+    },
+    "node_modules/@vue/language-core": {
+      "version": "2.2.12",
+      "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.2.12.tgz",
+      "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/language-core": "2.4.15",
+        "@vue/compiler-dom": "^3.5.0",
+        "@vue/compiler-vue2": "^2.7.16",
+        "@vue/shared": "^3.5.0",
+        "alien-signals": "^1.0.3",
+        "minimatch": "^9.0.3",
+        "muggle-string": "^0.4.1",
+        "path-browserify": "^1.0.1"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.5.32",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.32.tgz",
+      "integrity": "sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/shared": "3.5.32"
+      }
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.5.32",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.32.tgz",
+      "integrity": "sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/reactivity": "3.5.32",
+        "@vue/shared": "3.5.32"
+      }
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.5.32",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.32.tgz",
+      "integrity": "sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/reactivity": "3.5.32",
+        "@vue/runtime-core": "3.5.32",
+        "@vue/shared": "3.5.32",
+        "csstype": "^3.2.3"
+      }
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.5.32",
+      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.32.tgz",
+      "integrity": "sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.5.32",
+        "@vue/shared": "3.5.32"
+      },
+      "peerDependencies": {
+        "vue": "3.5.32"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.5.32",
+      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.32.tgz",
+      "integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==",
+      "license": "MIT"
+    },
+    "node_modules/@vueuse/core": {
+      "version": "12.0.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.0.0.tgz",
+      "integrity": "sha512-C12RukhXiJCbx4MGhjmd/gH52TjJsc3G0E0kQj/kb19H3Nt6n1CA4DRWuTdWWcaFRdlTe0npWDS942mvacvNBw==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/web-bluetooth": "^0.0.20",
+        "@vueuse/metadata": "12.0.0",
+        "@vueuse/shared": "12.0.0",
+        "vue": "^3.5.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vueuse/metadata": {
+      "version": "12.0.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.0.0.tgz",
+      "integrity": "sha512-Yzimd1D3sjxTDOlF05HekU5aSGdKjxhuhRFHA7gDWLn57PRbBIh+SF5NmjhJ0WRgF3my7T8LBucyxdFJjIfRJQ==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vueuse/shared": {
+      "version": "12.0.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.0.0.tgz",
+      "integrity": "sha512-3i6qtcq2PIio5i/vVYidkkcgvmTjCqrf26u+Fd4LhnbBmIT6FN8y6q/GJERp8lfcB9zVEfjdV0Br0443qZuJpw==",
+      "license": "MIT",
+      "dependencies": {
+        "vue": "^3.5.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/alien-signals": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-1.0.13.tgz",
+      "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/async-validator": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz",
+      "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==",
+      "license": "MIT"
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+      "license": "MIT"
+    },
+    "node_modules/axios": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz",
+      "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==",
+      "license": "MIT",
+      "dependencies": {
+        "follow-redirects": "^1.15.11",
+        "form-data": "^4.0.5",
+        "proxy-from-env": "^2.1.0"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/brace-expansion": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+      "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "license": "MIT",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+      "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+      "license": "MIT"
+    },
+    "node_modules/dayjs": {
+      "version": "1.11.20",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz",
+      "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==",
+      "license": "MIT"
+    },
+    "node_modules/de-indent": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
+      "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/element-plus": {
+      "version": "2.13.7",
+      "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.13.7.tgz",
+      "integrity": "sha512-XdHATFZOyzVFL1DaHQ90IOJQSg9UnSAV+bhDW+YB5UoZ0Hxs50mwqjqfwXkuwpSag+VXXizVcErBR6Movo5daw==",
+      "license": "MIT",
+      "dependencies": {
+        "@ctrl/tinycolor": "^4.2.0",
+        "@element-plus/icons-vue": "^2.3.2",
+        "@floating-ui/dom": "^1.0.1",
+        "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
+        "@types/lodash": "^4.17.20",
+        "@types/lodash-es": "^4.17.12",
+        "@vueuse/core": "12.0.0",
+        "async-validator": "^4.2.5",
+        "dayjs": "^1.11.19",
+        "lodash": "^4.17.23",
+        "lodash-es": "^4.17.23",
+        "lodash-unified": "^1.0.3",
+        "memoize-one": "^6.0.0",
+        "normalize-wheel-es": "^1.2.0",
+        "vue-component-type-helpers": "^3.2.4"
+      },
+      "peerDependencies": {
+        "vue": "^3.3.0"
+      }
+    },
+    "node_modules/entities": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
+      "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+      "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.21.5",
+        "@esbuild/android-arm": "0.21.5",
+        "@esbuild/android-arm64": "0.21.5",
+        "@esbuild/android-x64": "0.21.5",
+        "@esbuild/darwin-arm64": "0.21.5",
+        "@esbuild/darwin-x64": "0.21.5",
+        "@esbuild/freebsd-arm64": "0.21.5",
+        "@esbuild/freebsd-x64": "0.21.5",
+        "@esbuild/linux-arm": "0.21.5",
+        "@esbuild/linux-arm64": "0.21.5",
+        "@esbuild/linux-ia32": "0.21.5",
+        "@esbuild/linux-loong64": "0.21.5",
+        "@esbuild/linux-mips64el": "0.21.5",
+        "@esbuild/linux-ppc64": "0.21.5",
+        "@esbuild/linux-riscv64": "0.21.5",
+        "@esbuild/linux-s390x": "0.21.5",
+        "@esbuild/linux-x64": "0.21.5",
+        "@esbuild/netbsd-x64": "0.21.5",
+        "@esbuild/openbsd-x64": "0.21.5",
+        "@esbuild/sunos-x64": "0.21.5",
+        "@esbuild/win32-arm64": "0.21.5",
+        "@esbuild/win32-ia32": "0.21.5",
+        "@esbuild/win32-x64": "0.21.5"
+      }
+    },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+      "license": "MIT"
+    },
+    "node_modules/follow-redirects": {
+      "version": "1.16.0",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
+      "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "license": "MIT",
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+      "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+      "license": "MIT",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "hasown": "^2.0.2",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "license": "MIT",
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "license": "MIT",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
+      "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
+      "license": "MIT",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "he": "bin/he"
+      }
+    },
+    "node_modules/lodash": {
+      "version": "4.18.1",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+      "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
+      "license": "MIT"
+    },
+    "node_modules/lodash-es": {
+      "version": "4.18.1",
+      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
+      "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
+      "license": "MIT"
+    },
+    "node_modules/lodash-unified": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz",
+      "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
+      "license": "MIT",
+      "peerDependencies": {
+        "@types/lodash-es": "*",
+        "lodash": "*",
+        "lodash-es": "*"
+      }
+    },
+    "node_modules/magic-string": {
+      "version": "0.30.21",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+      "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.5"
+      }
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/memoize-one": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
+      "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
+      "license": "MIT"
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "license": "MIT",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "9.0.9",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
+      "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/muggle-string": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
+      "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.11",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/normalize-wheel-es": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
+      "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==",
+      "license": "BSD-3-Clause"
+    },
+    "node_modules/path-browserify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
+      "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "license": "ISC"
+    },
+    "node_modules/pinia": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz",
+      "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-api": "^6.6.3",
+        "vue-demi": "^0.14.10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.4.4",
+        "vue": "^2.7.0 || ^3.5.11"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.10",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz",
+      "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "nanoid": "^3.3.11",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/proxy-from-env": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+      "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/rollup": {
+      "version": "4.60.2",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz",
+      "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "1.0.8"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.60.2",
+        "@rollup/rollup-android-arm64": "4.60.2",
+        "@rollup/rollup-darwin-arm64": "4.60.2",
+        "@rollup/rollup-darwin-x64": "4.60.2",
+        "@rollup/rollup-freebsd-arm64": "4.60.2",
+        "@rollup/rollup-freebsd-x64": "4.60.2",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.60.2",
+        "@rollup/rollup-linux-arm-musleabihf": "4.60.2",
+        "@rollup/rollup-linux-arm64-gnu": "4.60.2",
+        "@rollup/rollup-linux-arm64-musl": "4.60.2",
+        "@rollup/rollup-linux-loong64-gnu": "4.60.2",
+        "@rollup/rollup-linux-loong64-musl": "4.60.2",
+        "@rollup/rollup-linux-ppc64-gnu": "4.60.2",
+        "@rollup/rollup-linux-ppc64-musl": "4.60.2",
+        "@rollup/rollup-linux-riscv64-gnu": "4.60.2",
+        "@rollup/rollup-linux-riscv64-musl": "4.60.2",
+        "@rollup/rollup-linux-s390x-gnu": "4.60.2",
+        "@rollup/rollup-linux-x64-gnu": "4.60.2",
+        "@rollup/rollup-linux-x64-musl": "4.60.2",
+        "@rollup/rollup-openbsd-x64": "4.60.2",
+        "@rollup/rollup-openharmony-arm64": "4.60.2",
+        "@rollup/rollup-win32-arm64-msvc": "4.60.2",
+        "@rollup/rollup-win32-ia32-msvc": "4.60.2",
+        "@rollup/rollup-win32-x64-gnu": "4.60.2",
+        "@rollup/rollup-win32-x64-msvc": "4.60.2",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.9.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+      "devOptional": true,
+      "license": "Apache-2.0",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/vite": {
+      "version": "5.4.21",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
+      "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "esbuild": "^0.21.3",
+        "postcss": "^8.4.43",
+        "rollup": "^4.20.0"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      },
+      "peerDependencies": {
+        "@types/node": "^18.0.0 || >=20.0.0",
+        "less": "*",
+        "lightningcss": "^1.21.0",
+        "sass": "*",
+        "sass-embedded": "*",
+        "stylus": "*",
+        "sugarss": "*",
+        "terser": "^5.4.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "less": {
+          "optional": true
+        },
+        "lightningcss": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "sass-embedded": {
+          "optional": true
+        },
+        "stylus": {
+          "optional": true
+        },
+        "sugarss": {
+          "optional": true
+        },
+        "terser": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vscode-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
+      "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/vue": {
+      "version": "3.5.32",
+      "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz",
+      "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.32",
+        "@vue/compiler-sfc": "3.5.32",
+        "@vue/runtime-dom": "3.5.32",
+        "@vue/server-renderer": "3.5.32",
+        "@vue/shared": "3.5.32"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-component-type-helpers": {
+      "version": "3.2.7",
+      "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-3.2.7.tgz",
+      "integrity": "sha512-+gPp5YGmhfsj1IN+xUo7y0fb4clfnOiiUA39y07yW1VzCRjzVgwLbtmdWlghh7mXrPsEaYc7rrIir/HT6C8vYQ==",
+      "license": "MIT"
+    },
+    "node_modules/vue-demi": {
+      "version": "0.14.10",
+      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
+      "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-router": {
+      "version": "4.6.4",
+      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz",
+      "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-api": "^6.6.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "vue": "^3.5.0"
+      }
+    },
+    "node_modules/vue-tsc": {
+      "version": "2.2.12",
+      "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.12.tgz",
+      "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/typescript": "2.4.15",
+        "@vue/language-core": "2.2.12"
+      },
+      "bin": {
+        "vue-tsc": "bin/vue-tsc.js"
+      },
+      "peerDependencies": {
+        "typescript": ">=5.0.0"
+      }
+    }
+  }
+}
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/package.json b/Code/WMS/WIDESEA_WMSClient_Vben/package.json
new file mode 100644
index 0000000..9dc9179
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/package.json
@@ -0,0 +1,25 @@
+{
+  "name": "widesea-wms-client-vben",
+  "version": "1.0.0",
+  "private": true,
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "@element-plus/icons-vue": "^2.3.1",
+    "axios": "^1.6.7",
+    "element-plus": "^2.5.6",
+    "pinia": "^2.1.7",
+    "vue": "^3.4.21",
+    "vue-router": "^4.3.0"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "^5.0.4",
+    "typescript": "^5.4.2",
+    "vite": "^5.1.6",
+    "vue-tsc": "^2.0.6"
+  }
+}
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/pnpm-lock.yaml b/Code/WMS/WIDESEA_WMSClient_Vben/pnpm-lock.yaml
new file mode 100644
index 0000000..35beac5
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/pnpm-lock.yaml
@@ -0,0 +1,1297 @@
+lockfileVersion: '9.0'
+
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
+
+importers:
+
+  .:
+    dependencies:
+      '@element-plus/icons-vue':
+        specifier: ^2.3.1
+        version: 2.3.2(vue@3.5.32(typescript@5.9.3))
+      axios:
+        specifier: ^1.6.7
+        version: 1.15.0
+      element-plus:
+        specifier: ^2.5.6
+        version: 2.13.7(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3))
+      pinia:
+        specifier: ^2.1.7
+        version: 2.3.1(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3))
+      vue:
+        specifier: ^3.4.21
+        version: 3.5.32(typescript@5.9.3)
+      vue-router:
+        specifier: ^4.3.0
+        version: 4.6.4(vue@3.5.32(typescript@5.9.3))
+    devDependencies:
+      '@vitejs/plugin-vue':
+        specifier: ^5.0.4
+        version: 5.2.4(vite@5.4.21)(vue@3.5.32(typescript@5.9.3))
+      typescript:
+        specifier: ^5.4.2
+        version: 5.9.3
+      vite:
+        specifier: ^5.1.6
+        version: 5.4.21
+      vue-tsc:
+        specifier: ^2.0.6
+        version: 2.2.12(typescript@5.9.3)
+
+packages:
+
+  '@babel/helper-string-parser@7.27.1':
+    resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-validator-identifier@7.28.5':
+    resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/parser@7.29.2':
+    resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+
+  '@babel/types@7.29.0':
+    resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
+    engines: {node: '>=6.9.0'}
+
+  '@ctrl/tinycolor@4.2.0':
+    resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==}
+    engines: {node: '>=14'}
+
+  '@element-plus/icons-vue@2.3.2':
+    resolution: {integrity: sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==}
+    peerDependencies:
+      vue: ^3.2.0
+
+  '@esbuild/aix-ppc64@0.21.5':
+    resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
+    engines: {node: '>=12'}
+    cpu: [ppc64]
+    os: [aix]
+
+  '@esbuild/android-arm64@0.21.5':
+    resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [android]
+
+  '@esbuild/android-arm@0.21.5':
+    resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [android]
+
+  '@esbuild/android-x64@0.21.5':
+    resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [android]
+
+  '@esbuild/darwin-arm64@0.21.5':
+    resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@esbuild/darwin-x64@0.21.5':
+    resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [darwin]
+
+  '@esbuild/freebsd-arm64@0.21.5':
+    resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [freebsd]
+
+  '@esbuild/freebsd-x64@0.21.5':
+    resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@esbuild/linux-arm64@0.21.5':
+    resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [linux]
+
+  '@esbuild/linux-arm@0.21.5':
+    resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [linux]
+
+  '@esbuild/linux-ia32@0.21.5':
+    resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [linux]
+
+  '@esbuild/linux-loong64@0.21.5':
+    resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
+    engines: {node: '>=12'}
+    cpu: [loong64]
+    os: [linux]
+
+  '@esbuild/linux-mips64el@0.21.5':
+    resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
+    engines: {node: '>=12'}
+    cpu: [mips64el]
+    os: [linux]
+
+  '@esbuild/linux-ppc64@0.21.5':
+    resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
+    engines: {node: '>=12'}
+    cpu: [ppc64]
+    os: [linux]
+
+  '@esbuild/linux-riscv64@0.21.5':
+    resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
+    engines: {node: '>=12'}
+    cpu: [riscv64]
+    os: [linux]
+
+  '@esbuild/linux-s390x@0.21.5':
+    resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
+    engines: {node: '>=12'}
+    cpu: [s390x]
+    os: [linux]
+
+  '@esbuild/linux-x64@0.21.5':
+    resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [linux]
+
+  '@esbuild/netbsd-x64@0.21.5':
+    resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [netbsd]
+
+  '@esbuild/openbsd-x64@0.21.5':
+    resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [openbsd]
+
+  '@esbuild/sunos-x64@0.21.5':
+    resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [sunos]
+
+  '@esbuild/win32-arm64@0.21.5':
+    resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [win32]
+
+  '@esbuild/win32-ia32@0.21.5':
+    resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [win32]
+
+  '@esbuild/win32-x64@0.21.5':
+    resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [win32]
+
+  '@floating-ui/core@1.7.5':
+    resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==}
+
+  '@floating-ui/dom@1.7.6':
+    resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==}
+
+  '@floating-ui/utils@0.2.11':
+    resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==}
+
+  '@jridgewell/sourcemap-codec@1.5.5':
+    resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+  '@rollup/rollup-android-arm-eabi@4.60.2':
+    resolution: {integrity: sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==}
+    cpu: [arm]
+    os: [android]
+
+  '@rollup/rollup-android-arm64@4.60.2':
+    resolution: {integrity: sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==}
+    cpu: [arm64]
+    os: [android]
+
+  '@rollup/rollup-darwin-arm64@4.60.2':
+    resolution: {integrity: sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@rollup/rollup-darwin-x64@4.60.2':
+    resolution: {integrity: sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==}
+    cpu: [x64]
+    os: [darwin]
+
+  '@rollup/rollup-freebsd-arm64@4.60.2':
+    resolution: {integrity: sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==}
+    cpu: [arm64]
+    os: [freebsd]
+
+  '@rollup/rollup-freebsd-x64@4.60.2':
+    resolution: {integrity: sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@rollup/rollup-linux-arm-gnueabihf@4.60.2':
+    resolution: {integrity: sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==}
+    cpu: [arm]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-arm-musleabihf@4.60.2':
+    resolution: {integrity: sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==}
+    cpu: [arm]
+    os: [linux]
+    libc: [musl]
+
+  '@rollup/rollup-linux-arm64-gnu@4.60.2':
+    resolution: {integrity: sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-arm64-musl@4.60.2':
+    resolution: {integrity: sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  '@rollup/rollup-linux-loong64-gnu@4.60.2':
+    resolution: {integrity: sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==}
+    cpu: [loong64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-loong64-musl@4.60.2':
+    resolution: {integrity: sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==}
+    cpu: [loong64]
+    os: [linux]
+    libc: [musl]
+
+  '@rollup/rollup-linux-ppc64-gnu@4.60.2':
+    resolution: {integrity: sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==}
+    cpu: [ppc64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-ppc64-musl@4.60.2':
+    resolution: {integrity: sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==}
+    cpu: [ppc64]
+    os: [linux]
+    libc: [musl]
+
+  '@rollup/rollup-linux-riscv64-gnu@4.60.2':
+    resolution: {integrity: sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==}
+    cpu: [riscv64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-riscv64-musl@4.60.2':
+    resolution: {integrity: sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==}
+    cpu: [riscv64]
+    os: [linux]
+    libc: [musl]
+
+  '@rollup/rollup-linux-s390x-gnu@4.60.2':
+    resolution: {integrity: sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==}
+    cpu: [s390x]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-x64-gnu@4.60.2':
+    resolution: {integrity: sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-x64-musl@4.60.2':
+    resolution: {integrity: sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  '@rollup/rollup-openbsd-x64@4.60.2':
+    resolution: {integrity: sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==}
+    cpu: [x64]
+    os: [openbsd]
+
+  '@rollup/rollup-openharmony-arm64@4.60.2':
+    resolution: {integrity: sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==}
+    cpu: [arm64]
+    os: [openharmony]
+
+  '@rollup/rollup-win32-arm64-msvc@4.60.2':
+    resolution: {integrity: sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==}
+    cpu: [arm64]
+    os: [win32]
+
+  '@rollup/rollup-win32-ia32-msvc@4.60.2':
+    resolution: {integrity: sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==}
+    cpu: [ia32]
+    os: [win32]
+
+  '@rollup/rollup-win32-x64-gnu@4.60.2':
+    resolution: {integrity: sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==}
+    cpu: [x64]
+    os: [win32]
+
+  '@rollup/rollup-win32-x64-msvc@4.60.2':
+    resolution: {integrity: sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==}
+    cpu: [x64]
+    os: [win32]
+
+  '@sxzz/popperjs-es@2.11.8':
+    resolution: {integrity: sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==}
+
+  '@types/estree@1.0.8':
+    resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+  '@types/lodash-es@4.17.12':
+    resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
+
+  '@types/lodash@4.17.24':
+    resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==}
+
+  '@types/web-bluetooth@0.0.20':
+    resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
+
+  '@vitejs/plugin-vue@5.2.4':
+    resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==}
+    engines: {node: ^18.0.0 || >=20.0.0}
+    peerDependencies:
+      vite: ^5.0.0 || ^6.0.0
+      vue: ^3.2.25
+
+  '@volar/language-core@2.4.15':
+    resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==}
+
+  '@volar/source-map@2.4.15':
+    resolution: {integrity: sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==}
+
+  '@volar/typescript@2.4.15':
+    resolution: {integrity: sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==}
+
+  '@vue/compiler-core@3.5.32':
+    resolution: {integrity: sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==}
+
+  '@vue/compiler-dom@3.5.32':
+    resolution: {integrity: sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==}
+
+  '@vue/compiler-sfc@3.5.32':
+    resolution: {integrity: sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==}
+
+  '@vue/compiler-ssr@3.5.32':
+    resolution: {integrity: sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==}
+
+  '@vue/compiler-vue2@2.7.16':
+    resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==}
+
+  '@vue/devtools-api@6.6.4':
+    resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==}
+
+  '@vue/language-core@2.2.12':
+    resolution: {integrity: sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  '@vue/reactivity@3.5.32':
+    resolution: {integrity: sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==}
+
+  '@vue/runtime-core@3.5.32':
+    resolution: {integrity: sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==}
+
+  '@vue/runtime-dom@3.5.32':
+    resolution: {integrity: sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==}
+
+  '@vue/server-renderer@3.5.32':
+    resolution: {integrity: sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==}
+    peerDependencies:
+      vue: 3.5.32
+
+  '@vue/shared@3.5.32':
+    resolution: {integrity: sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==}
+
+  '@vueuse/core@12.0.0':
+    resolution: {integrity: sha512-C12RukhXiJCbx4MGhjmd/gH52TjJsc3G0E0kQj/kb19H3Nt6n1CA4DRWuTdWWcaFRdlTe0npWDS942mvacvNBw==}
+
+  '@vueuse/metadata@12.0.0':
+    resolution: {integrity: sha512-Yzimd1D3sjxTDOlF05HekU5aSGdKjxhuhRFHA7gDWLn57PRbBIh+SF5NmjhJ0WRgF3my7T8LBucyxdFJjIfRJQ==}
+
+  '@vueuse/shared@12.0.0':
+    resolution: {integrity: sha512-3i6qtcq2PIio5i/vVYidkkcgvmTjCqrf26u+Fd4LhnbBmIT6FN8y6q/GJERp8lfcB9zVEfjdV0Br0443qZuJpw==}
+
+  alien-signals@1.0.13:
+    resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==}
+
+  async-validator@4.2.5:
+    resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
+
+  asynckit@0.4.0:
+    resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+  axios@1.15.0:
+    resolution: {integrity: sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==}
+
+  balanced-match@1.0.2:
+    resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+  brace-expansion@2.1.0:
+    resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==}
+
+  call-bind-apply-helpers@1.0.2:
+    resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+    engines: {node: '>= 0.4'}
+
+  combined-stream@1.0.8:
+    resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+    engines: {node: '>= 0.8'}
+
+  csstype@3.2.3:
+    resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+  dayjs@1.11.20:
+    resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==}
+
+  de-indent@1.0.2:
+    resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
+
+  delayed-stream@1.0.0:
+    resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+    engines: {node: '>=0.4.0'}
+
+  dunder-proto@1.0.1:
+    resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+    engines: {node: '>= 0.4'}
+
+  element-plus@2.13.7:
+    resolution: {integrity: sha512-XdHATFZOyzVFL1DaHQ90IOJQSg9UnSAV+bhDW+YB5UoZ0Hxs50mwqjqfwXkuwpSag+VXXizVcErBR6Movo5daw==}
+    peerDependencies:
+      vue: ^3.3.0
+
+  entities@7.0.1:
+    resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
+    engines: {node: '>=0.12'}
+
+  es-define-property@1.0.1:
+    resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+    engines: {node: '>= 0.4'}
+
+  es-errors@1.3.0:
+    resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+    engines: {node: '>= 0.4'}
+
+  es-object-atoms@1.1.1:
+    resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
+    engines: {node: '>= 0.4'}
+
+  es-set-tostringtag@2.1.0:
+    resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
+    engines: {node: '>= 0.4'}
+
+  esbuild@0.21.5:
+    resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
+    engines: {node: '>=12'}
+    hasBin: true
+
+  estree-walker@2.0.2:
+    resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
+  follow-redirects@1.16.0:
+    resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==}
+    engines: {node: '>=4.0'}
+    peerDependencies:
+      debug: '*'
+    peerDependenciesMeta:
+      debug:
+        optional: true
+
+  form-data@4.0.5:
+    resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
+    engines: {node: '>= 6'}
+
+  fsevents@2.3.3:
+    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+    os: [darwin]
+
+  function-bind@1.1.2:
+    resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+  get-intrinsic@1.3.0:
+    resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+    engines: {node: '>= 0.4'}
+
+  get-proto@1.0.1:
+    resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+    engines: {node: '>= 0.4'}
+
+  gopd@1.2.0:
+    resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+    engines: {node: '>= 0.4'}
+
+  has-symbols@1.1.0:
+    resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+    engines: {node: '>= 0.4'}
+
+  has-tostringtag@1.0.2:
+    resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+    engines: {node: '>= 0.4'}
+
+  hasown@2.0.3:
+    resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==}
+    engines: {node: '>= 0.4'}
+
+  he@1.2.0:
+    resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
+    hasBin: true
+
+  lodash-es@4.18.1:
+    resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
+
+  lodash-unified@1.0.3:
+    resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==}
+    peerDependencies:
+      '@types/lodash-es': '*'
+      lodash: '*'
+      lodash-es: '*'
+
+  lodash@4.18.1:
+    resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
+
+  magic-string@0.30.21:
+    resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+  math-intrinsics@1.1.0:
+    resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+    engines: {node: '>= 0.4'}
+
+  memoize-one@6.0.0:
+    resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==}
+
+  mime-db@1.52.0:
+    resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+    engines: {node: '>= 0.6'}
+
+  mime-types@2.1.35:
+    resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+    engines: {node: '>= 0.6'}
+
+  minimatch@9.0.9:
+    resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==}
+    engines: {node: '>=16 || 14 >=14.17'}
+
+  muggle-string@0.4.1:
+    resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
+
+  nanoid@3.3.11:
+    resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+    engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+    hasBin: true
+
+  normalize-wheel-es@1.2.0:
+    resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==}
+
+  path-browserify@1.0.1:
+    resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+
+  picocolors@1.1.1:
+    resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+  pinia@2.3.1:
+    resolution: {integrity: sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==}
+    peerDependencies:
+      typescript: '>=4.4.4'
+      vue: ^2.7.0 || ^3.5.11
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  postcss@8.5.10:
+    resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==}
+    engines: {node: ^10 || ^12 || >=14}
+
+  proxy-from-env@2.1.0:
+    resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==}
+    engines: {node: '>=10'}
+
+  rollup@4.60.2:
+    resolution: {integrity: sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==}
+    engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+    hasBin: true
+
+  source-map-js@1.2.1:
+    resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+    engines: {node: '>=0.10.0'}
+
+  typescript@5.9.3:
+    resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+    engines: {node: '>=14.17'}
+    hasBin: true
+
+  vite@5.4.21:
+    resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==}
+    engines: {node: ^18.0.0 || >=20.0.0}
+    hasBin: true
+    peerDependencies:
+      '@types/node': ^18.0.0 || >=20.0.0
+      less: '*'
+      lightningcss: ^1.21.0
+      sass: '*'
+      sass-embedded: '*'
+      stylus: '*'
+      sugarss: '*'
+      terser: ^5.4.0
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+      less:
+        optional: true
+      lightningcss:
+        optional: true
+      sass:
+        optional: true
+      sass-embedded:
+        optional: true
+      stylus:
+        optional: true
+      sugarss:
+        optional: true
+      terser:
+        optional: true
+
+  vscode-uri@3.1.0:
+    resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
+
+  vue-component-type-helpers@3.2.7:
+    resolution: {integrity: sha512-+gPp5YGmhfsj1IN+xUo7y0fb4clfnOiiUA39y07yW1VzCRjzVgwLbtmdWlghh7mXrPsEaYc7rrIir/HT6C8vYQ==}
+
+  vue-demi@0.14.10:
+    resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
+    engines: {node: '>=12'}
+    hasBin: true
+    peerDependencies:
+      '@vue/composition-api': ^1.0.0-rc.1
+      vue: ^3.0.0-0 || ^2.6.0
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+
+  vue-router@4.6.4:
+    resolution: {integrity: sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==}
+    peerDependencies:
+      vue: ^3.5.0
+
+  vue-tsc@2.2.12:
+    resolution: {integrity: sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==}
+    hasBin: true
+    peerDependencies:
+      typescript: '>=5.0.0'
+
+  vue@3.5.32:
+    resolution: {integrity: sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+snapshots:
+
+  '@babel/helper-string-parser@7.27.1': {}
+
+  '@babel/helper-validator-identifier@7.28.5': {}
+
+  '@babel/parser@7.29.2':
+    dependencies:
+      '@babel/types': 7.29.0
+
+  '@babel/types@7.29.0':
+    dependencies:
+      '@babel/helper-string-parser': 7.27.1
+      '@babel/helper-validator-identifier': 7.28.5
+
+  '@ctrl/tinycolor@4.2.0': {}
+
+  '@element-plus/icons-vue@2.3.2(vue@3.5.32(typescript@5.9.3))':
+    dependencies:
+      vue: 3.5.32(typescript@5.9.3)
+
+  '@esbuild/aix-ppc64@0.21.5':
+    optional: true
+
+  '@esbuild/android-arm64@0.21.5':
+    optional: true
+
+  '@esbuild/android-arm@0.21.5':
+    optional: true
+
+  '@esbuild/android-x64@0.21.5':
+    optional: true
+
+  '@esbuild/darwin-arm64@0.21.5':
+    optional: true
+
+  '@esbuild/darwin-x64@0.21.5':
+    optional: true
+
+  '@esbuild/freebsd-arm64@0.21.5':
+    optional: true
+
+  '@esbuild/freebsd-x64@0.21.5':
+    optional: true
+
+  '@esbuild/linux-arm64@0.21.5':
+    optional: true
+
+  '@esbuild/linux-arm@0.21.5':
+    optional: true
+
+  '@esbuild/linux-ia32@0.21.5':
+    optional: true
+
+  '@esbuild/linux-loong64@0.21.5':
+    optional: true
+
+  '@esbuild/linux-mips64el@0.21.5':
+    optional: true
+
+  '@esbuild/linux-ppc64@0.21.5':
+    optional: true
+
+  '@esbuild/linux-riscv64@0.21.5':
+    optional: true
+
+  '@esbuild/linux-s390x@0.21.5':
+    optional: true
+
+  '@esbuild/linux-x64@0.21.5':
+    optional: true
+
+  '@esbuild/netbsd-x64@0.21.5':
+    optional: true
+
+  '@esbuild/openbsd-x64@0.21.5':
+    optional: true
+
+  '@esbuild/sunos-x64@0.21.5':
+    optional: true
+
+  '@esbuild/win32-arm64@0.21.5':
+    optional: true
+
+  '@esbuild/win32-ia32@0.21.5':
+    optional: true
+
+  '@esbuild/win32-x64@0.21.5':
+    optional: true
+
+  '@floating-ui/core@1.7.5':
+    dependencies:
+      '@floating-ui/utils': 0.2.11
+
+  '@floating-ui/dom@1.7.6':
+    dependencies:
+      '@floating-ui/core': 1.7.5
+      '@floating-ui/utils': 0.2.11
+
+  '@floating-ui/utils@0.2.11': {}
+
+  '@jridgewell/sourcemap-codec@1.5.5': {}
+
+  '@rollup/rollup-android-arm-eabi@4.60.2':
+    optional: true
+
+  '@rollup/rollup-android-arm64@4.60.2':
+    optional: true
+
+  '@rollup/rollup-darwin-arm64@4.60.2':
+    optional: true
+
+  '@rollup/rollup-darwin-x64@4.60.2':
+    optional: true
+
+  '@rollup/rollup-freebsd-arm64@4.60.2':
+    optional: true
+
+  '@rollup/rollup-freebsd-x64@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-arm-gnueabihf@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-arm-musleabihf@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-arm64-gnu@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-arm64-musl@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-loong64-gnu@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-loong64-musl@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-ppc64-gnu@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-ppc64-musl@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-riscv64-gnu@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-riscv64-musl@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-s390x-gnu@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-x64-gnu@4.60.2':
+    optional: true
+
+  '@rollup/rollup-linux-x64-musl@4.60.2':
+    optional: true
+
+  '@rollup/rollup-openbsd-x64@4.60.2':
+    optional: true
+
+  '@rollup/rollup-openharmony-arm64@4.60.2':
+    optional: true
+
+  '@rollup/rollup-win32-arm64-msvc@4.60.2':
+    optional: true
+
+  '@rollup/rollup-win32-ia32-msvc@4.60.2':
+    optional: true
+
+  '@rollup/rollup-win32-x64-gnu@4.60.2':
+    optional: true
+
+  '@rollup/rollup-win32-x64-msvc@4.60.2':
+    optional: true
+
+  '@sxzz/popperjs-es@2.11.8': {}
+
+  '@types/estree@1.0.8': {}
+
+  '@types/lodash-es@4.17.12':
+    dependencies:
+      '@types/lodash': 4.17.24
+
+  '@types/lodash@4.17.24': {}
+
+  '@types/web-bluetooth@0.0.20': {}
+
+  '@vitejs/plugin-vue@5.2.4(vite@5.4.21)(vue@3.5.32(typescript@5.9.3))':
+    dependencies:
+      vite: 5.4.21
+      vue: 3.5.32(typescript@5.9.3)
+
+  '@volar/language-core@2.4.15':
+    dependencies:
+      '@volar/source-map': 2.4.15
+
+  '@volar/source-map@2.4.15': {}
+
+  '@volar/typescript@2.4.15':
+    dependencies:
+      '@volar/language-core': 2.4.15
+      path-browserify: 1.0.1
+      vscode-uri: 3.1.0
+
+  '@vue/compiler-core@3.5.32':
+    dependencies:
+      '@babel/parser': 7.29.2
+      '@vue/shared': 3.5.32
+      entities: 7.0.1
+      estree-walker: 2.0.2
+      source-map-js: 1.2.1
+
+  '@vue/compiler-dom@3.5.32':
+    dependencies:
+      '@vue/compiler-core': 3.5.32
+      '@vue/shared': 3.5.32
+
+  '@vue/compiler-sfc@3.5.32':
+    dependencies:
+      '@babel/parser': 7.29.2
+      '@vue/compiler-core': 3.5.32
+      '@vue/compiler-dom': 3.5.32
+      '@vue/compiler-ssr': 3.5.32
+      '@vue/shared': 3.5.32
+      estree-walker: 2.0.2
+      magic-string: 0.30.21
+      postcss: 8.5.10
+      source-map-js: 1.2.1
+
+  '@vue/compiler-ssr@3.5.32':
+    dependencies:
+      '@vue/compiler-dom': 3.5.32
+      '@vue/shared': 3.5.32
+
+  '@vue/compiler-vue2@2.7.16':
+    dependencies:
+      de-indent: 1.0.2
+      he: 1.2.0
+
+  '@vue/devtools-api@6.6.4': {}
+
+  '@vue/language-core@2.2.12(typescript@5.9.3)':
+    dependencies:
+      '@volar/language-core': 2.4.15
+      '@vue/compiler-dom': 3.5.32
+      '@vue/compiler-vue2': 2.7.16
+      '@vue/shared': 3.5.32
+      alien-signals: 1.0.13
+      minimatch: 9.0.9
+      muggle-string: 0.4.1
+      path-browserify: 1.0.1
+    optionalDependencies:
+      typescript: 5.9.3
+
+  '@vue/reactivity@3.5.32':
+    dependencies:
+      '@vue/shared': 3.5.32
+
+  '@vue/runtime-core@3.5.32':
+    dependencies:
+      '@vue/reactivity': 3.5.32
+      '@vue/shared': 3.5.32
+
+  '@vue/runtime-dom@3.5.32':
+    dependencies:
+      '@vue/reactivity': 3.5.32
+      '@vue/runtime-core': 3.5.32
+      '@vue/shared': 3.5.32
+      csstype: 3.2.3
+
+  '@vue/server-renderer@3.5.32(vue@3.5.32(typescript@5.9.3))':
+    dependencies:
+      '@vue/compiler-ssr': 3.5.32
+      '@vue/shared': 3.5.32
+      vue: 3.5.32(typescript@5.9.3)
+
+  '@vue/shared@3.5.32': {}
+
+  '@vueuse/core@12.0.0(typescript@5.9.3)':
+    dependencies:
+      '@types/web-bluetooth': 0.0.20
+      '@vueuse/metadata': 12.0.0
+      '@vueuse/shared': 12.0.0(typescript@5.9.3)
+      vue: 3.5.32(typescript@5.9.3)
+    transitivePeerDependencies:
+      - typescript
+
+  '@vueuse/metadata@12.0.0': {}
+
+  '@vueuse/shared@12.0.0(typescript@5.9.3)':
+    dependencies:
+      vue: 3.5.32(typescript@5.9.3)
+    transitivePeerDependencies:
+      - typescript
+
+  alien-signals@1.0.13: {}
+
+  async-validator@4.2.5: {}
+
+  asynckit@0.4.0: {}
+
+  axios@1.15.0:
+    dependencies:
+      follow-redirects: 1.16.0
+      form-data: 4.0.5
+      proxy-from-env: 2.1.0
+    transitivePeerDependencies:
+      - debug
+
+  balanced-match@1.0.2: {}
+
+  brace-expansion@2.1.0:
+    dependencies:
+      balanced-match: 1.0.2
+
+  call-bind-apply-helpers@1.0.2:
+    dependencies:
+      es-errors: 1.3.0
+      function-bind: 1.1.2
+
+  combined-stream@1.0.8:
+    dependencies:
+      delayed-stream: 1.0.0
+
+  csstype@3.2.3: {}
+
+  dayjs@1.11.20: {}
+
+  de-indent@1.0.2: {}
+
+  delayed-stream@1.0.0: {}
+
+  dunder-proto@1.0.1:
+    dependencies:
+      call-bind-apply-helpers: 1.0.2
+      es-errors: 1.3.0
+      gopd: 1.2.0
+
+  element-plus@2.13.7(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)):
+    dependencies:
+      '@ctrl/tinycolor': 4.2.0
+      '@element-plus/icons-vue': 2.3.2(vue@3.5.32(typescript@5.9.3))
+      '@floating-ui/dom': 1.7.6
+      '@popperjs/core': '@sxzz/popperjs-es@2.11.8'
+      '@types/lodash': 4.17.24
+      '@types/lodash-es': 4.17.12
+      '@vueuse/core': 12.0.0(typescript@5.9.3)
+      async-validator: 4.2.5
+      dayjs: 1.11.20
+      lodash: 4.18.1
+      lodash-es: 4.18.1
+      lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1)
+      memoize-one: 6.0.0
+      normalize-wheel-es: 1.2.0
+      vue: 3.5.32(typescript@5.9.3)
+      vue-component-type-helpers: 3.2.7
+    transitivePeerDependencies:
+      - typescript
+
+  entities@7.0.1: {}
+
+  es-define-property@1.0.1: {}
+
+  es-errors@1.3.0: {}
+
+  es-object-atoms@1.1.1:
+    dependencies:
+      es-errors: 1.3.0
+
+  es-set-tostringtag@2.1.0:
+    dependencies:
+      es-errors: 1.3.0
+      get-intrinsic: 1.3.0
+      has-tostringtag: 1.0.2
+      hasown: 2.0.3
+
+  esbuild@0.21.5:
+    optionalDependencies:
+      '@esbuild/aix-ppc64': 0.21.5
+      '@esbuild/android-arm': 0.21.5
+      '@esbuild/android-arm64': 0.21.5
+      '@esbuild/android-x64': 0.21.5
+      '@esbuild/darwin-arm64': 0.21.5
+      '@esbuild/darwin-x64': 0.21.5
+      '@esbuild/freebsd-arm64': 0.21.5
+      '@esbuild/freebsd-x64': 0.21.5
+      '@esbuild/linux-arm': 0.21.5
+      '@esbuild/linux-arm64': 0.21.5
+      '@esbuild/linux-ia32': 0.21.5
+      '@esbuild/linux-loong64': 0.21.5
+      '@esbuild/linux-mips64el': 0.21.5
+      '@esbuild/linux-ppc64': 0.21.5
+      '@esbuild/linux-riscv64': 0.21.5
+      '@esbuild/linux-s390x': 0.21.5
+      '@esbuild/linux-x64': 0.21.5
+      '@esbuild/netbsd-x64': 0.21.5
+      '@esbuild/openbsd-x64': 0.21.5
+      '@esbuild/sunos-x64': 0.21.5
+      '@esbuild/win32-arm64': 0.21.5
+      '@esbuild/win32-ia32': 0.21.5
+      '@esbuild/win32-x64': 0.21.5
+
+  estree-walker@2.0.2: {}
+
+  follow-redirects@1.16.0: {}
+
+  form-data@4.0.5:
+    dependencies:
+      asynckit: 0.4.0
+      combined-stream: 1.0.8
+      es-set-tostringtag: 2.1.0
+      hasown: 2.0.3
+      mime-types: 2.1.35
+
+  fsevents@2.3.3:
+    optional: true
+
+  function-bind@1.1.2: {}
+
+  get-intrinsic@1.3.0:
+    dependencies:
+      call-bind-apply-helpers: 1.0.2
+      es-define-property: 1.0.1
+      es-errors: 1.3.0
+      es-object-atoms: 1.1.1
+      function-bind: 1.1.2
+      get-proto: 1.0.1
+      gopd: 1.2.0
+      has-symbols: 1.1.0
+      hasown: 2.0.3
+      math-intrinsics: 1.1.0
+
+  get-proto@1.0.1:
+    dependencies:
+      dunder-proto: 1.0.1
+      es-object-atoms: 1.1.1
+
+  gopd@1.2.0: {}
+
+  has-symbols@1.1.0: {}
+
+  has-tostringtag@1.0.2:
+    dependencies:
+      has-symbols: 1.1.0
+
+  hasown@2.0.3:
+    dependencies:
+      function-bind: 1.1.2
+
+  he@1.2.0: {}
+
+  lodash-es@4.18.1: {}
+
+  lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1):
+    dependencies:
+      '@types/lodash-es': 4.17.12
+      lodash: 4.18.1
+      lodash-es: 4.18.1
+
+  lodash@4.18.1: {}
+
+  magic-string@0.30.21:
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.5.5
+
+  math-intrinsics@1.1.0: {}
+
+  memoize-one@6.0.0: {}
+
+  mime-db@1.52.0: {}
+
+  mime-types@2.1.35:
+    dependencies:
+      mime-db: 1.52.0
+
+  minimatch@9.0.9:
+    dependencies:
+      brace-expansion: 2.1.0
+
+  muggle-string@0.4.1: {}
+
+  nanoid@3.3.11: {}
+
+  normalize-wheel-es@1.2.0: {}
+
+  path-browserify@1.0.1: {}
+
+  picocolors@1.1.1: {}
+
+  pinia@2.3.1(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)):
+    dependencies:
+      '@vue/devtools-api': 6.6.4
+      vue: 3.5.32(typescript@5.9.3)
+      vue-demi: 0.14.10(vue@3.5.32(typescript@5.9.3))
+    optionalDependencies:
+      typescript: 5.9.3
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+
+  postcss@8.5.10:
+    dependencies:
+      nanoid: 3.3.11
+      picocolors: 1.1.1
+      source-map-js: 1.2.1
+
+  proxy-from-env@2.1.0: {}
+
+  rollup@4.60.2:
+    dependencies:
+      '@types/estree': 1.0.8
+    optionalDependencies:
+      '@rollup/rollup-android-arm-eabi': 4.60.2
+      '@rollup/rollup-android-arm64': 4.60.2
+      '@rollup/rollup-darwin-arm64': 4.60.2
+      '@rollup/rollup-darwin-x64': 4.60.2
+      '@rollup/rollup-freebsd-arm64': 4.60.2
+      '@rollup/rollup-freebsd-x64': 4.60.2
+      '@rollup/rollup-linux-arm-gnueabihf': 4.60.2
+      '@rollup/rollup-linux-arm-musleabihf': 4.60.2
+      '@rollup/rollup-linux-arm64-gnu': 4.60.2
+      '@rollup/rollup-linux-arm64-musl': 4.60.2
+      '@rollup/rollup-linux-loong64-gnu': 4.60.2
+      '@rollup/rollup-linux-loong64-musl': 4.60.2
+      '@rollup/rollup-linux-ppc64-gnu': 4.60.2
+      '@rollup/rollup-linux-ppc64-musl': 4.60.2
+      '@rollup/rollup-linux-riscv64-gnu': 4.60.2
+      '@rollup/rollup-linux-riscv64-musl': 4.60.2
+      '@rollup/rollup-linux-s390x-gnu': 4.60.2
+      '@rollup/rollup-linux-x64-gnu': 4.60.2
+      '@rollup/rollup-linux-x64-musl': 4.60.2
+      '@rollup/rollup-openbsd-x64': 4.60.2
+      '@rollup/rollup-openharmony-arm64': 4.60.2
+      '@rollup/rollup-win32-arm64-msvc': 4.60.2
+      '@rollup/rollup-win32-ia32-msvc': 4.60.2
+      '@rollup/rollup-win32-x64-gnu': 4.60.2
+      '@rollup/rollup-win32-x64-msvc': 4.60.2
+      fsevents: 2.3.3
+
+  source-map-js@1.2.1: {}
+
+  typescript@5.9.3: {}
+
+  vite@5.4.21:
+    dependencies:
+      esbuild: 0.21.5
+      postcss: 8.5.10
+      rollup: 4.60.2
+    optionalDependencies:
+      fsevents: 2.3.3
+
+  vscode-uri@3.1.0: {}
+
+  vue-component-type-helpers@3.2.7: {}
+
+  vue-demi@0.14.10(vue@3.5.32(typescript@5.9.3)):
+    dependencies:
+      vue: 3.5.32(typescript@5.9.3)
+
+  vue-router@4.6.4(vue@3.5.32(typescript@5.9.3)):
+    dependencies:
+      '@vue/devtools-api': 6.6.4
+      vue: 3.5.32(typescript@5.9.3)
+
+  vue-tsc@2.2.12(typescript@5.9.3):
+    dependencies:
+      '@volar/typescript': 2.4.15
+      '@vue/language-core': 2.2.12(typescript@5.9.3)
+      typescript: 5.9.3
+
+  vue@3.5.32(typescript@5.9.3):
+    dependencies:
+      '@vue/compiler-dom': 3.5.32
+      '@vue/compiler-sfc': 3.5.32
+      '@vue/runtime-dom': 3.5.32
+      '@vue/server-renderer': 3.5.32(vue@3.5.32(typescript@5.9.3))
+      '@vue/shared': 3.5.32
+    optionalDependencies:
+      typescript: 5.9.3
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/App.vue b/Code/WMS/WIDESEA_WMSClient_Vben/src/App.vue
new file mode 100644
index 0000000..1dd8312
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/App.vue
@@ -0,0 +1,27 @@
+<template>
+  <router-view />
+</template>
+
+<script setup lang="ts">
+import { onMounted } from 'vue';
+
+onMounted(() => {
+  console.log('WMS Vben Admin App mounted');
+});
+</script>
+
+<style>
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+
+html,
+body,
+#app {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/api/auth.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/auth.ts
new file mode 100644
index 0000000..d3a04a7
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/auth.ts
@@ -0,0 +1,50 @@
+import axios from 'axios';
+import type { AxiosInstance, AxiosResponse } from 'axios';
+
+const baseURL = import.meta.env.VITE_APP_API_URL || 'http://localhost:9291';
+
+const http: AxiosInstance = axios.create({
+  baseURL,
+  timeout: 30000,
+});
+
+http.interceptors.request.use(
+  (config) => {
+    const token = localStorage.getItem('token');
+    if (token) {
+      config.headers.Authorization = `Bearer ${token}`;
+    }
+    return config;
+  },
+  (error) => Promise.reject(error)
+);
+
+http.interceptors.response.use(
+  (response: AxiosResponse) => response.data,
+  (error) => {
+    if (error.response?.status === 401) {
+      localStorage.removeItem('token');
+      window.location.href = '/login';
+    }
+    return Promise.reject(error);
+  }
+);
+
+export interface LoginRequest {
+  username: string;
+  password: string;
+}
+
+export interface LoginResponse {
+  success: boolean;
+  message?: string;
+  data?: {
+    token: string;
+  };
+}
+
+export const login = (data: LoginRequest): Promise<LoginResponse> => {
+  return http.post('/api/Login', data);
+};
+
+export default http;
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/api/client.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/client.ts
new file mode 100644
index 0000000..4743309
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/client.ts
@@ -0,0 +1,56 @@
+/**
+ * axios 瀹㈡埛绔皝瑁�
+ * 缁熶竴閰嶇疆锛歜aseURL銆乼imeout銆佽姹�/鍝嶅簲鎷︽埅鍣�
+ */
+import axios from 'axios';
+import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
+
+const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:9291';
+
+/** 鍒涘缓 axios 瀹炰緥 */
+const client: AxiosInstance = axios.create({
+  baseURL: BASE_URL,
+  timeout: 30000,
+  headers: { 'Content-Type': 'application/json' },
+});
+
+let isRefreshing = false;
+let refreshQueue: Array<(token?: string) => void> = [];
+
+/** 璇锋眰鎷︽埅鍣細娉ㄥ叆 Bearer Token */
+client.interceptors.request.use(
+  (config: InternalAxiosRequestConfig) => {
+    const userStr = localStorage.getItem('user');
+    if (userStr) {
+      try {
+        const userData = JSON.parse(userStr);
+        if (userData.token) {
+          config.headers.Authorization = `Bearer ${userData.token}`;
+        }
+      } catch {}
+    }
+    return config;
+  },
+  (error) => Promise.reject(error)
+);
+
+/** 鍝嶅簲鎷︽埅鍣細缁熶竴閿欒澶勭悊 + 401 Token 杩囨湡璺宠浆鐧诲綍 */
+client.interceptors.response.use(
+  (response: AxiosResponse) => response.data,
+  async (error) => {
+    const status = error.response?.status;
+    const data = error.response?.data;
+
+    // 401 鏈巿鏉�
+    if (status === 401 || data?.code === 401) {
+      localStorage.removeItem('user');
+      window.location.href = '/#/login';
+      return Promise.reject(error);
+    }
+
+    return Promise.reject(error);
+  }
+);
+
+export { client };
+export type { AxiosRequestConfig };
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/api/index.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/index.ts
new file mode 100644
index 0000000..1db51da
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/index.ts
@@ -0,0 +1,6 @@
+export { client } from './client';
+export { userApi } from './modules/user';
+export { menuApi } from './modules/menu';
+export { stockApi } from './modules/stock';
+export { inboundApi } from './modules/inbound';
+export { outboundApi } from './modules/outbound';
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/inbound.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/inbound.ts
new file mode 100644
index 0000000..f33daec
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/inbound.ts
@@ -0,0 +1,6 @@
+import { client } from '../client';
+
+export const inboundApi = {
+  getPageList: (params: any) => client.get('/api/InboundOrder/getPageList', { params }),
+  getDetail: (id: number) => client.get(`/api/InboundOrderDetail/${id}`),
+};
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/menu.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/menu.ts
new file mode 100644
index 0000000..3d181d0
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/menu.ts
@@ -0,0 +1,28 @@
+/**
+ * 鑿滃崟 API 妯″潡
+ * 瀵规帴 WMS 鍚庣 /api/Sys_Menu/getTreeMenu 鎺ュ彛
+ */
+import { client } from '../client';
+
+/** 鍚庣杩斿洖鐨勮彍鍗曡妭鐐� */
+export interface BackendMenuNode {
+  id: string | number;
+  name?: string;
+  text?: string;
+  url?: string;
+  path?: string;
+  icon?: string;
+  children?: BackendMenuNode[];
+  [key: string]: unknown;
+}
+
+export const menuApi = {
+  /**
+   * 鑾峰彇鏍戝舰鑿滃崟
+   * GET /api/Sys_Menu/getTreeMenu
+   */
+  getTreeMenu: async (): Promise<BackendMenuNode[]> => {
+    const res = await client.get('/api/Sys_Menu/getTreeMenu');
+    return res || [];
+  },
+};
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/outbound.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/outbound.ts
new file mode 100644
index 0000000..100f1ef
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/outbound.ts
@@ -0,0 +1,6 @@
+import { client } from '../client';
+
+export const outboundApi = {
+  getPageList: (params: any) => client.get('/api/OutboundOrder/getPageList', { params }),
+  getDetail: (id: number) => client.get(`/api/OutboundOrderDetail/${id}`),
+};
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/stock.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/stock.ts
new file mode 100644
index 0000000..aa3c9dd
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/stock.ts
@@ -0,0 +1,6 @@
+import { client } from '../client';
+
+export const stockApi = {
+  getPageList: (params: any) => client.get('/api/StockInfo/getDetailPageList', { params }),
+  getDetail: (id: number) => client.get(`/api/StockInfoDetail/${id}`),
+};
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/user.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/user.ts
new file mode 100644
index 0000000..394b60c
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/api/modules/user.ts
@@ -0,0 +1,8 @@
+import { client } from '../client';
+
+export const userApi = {
+  getCaptcha: () => client.get('/api/User/getVierificationCode'),
+  login: (params: any) => client.post('/api/User/login', params),
+  getCurrentUser: () => client.post('/api/User/getCurrentUserInfo'),
+  replaceToken: () => client.post('/api/User/replaceToken'),
+};
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/layouts/MainLayout.vue b/Code/WMS/WIDESEA_WMSClient_Vben/src/layouts/MainLayout.vue
new file mode 100644
index 0000000..fa5bab6
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/layouts/MainLayout.vue
@@ -0,0 +1,158 @@
+<template>
+  <el-container class="main-layout">
+    <el-aside :width="collapsed ? '64px' : '200px'">
+      <div class="logo" @click="collapsed = !collapsed">
+        <span v-if="!collapsed">WMS绠$悊绯荤粺</span>
+        <span v-else>W</span>
+      </div>
+      <el-scrollbar>
+        <el-menu
+          :default-active="activeMenu"
+          class="el-menu-vertical"
+          :collapse="collapsed"
+          :router="true"
+          @select="handleMenuSelect"
+        >
+          <template v-for="item in menuList" :key="item.id">
+            <el-sub-menu v-if="item.children?.length" :index="String(item.id)">
+              <template #title>
+                <span>{{ item.name || item.text }}</span>
+              </template>
+              <el-menu-item
+                v-for="child in item.children"
+                :key="child.id"
+                :index="child.path || String(child.id)"
+              >
+                <span>{{ child.name || child.text }}</span>
+              </el-menu-item>
+            </el-sub-menu>
+            <el-menu-item v-else :index="item.path || String(item.id)">
+              <span>{{ item.name || item.text }}</span>
+            </el-menu-item>
+          </template>
+        </el-menu>
+      </el-scrollbar>
+    </el-aside>
+    <el-container>
+      <el-header>
+        <div class="header-left">
+          <span class="project-title">WIDESEA WMS</span>
+        </div>
+        <div class="header-right">
+          <span class="username">{{ username }}</span>
+          <el-button link @click="handleLogout">閫�鍑�</el-button>
+        </div>
+      </el-header>
+      <el-main>
+        <router-view />
+      </el-main>
+    </el-container>
+  </el-container>
+</template>
+
+<script setup lang="ts">
+import { ref, computed, onMounted } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+import { useMenuStore } from '@/store/modules/menu';
+import { ElMessage } from 'element-plus';
+
+const route = useRoute();
+const router = useRouter();
+const menuStore = useMenuStore();
+
+const collapsed = ref(false);
+const menuList = ref<any[]>([]);
+
+const username = computed(() => {
+  const userStr = localStorage.getItem('user');
+  if (userStr) {
+    try {
+      const user = JSON.parse(userStr);
+      return user.userTrueName || user.userName || '鏈櫥褰�';
+    } catch {}
+  }
+  return '鏈櫥褰�';
+});
+
+const activeMenu = computed(() => route.path);
+
+function handleMenuSelect(index: string) {
+  const menu = menuStore.findMenuByPath(index);
+  if (menu?.path) {
+    router.push(menu.path);
+  }
+}
+
+async function loadMenus() {
+  try {
+    const menus = await menuStore.loadMenus();
+    menuList.value = menus || [];
+  } catch (error) {
+    console.error('鍔犺浇鑿滃崟澶辫触:', error);
+    ElMessage.error('鍔犺浇鑿滃崟澶辫触');
+  }
+}
+
+function handleLogout() {
+  localStorage.removeItem('user');
+  menuStore.resetMenus();
+  router.push('/login');
+}
+
+onMounted(() => {
+  loadMenus();
+});
+</script>
+
+<style scoped>
+.main-layout {
+  height: 100%;
+}
+.el-aside {
+  background-color: #304156;
+  color: #fff;
+  transition: width 0.3s;
+}
+.logo {
+  height: 60px;
+  line-height: 60px;
+  text-align: center;
+  font-size: 18px;
+  color: #fff;
+  cursor: pointer;
+  background-color: #263445;
+}
+.el-menu-vertical {
+  border-right: none;
+  background-color: transparent;
+}
+.el-menu-vertical:not(.el-menu--collapse) {
+  width: 200px;
+}
+.el-header {
+  background-color: #fff;
+  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
+  line-height: 60px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0 20px;
+}
+.project-title {
+  font-weight: 600;
+  font-size: 16px;
+  color: #333;
+}
+.header-right {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+.username {
+  color: #666;
+}
+.el-main {
+  background-color: #f0f2f5;
+  padding: 16px;
+}
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/locales/zh-CN.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/locales/zh-CN.ts
new file mode 100644
index 0000000..5e1c2ea
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/locales/zh-CN.ts
@@ -0,0 +1,21 @@
+export default {
+  common: {
+    ok: '纭畾',
+    cancel: '鍙栨秷',
+    save: '淇濆瓨',
+    delete: '鍒犻櫎',
+    edit: '缂栬緫',
+    add: '鏂板',
+    search: '鎼滅储',
+    reset: '閲嶇疆',
+  },
+  login: {
+    title: 'WMS绠$悊绯荤粺',
+    username: '鐢ㄦ埛鍚�',
+    password: '瀵嗙爜',
+    loginBtn: '鐧诲綍',
+  },
+  menu: {
+    dashboard: '棣栭〉',
+  },
+};
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/main.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/main.ts
new file mode 100644
index 0000000..9d96edf
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/main.ts
@@ -0,0 +1,15 @@
+import { createApp } from 'vue';
+import { createPinia } from 'pinia';
+import ElementPlus from 'element-plus';
+import 'element-plus/dist/index.css';
+import App from './App.vue';
+import router from './router';
+
+const app = createApp(App);
+const pinia = createPinia();
+
+app.use(pinia);
+app.use(router);
+app.use(ElementPlus);
+
+app.mount('#app');
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/router/index.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/router/index.ts
new file mode 100644
index 0000000..9a71d7d
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/router/index.ts
@@ -0,0 +1,81 @@
+/**
+ * 璺敱閰嶇疆
+ * 鏀寔鍔ㄦ�佽彍鍗曡矾鐢辨敞鍐�
+ */
+import { createRouter, createWebHashHistory } from 'vue-router';
+import type { RouteRecordRaw } from 'vue-router';
+import { useMenuStore } from '@/store/modules/menu';
+import { transformMenuToRoutes } from '@/utils/menuTransform';
+
+const routes: RouteRecordRaw[] = [
+  {
+    path: '/login',
+    name: 'Login',
+    component: () => import('@/views/login/index.vue'),
+    meta: { anonymous: true },
+  },
+  {
+    path: '/',
+    name: 'root',
+    component: () => import('@/layouts/MainLayout.vue'),
+    redirect: '/home',
+    children: [
+      { path: '/home', name: 'Home', component: () => import('@/views/dashboard/index.vue'), meta: { title: '棣栭〉', icon: 'el-icon-home' } },
+    ],
+  },
+  { path: '/:pathMatch(.*)*', redirect: '/home' },
+];
+
+const router = createRouter({
+  history: createWebHashHistory(),
+  routes,
+});
+
+/**
+ * 鍔ㄦ�佹敞鍐岃矾鐢�
+ */
+export async function registerDynamicRoutes() {
+  const menuStore = useMenuStore();
+
+  if (!menuStore.loaded) {
+    await menuStore.loadMenus();
+  }
+
+  const dynamicRoutes = transformMenuToRoutes(menuStore.menus);
+  const rootRoute = router.getRoutes().find((r) => r.name === 'root');
+  if (!rootRoute) return;
+
+  dynamicRoutes.forEach((route) => {
+    const exists = router.getRoutes().some((r) => r.name === route.name);
+    if (!exists && route.name) {
+      router.addRoute('root', route);
+    }
+  });
+
+  return dynamicRoutes;
+}
+
+router.beforeEach(async (to, from, next) => {
+  if (to.meta?.anonymous) {
+    return next();
+  }
+
+  const userStr = localStorage.getItem('user');
+  if (!userStr) {
+    return next('/login');
+  }
+
+  const menuStore = useMenuStore();
+  if (!menuStore.loaded) {
+    try {
+      await registerDynamicRoutes();
+    } catch (error) {
+      console.error('娉ㄥ唽鍔ㄦ�佽矾鐢卞け璐�:', error);
+    }
+  }
+
+  next();
+});
+
+export { router };
+export default router;
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/store/index.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/store/index.ts
new file mode 100644
index 0000000..2fcfbda
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/store/index.ts
@@ -0,0 +1,5 @@
+/**
+ * Store 缁熶竴瀵煎嚭
+ */
+export { useMenuStore } from './modules/menu';
+export { useUserStore } from './user';
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/store/modules/menu.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/store/modules/menu.ts
new file mode 100644
index 0000000..34ed521
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/store/modules/menu.ts
@@ -0,0 +1,57 @@
+/**
+ * 鑿滃崟鐘舵�佺鐞�
+ */
+import { defineStore } from 'pinia';
+import { menuApi, type BackendMenuNode } from '@/api/modules/menu';
+import { normalizeMenus, addHomeMenu } from '@/utils/menuTransform';
+
+interface MenuState {
+  menus: BackendMenuNode[];
+  loaded: boolean;
+}
+
+export const useMenuStore = defineStore('menu', {
+  state: (): MenuState => ({
+    menus: [],
+    loaded: false,
+  }),
+
+  getters: {
+    flatMenus: (state) => {
+      const flat: BackendMenuNode[] = [];
+      const flatten = (items: BackendMenuNode[]) => {
+        items.forEach((item) => {
+          flat.push(item);
+          if (item.children?.length) {
+            flatten(item.children);
+          }
+        });
+      };
+      flatten(state.menus);
+      return flat;
+    },
+  },
+
+  actions: {
+    async loadMenus() {
+      try {
+        const data = await menuApi.getTreeMenu();
+        this.menus = addHomeMenu(data || []);
+        this.loaded = true;
+        return this.menus;
+      } catch (error) {
+        console.error('鍔犺浇鑿滃崟澶辫触:', error);
+        throw error;
+      }
+    },
+
+    findMenuByPath(path: string): BackendMenuNode | null {
+      return this.flatMenus.find((m) => m.path === path) || null;
+    },
+
+    resetMenus() {
+      this.menus = [];
+      this.loaded = false;
+    },
+  },
+});
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/store/user.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/store/user.ts
new file mode 100644
index 0000000..028f1f6
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/store/user.ts
@@ -0,0 +1,43 @@
+import { defineStore } from 'pinia';
+import { ref, computed } from 'vue';
+
+interface UserInfo {
+  token: string;
+  userName: string;
+  userTrueName: string;
+  img: string;
+}
+
+export const useUserStore = defineStore('user', () => {
+  const userInfo = ref<UserInfo | null>(null);
+  const token = ref<string>('');
+  const isLogin = computed(() => !!token.value);
+
+  function init() {
+    const stored = localStorage.getItem('user');
+    if (stored) {
+      try {
+        const info = JSON.parse(stored) as UserInfo;
+        userInfo.value = info;
+        token.value = info?.token || '';
+      } catch {
+        token.value = '';
+      }
+    }
+  }
+
+  function setUserInfo(info: UserInfo) {
+    userInfo.value = info;
+    token.value = info?.token || '';
+    localStorage.setItem('user', JSON.stringify(info));
+  }
+
+  function clearUserInfo() {
+    userInfo.value = null;
+    token.value = '';
+    localStorage.removeItem('user');
+  }
+
+  init();
+  return { userInfo, token, isLogin, setUserInfo, clearUserInfo };
+});
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/utils/menuTransform.ts b/Code/WMS/WIDESEA_WMSClient_Vben/src/utils/menuTransform.ts
new file mode 100644
index 0000000..cef9744
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/utils/menuTransform.ts
@@ -0,0 +1,143 @@
+/**
+ * 鑿滃崟鏁版嵁杞崲宸ュ叿
+ * 灏嗗悗绔彍鍗曟牸寮忚浆鎹负 Vben Admin 鑿滃崟鏍煎紡
+ */
+import type { RouteRecordRaw } from 'vue-router';
+import type { BackendMenuNode } from '@/api/modules/menu';
+
+/** Element Plus 鍥炬爣鍚嶇О鏄犲皠 */
+const iconMap: Record<string, string> = {
+  'el-icon-menu': 'Menu',
+  'el-icon-user': 'User',
+  'el-icon-setting': 'Setting',
+  'el-icon-home': 'HomeFilled',
+  'el-icon-document': 'Document',
+  'el-icon-edit': 'Edit',
+  'el-icon-view': 'View',
+  'el-icon-delete': 'Delete',
+  'el-icon-search': 'Search',
+  'el-icon-refresh': 'Refresh',
+  'el-icon-download': 'Download',
+  'el-icon-upload': 'Upload',
+  'el-icon-goods': 'Goods',
+  'el-icon-box': 'Box',
+  'el-icon-truck': 'Van',
+  'el-icon-shop': 'Shop',
+  'el-icon-list': 'List',
+  'el-icon-grid': 'Grid',
+  'el-icon-s-custom': 'UserFilled',
+  'el-icon-s-order': 'List',
+  'el-icon-s-grid': 'Grid',
+  'el-icon-s-home': 'HomeFilled',
+  'el-icon-s-data': 'DataLine',
+  'el-icon-s-check': 'CircleCheck',
+  'el-icon-s-management': 'Management',
+};
+
+/**
+ * 杞崲鍥炬爣鍚嶇О
+ * el-icon-menu -> Menu
+ */
+export function transformIcon(icon?: string): string {
+  if (!icon) return 'Menu';
+  return iconMap[icon] || 'Menu';
+}
+
+/**
+ * 鏍囧噯鍖栬彍鍗曡矾寰�
+ * "/Manager/home" -> "/home"
+ */
+export function normalizePath(url?: string): string {
+  if (!url) return '/';
+  let path = url.replace('/Manager', '') || '/';
+  if (!path.startsWith('/')) {
+    path = '/' + path;
+  }
+  return path;
+}
+
+/**
+ * 妫�鏌ユ槸鍚︿负澶栭儴閾炬帴
+ */
+function isExternalUrl(url?: string): boolean {
+  if (!url) return false;
+  return url.startsWith('http://') || url.startsWith('https://');
+}
+
+/**
+ * 灏嗗悗绔彍鍗曡妭鐐硅浆鎹负 Vben 鑿滃崟椤�
+ */
+export function transformMenuItem(menu: BackendMenuNode): RouteRecordRaw | null {
+  const name = menu.name || menu.text || '鏈懡鍚�';
+  const url = menu.url || menu.path || '';
+  const path = normalizePath(url);
+
+  // 璺宠繃澶栭儴閾炬帴
+  if (isExternalUrl(url)) {
+    return null;
+  }
+
+  const route: RouteRecordRaw = {
+    path,
+    name: path.replace(/\//g, '_').replace(/^_/, '') || 'root',
+    meta: {
+      title: name,
+      icon: menu.icon || 'el-icon-menu',
+    },
+  };
+
+  // 閫掑綊澶勭悊瀛愯彍鍗�
+  if (menu.children?.length) {
+    const children = menu.children
+      .map((child) => transformMenuItem(child))
+      .filter((r): r is RouteRecordRaw => r !== null);
+    if (children.length > 0) {
+      route.children = children;
+    }
+  }
+
+  return route;
+}
+
+/**
+ * 灏嗗悗绔彍鍗曟暟缁勮浆鎹负璺敱鏁扮粍
+ */
+export function transformMenuToRoutes(menus: BackendMenuNode[]): RouteRecordRaw[] {
+  const routes: RouteRecordRaw[] = [];
+
+  menus.forEach((menu) => {
+    const route = transformMenuItem(menu);
+    if (route) {
+      routes.push(route);
+    }
+  });
+
+  return routes;
+}
+
+/**
+ * 灏嗗悗绔彍鍗曟暟缁勬爣鍑嗗寲
+ */
+export function normalizeMenus(menus: BackendMenuNode[]): BackendMenuNode[] {
+  return menus.map((menu) => ({
+    ...menu,
+    path: normalizePath(menu.url || menu.path),
+    icon: menu.icon || 'el-icon-menu',
+    children: menu.children ? normalizeMenus(menu.children) : undefined,
+  }));
+}
+
+/**
+ * 涓鸿彍鍗曞垪琛ㄦ坊鍔犻椤甸」
+ */
+export function addHomeMenu(menus: BackendMenuNode[]): BackendMenuNode[] {
+  const normalized = normalizeMenus(menus);
+  normalized.push({
+    id: 'home',
+    name: '棣栭〉',
+    text: '棣栭〉',
+    path: '/home',
+    icon: 'el-icon-home',
+  });
+  return normalized;
+}
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/views/dashboard/index.vue b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/dashboard/index.vue
new file mode 100644
index 0000000..1745f6a
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/dashboard/index.vue
@@ -0,0 +1,47 @@
+<template>
+  <div class="dashboard">
+    <h1>娆㈣繋浣跨敤WMS绠$悊绯荤粺</h1>
+    <el-row :gutter="20">
+      <el-col :span="6">
+        <el-card>
+          <template #header>鎬诲簱瀛�</template>
+          <div class="stat-value">10,000</div>
+        </el-card>
+      </el-col>
+      <el-col :span="6">
+        <el-card>
+          <template #header>浠婃棩鍏ュ簱</template>
+          <div class="stat-value">150</div>
+        </el-card>
+      </el-col>
+      <el-col :span="6">
+        <el-card>
+          <template #header>浠婃棩鍑哄簱</template>
+          <div class="stat-value">120</div>
+        </el-card>
+      </el-col>
+      <el-col :span="6">
+        <el-card>
+          <template #header>寰呭鐞嗕换鍔�</template>
+          <div class="stat-value">25</div>
+        </el-card>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+</script>
+
+<style scoped>
+.dashboard h1 {
+  margin-bottom: 20px;
+  color: #333;
+}
+.stat-value {
+  font-size: 28px;
+  font-weight: bold;
+  text-align: center;
+  color: #409eff;
+}
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/views/inbound/inboundOrderDetail.vue b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/inbound/inboundOrderDetail.vue
new file mode 100644
index 0000000..4f5ae51
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/inbound/inboundOrderDetail.vue
@@ -0,0 +1,105 @@
+<template>
+  <div class="inbound-detail-page">
+    <el-card shadow="never">
+      <template #header>
+        <span>鍏ュ簱鍗曟槑缁� - {{ route.query.inboundOrderNo || '' }}</span>
+      </template>
+
+      <el-form :inline="true" :model="queryForm" class="search-form">
+        <el-form-item label="鐗╂枡缂栧彿">
+          <el-input v-model="queryForm.materielCode" placeholder="璇疯緭鍏ョ墿鏂欑紪鍙�" clearable />
+        </el-form-item>
+        <el-form-item label="鐗╂枡鍚嶇О">
+          <el-input v-model="queryForm.materielName" placeholder="璇疯緭鍏ョ墿鏂欏悕绉�" clearable />
+        </el-form-item>
+        <el-form-item label="鎵规鍙�">
+          <el-input v-model="queryForm.batchNo" placeholder="璇疯緭鍏ユ壒娆″彿" clearable />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鏌ヨ</el-button>
+          <el-button @click="handleReset">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+
+      <el-table v-loading="loading" :data="tableData" border stripe>
+        <el-table-column prop="materielCode" label="鐗╂枡缂栧彿" min-width="150" show-overflow-tooltip />
+        <el-table-column prop="materielName" label="鐗╂枡鍚嶇О" min-width="160" show-overflow-tooltip />
+        <el-table-column prop="batchNo" label="鎵规鍙�" min-width="120" align="center" />
+        <el-table-column prop="orderQuantity" label="鍗曟嵁鏁伴噺" min-width="100" align="center" />
+        <el-table-column prop="receiptQuantity" label="缁勭洏鏁伴噺" min-width="120" align="center" />
+        <el-table-column prop="overInQuantity" label="涓婃灦鏁伴噺" min-width="120" align="center" />
+        <el-table-column prop="orderDetailStatus" label="鏄庣粏鐘舵��" min-width="110" align="center">
+          <template #default="{ row }">
+            {{ getDetailStatusText(row.orderDetailStatus) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="creater" label="鍒涘缓浜�" min-width="90" align="center" />
+        <el-table-column prop="createDate" label="鍒涘缓鏃堕棿" min-width="160" align="center" />
+      </el-table>
+
+      <el-pagination
+        v-model:current-page="pagination.page"
+        v-model:page-size="pagination.pageSize"
+        :total="pagination.total"
+        :page-sizes="[10, 20, 50, 100]"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handlePageChange"
+        style="margin-top: 16px; justify-content: flex-end"
+      />
+    </el-card>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { useRoute } from 'vue-router';
+import { ElMessage } from 'element-plus';
+import { client } from '@/api/client';
+
+const route = useRoute();
+const loading = ref(false);
+const tableData = ref([]);
+const detailStatusOptions = ref([]);
+
+const queryForm = reactive({ materielCode: '', materielName: '', batchNo: '' });
+const pagination = reactive({ page: 1, pageSize: 20, total: 0 });
+
+async function loadData() {
+  loading.value = true;
+  try {
+    const orderId = route.query.id;
+    const wheres = [{ name: 'orderId', value: String(orderId), displayType: 'int' }];
+    if (queryForm.materielCode) wheres.push({ name: 'materielCode', value: queryForm.materielCode, displayType: 'like' });
+    if (queryForm.materielName) wheres.push({ name: 'materielName', value: queryForm.materielName, displayType: 'like' });
+    if (queryForm.batchNo) wheres.push({ name: 'batchNo', value: queryForm.batchNo, displayType: 'like' });
+    const res = await client.post('/api/InboundOrderDetail/getPageList', {
+      page: pagination.page, rows: pagination.pageSize, sort: 'id', order: 'asc',
+      wheres: JSON.stringify(wheres),
+    });
+    tableData.value = res?.rows || [];
+    pagination.total = res?.total || 0;
+  } catch { ElMessage.error('鍔犺浇鏁版嵁澶辫触'); }
+  finally { loading.value = false; }
+}
+
+async function loadDictionary() {
+  try {
+    const res = await client.post('/api/Sys_Dictionary/GetVueDictionary', ['orderDetailStatusEnum']);
+    detailStatusOptions.value = res?.find(item => item.dicNo === 'orderDetailStatusEnum')?.data || [];
+  } catch { detailStatusOptions.value = []; }
+}
+
+function handleSearch() { pagination.page = 1; loadData(); }
+function handleReset() { queryForm.materielCode = ''; queryForm.materielName = ''; queryForm.batchNo = ''; handleSearch(); }
+function handleSizeChange() { loadData(); }
+function handlePageChange() { loadData(); }
+const getDetailStatusText = (val) => detailStatusOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+
+onMounted(() => { loadDictionary(); loadData(); });
+</script>
+
+<style scoped>
+.inbound-detail-page { padding: 16px; }
+.search-form { margin-bottom: 12px; }
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/views/inbound/index.vue b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/inbound/index.vue
new file mode 100644
index 0000000..e71026b
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/inbound/index.vue
@@ -0,0 +1,275 @@
+<template>
+  <div class="inbound-page">
+    <!-- 鎼滅储 -->
+    <el-card class="search-card" shadow="never">
+      <el-form :inline="true" :model="queryForm" label-width="90px">
+        <el-form-item label="鍗曟嵁缂栧彿">
+          <el-input v-model="queryForm.inboundOrderNo" placeholder="璇疯緭鍏ュ崟鎹紪鍙�" clearable style="width: 170px" />
+        </el-form-item>
+        <el-form-item label="涓婃父鍗曟嵁">
+          <el-input v-model="queryForm.upperOrderNo" placeholder="璇疯緭鍏ヤ笂娓稿崟鎹紪鍙�" clearable style="width: 170px" />
+        </el-form-item>
+        <el-form-item label="鍗曟嵁绫诲瀷">
+          <el-select v-model="queryForm.orderType" placeholder="璇烽�夋嫨" clearable style="width: 150px">
+            <el-option v-for="item in orderTypeOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍗曟嵁鐘舵��">
+          <el-select v-model="queryForm.orderStatus" placeholder="璇烽�夋嫨" clearable style="width: 140px">
+            <el-option v-for="item in orderStatusOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍒涘缓鏃堕棿">
+          <el-date-picker v-model="queryForm.createDate" type="daterange" range-separator="鑷�" start-placeholder="寮�濮�" end-placeholder="缁撴潫" value-format="YYYY-MM-DD" />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鏌ヨ</el-button>
+          <el-button @click="handleReset">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 琛ㄦ牸 -->
+    <el-card class="table-card" shadow="never">
+      <div class="toolbar">
+        <el-button type="primary" @click="handleAdd">鏂板</el-button>
+        <el-button type="danger" :disabled="!selectedRows.length" @click="handleBatchDelete">鎵归噺鍒犻櫎</el-button>
+      </div>
+
+      <el-table v-loading="loading" :data="tableData" border stripe @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="50" align="center" />
+        <el-table-column prop="inboundOrderNo" label="鍗曟嵁缂栧彿" min-width="140" show-overflow-tooltip />
+        <el-table-column prop="upperOrderNo" label="涓婃父鍗曟嵁缂栧彿" min-width="150" show-overflow-tooltip />
+        <el-table-column prop="warehouseId" label="浠撳簱" min-width="100" align="center">
+          <template #default="{ row }">
+            {{ getWarehouseText(row.warehouseId) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="orderType" label="鍗曟嵁绫诲瀷" min-width="140" align="center">
+          <template #default="{ row }">
+            {{ getOrderTypeText(row.orderType) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="orderStatus" label="鍗曟嵁鐘舵��" min-width="100" align="center">
+          <template #default="{ row }">
+            {{ getOrderStatusText(row.orderStatus) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="createType" label="鍒涘缓鏂瑰紡" min-width="110" align="center">
+          <template #default="{ row }">
+            {{ getCreateTypeText(row.createType) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="creater" label="鍒涘缓浜�" min-width="90" align="center" />
+        <el-table-column prop="createDate" label="鍒涘缓鏃堕棿" min-width="160" align="center" />
+        <el-table-column label="鎿嶄綔" width="180" align="center" fixed="right">
+          <template #default="{ row }">
+            <el-button link type="primary" size="small" @click="goDetail(row)">鏄庣粏</el-button>
+            <el-button link type="primary" size="small" @click="handleEdit(row)">缂栬緫</el-button>
+            <el-button link type="danger" size="small" @click="handleDelete(row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <el-pagination
+        v-model:current-page="pagination.page"
+        v-model:page-size="pagination.pageSize"
+        :total="pagination.total"
+        :page-sizes="[10, 20, 50, 100]"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handlePageChange"
+        style="margin-top: 16px; justify-content: flex-end"
+      />
+    </el-card>
+
+    <!-- 鏄庣粏鎶藉眽 -->
+    <el-drawer v-model="detailDrawerVisible" title="鍏ュ簱鍗曟槑缁�" size="70%" direction="rtl" destroy-on-close>
+      <el-table :data="detailTableData" border stripe max-height="600">
+        <el-table-column prop="materielCode" label="鐗╂枡缂栧彿" min-width="150" show-overflow-tooltip />
+        <el-table-column prop="materielName" label="鐗╂枡鍚嶇О" min-width="150" show-overflow-tooltip />
+        <el-table-column prop="batchNo" label="鎵规鍙�" min-width="120" align="center" />
+        <el-table-column prop="orderQuantity" label="鍗曟嵁鏁伴噺" min-width="100" align="center" />
+        <el-table-column prop="receiptQuantity" label="缁勭洏鏁伴噺" min-width="120" align="center" />
+        <el-table-column prop="overInQuantity" label="涓婃灦鏁伴噺" min-width="120" align="center" />
+        <el-table-column prop="orderDetailStatus" label="鏄庣粏鐘舵��" min-width="110" align="center">
+          <template #default="{ row }">
+            {{ getDetailStatusText(row.orderDetailStatus) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="creater" label="鍒涘缓浜�" min-width="90" align="center" />
+        <el-table-column prop="createDate" label="鍒涘缓鏃堕棿" min-width="160" align="center" />
+      </el-table>
+    </el-drawer>
+
+    <!-- 缂栬緫寮圭獥 -->
+    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="560px" destroy-on-close>
+      <el-form :model="editForm" :rules="editRules" ref="editFormRef" label-width="100px">
+        <el-form-item label="鍗曟嵁绫诲瀷" prop="orderType">
+          <el-select v-model="editForm.orderType" placeholder="璇烽�夋嫨鍗曟嵁绫诲瀷" style="width: 100%">
+            <el-option v-for="item in orderTypeOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍗曟嵁缂栧彿" prop="inboundOrderNo">
+          <el-input v-model="editForm.inboundOrderNo" placeholder="璇疯緭鍏ュ崟鎹紪鍙�" />
+        </el-form-item>
+        <el-form-item label="涓婃父鍗曟嵁">
+          <el-input v-model="editForm.upperOrderNo" placeholder="璇疯緭鍏ヤ笂娓稿崟鎹紪鍙�" />
+        </el-form-item>
+        <el-form-item label="浠撳簱" prop="warehouseId">
+          <el-select v-model="editForm.warehouseId" placeholder="璇烽�夋嫨浠撳簱" style="width: 100%">
+            <el-option v-for="item in warehouseOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="澶囨敞">
+          <el-input v-model="editForm.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="submitLoading">纭畾</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { useRouter } from 'vue-router';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import { inboundApi } from '@/api/modules/inbound';
+import { client } from '@/api/client';
+
+const router = useRouter();
+
+// 鎼滅储
+const queryForm = reactive({ inboundOrderNo: '', upperOrderNo: '', orderType: undefined, orderStatus: undefined, createDate: '' });
+
+// 琛ㄦ牸
+const loading = ref(false);
+const tableData = ref([]);
+const selectedRows = ref([]);
+
+// 瀛楀吀
+const orderTypeOptions = ref([]);
+const orderStatusOptions = ref([]);
+const warehouseOptions = ref([]);
+const createTypeOptions = ref([]);
+const detailStatusOptions = ref([]);
+
+// 鍒嗛〉
+const pagination = reactive({ page: 1, pageSize: 20, total: 0 });
+
+// 鏄庣粏鎶藉眽
+const detailDrawerVisible = ref(false);
+const detailTableData = ref([]);
+const currentRow = ref(null);
+
+// 缂栬緫寮圭獥
+const dialogVisible = ref(false);
+const dialogTitle = ref('鏂板鍏ュ簱鍗�');
+const editFormRef = ref(null);
+const submitLoading = ref(false);
+const editForm = reactive({ id: undefined, orderType: undefined, inboundOrderNo: '', upperOrderNo: '', warehouseId: undefined, remark: '' });
+const editRules = {
+  orderType: [{ required: true, message: '璇烽�夋嫨鍗曟嵁绫诲瀷', trigger: 'change' }],
+  inboundOrderNo: [{ required: true, message: '璇疯緭鍏ュ崟鎹紪鍙�', trigger: 'blur' }],
+  warehouseId: [{ required: true, message: '璇烽�夋嫨浠撳簱', trigger: 'change' }],
+};
+
+async function loadData() {
+  loading.value = true;
+  try {
+    const wheres = [
+      queryForm.inboundOrderNo ? { name: 'inboundOrderNo', value: queryForm.inboundOrderNo, displayType: 'like' } : null,
+      queryForm.upperOrderNo ? { name: 'upperOrderNo', value: queryForm.upperOrderNo, displayType: 'like' } : null,
+      queryForm.orderType !== undefined ? { name: 'orderType', value: queryForm.orderType, displayType: 'int' } : null,
+      queryForm.orderStatus !== undefined ? { name: 'orderStatus', value: queryForm.orderStatus, displayType: 'int' } : null,
+    ].filter(Boolean);
+    const res = await inboundApi.getPageList({ page: pagination.page, rows: pagination.pageSize, sort: 'id', order: 'desc', wheres: JSON.stringify(wheres) });
+    tableData.value = res?.rows || [];
+    pagination.total = res?.total || 0;
+  } catch { ElMessage.error('鍔犺浇鏁版嵁澶辫触'); }
+  finally { loading.value = false; }
+}
+
+async function loadDetail(row) {
+  try {
+    const res = await client.post('/api/InboundOrderDetail/getPageList', {
+      page: 1, rows: 200, sort: 'id', order: 'asc',
+      wheres: JSON.stringify([{ name: 'orderId', value: row.id, displayType: 'int' }]),
+    });
+    detailTableData.value = res?.rows || [];
+  } catch { detailTableData.value = []; ElMessage.error('鍔犺浇鏄庣粏澶辫触'); }
+}
+
+async function loadDictionary() {
+  try {
+    const res = await client.post('/api/Sys_Dictionary/GetVueDictionary', ['inOrderType', 'inboundState', 'warehouses', 'createType', 'orderDetailStatusEnum']);
+    const findData = (dicNo) => res?.find(item => item.dicNo === dicNo)?.data || [];
+    orderTypeOptions.value = findData('inOrderType');
+    orderStatusOptions.value = findData('inboundState');
+    warehouseOptions.value = findData('warehouses');
+    createTypeOptions.value = findData('createType');
+    detailStatusOptions.value = findData('orderDetailStatusEnum');
+  } catch {
+    orderTypeOptions.value = []; orderStatusOptions.value = []; warehouseOptions.value = [];
+  }
+}
+
+function goDetail(row) { router.push({ path: '/inbound/inboundOrderDetail', query: { id: row.id, inboundOrderNo: row.inboundOrderNo } }); }
+
+function handleSearch() { pagination.page = 1; loadData(); }
+function handleReset() { queryForm.inboundOrderNo = ''; queryForm.upperOrderNo = ''; queryForm.orderType = undefined; queryForm.orderStatus = undefined; queryForm.createDate = ''; handleSearch(); }
+
+function handleAdd() {
+  editForm.id = undefined; editForm.orderType = undefined; editForm.inboundOrderNo = ''; editForm.upperOrderNo = ''; editForm.warehouseId = undefined; editForm.remark = '';
+  dialogTitle.value = '鏂板鍏ュ簱鍗�'; dialogVisible.value = true;
+}
+
+function handleEdit(row) {
+  Object.assign(editForm, { id: row.id, orderType: row.orderType, inboundOrderNo: row.inboundOrderNo, upperOrderNo: row.upperOrderNo, warehouseId: row.warehouseId, remark: row.remark });
+  dialogTitle.value = '缂栬緫鍏ュ簱鍗�'; dialogVisible.value = true;
+}
+
+async function handleSubmit() {
+  await editFormRef.value.validate();
+  submitLoading.value = true;
+  try {
+    if (editForm.id) { await inboundApi.update(editForm); ElMessage.success('鏇存柊鎴愬姛'); }
+    else { await inboundApi.add(editForm); ElMessage.success('鏂板鎴愬姛'); }
+    dialogVisible.value = false; loadData();
+  } catch { ElMessage.error('鎿嶄綔澶辫触'); }
+  finally { submitLoading.value = false; }
+}
+
+function handleDelete(row) {
+  ElMessageBox.confirm(`纭畾鍒犻櫎鍏ュ簱鍗曘��${row.inboundOrderNo}銆嶅悧锛焋, '鎻愮ず', { type: 'warning' })
+    .then(async () => { await inboundApi.deleteById(row.id); ElMessage.success('鍒犻櫎鎴愬姛'); loadData(); }).catch(() => {});
+}
+
+function handleBatchDelete() {
+  const ids = selectedRows.value.map(r => r.id);
+  ElMessageBox.confirm(`纭畾鍒犻櫎閫変腑鐨� ${ids.length} 鏉¤褰曞悧锛焋, '鎻愮ず', { type: 'warning' })
+    .then(async () => { await Promise.all(ids.map(id => inboundApi.deleteById(id))); ElMessage.success('鍒犻櫎鎴愬姛'); loadData(); }).catch(() => {});
+}
+
+function handleSelectionChange(rows) { selectedRows.value = rows; }
+function handleSizeChange() { loadData(); }
+function handlePageChange() { loadData(); }
+
+const getWarehouseText = (val) => warehouseOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+const getOrderTypeText = (val) => orderTypeOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+const getOrderStatusText = (val) => orderStatusOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+const getCreateTypeText = (val) => createTypeOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+const getDetailStatusText = (val) => detailStatusOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+
+onMounted(() => { loadDictionary(); loadData(); });
+</script>
+
+<style scoped>
+.inbound-page { padding: 16px; }
+.search-card { margin-bottom: 12px; }
+.table-card { margin-bottom: 12px; }
+.toolbar { margin-bottom: 12px; }
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/views/login/index.vue b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/login/index.vue
new file mode 100644
index 0000000..03312f9
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/login/index.vue
@@ -0,0 +1,196 @@
+<template>
+  <div class="login-container">
+    <div class="login-box">
+      <div class="login-header">
+        <h2>WIDESEA WMS</h2>
+        <p>浠撳簱绠$悊绯荤粺</p>
+      </div>
+
+      <el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" class="login-form">
+        <el-form-item prop="username">
+          <el-input
+            v-model="loginForm.username"
+            placeholder="璇疯緭鍏ヨ处鍙�"
+            size="large"
+            prefix-icon="User"
+          />
+        </el-form-item>
+        <el-form-item prop="password">
+          <el-input
+            v-model="loginForm.password"
+            type="password"
+            placeholder="璇疯緭鍏ュ瘑鐮�"
+            size="large"
+            prefix-icon="Lock"
+            show-password
+          />
+        </el-form-item>
+        <el-form-item prop="verificationCode">
+          <el-input
+            v-model="loginForm.verificationCode"
+            placeholder="璇疯緭鍏ラ獙璇佺爜"
+            size="large"
+            prefix-icon="CircleCheck"
+            style="width: 60%"
+            @keyup.enter="handleLogin"
+          />
+          <div class="captcha-box" @click="loadCaptcha">
+            <img v-if="captchaImg" :src="captchaImg" alt="楠岃瘉鐮�" />
+            <span v-else class="captcha-placeholder">鐐瑰嚮鍒锋柊</span>
+          </div>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" size="large" style="width: 100%" :loading="loading" @click="handleLogin">
+            {{ loading ? '鐧诲綍涓�...' : '鐧� 褰�' }}
+          </el-button>
+        </el-form-item>
+      </el-form>
+
+      <div class="login-footer">
+        <span>婕旂ず璐﹀彿锛歛dmin666 &nbsp;&nbsp; 瀵嗙爜锛�123456</span>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted } from 'vue';
+import { useRouter } from 'vue-router';
+import { ElMessage } from 'element-plus';
+import { User, Lock, CircleCheck } from '@element-plus/icons-vue';
+import { userApi } from '@/api/modules/user';
+import { useUserStore } from '@/store';
+
+const router = useRouter();
+const userStore = useUserStore();
+const loginFormRef = ref();
+const loading = ref(false);
+const captchaImg = ref('');
+const uuid = ref('');
+
+const loginForm = reactive({
+  username: 'admin',
+  password: '123456',
+  verificationCode: '',
+});
+
+const loginRules = {
+  username: [{ required: true, message: '璇疯緭鍏ヨ处鍙�', trigger: 'blur' }],
+  password: [{ required: true, message: '璇疯緭鍏ュ瘑鐮�', trigger: 'blur' }],
+  verificationCode: [{ required: true, message: '璇疯緭鍏ラ獙璇佺爜', trigger: 'blur' }],
+};
+
+async function loadCaptcha() {
+  try {
+    const res = await userApi.getCaptcha();
+    if (res?.img) {
+      captchaImg.value = `data:image/png;base64,${res.img}`;
+      uuid.value = res.uuid;
+    }
+  } catch {
+    ElMessage.error('鑾峰彇楠岃瘉鐮佸け璐�');
+  }
+}
+
+async function handleLogin() {
+  if (!loginFormRef.value) return;
+  await loginFormRef.value.validate(async (valid) => {
+    if (!valid) return;
+    loading.value = true;
+    try {
+      const res = await userApi.login({
+        userName: loginForm.username,
+        password: loginForm.password,
+        verificationCode: loginForm.verificationCode,
+        UUID: uuid.value,
+      });
+      if (res?.status === false) {
+        ElMessage.error(res.message || '鐧诲綍澶辫触');
+        loadCaptcha();
+        return;
+      }
+      const userData = res.data || res;
+      userStore.setUserInfo({
+        token: userData.token || userData.access_token || '',
+        userName: userData.userName || loginForm.username,
+        userTrueName: userData.userTrueName || userData.name || '',
+        img: userData.img || '',
+      });
+      ElMessage.success('鐧诲綍鎴愬姛');
+      router.push('/');
+    } catch {
+      ElMessage.error('鐧诲綍寮傚父');
+      loadCaptcha();
+    } finally {
+      loading.value = false;
+    }
+  });
+}
+
+onMounted(() => {
+  loadCaptcha();
+});
+</script>
+
+<style scoped>
+.login-container {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-height: 100vh;
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+}
+.login-box {
+  width: 420px;
+  padding: 40px;
+  background: #fff;
+  border-radius: 12px;
+  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
+}
+.login-header {
+  text-align: center;
+  margin-bottom: 30px;
+}
+.login-header h2 {
+  margin: 0 0 8px;
+  font-size: 28px;
+  color: #333;
+  font-weight: 600;
+}
+.login-header p {
+  margin: 0;
+  font-size: 14px;
+  color: #999;
+}
+.login-form {
+  margin-top: 20px;
+}
+.captcha-box {
+  width: 38%;
+  height: 40px;
+  margin-left: 10px;
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+  overflow: hidden;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  background: #f5f7fa;
+}
+.captcha-box img {
+  width: 100%;
+  height: 100%;
+  object-fit: fill;
+}
+.captcha-placeholder {
+  font-size: 12px;
+  color: #999;
+}
+.login-footer {
+  margin-top: 20px;
+  text-align: center;
+  font-size: 12px;
+  color: #999;
+}
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/views/outbound/index.vue b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/outbound/index.vue
new file mode 100644
index 0000000..5d5a1f9
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/outbound/index.vue
@@ -0,0 +1,267 @@
+<template>
+  <div class="outbound-page">
+    <!-- 鎼滅储 -->
+    <el-card class="search-card" shadow="never">
+      <el-form :inline="true" :model="queryForm" label-width="90px">
+        <el-form-item label="鍗曟嵁缂栧彿">
+          <el-input v-model="queryForm.orderNo" placeholder="璇疯緭鍏ュ崟鎹紪鍙�" clearable style="width: 170px" />
+        </el-form-item>
+        <el-form-item label="涓婃父鍗曟嵁">
+          <el-input v-model="queryForm.upperOrderNo" placeholder="璇疯緭鍏ヤ笂娓稿崟鎹紪鍙�" clearable style="width: 170px" />
+        </el-form-item>
+        <el-form-item label="鍗曟嵁绫诲瀷">
+          <el-select v-model="queryForm.orderType" placeholder="璇烽�夋嫨" clearable style="width: 150px">
+            <el-option v-for="item in orderTypeOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍗曟嵁鐘舵��">
+          <el-select v-model="queryForm.orderStatus" placeholder="璇烽�夋嫨" clearable style="width: 140px">
+            <el-option v-for="item in orderStatusOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍒涘缓鏃堕棿">
+          <el-date-picker v-model="queryForm.createDate" type="daterange" range-separator="鑷�" start-placeholder="寮�濮�" end-placeholder="缁撴潫" value-format="YYYY-MM-DD" />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鏌ヨ</el-button>
+          <el-button @click="handleReset">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 琛ㄦ牸 -->
+    <el-card class="table-card" shadow="never">
+      <div class="toolbar">
+        <el-button type="primary" @click="handleAdd">鏂板</el-button>
+        <el-button type="danger" :disabled="!selectedRows.length" @click="handleBatchDelete">鎵归噺鍒犻櫎</el-button>
+      </div>
+
+      <el-table v-loading="loading" :data="tableData" border stripe @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="50" align="center" />
+        <el-table-column prop="orderNo" label="鍗曟嵁缂栧彿" min-width="160" show-overflow-tooltip />
+        <el-table-column prop="upperOrderNo" label="涓婃父鍗曟嵁缂栧彿" min-width="160" show-overflow-tooltip />
+        <el-table-column prop="warehouseId" label="浠撳簱" min-width="100" align="center">
+          <template #default="{ row }">
+            {{ getWarehouseText(row.warehouseId) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="orderType" label="鍗曟嵁绫诲瀷" min-width="150" align="center">
+          <template #default="{ row }">
+            {{ getOrderTypeText(row.orderType) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="orderStatus" label="鍗曟嵁鐘舵��" min-width="100" align="center">
+          <template #default="{ row }">
+            {{ getOrderStatusText(row.orderStatus) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="createType" label="鍒涘缓鏂瑰紡" min-width="110" align="center">
+          <template #default="{ row }">
+            {{ getCreateTypeText(row.createType) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="departmentName" label="閮ㄩ棬鍚嶇О" min-width="160" show-overflow-tooltip />
+        <el-table-column prop="creater" label="鍒涘缓浜�" min-width="90" align="center" />
+        <el-table-column prop="createDate" label="鍒涘缓鏃堕棿" min-width="160" align="center" />
+        <el-table-column label="鎿嶄綔" width="180" align="center" fixed="right">
+          <template #default="{ row }">
+            <el-button link type="primary" size="small" @click="goDetail(row)">鏄庣粏</el-button>
+            <el-button link type="primary" size="small" @click="handleEdit(row)">缂栬緫</el-button>
+            <el-button link type="danger" size="small" @click="handleDelete(row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <el-pagination
+        v-model:current-page="pagination.page"
+        v-model:page-size="pagination.pageSize"
+        :total="pagination.total"
+        :page-sizes="[10, 20, 50, 100]"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handlePageChange"
+        style="margin-top: 16px; justify-content: flex-end"
+      />
+    </el-card>
+
+    <!-- 鏄庣粏鎶藉眽 -->
+    <el-drawer v-model="detailDrawerVisible" title="鍑哄簱鍗曟槑缁�" size="70%" direction="rtl" destroy-on-close>
+      <el-table :data="detailTableData" border stripe max-height="600">
+        <el-table-column prop="materielCode" label="鐗╂枡缂栧彿" min-width="150" show-overflow-tooltip />
+        <el-table-column prop="materielName" label="鐗╂枡鍚嶇О" min-width="150" show-overflow-tooltip />
+        <el-table-column prop="batchNo" label="鎵规鍙�" min-width="120" align="center" />
+        <el-table-column prop="orderQuantity" label="鍗曟嵁鏁伴噺" min-width="100" align="center" />
+        <el-table-column prop="rowNo" label="琛屽彿" min-width="80" align="center" />
+        <el-table-column prop="lockQuantity" label="閿佸畾鏁伴噺" min-width="120" align="center" />
+        <el-table-column prop="overOutQuantity" label="宸插嚭鏁伴噺" min-width="120" align="center" />
+        <el-table-column prop="orderDetailStatus" label="鏄庣粏鐘舵��" min-width="110" align="center">
+          <template #default="{ row }">
+            {{ getDetailStatusText(row.orderDetailStatus) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="creater" label="鍒涘缓浜�" min-width="90" align="center" />
+        <el-table-column prop="createDate" label="鍒涘缓鏃堕棿" min-width="160" align="center" />
+      </el-table>
+    </el-drawer>
+
+    <!-- 缂栬緫寮圭獥 -->
+    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="560px" destroy-on-close>
+      <el-form :model="editForm" :rules="editRules" ref="editFormRef" label-width="100px">
+        <el-form-item label="鍗曟嵁绫诲瀷" prop="orderType">
+          <el-select v-model="editForm.orderType" placeholder="璇烽�夋嫨鍗曟嵁绫诲瀷" style="width: 100%">
+            <el-option v-for="item in orderTypeOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍗曟嵁缂栧彿" prop="orderNo">
+          <el-input v-model="editForm.orderNo" placeholder="璇疯緭鍏ュ崟鎹紪鍙�" readonly />
+        </el-form-item>
+        <el-form-item label="涓婃父鍗曟嵁">
+          <el-input v-model="editForm.upperOrderNo" placeholder="璇疯緭鍏ヤ笂娓稿崟鎹紪鍙�" />
+        </el-form-item>
+        <el-form-item label="浠撳簱" prop="warehouseId">
+          <el-select v-model="editForm.warehouseId" placeholder="璇烽�夋嫨浠撳簱" style="width: 100%">
+            <el-option v-for="item in warehouseOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="澶囨敞">
+          <el-input v-model="editForm.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="submitLoading">纭畾</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { useRouter } from 'vue-router';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import { outboundApi } from '@/api/modules/outbound';
+import { client } from '@/api/client';
+
+const router = useRouter();
+
+const queryForm = reactive({ orderNo: '', upperOrderNo: '', orderType: undefined, orderStatus: undefined, createDate: '' });
+const loading = ref(false);
+const tableData = ref([]);
+const selectedRows = ref([]);
+
+const orderTypeOptions = ref([]);
+const orderStatusOptions = ref([]);
+const warehouseOptions = ref([]);
+const createTypeOptions = ref([]);
+const detailStatusOptions = ref([]);
+
+const pagination = reactive({ page: 1, pageSize: 20, total: 0 });
+
+const detailDrawerVisible = ref(false);
+const detailTableData = ref([]);
+
+const dialogVisible = ref(false);
+const dialogTitle = ref('鏂板鍑哄簱鍗�');
+const editFormRef = ref(null);
+const submitLoading = ref(false);
+const editForm = reactive({ id: undefined, orderType: undefined, orderNo: '', upperOrderNo: '', warehouseId: undefined, remark: '' });
+const editRules = {
+  orderType: [{ required: true, message: '璇烽�夋嫨鍗曟嵁绫诲瀷', trigger: 'change' }],
+  orderNo: [{ required: true, message: '璇疯緭鍏ュ崟鎹紪鍙�', trigger: 'blur' }],
+  warehouseId: [{ required: true, message: '璇烽�夋嫨浠撳簱', trigger: 'change' }],
+};
+
+async function loadData() {
+  loading.value = true;
+  try {
+    const wheres = [
+      queryForm.orderNo ? { name: 'orderNo', value: queryForm.orderNo, displayType: 'like' } : null,
+      queryForm.upperOrderNo ? { name: 'upperOrderNo', value: queryForm.upperOrderNo, displayType: 'like' } : null,
+      queryForm.orderType !== undefined ? { name: 'orderType', value: queryForm.orderType, displayType: 'int' } : null,
+      queryForm.orderStatus !== undefined ? { name: 'orderStatus', value: queryForm.orderStatus, displayType: 'int' } : null,
+    ].filter(Boolean);
+    const res = await outboundApi.getPageList({ page: pagination.page, rows: pagination.pageSize, sort: 'id', order: 'desc', wheres: JSON.stringify(wheres) });
+    tableData.value = res?.rows || [];
+    pagination.total = res?.total || 0;
+  } catch { ElMessage.error('鍔犺浇鏁版嵁澶辫触'); }
+  finally { loading.value = false; }
+}
+
+async function loadDetail(row) {
+  try {
+    const res = await client.post('/api/OutboundOrderDetail/getPageList', {
+      page: 1, rows: 200, sort: 'id', order: 'asc',
+      wheres: JSON.stringify([{ name: 'orderId', value: row.id, displayType: 'int' }]),
+    });
+    detailTableData.value = res?.rows || [];
+  } catch { detailTableData.value = []; ElMessage.error('鍔犺浇鏄庣粏澶辫触'); }
+}
+
+async function loadDictionary() {
+  try {
+    const res = await client.post('/api/Sys_Dictionary/GetVueDictionary', ['outOrderType', 'outboundStatusEnum', 'warehouses', 'createType', 'orderDetailStatusEnum']);
+    const findData = (dicNo) => res?.find(item => item.dicNo === dicNo)?.data || [];
+    orderTypeOptions.value = findData('outOrderType');
+    orderStatusOptions.value = findData('outboundStatusEnum');
+    warehouseOptions.value = findData('warehouses');
+    createTypeOptions.value = findData('createType');
+    detailStatusOptions.value = findData('orderDetailStatusEnum');
+  } catch { orderTypeOptions.value = []; orderStatusOptions.value = []; warehouseOptions.value = []; }
+}
+
+function goDetail(row) { router.push({ path: '/outbound/outboundOrderDetail', query: { id: row.id, orderNo: row.orderNo } }); }
+
+function handleSearch() { pagination.page = 1; loadData(); }
+function handleReset() { queryForm.orderNo = ''; queryForm.upperOrderNo = ''; queryForm.orderType = undefined; queryForm.orderStatus = undefined; queryForm.createDate = ''; handleSearch(); }
+
+function handleAdd() {
+  editForm.id = undefined; editForm.orderType = undefined; editForm.orderNo = ''; editForm.upperOrderNo = ''; editForm.warehouseId = undefined; editForm.remark = '';
+  dialogTitle.value = '鏂板鍑哄簱鍗�'; dialogVisible.value = true;
+}
+
+function handleEdit(row) {
+  Object.assign(editForm, { id: row.id, orderType: row.orderType, orderNo: row.orderNo, upperOrderNo: row.upperOrderNo, warehouseId: row.warehouseId, remark: row.remark });
+  dialogTitle.value = '缂栬緫鍑哄簱鍗�'; dialogVisible.value = true;
+}
+
+async function handleSubmit() {
+  await editFormRef.value.validate();
+  submitLoading.value = true;
+  try {
+    if (editForm.id) { await outboundApi.update(editForm); ElMessage.success('鏇存柊鎴愬姛'); }
+    else { await outboundApi.add(editForm); ElMessage.success('鏂板鎴愬姛'); }
+    dialogVisible.value = false; loadData();
+  } catch { ElMessage.error('鎿嶄綔澶辫触'); }
+  finally { submitLoading.value = false; }
+}
+
+function handleDelete(row) {
+  ElMessageBox.confirm(`纭畾鍒犻櫎鍑哄簱鍗曘��${row.orderNo}銆嶅悧锛焋, '鎻愮ず', { type: 'warning' })
+    .then(async () => { await outboundApi.deleteById(row.id); ElMessage.success('鍒犻櫎鎴愬姛'); loadData(); }).catch(() => {});
+}
+
+function handleBatchDelete() {
+  const ids = selectedRows.value.map(r => r.id);
+  ElMessageBox.confirm(`纭畾鍒犻櫎閫変腑鐨� ${ids.length} 鏉¤褰曞悧锛焋, '鎻愮ず', { type: 'warning' })
+    .then(async () => { await Promise.all(ids.map(id => outboundApi.deleteById(id))); ElMessage.success('鍒犻櫎鎴愬姛'); loadData(); }).catch(() => {});
+}
+
+function handleSelectionChange(rows) { selectedRows.value = rows; }
+function handleSizeChange() { loadData(); }
+function handlePageChange() { loadData(); }
+
+const getWarehouseText = (val) => warehouseOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+const getOrderTypeText = (val) => orderTypeOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+const getOrderStatusText = (val) => orderStatusOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+const getCreateTypeText = (val) => createTypeOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+const getDetailStatusText = (val) => detailStatusOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+
+onMounted(() => { loadDictionary(); loadData(); });
+</script>
+
+<style scoped>
+.outbound-page { padding: 16px; }
+.search-card { margin-bottom: 12px; }
+.table-card { margin-bottom: 12px; }
+.toolbar { margin-bottom: 12px; }
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/views/outbound/outboundOrderDetail.vue b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/outbound/outboundOrderDetail.vue
new file mode 100644
index 0000000..5c34d7d
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/outbound/outboundOrderDetail.vue
@@ -0,0 +1,106 @@
+<template>
+  <div class="outbound-detail-page">
+    <el-card shadow="never">
+      <template #header>
+        <span>鍑哄簱鍗曟槑缁� - {{ route.query.orderNo || '' }}</span>
+      </template>
+
+      <el-form :inline="true" :model="queryForm" class="search-form">
+        <el-form-item label="鐗╂枡缂栧彿">
+          <el-input v-model="queryForm.materielCode" placeholder="璇疯緭鍏ョ墿鏂欑紪鍙�" clearable />
+        </el-form-item>
+        <el-form-item label="鐗╂枡鍚嶇О">
+          <el-input v-model="queryForm.materielName" placeholder="璇疯緭鍏ョ墿鏂欏悕绉�" clearable />
+        </el-form-item>
+        <el-form-item label="鎵规鍙�">
+          <el-input v-model="queryForm.batchNo" placeholder="璇疯緭鍏ユ壒娆″彿" clearable />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鏌ヨ</el-button>
+          <el-button @click="handleReset">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+
+      <el-table v-loading="loading" :data="tableData" border stripe>
+        <el-table-column prop="materielCode" label="鐗╂枡缂栧彿" min-width="150" show-overflow-tooltip />
+        <el-table-column prop="materielName" label="鐗╂枡鍚嶇О" min-width="160" show-overflow-tooltip />
+        <el-table-column prop="batchNo" label="鎵规鍙�" min-width="120" align="center" />
+        <el-table-column prop="orderQuantity" label="鍗曟嵁鏁伴噺" min-width="100" align="center" />
+        <el-table-column prop="rowNo" label="琛屽彿" min-width="80" align="center" />
+        <el-table-column prop="lockQuantity" label="閿佸畾鏁伴噺" min-width="120" align="center" />
+        <el-table-column prop="overOutQuantity" label="宸插嚭鏁伴噺" min-width="120" align="center" />
+        <el-table-column prop="orderDetailStatus" label="鏄庣粏鐘舵��" min-width="110" align="center">
+          <template #default="{ row }">
+            {{ getDetailStatusText(row.orderDetailStatus) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="creater" label="鍒涘缓浜�" min-width="90" align="center" />
+        <el-table-column prop="createDate" label="鍒涘缓鏃堕棿" min-width="160" align="center" />
+      </el-table>
+
+      <el-pagination
+        v-model:current-page="pagination.page"
+        v-model:page-size="pagination.pageSize"
+        :total="pagination.total"
+        :page-sizes="[10, 20, 50, 100]"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handlePageChange"
+        style="margin-top: 16px; justify-content: flex-end"
+      />
+    </el-card>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { useRoute } from 'vue-router';
+import { ElMessage } from 'element-plus';
+import { client } from '@/api/client';
+
+const route = useRoute();
+const loading = ref(false);
+const tableData = ref([]);
+const detailStatusOptions = ref([]);
+
+const queryForm = reactive({ materielCode: '', materielName: '', batchNo: '' });
+const pagination = reactive({ page: 1, pageSize: 20, total: 0 });
+
+async function loadData() {
+  loading.value = true;
+  try {
+    const orderId = route.query.id;
+    const wheres = [{ name: 'orderId', value: String(orderId), displayType: 'int' }];
+    if (queryForm.materielCode) wheres.push({ name: 'materielCode', value: queryForm.materielCode, displayType: 'like' });
+    if (queryForm.materielName) wheres.push({ name: 'materielName', value: queryForm.materielName, displayType: 'like' });
+    if (queryForm.batchNo) wheres.push({ name: 'batchNo', value: queryForm.batchNo, displayType: 'like' });
+    const res = await client.post('/api/OutboundOrderDetail/getPageList', {
+      page: pagination.page, rows: pagination.pageSize, sort: 'id', order: 'asc',
+      wheres: JSON.stringify(wheres),
+    });
+    tableData.value = res?.rows || [];
+    pagination.total = res?.total || 0;
+  } catch { ElMessage.error('鍔犺浇鏁版嵁澶辫触'); }
+  finally { loading.value = false; }
+}
+
+async function loadDictionary() {
+  try {
+    const res = await client.post('/api/Sys_Dictionary/GetVueDictionary', ['orderDetailStatusEnum']);
+    detailStatusOptions.value = res?.find(item => item.dicNo === 'orderDetailStatusEnum')?.data || [];
+  } catch { detailStatusOptions.value = []; }
+}
+
+function handleSearch() { pagination.page = 1; loadData(); }
+function handleReset() { queryForm.materielCode = ''; queryForm.materielName = ''; queryForm.batchNo = ''; handleSearch(); }
+function handleSizeChange() { loadData(); }
+function handlePageChange() { loadData(); }
+const getDetailStatusText = (val) => detailStatusOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+
+onMounted(() => { loadDictionary(); loadData(); });
+</script>
+
+<style scoped>
+.outbound-detail-page { padding: 16px; }
+.search-form { margin-bottom: 12px; }
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/views/stock/index.vue b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/stock/index.vue
new file mode 100644
index 0000000..8359717
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/stock/index.vue
@@ -0,0 +1,340 @@
+<template>
+  <div class="stock-page">
+    <!-- 鎼滅储鍖哄煙 -->
+    <el-card class="search-card" shadow="never">
+      <el-form :inline="true" :model="queryForm" label-width="80px">
+        <el-form-item label="鎵樼洏缂栧彿">
+          <el-input v-model="queryForm.palletCode" placeholder="璇疯緭鍏ユ墭鐩樼紪鍙�" clearable style="width: 180px" />
+        </el-form-item>
+        <el-form-item label="璐т綅缂栧彿">
+          <el-input v-model="queryForm.locationCode" placeholder="璇疯緭鍏ヨ揣浣嶇紪鍙�" clearable style="width: 180px" />
+        </el-form-item>
+        <el-form-item label="浠撳簱">
+          <el-select v-model="queryForm.warehouseId" placeholder="璇烽�夋嫨浠撳簱" clearable style="width: 160px">
+            <el-option v-for="item in warehouseOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="搴撳瓨鐘舵��">
+          <el-select v-model="queryForm.stockStatus" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 140px">
+            <el-option v-for="item in stockStatusOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鏌ヨ</el-button>
+          <el-button @click="handleReset">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 鏁版嵁琛ㄦ牸 -->
+    <el-card class="table-card" shadow="never">
+      <div class="toolbar">
+        <el-button type="primary" @click="handleAdd">鏂板</el-button>
+        <el-button type="danger" :disabled="!selectedRows.length" @click="handleBatchDelete">鎵归噺鍒犻櫎</el-button>
+      </div>
+
+      <el-table
+        v-loading="loading"
+        :data="tableData"
+        border
+        stripe
+        @selection-change="handleSelectionChange"
+        @expand-change="handleExpandChange"
+        :expand-row-keys="expandedRows"
+        row-key="id"
+      >
+        <el-table-column type="selection" width="50" align="center" />
+        <el-table-column type="expand" width="50">
+          <template #default="{ row }">
+            <div class="expand-panel">
+              <div class="expand-header">
+                <span class="expand-title">搴撳瓨鏄庣粏</span>
+                <span class="expand-subtitle">鎵樼洏锛歿{ row.palletCode }} / 璐т綅锛歿{ row.locationCode }}</span>
+              </div>
+              <el-table :data="detailData[row.id] || []" border stripe size="small" max-height="400">
+                <el-table-column prop="materielName" label="鐗╂枡鍚嶇О" min-width="160" show-overflow-tooltip />
+                <el-table-column prop="serialNumber" label="鐢佃姱鐮�" min-width="160" show-overflow-tooltip />
+                <el-table-column prop="stockQuantity" label="搴撳瓨鏁伴噺" min-width="120" align="center" />
+                <el-table-column prop="status" label="鐘舵��" min-width="120" align="center">
+                  <template #default="{ row: dr }">
+                    {{ getStatusText(dr.status) }}
+                  </template>
+                </el-table-column>
+                <el-table-column prop="inboundOrderRowNo" label="閫氶亾鍙�" min-width="120" align="center" />
+              </el-table>
+              <div v-if="!detailData[row.id] && !detailLoading[row.id]" class="expand-empty">鏆傛棤鏄庣粏鏁版嵁</div>
+              <div v-if="detailLoading[row.id]" class="expand-loading">鍔犺浇涓�...</div>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="palletCode" label="鎵樼洏缂栧彿" min-width="130" show-overflow-tooltip />
+        <el-table-column prop="locationCode" label="璐т綅缂栧彿" min-width="150" show-overflow-tooltip />
+        <el-table-column prop="warehouseId" label="浠撳簱" min-width="110" align="center">
+          <template #default="{ row }">
+            {{ getWarehouseText(row.warehouseId) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="stockStatus" label="搴撳瓨鐘舵��" min-width="120" align="center">
+          <template #default="{ row }">
+            {{ getStockStatusText(row.stockStatus) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="outboundDate" label="鍑哄簱鏃ユ湡" min-width="160" align="center" />
+        <el-table-column prop="creater" label="鍒涘缓浜�" min-width="100" align="center" />
+        <el-table-column prop="createDate" label="鍒涘缓鏃堕棿" min-width="160" align="center" />
+        <el-table-column label="鎿嶄綔" width="150" align="center" fixed="right">
+          <template #default="{ row }">
+            <el-button link type="primary" size="small" @click="handleEdit(row)">缂栬緫</el-button>
+            <el-button link type="danger" size="small" @click="handleDelete(row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <el-pagination
+        v-model:current-page="pagination.page"
+        v-model:page-size="pagination.pageSize"
+        :total="pagination.total"
+        :page-sizes="[10, 20, 50, 100]"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handlePageChange"
+        style="margin-top: 16px; justify-content: flex-end"
+      />
+    </el-card>
+
+    <!-- 缂栬緫寮圭獥 -->
+    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="560px" destroy-on-close>
+      <el-form :model="editForm" :rules="editRules" ref="editFormRef" label-width="100px">
+        <el-form-item label="鎵樼洏缂栧彿" prop="palletCode">
+          <el-input v-model="editForm.palletCode" placeholder="璇疯緭鍏ユ墭鐩樼紪鍙�" />
+        </el-form-item>
+        <el-form-item label="璐т綅缂栧彿" prop="locationCode">
+          <el-input v-model="editForm.locationCode" placeholder="璇疯緭鍏ヨ揣浣嶇紪鍙�" />
+        </el-form-item>
+        <el-form-item label="浠撳簱" prop="warehouseId">
+          <el-select v-model="editForm.warehouseId" placeholder="璇烽�夋嫨浠撳簱" style="width: 100%">
+            <el-option v-for="item in warehouseOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="搴撳瓨鐘舵��" prop="stockStatus">
+          <el-select v-model="editForm.stockStatus" placeholder="璇烽�夋嫨搴撳瓨鐘舵��" style="width: 100%">
+            <el-option v-for="item in stockStatusOptions" :key="item.key" :label="item.value" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="澶囨敞">
+          <el-input v-model="editForm.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="submitLoading">纭畾</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import { stockApi } from '@/api/modules/stock';
+import { client } from '@/api/client';
+
+const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:9291';
+
+// 鎼滅储
+const queryForm = reactive({
+  palletCode: '',
+  locationCode: '',
+  warehouseId: undefined,
+  stockStatus: undefined,
+});
+
+// 琛ㄦ牸
+const loading = ref(false);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const expandedRows = ref([]);
+const detailData = ref({});
+const detailLoading = ref({});
+
+// 瀛楀吀
+const warehouseOptions = ref([]);
+const stockStatusOptions = ref([]);
+
+// 鍒嗛〉
+const pagination = reactive({ page: 1, pageSize: 20, total: 0 });
+
+// 缂栬緫寮圭獥
+const dialogVisible = ref(false);
+const dialogTitle = ref('鏂板搴撳瓨');
+const editFormRef = ref(null);
+const submitLoading = ref(false);
+const editForm = reactive({
+  id: undefined,
+  palletCode: '',
+  locationCode: '',
+  warehouseId: undefined,
+  stockStatus: undefined,
+  remark: '',
+});
+const editRules = {
+  palletCode: [{ required: true, message: '璇疯緭鍏ユ墭鐩樼紪鍙�', trigger: 'blur' }],
+  locationCode: [{ required: true, message: '璇疯緭鍏ヨ揣浣嶇紪鍙�', trigger: 'blur' }],
+  warehouseId: [{ required: true, message: '璇烽�夋嫨浠撳簱', trigger: 'change' }],
+};
+
+async function loadData() {
+  loading.value = true;
+  try {
+    const params = buildQueryParams();
+    const res = await stockApi.getPageList(params);
+    tableData.value = res?.rows || [];
+    pagination.total = res?.total || 0;
+  } catch {
+    ElMessage.error('鍔犺浇鏁版嵁澶辫触');
+  } finally {
+    loading.value = false;
+  }
+}
+
+function buildQueryParams() {
+  const wheres = [
+    queryForm.palletCode ? { name: 'palletCode', value: queryForm.palletCode, displayType: 'like' } : null,
+    queryForm.locationCode ? { name: 'locationCode', value: queryForm.locationCode, displayType: 'like' } : null,
+    queryForm.warehouseId ? { name: 'warehouseId', value: queryForm.warehouseId, displayType: 'int' } : null,
+    queryForm.stockStatus !== undefined ? { name: 'stockStatus', value: queryForm.stockStatus, displayType: 'int' } : null,
+  ].filter(Boolean);
+  return {
+    page: pagination.page,
+    rows: pagination.pageSize,
+    sort: 'id',
+    order: 'desc',
+    wheres: JSON.stringify(wheres),
+  };
+}
+
+async function loadDetailData(row) {
+  if (detailData.value[row.id] || detailLoading.value[row.id]) return;
+  detailLoading.value[row.id] = true;
+  try {
+    const res = await client.post('/api/StockInfoDetail/getPageData', {
+      page: 1, rows: 200, sort: 'id', order: 'asc',
+      wheres: JSON.stringify([{ name: 'stockId', value: String(row.id), displayType: 'int' }]),
+    });
+    detailData.value[row.id] = res?.rows || [];
+  } catch {
+    detailData.value[row.id] = [];
+    ElMessage.error('鍔犺浇鏄庣粏澶辫触');
+  } finally {
+    detailLoading.value[row.id] = false;
+  }
+}
+
+async function loadDictionary() {
+  try {
+    const res = await client.post('/api/Sys_Dictionary/GetVueDictionary', ['warehouseEnum', 'stockStatusEmun']);
+    const wh = res?.find(item => item.dicNo === 'warehouseEnum');
+    warehouseOptions.value = wh?.data || [];
+    const ss = res?.find(item => item.dicNo === 'stockStatusEmun');
+    stockStatusOptions.value = ss?.data || [];
+  } catch {
+    warehouseOptions.value = [];
+    stockStatusOptions.value = [];
+  }
+}
+
+function handleSearch() { pagination.page = 1; loadData(); }
+
+function handleReset() {
+  queryForm.palletCode = '';
+  queryForm.locationCode = '';
+  queryForm.warehouseId = undefined;
+  queryForm.stockStatus = undefined;
+  handleSearch();
+}
+
+function handleAdd() {
+  editForm.id = undefined;
+  editForm.palletCode = '';
+  editForm.locationCode = '';
+  editForm.warehouseId = undefined;
+  editForm.stockStatus = undefined;
+  editForm.remark = '';
+  dialogTitle.value = '鏂板搴撳瓨';
+  dialogVisible.value = true;
+}
+
+function handleEdit(row) {
+  Object.assign(editForm, { id: row.id, palletCode: row.palletCode, locationCode: row.locationCode, warehouseId: row.warehouseId, stockStatus: row.stockStatus, remark: row.remark });
+  dialogTitle.value = '缂栬緫搴撳瓨';
+  dialogVisible.value = true;
+}
+
+async function handleSubmit() {
+  await editFormRef.value.validate();
+  submitLoading.value = true;
+  try {
+    if (editForm.id) {
+      await stockApi.updateStock(editForm);
+      ElMessage.success('鏇存柊鎴愬姛');
+    } else {
+      await stockApi.addStock(editForm);
+      ElMessage.success('鏂板鎴愬姛');
+    }
+    dialogVisible.value = false;
+    loadData();
+  } catch { ElMessage.error('鎿嶄綔澶辫触'); }
+  finally { submitLoading.value = false; }
+}
+
+function handleDelete(row) {
+  ElMessageBox.confirm(`纭畾鍒犻櫎搴撳瓨銆�${row.palletCode}銆嶅悧锛焋, '鎻愮ず', { type: 'warning' })
+    .then(async () => {
+      await stockApi.deleteStock(row.id);
+      ElMessage.success('鍒犻櫎鎴愬姛');
+      loadData();
+    }).catch(() => {});
+}
+
+function handleBatchDelete() {
+  const ids = selectedRows.value.map(r => r.id);
+  ElMessageBox.confirm(`纭畾鍒犻櫎閫変腑鐨� ${ids.length} 鏉¤褰曞悧锛焋, '鎻愮ず', { type: 'warning' })
+    .then(async () => {
+      await Promise.all(ids.map(id => stockApi.deleteStock(id)));
+      ElMessage.success('鍒犻櫎鎴愬姛');
+      loadData();
+    }).catch(() => {});
+}
+
+function handleSelectionChange(rows) { selectedRows.value = rows; }
+
+function handleExpandChange(row, expanded) {
+  if (expanded) {
+    expandedRows.value.push(row.id);
+    loadDetailData(row);
+  } else {
+    expandedRows.value = expandedRows.value.filter(id => id !== row.id);
+  }
+}
+
+function handleSizeChange() { loadData(); }
+function handlePageChange() { loadData(); }
+
+const getWarehouseText = (val) => warehouseOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+const getStockStatusText = (val) => stockStatusOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+const getStatusText = (val) => stockStatusOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+
+onMounted(() => { loadDictionary(); loadData(); });
+</script>
+
+<style scoped>
+.stock-page { padding: 16px; }
+.search-card { margin-bottom: 12px; }
+.table-card { margin-bottom: 12px; }
+.toolbar { margin-bottom: 12px; }
+.expand-panel { margin: 8px 16px 16px; padding: 12px; background: #fafafa; border-radius: 8px; }
+.expand-header { margin-bottom: 12px; }
+.expand-title { font-size: 15px; font-weight: 700; color: #303133; margin-right: 12px; }
+.expand-subtitle { font-size: 13px; color: #606266; }
+.expand-empty, .expand-loading { padding: 14px 12px; color: #909399; text-align: center; }
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/src/views/stock/stockInfoDetail.vue b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/stock/stockInfoDetail.vue
new file mode 100644
index 0000000..a4715bd
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/src/views/stock/stockInfoDetail.vue
@@ -0,0 +1,119 @@
+<template>
+  <div class="stock-detail-page">
+    <el-card shadow="never">
+      <template #header>
+        <span>搴撳瓨鏄庣粏 - {{ route.query.palletCode || '' }}</span>
+      </template>
+
+      <!-- 鎼滅储 -->
+      <el-form :inline="true" :model="queryForm" class="search-form">
+        <el-form-item label="鐗╂枡鍚嶇О">
+          <el-input v-model="queryForm.materielName" placeholder="璇疯緭鍏ョ墿鏂欏悕绉�" clearable />
+        </el-form-item>
+        <el-form-item label="鐢佃姱鐮�">
+          <el-input v-model="queryForm.serialNumber" placeholder="璇疯緭鍏ョ數鑺爜" clearable />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鏌ヨ</el-button>
+          <el-button @click="handleReset">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+
+      <!-- 琛ㄦ牸 -->
+      <el-table v-loading="loading" :data="tableData" border stripe>
+        <el-table-column prop="materielCode" label="鐗╂枡缂栫爜" min-width="140" show-overflow-tooltip />
+        <el-table-column prop="materielName" label="鐗╂枡鍚嶇О" min-width="160" show-overflow-tooltip />
+        <el-table-column prop="serialNumber" label="鐢佃姱鐮�" min-width="180" show-overflow-tooltip />
+        <el-table-column prop="stockQuantity" label="搴撳瓨鏁伴噺" min-width="120" align="center" />
+        <el-table-column prop="status" label="鐘舵��" min-width="120" align="center">
+          <template #default="{ row }">
+            {{ getStatusText(row.status) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="inboundOrderRowNo" label="閫氶亾鍙�" min-width="120" align="center" />
+        <el-table-column prop="creater" label="鍒涘缓浜�" min-width="100" align="center" />
+        <el-table-column prop="createDate" label="鍒涘缓鏃堕棿" min-width="160" align="center" />
+      </el-table>
+
+      <el-pagination
+        v-model:current-page="pagination.page"
+        v-model:page-size="pagination.pageSize"
+        :total="pagination.total"
+        :page-sizes="[10, 20, 50, 100]"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handlePageChange"
+        style="margin-top: 16px; justify-content: flex-end"
+      />
+    </el-card>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { useRoute } from 'vue-router';
+import { ElMessage } from 'element-plus';
+import { client } from '@/api/client';
+
+const route = useRoute();
+const loading = ref(false);
+const tableData = ref([]);
+const stockStatusOptions = ref([]);
+
+const queryForm = reactive({
+  materielName: '',
+  serialNumber: '',
+});
+
+const pagination = reactive({ page: 1, pageSize: 20, total: 0 });
+
+async function loadData() {
+  loading.value = true;
+  try {
+    const stockId = route.query.id;
+    const wheres = [{ name: 'stockId', value: String(stockId), displayType: 'int' }];
+    if (queryForm.materielName) wheres.push({ name: 'materielName', value: queryForm.materielName, displayType: 'like' });
+    if (queryForm.serialNumber) wheres.push({ name: 'serialNumber', value: queryForm.serialNumber, displayType: 'like' });
+    const res = await client.post('/api/StockInfoDetail/getPageData', {
+      page: pagination.page,
+      rows: pagination.pageSize,
+      sort: 'id',
+      order: 'asc',
+      wheres: JSON.stringify(wheres),
+    });
+    tableData.value = res?.rows || [];
+    pagination.total = res?.total || 0;
+  } catch {
+    ElMessage.error('鍔犺浇鏁版嵁澶辫触');
+  } finally {
+    loading.value = false;
+  }
+}
+
+async function loadDictionary() {
+  try {
+    const res = await client.post('/api/Sys_Dictionary/GetVueDictionary', ['stockStatusEmun']);
+    const ss = res?.find(item => item.dicNo === 'stockStatusEmun');
+    stockStatusOptions.value = ss?.data || [];
+  } catch {
+    stockStatusOptions.value = [];
+  }
+}
+
+function handleSearch() { pagination.page = 1; loadData(); }
+function handleReset() {
+  queryForm.materielName = '';
+  queryForm.serialNumber = '';
+  handleSearch();
+}
+function handleSizeChange() { loadData(); }
+function handlePageChange() { loadData(); }
+const getStatusText = (val) => stockStatusOptions.value.find(o => `${o.key}` === `${val}`)?.value || val || '-';
+
+onMounted(() => { loadDictionary(); loadData(); });
+</script>
+
+<style scoped>
+.stock-detail-page { padding: 16px; }
+.search-form { margin-bottom: 12px; }
+</style>
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/tsconfig.json b/Code/WMS/WIDESEA_WMSClient_Vben/tsconfig.json
new file mode 100644
index 0000000..db9261f
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/tsconfig.json
@@ -0,0 +1,21 @@
+{
+  "compilerOptions": {
+    "target": "ES2020",
+    "useDefineForClassFields": true,
+    "module": "ESNext",
+    "lib": ["ES2020", "DOM", "DOM.Iterable"],
+    "skipLibCheck": true,
+    "moduleResolution": "bundler",
+    "allowImportingTsExtensions": true,
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "noEmit": true,
+    "jsx": "preserve",
+    "strict": false,
+    "noUnusedLocals": false,
+    "noUnusedParameters": false,
+    "baseUrl": ".",
+    "paths": { "@/*": ["src/*"] }
+  },
+  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
+}
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/tsconfig.node.json b/Code/WMS/WIDESEA_WMSClient_Vben/tsconfig.node.json
new file mode 100644
index 0000000..97ede7e
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+  "compilerOptions": {
+    "composite": true,
+    "skipLibCheck": true,
+    "module": "ESNext",
+    "moduleResolution": "bundler",
+    "allowSyntheticDefaultImports": true,
+    "strict": true
+  },
+  "include": ["vite.config.ts"]
+}
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben/vite.config.ts b/Code/WMS/WIDESEA_WMSClient_Vben/vite.config.ts
new file mode 100644
index 0000000..626de4f
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben/vite.config.ts
@@ -0,0 +1,21 @@
+import { defineConfig } from 'vite';
+import vue from '@vitejs/plugin-vue';
+import { resolve } from 'path';
+
+export default defineConfig({
+  plugins: [vue()],
+  resolve: {
+    alias: {
+      '@': resolve(__dirname, 'src'),
+    },
+  },
+  server: {
+    port: 3000,
+    proxy: {
+      '/api': {
+        target: 'http://localhost:9291',
+        changeOrigin: true,
+      },
+    },
+  },
+});
diff --git a/Code/WMS/WIDESEA_WMSClient_Vben_v2 b/Code/WMS/WIDESEA_WMSClient_Vben_v2
new file mode 160000
index 0000000..07c4ad0
--- /dev/null
+++ b/Code/WMS/WIDESEA_WMSClient_Vben_v2
@@ -0,0 +1 @@
+Subproject commit 07c4ad05f40507d7d797619814bf75a47c29a9f4
diff --git a/Code/WMS/WMS_Api_Design.md b/Code/WMS/WMS_Api_Design.md
new file mode 100644
index 0000000..5f24b9d
--- /dev/null
+++ b/Code/WMS/WMS_Api_Design.md
@@ -0,0 +1,203 @@
+# WMS 鍓嶇 API 璁捐鏂囨。
+
+> 鏈枃妗d负 Vben Admin 鍓嶇椤圭洰锛圵IDESEA_WMSClient_Vben锛夋彁渚� API 閫傞厤灞傝璁″弬鑰冦��
+
+## 鐩綍缁撴瀯
+
+```
+WIDESEA_WMSClient_Vben/
+鈹溾攢鈹� src/
+鈹�   鈹溾攢鈹� api/
+鈹�   鈹�   鈹溾攢鈹� client.ts          # axios 瀹炰緥灏佽
+鈹�   鈹�   鈹溾攢鈹� modules/
+鈹�   鈹�   鈹�   鈹溾攢鈹� user.ts        # 鐢ㄦ埛璁よ瘉妯″潡
+鈹�   鈹�   鈹�   鈹溾攢鈹� menu.ts        # 鑿滃崟妯″潡
+鈹�   鈹�   鈹�   鈹溾攢鈹� stock.ts       # 搴撳瓨妯″潡
+鈹�   鈹�   鈹�   鈹溾攢鈹� inbound.ts      # 鍏ュ簱妯″潡
+鈹�   鈹�   鈹�   鈹溾攢鈹� outbound.ts    # 鍑哄簱妯″潡
+鈹�   鈹�   鈹�   鈹斺攢鈹� check.ts        # 鐩樼偣妯″潡
+鈹�   鈹�   鈹斺攢鈹� index.ts           # 缁熶竴瀵煎嚭
+```
+
+## 1. axios 瀹㈡埛绔皝瑁� (`api/client.ts`)
+
+```typescript
+import axios from 'axios';
+import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
+import { useUserStore } from '@/store/modules/user';
+import { useAuthStore } from '@/store/modules/auth';
+
+const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:9291';
+
+const client: AxiosInstance = axios.create({
+  baseURL: BASE_URL,
+  timeout: 30000,
+  headers: { 'Content-Type': 'application/json' },
+});
+
+// 璇锋眰鎷︽埅鍣細娉ㄥ叆 Bearer Token
+client.interceptors.request.use(
+  (config) => {
+    const userStore = useUserStore();
+    const token = userStore.token;
+    if (token) {
+      config.headers.Authorization = `Bearer ${token}`;
+    }
+    return config;
+  },
+  (error) => Promise.reject(error)
+);
+
+// 鍝嶅簲鎷︽埅鍣細缁熶竴閿欒澶勭悊 + 401 token 杩囨湡璺宠浆鐧诲綍
+client.interceptors.response.use(
+  (response: AxiosResponse) => response.data,
+  async (error) => {
+    const status = error.response?.status;
+    const raw = error.response?.data;
+
+    // 涓氬姟閿欒鐮侊紙闈� HTTP 鐘舵�佺爜锛夊彲浠� raw.code 鍒ゆ柇
+    if (raw?.code === 401 || status === 401) {
+      const authStore = useAuthStore();
+      authStore.logout(true); // true = token 杩囨湡琚姩鐧诲嚭
+    }
+
+    return Promise.reject(error);
+  }
+);
+
+export default client;
+```
+
+## 2. 璇锋眰鎷︽埅鍣ㄩ�昏緫
+
+| 鍦烘櫙 | 澶勭悊鏂瑰紡 |
+|------|---------|
+| 鏈� Token | `Authorization: Bearer <token>` 娉ㄥ叆璇锋眰澶� |
+| 鏃� Token | 鏀捐锛岃鍚庣杩斿洖 401 |
+| 涓诲姩鐧诲嚭 | 娓呯┖ token 璺宠浆鐧诲綍椤� |
+
+## 3. 鍝嶅簲鎷︽埅鍣ㄩ�昏緫
+
+| 鍦烘櫙 | 澶勭悊鏂瑰紡 |
+|------|---------|
+| 2xx 鍝嶅簲 | 杩斿洖 `response.data` |
+| HTTP 401 / 涓氬姟 code 401 | 璋冪敤 `authStore.logout(true)` 璺宠浆鐧诲綍 |
+| 鍏朵粬閿欒 | 鎶涘嚭寮傚父锛岀敱鍚勬ā鍧楄嚜琛屽鐞� |
+
+## 4. 鎺ュ彛绛惧悕
+
+### 4.1 鐢ㄦ埛妯″潡 (`modules/user.ts`)
+
+```typescript
+/** 鑾峰彇楠岃瘉鐮侊紝杩斿洖 { img: string, uuid: string } */
+export function getVerificationCode(): Promise<{ img: string; uuid: string }>;
+
+/** 鐧诲綍 */
+export function login(params: {
+  userName: string;
+  password: string;
+  verificationCode: string;
+  UUID: string;
+}): Promise<{ token: string; expires: number }>;
+
+/** 褰撳墠鐢ㄦ埛淇℃伅 */
+export function getCurrentUserInfo(): Promise<UserInfo>;
+
+/** 鍒锋柊 Token */
+export function replaceToken(): Promise<{ token: string; expires: number }>;
+```
+
+### 4.2 鑿滃崟妯″潡 (`modules/menu.ts`)
+
+```typescript
+/** 鑾峰彇鏍戝舰鑿滃崟 */
+export function getTreeMenu(): Promise<MenuTreeNode[]>;
+
+interface MenuTreeNode {
+  id: string;
+  name: string;
+  path: string;
+  component?: string;
+  icon?: string;
+  children?: MenuTreeNode[];
+}
+```
+
+### 4.3 搴撳瓨妯″潡 (`modules/stock.ts`)
+
+```typescript
+/** 搴撳瓨鍒楄〃锛堝垎椤碉級 */
+export function getStockList(params: StockQuery): Promise<PageResult<StockItem>>;
+
+/** 搴撳瓨璇︽儏 */
+export function getStockDetail(id: string): Promise<StockItem>;
+```
+
+### 4.4 鍏ュ簱妯″潡 (`modules/inbound.ts`)
+
+```typescript
+/** 鍏ュ簱鍗曞垪琛� */
+export function getInboundOrderList(params: InboundQuery): Promise<PageResult<InboundOrder>>;
+
+/** 鍒涘缓鍏ュ簱鍗� */
+export function createInboundOrder(data: CreateInboundOrder): Promise<{ id: string }>;
+
+/** 鎻愪氦鍏ュ簱鍗� */
+export function submitInboundOrder(id: string): Promise<void>;
+```
+
+### 4.5 鍑哄簱妯″潡 (`modules/outbound.ts`)
+
+```typescript
+/** 鍑哄簱鍗曞垪琛� */
+export function getOutboundOrderList(params: OutboundQuery): Promise<PageResult<OutboundOrder>>;
+
+/** 鍒涘缓鍑哄簱鍗� */
+export function createOutboundOrder(data: CreateOutboundOrder): Promise<{ id: string }>;
+
+/** 鎻愪氦鍑哄簱鍗� */
+export function submitOutboundOrder(id: string): Promise<void>;
+```
+
+### 4.6 鐩樼偣妯″潡 (`modules/check.ts`)
+
+```typescript
+/** 鐩樼偣鍗曞垪琛� */
+export function getCheckOrderList(params: CheckQuery): Promise<PageResult<CheckOrder>>;
+
+/** 鍒涘缓鐩樼偣鍗� */
+export function createCheckOrder(data: CreateCheckOrder): Promise<{ id: string }>;
+
+/** 鎻愪氦鐩樼偣鍗� */
+export function submitCheckOrder(id: string): Promise<void>;
+```
+
+## 5. 閫氱敤绫诲瀷瀹氫箟
+
+```typescript
+/** 鍒嗛〉缁撴灉 */
+interface PageResult<T> {
+  items: T[];
+  total: number;
+  page: number;
+  pageSize: number;
+}
+
+/** 閫氱敤鎿嶄綔缁撴灉锛堟棤鏁版嵁杩斿洖鏃讹級 */
+interface OpResult {
+  code: number;
+  message: string;
+}
+```
+
+## 6. 鐜鍙橀噺
+
+```env
+# .env.development
+VITE_API_BASE_URL=http://localhost:9291
+
+# .env.production
+VITE_API_BASE_URL=/api
+```
+
+> **娉ㄦ剰**: 鐢熶骇鐜浣跨敤 `/api` 浠g悊锛岄伩鍏嶈法鍩熴��

--
Gitblit v1.9.3