From c493779a8504fe1eb548c865ff268a7f7436ec01 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期四, 19 三月 2026 11:43:36 +0800
Subject: [PATCH] feat: 集成机械手客户端并重构模拟器前端工作台

---
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Controllers/RobotClientsController.cs |  126 ++
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs                                |    4 
 Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json                            |  146 --
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/router/index.ts                      |    5 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask.cs                         |    2 
 Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/v18/DocumentLayout.json                            |   24 
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue                 |   25 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs          |    2 
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/DetailsView.vue                |  251 +++--
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json                                       |   10 
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue                   |  380 ++++++--
 项目资料/设备协议/机械手协议/~$交互流程表(1).xlsx                                                                     |    0 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs                           |    5 
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Program.cs                            |    1 
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts                         |   42 
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/ProtocolTemplatesView.vue      |   20 
 Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs                                     |   11 
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/types/index.ts                       |   55 +
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_DTO/TaskInfo/WMSTaskDTO.cs                                    |    2 
 Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/v18/DocumentLayout.backup.json                     |   21 
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/RobotClientsView.vue           |  452 ++++++++++
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/EditView.vue                   |   44 
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Services/RobotClientManager.cs        |  588 +++++++++++++
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/App.vue                              |  201 +++-
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/style.css                            |  145 ++
 25 files changed, 2,012 insertions(+), 550 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Controllers/RobotClientsController.cs b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Controllers/RobotClientsController.cs
new file mode 100644
index 0000000..8192d03
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Controllers/RobotClientsController.cs
@@ -0,0 +1,126 @@
+锘縰sing Microsoft.AspNetCore.Mvc;
+using WIDESEAWCS_S7Simulator.Server.Services;
+
+namespace WIDESEAWCS_S7Simulator.Server.Controllers;
+
+/// <summary>
+/// 鏈烘鎵嬪鎴风绠$悊鎺ュ彛锛堜富鍔ㄨ繛鎺ユā寮忥級銆�
+/// </summary>
+[ApiController]
+[Route("api/[controller]")]
+public class RobotClientsController : ControllerBase
+{
+    private readonly IRobotClientManager _robotClientManager;
+    private readonly ILogger<RobotClientsController> _logger;
+
+    public RobotClientsController(IRobotClientManager robotClientManager, ILogger<RobotClientsController> logger)
+    {
+        _robotClientManager = robotClientManager;
+        _logger = logger;
+    }
+
+    [HttpGet("status")]
+    [ProducesResponseType(typeof(RobotServerCollectionStatusResponse), StatusCodes.Status200OK)]
+    public async Task<ActionResult<RobotServerCollectionStatusResponse>> GetStatus()
+    {
+        var status = await _robotClientManager.GetStatusAsync();
+        return Ok(status);
+    }
+
+    [HttpPost("start")]
+    [ProducesResponseType(typeof(RobotServerCollectionStatusResponse), StatusCodes.Status200OK)]
+    [ProducesResponseType(StatusCodes.Status400BadRequest)]
+    public async Task<ActionResult<RobotServerCollectionStatusResponse>> Start([FromBody] RobotServerStartRequest request)
+    {
+        try
+        {
+            var status = await _robotClientManager.StartAsync(request, HttpContext.RequestAborted);
+            return Ok(status);
+        }
+        catch (ArgumentException ex)
+        {
+            return BadRequest(new { error = ex.Message });
+        }
+        catch (Exception ex)
+        {
+            _logger.LogError(ex, "鍚姩鏈烘鎵嬪鎴风瀹炰緥澶辫触");
+            return StatusCode(StatusCodes.Status500InternalServerError, new { error = "鍚姩鏈烘鎵嬪鎴风瀹炰緥澶辫触" });
+        }
+    }
+
+    [HttpPost("stop")]
+    [ProducesResponseType(StatusCodes.Status200OK)]
+    public async Task<ActionResult> Stop([FromQuery] string? serverId = null)
+    {
+        await _robotClientManager.StopAsync(serverId);
+        return Ok(new { message = string.IsNullOrWhiteSpace(serverId) ? "鏈烘鎵嬪鎴风宸插叏閮ㄥ仠姝�" : $"鏈烘鎵嬪鎴风 {serverId} 宸插仠姝�" });
+    }
+
+    [HttpPost("send")]
+    [ProducesResponseType(StatusCodes.Status200OK)]
+    [ProducesResponseType(StatusCodes.Status400BadRequest)]
+    public async Task<ActionResult> Send([FromBody] RobotServerSendRequest request)
+    {
+        if (string.IsNullOrWhiteSpace(request.Message))
+        {
+            return BadRequest(new { error = "鍙戦�佸唴瀹逛笉鑳戒负绌�" });
+        }
+
+        try
+        {
+            if (string.IsNullOrWhiteSpace(request.ServerId))
+            {
+                return BadRequest(new { error = "ServerId 涓嶈兘涓虹┖" });
+            }
+
+            if (request.ClientId.HasValue)
+            {
+                await _robotClientManager.SendToClientAsync(request.ServerId, request.ClientId.Value, request.Message);
+            }
+            else
+            {
+                await _robotClientManager.SendToAllAsync(request.ServerId, request.Message);
+            }
+
+            return Ok(new { message = "鍙戦�佹垚鍔�" });
+        }
+        catch (InvalidOperationException ex)
+        {
+            return BadRequest(new { error = ex.Message });
+        }
+        catch (Exception ex)
+        {
+            _logger.LogError(ex, "鍙戦�佹満姊版墜瀹㈡埛绔秷鎭け璐�");
+            return StatusCode(StatusCodes.Status500InternalServerError, new { error = "鍙戦�佹満姊版墜瀹㈡埛绔秷鎭け璐�" });
+        }
+    }
+
+    /// <summary>
+    /// 娓呯┖鎸囧畾瀹㈡埛绔疄渚嬬殑娑堟伅鏃ュ織銆�
+    /// </summary>
+    [HttpPost("clear-received")]
+    [ProducesResponseType(StatusCodes.Status200OK)]
+    [ProducesResponseType(StatusCodes.Status400BadRequest)]
+    public async Task<ActionResult> ClearReceived([FromQuery] string serverId)
+    {
+        if (string.IsNullOrWhiteSpace(serverId))
+        {
+            return BadRequest(new { error = "ServerId 涓嶈兘涓虹┖" });
+        }
+
+        try
+        {
+            await _robotClientManager.ClearReceivedMessagesAsync(serverId);
+            return Ok(new { message = $"瀹炰緥 {serverId} 鐨勬帴鏀舵秷鎭凡娓呯┖" });
+        }
+        catch (InvalidOperationException ex)
+        {
+            return BadRequest(new { error = ex.Message });
+        }
+        catch (Exception ex)
+        {
+            _logger.LogError(ex, "娓呯┖鎺ユ敹娑堟伅澶辫触");
+            return StatusCode(StatusCodes.Status500InternalServerError, new { error = "娓呯┖鎺ユ敹娑堟伅澶辫触" });
+        }
+    }
+}
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Program.cs b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Program.cs
index 7ca0d53..18b602a 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Program.cs
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Program.cs
@@ -46,6 +46,7 @@
 
 builder.Services.AddSingleton<IPersistenceService>(sp => new FilePersistenceService(dataPath));
 builder.Services.AddSingleton<IProtocolTemplateService>(sp => new FileProtocolTemplateService(dataPath));
+builder.Services.AddSingleton<IRobotClientManager, RobotClientManager>();
 builder.Services.Configure<ProtocolMonitoringOptions>(builder.Configuration.GetSection("ProtocolMonitoring"));
 builder.Services.AddSingleton<MirrorAckProtocolHandler>();
 builder.Services.AddSingleton<IDeviceProtocolHandler, WcsLineProtocolHandler>();
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Services/RobotClientManager.cs b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Services/RobotClientManager.cs
new file mode 100644
index 0000000..1fd7887
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Services/RobotClientManager.cs
@@ -0,0 +1,588 @@
+锘縰sing System.Collections.Concurrent;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+
+namespace WIDESEAWCS_S7Simulator.Server.Services;
+
+public interface IRobotClientManager
+{
+    Task<RobotServerCollectionStatusResponse> StartAsync(RobotServerStartRequest request, CancellationToken cancellationToken = default);
+    Task StopAsync(string? serverId = null);
+    Task<RobotServerCollectionStatusResponse> GetStatusAsync();
+    Task SendToClientAsync(string serverId, int clientId, string message);
+    Task SendToAllAsync(string serverId, string message);
+    Task ClearReceivedMessagesAsync(string serverId);
+}
+
+/// <summary>
+/// 鏈烘鎵� TCP 瀹㈡埛绔瀹炰緥绠$悊鍣ㄣ��
+/// 涓�涓� ServerId 瀵瑰簲涓�涓� TcpClient锛屼富鍔ㄨ繛鎺ョ洰鏍囨湇鍔$銆�
+/// </summary>
+public sealed class RobotClientManager : IRobotClientManager, IDisposable
+{
+    private readonly ILogger<RobotClientManager> _logger;
+    private readonly ConcurrentDictionary<string, RobotClientRuntime> _clients = new(StringComparer.OrdinalIgnoreCase);
+    private bool _disposed;
+
+    public RobotClientManager(ILogger<RobotClientManager> logger)
+    {
+        _logger = logger;
+    }
+
+    public async Task<RobotServerCollectionStatusResponse> StartAsync(RobotServerStartRequest request, CancellationToken cancellationToken = default)
+    {
+        ValidateStartRequest(request);
+        EnsureLocalPortAvailable(request.LocalPort);
+
+        var key = request.ServerId.Trim();
+        if (_clients.ContainsKey(key))
+        {
+            throw new InvalidOperationException($"瀹㈡埛绔疄渚� '{key}' 宸插瓨鍦�");
+        }
+
+        var runtime = new RobotClientRuntime
+        {
+            ServerId = key,
+            RemoteIp = request.ListenIp,
+            RemotePort = request.ListenPort,
+            LocalPort = request.LocalPort,
+            Cancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken),
+            Connected = false
+        };
+
+        runtime.ConnectionLoopTask = Task.Run(() => ConnectionLoopAsync(runtime), runtime.Cancellation.Token);
+
+        if (!_clients.TryAdd(key, runtime))
+        {
+            await StopRuntimeAsync(runtime);
+            throw new InvalidOperationException($"瀹㈡埛绔疄渚� '{key}' 鍒涘缓澶辫触");
+        }
+
+        _logger.LogInformation("鏈烘鎵嬪鎴风宸插惎鍔�: {ServerId} 鏈湴:{LocalPort} -> 杩滅:{Ip}:{Port}",
+            key,
+            request.LocalPort,
+            request.ListenIp,
+            request.ListenPort);
+
+        return await GetStatusAsync();
+    }
+
+    public async Task StopAsync(string? serverId = null)
+    {
+        if (string.IsNullOrWhiteSpace(serverId))
+        {
+            var all = _clients.Values.ToArray();
+            _clients.Clear();
+            await Task.WhenAll(all.Select(StopRuntimeAsync));
+            return;
+        }
+
+        if (_clients.TryRemove(serverId.Trim(), out var runtime))
+        {
+            await StopRuntimeAsync(runtime);
+        }
+    }
+
+    public Task<RobotServerCollectionStatusResponse> GetStatusAsync()
+    {
+        var servers = _clients.Values
+            .OrderBy(x => x.ServerId, StringComparer.OrdinalIgnoreCase)
+            .Select(ToStatusItem)
+            .ToArray();
+
+        return Task.FromResult(new RobotServerCollectionStatusResponse
+        {
+            RunningServerCount = servers.Count(x => x.Running),
+            Servers = servers
+        });
+    }
+
+    public async Task SendToClientAsync(string serverId, int clientId, string message)
+    {
+        var runtime = GetClientOrThrow(serverId);
+        if (clientId != 1)
+        {
+            throw new InvalidOperationException($"瀹㈡埛绔疄渚� '{runtime.ServerId}' 浠呮敮鎸� ClientId=1");
+        }
+
+        await SendFrameAsync(runtime, message, CancellationToken.None);
+    }
+
+    public async Task SendToAllAsync(string serverId, string message)
+    {
+        var runtime = GetClientOrThrow(serverId);
+        await SendFrameAsync(runtime, message, CancellationToken.None);
+    }
+
+    /// <summary>
+    /// 娓呯┖鎸囧畾瀹㈡埛绔疄渚嬬殑鏀跺彂娑堟伅鏃ュ織銆�
+    /// </summary>
+    public Task ClearReceivedMessagesAsync(string serverId)
+    {
+        var runtime = GetClientOrThrow(serverId);
+
+        while (runtime.ReceivedMessages.TryDequeue(out _))
+        {
+        }
+
+        while (runtime.SentMessages.TryDequeue(out _))
+        {
+        }
+
+        return Task.CompletedTask;
+    }
+
+    private RobotClientRuntime GetClientOrThrow(string serverId)
+    {
+        if (string.IsNullOrWhiteSpace(serverId))
+        {
+            throw new ArgumentException("ServerId 涓嶈兘涓虹┖");
+        }
+
+        if (!_clients.TryGetValue(serverId.Trim(), out var runtime))
+        {
+            throw new InvalidOperationException($"瀹㈡埛绔疄渚� '{serverId}' 涓嶅瓨鍦�");
+        }
+
+        return runtime;
+    }
+
+    /// <summary>
+    /// 瀹㈡埛绔繛鎺ュ畧鎶ゅ惊鐜細鏂紑鍚庤嚜鍔ㄩ噸杩炪��
+    /// </summary>
+    private async Task ConnectionLoopAsync(RobotClientRuntime runtime)
+    {
+        var token = runtime.Cancellation.Token;
+
+        while (!token.IsCancellationRequested)
+        {
+            if (!runtime.Connected)
+            {
+                try
+                {
+                    await ConnectOnceAsync(runtime, token);
+                }
+                catch (OperationCanceledException)
+                {
+                    break;
+                }
+                catch (Exception ex)
+                {
+                    runtime.LastError = ex.Message;
+                    _logger.LogWarning(ex, "[{ServerId}] 杩炴帴澶辫触锛屽皢鍦� 2 绉掑悗閲嶈瘯", runtime.ServerId);
+                    await DelayForReconnect(token);
+                    continue;
+                }
+            }
+
+            var tcpClient = runtime.TcpClient;
+            if (tcpClient == null)
+            {
+                await DelayForReconnect(token);
+                continue;
+            }
+
+            await ReceiveLoopAsync(runtime, tcpClient);
+            await DelayForReconnect(token);
+        }
+    }
+
+    /// <summary>
+    /// 鍗曟杩炴帴鍔ㄤ綔銆傛垚鍔熷悗鏇存柊杩愯鏃惰繛鎺ョ姸鎬併��
+    /// </summary>
+    private async Task ConnectOnceAsync(RobotClientRuntime runtime, CancellationToken token)
+    {
+        var tcpClient = new TcpClient(AddressFamily.InterNetwork);
+        try
+        {
+            // 姣忔閲嶈繛閮藉浐瀹氱粦瀹氬悓涓�鏈湴绔彛銆�
+            tcpClient.Client.Bind(new IPEndPoint(IPAddress.Any, runtime.LocalPort));
+            await tcpClient.ConnectAsync(runtime.RemoteIp, runtime.RemotePort, token);
+        }
+        catch
+        {
+            tcpClient.Dispose();
+            throw;
+        }
+
+        runtime.TcpClient = tcpClient;
+        runtime.Connected = true;
+        runtime.ConnectedAt = DateTimeOffset.Now;
+        runtime.LastError = null;
+
+        _logger.LogInformation("[{ServerId}] 宸茶繛鎺� 鏈湴:{LocalPort} -> 杩滅:{Ip}:{Port}",
+            runtime.ServerId,
+            runtime.LocalPort,
+            runtime.RemoteIp,
+            runtime.RemotePort);
+    }
+
+    /// <summary>
+    /// 鍗曚釜瀹㈡埛绔敹鍖呭惊鐜紝鏀寔甯у崗璁拰鏅�氭枃鏈袱绉嶈緭鍏ャ��
+    /// </summary>
+    private async Task ReceiveLoopAsync(RobotClientRuntime runtime, TcpClient tcpClient)
+    {
+        var token = runtime.Cancellation.Token;
+        var buffer = new byte[2048];
+        var cache = new StringBuilder();
+
+        try
+        {
+            var stream = tcpClient.GetStream();
+            while (!token.IsCancellationRequested)
+            {
+                var length = await stream.ReadAsync(buffer, 0, buffer.Length, token);
+                if (length <= 0)
+                {
+                    break;
+                }
+
+                runtime.LastReceivedAt = DateTimeOffset.Now;
+                cache.Append(Encoding.UTF8.GetString(buffer, 0, length));
+                TryReadMessages(runtime, cache);
+            }
+        }
+        catch (OperationCanceledException)
+        {
+            // 姝e父鍋滄銆�
+        }
+        catch (Exception ex)
+        {
+            runtime.LastError = ex.Message;
+            _logger.LogWarning(ex, "[{ServerId}] 瀹㈡埛绔敹鍖呭紓甯�", runtime.ServerId);
+        }
+        finally
+        {
+            runtime.Connected = false;
+            await CloseRuntimeSocketAsync(runtime);
+            _logger.LogWarning("[{ServerId}] 瀹㈡埛绔繛鎺ュ凡鏂紑锛屽噯澶囪嚜鍔ㄩ噸杩�", runtime.ServerId);
+        }
+    }
+
+    private void TryReadMessages(RobotClientRuntime runtime, StringBuilder cache)
+    {
+        const string start = "<START>";
+        const string end = "<END>";
+
+        while (true)
+        {
+            var text = cache.ToString();
+            var startIndex = text.IndexOf(start, StringComparison.Ordinal);
+            var endIndex = text.IndexOf(end, StringComparison.Ordinal);
+
+            // 鏈懡涓抚鍗忚鏃讹紝鎸夋暣娈垫枃鏈褰曪紝閬垮厤娑堟伅涓㈠け銆�
+            if (startIndex < 0 || endIndex < 0 || endIndex <= startIndex)
+            {
+                if (cache.Length > 0 && cache.Length < 2048 && !text.Contains("<START>", StringComparison.Ordinal))
+                {
+                    AppendReceived(runtime, text.Trim());
+                    cache.Clear();
+                }
+
+                if (cache.Length > 10240)
+                {
+                    cache.Clear();
+                }
+
+                return;
+            }
+
+            var contentStart = startIndex + start.Length;
+            var contentLength = endIndex - contentStart;
+            var content = text.Substring(contentStart, contentLength);
+            cache.Remove(0, endIndex + end.Length);
+            AppendReceived(runtime, content);
+        }
+    }
+
+    private void AppendReceived(RobotClientRuntime runtime, string message)
+    {
+        if (string.IsNullOrWhiteSpace(message))
+        {
+            return;
+        }
+
+        runtime.LastReceivedMessage = message;
+        runtime.ReceivedMessages.Enqueue(new RobotServerReceivedMessageItem
+        {
+            ReceivedAt = DateTimeOffset.Now,
+            ClientId = 1,
+            RemoteEndPoint = $"{runtime.RemoteIp}:{runtime.RemotePort}",
+            Message = message
+        });
+
+        while (runtime.ReceivedMessages.Count > 500)
+        {
+            runtime.ReceivedMessages.TryDequeue(out _);
+        }
+
+        _logger.LogInformation("[{ServerId}] 鏀跺埌: {Message}", runtime.ServerId, message);
+    }
+
+    private async Task SendFrameAsync(RobotClientRuntime runtime, string message, CancellationToken token)
+    {
+        if (!runtime.Connected)
+        {
+            throw new InvalidOperationException($"瀹㈡埛绔疄渚� '{runtime.ServerId}' 鏈繛鎺�");
+        }
+
+        var frame = $"<START>{message}<END>";
+        var bytes = Encoding.UTF8.GetBytes(frame);
+
+        await runtime.SendLock.WaitAsync(token);
+        try
+        {
+            if (runtime.TcpClient == null)
+            {
+                throw new InvalidOperationException($"瀹㈡埛绔疄渚� '{runtime.ServerId}' 鏈繛鎺�");
+            }
+
+            var stream = runtime.TcpClient.GetStream();
+            await stream.WriteAsync(bytes, 0, bytes.Length, token);
+            await stream.FlushAsync(token);
+            runtime.LastSentAt = DateTimeOffset.Now;
+
+            runtime.SentMessages.Enqueue(new RobotServerSentMessageItem
+            {
+                SentAt = DateTimeOffset.Now,
+                ClientId = 1,
+                RemoteEndPoint = $"{runtime.RemoteIp}:{runtime.RemotePort}",
+                Message = message
+            });
+
+            while (runtime.SentMessages.Count > 500)
+            {
+                runtime.SentMessages.TryDequeue(out _);
+            }
+
+            _logger.LogInformation("[{ServerId}] 鍙戦��: {Frame}", runtime.ServerId, frame);
+        }
+        finally
+        {
+            runtime.SendLock.Release();
+        }
+    }
+
+    private static async Task CloseRuntimeSocketAsync(RobotClientRuntime runtime)
+    {
+        await runtime.SendLock.WaitAsync();
+        try
+        {
+            if (runtime.TcpClient != null)
+            {
+                try { runtime.TcpClient.Close(); } catch { }
+                runtime.TcpClient.Dispose();
+                runtime.TcpClient = null;
+            }
+            runtime.Connected = false;
+        }
+        finally
+        {
+            runtime.SendLock.Release();
+        }
+    }
+
+    private async Task StopRuntimeAsync(RobotClientRuntime runtime)
+    {
+        try { runtime.Cancellation.Cancel(); } catch { }
+
+        if (runtime.ConnectionLoopTask != null)
+        {
+            try { await runtime.ConnectionLoopTask; } catch { }
+        }
+
+        await CloseRuntimeSocketAsync(runtime);
+        runtime.Cancellation.Dispose();
+        _logger.LogInformation("鏈烘鎵嬪鎴风宸插仠姝�: {ServerId}", runtime.ServerId);
+    }
+
+    private static RobotServerStatusItem ToStatusItem(RobotClientRuntime runtime)
+    {
+        var clients = new[]
+        {
+            new RobotServerClientStatusItem
+            {
+                ClientId = 1,
+                RemoteEndPoint = $"{runtime.RemoteIp}:{runtime.RemotePort}",
+                Connected = runtime.Connected,
+                ConnectedAt = runtime.ConnectedAt,
+                LastReceivedAt = runtime.LastReceivedAt,
+                LastSentAt = runtime.LastSentAt,
+                LastReceivedMessage = runtime.LastReceivedMessage,
+                LastError = runtime.LastError
+            }
+        };
+
+        var receivedMessages = runtime.ReceivedMessages
+            .Reverse()
+            .Take(200)
+            .ToArray();
+
+        var sentMessages = runtime.SentMessages
+            .Reverse()
+            .Take(200)
+            .ToArray();
+
+        return new RobotServerStatusItem
+        {
+            ServerId = runtime.ServerId,
+            Running = !runtime.Cancellation.IsCancellationRequested,
+            ListenIp = runtime.RemoteIp,
+            ListenPort = runtime.RemotePort,
+            LocalPort = runtime.LocalPort,
+            ConnectedCount = runtime.Connected ? 1 : 0,
+            Clients = clients,
+            ReceivedMessages = receivedMessages,
+            SentMessages = sentMessages
+        };
+    }
+
+    private static void ValidateStartRequest(RobotServerStartRequest request)
+    {
+        if (string.IsNullOrWhiteSpace(request.ServerId))
+        {
+            throw new ArgumentException("ServerId 涓嶈兘涓虹┖");
+        }
+
+        if (string.IsNullOrWhiteSpace(request.ListenIp))
+        {
+            throw new ArgumentException("鐩爣鏈嶅姟绔湴鍧�涓嶈兘涓虹┖");
+        }
+
+        if (request.ListenPort <= 0 || request.ListenPort > 65535)
+        {
+            throw new ArgumentException("鐩爣鏈嶅姟绔鍙e繀椤诲湪 1-65535 鑼冨洿鍐�");
+        }
+
+        if (request.LocalPort <= 0 || request.LocalPort > 65535)
+        {
+            throw new ArgumentException("瀹㈡埛绔湰鍦扮鍙e繀椤诲湪 1-65535 鑼冨洿鍐�");
+        }
+    }
+
+    /// <summary>
+    /// 鍚姩鍓嶆鏌ユ湰鍦扮鍙f槸鍚﹀彲鐢紝閬垮厤瀹炰緥杩涘叆鏃犳晥閲嶈繛鐘舵�併��
+    /// </summary>
+    private static void EnsureLocalPortAvailable(int localPort)
+    {
+        Socket? probe = null;
+        try
+        {
+            probe = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+            probe.Bind(new IPEndPoint(IPAddress.Any, localPort));
+        }
+        catch (SocketException ex)
+        {
+            throw new InvalidOperationException($"鏈湴绔彛 {localPort} 宸茶鍗犵敤鎴栦笉鍙敤", ex);
+        }
+        finally
+        {
+            try { probe?.Dispose(); } catch { }
+        }
+    }
+
+    private static async Task DelayForReconnect(CancellationToken token)
+    {
+        try
+        {
+            await Task.Delay(TimeSpan.FromSeconds(2), token);
+        }
+        catch (OperationCanceledException)
+        {
+        }
+    }
+
+    public void Dispose()
+    {
+        if (_disposed)
+        {
+            return;
+        }
+
+        _disposed = true;
+        StopAsync().GetAwaiter().GetResult();
+    }
+
+    private sealed class RobotClientRuntime
+    {
+        public string ServerId { get; set; } = string.Empty;
+        public string RemoteIp { get; set; } = string.Empty;
+        public int RemotePort { get; set; }
+        public int LocalPort { get; set; }
+        public TcpClient? TcpClient { get; set; }
+        public CancellationTokenSource Cancellation { get; set; } = default!;
+        public Task? ConnectionLoopTask { get; set; }
+        public SemaphoreSlim SendLock { get; } = new(1, 1);
+        public bool Connected { get; set; }
+        public DateTimeOffset? ConnectedAt { get; set; }
+        public DateTimeOffset? LastReceivedAt { get; set; }
+        public DateTimeOffset? LastSentAt { get; set; }
+        public string? LastReceivedMessage { get; set; }
+        public string? LastError { get; set; }
+        public ConcurrentQueue<RobotServerReceivedMessageItem> ReceivedMessages { get; } = new();
+        public ConcurrentQueue<RobotServerSentMessageItem> SentMessages { get; } = new();
+    }
+}
+
+public sealed class RobotServerStartRequest
+{
+    public string ServerId { get; set; } = "default";
+    public string ListenIp { get; set; } = "127.0.0.1";
+    public int ListenPort { get; set; } = 2000;
+    public int LocalPort { get; set; } = 2001;
+}
+
+public sealed class RobotServerSendRequest
+{
+    public string ServerId { get; set; } = string.Empty;
+    public int? ClientId { get; set; }
+    public string Message { get; set; } = string.Empty;
+}
+
+public sealed class RobotServerCollectionStatusResponse
+{
+    public int RunningServerCount { get; set; }
+    public IReadOnlyList<RobotServerStatusItem> Servers { get; set; } = Array.Empty<RobotServerStatusItem>();
+}
+
+public sealed class RobotServerStatusItem
+{
+    public string ServerId { get; set; } = string.Empty;
+    public bool Running { get; set; }
+    public string ListenIp { get; set; } = string.Empty;
+    public int ListenPort { get; set; }
+    public int LocalPort { get; set; }
+    public int ConnectedCount { get; set; }
+    public IReadOnlyList<RobotServerClientStatusItem> Clients { get; set; } = Array.Empty<RobotServerClientStatusItem>();
+    public IReadOnlyList<RobotServerReceivedMessageItem> ReceivedMessages { get; set; } = Array.Empty<RobotServerReceivedMessageItem>();
+    public IReadOnlyList<RobotServerSentMessageItem> SentMessages { get; set; } = Array.Empty<RobotServerSentMessageItem>();
+}
+
+public sealed class RobotServerClientStatusItem
+{
+    public int ClientId { get; set; }
+    public string? RemoteEndPoint { get; set; }
+    public bool Connected { get; set; }
+    public DateTimeOffset? ConnectedAt { get; set; }
+    public DateTimeOffset? LastReceivedAt { get; set; }
+    public DateTimeOffset? LastSentAt { get; set; }
+    public string? LastReceivedMessage { get; set; }
+    public string? LastError { get; set; }
+}
+
+public sealed class RobotServerReceivedMessageItem
+{
+    public DateTimeOffset ReceivedAt { get; set; }
+    public int ClientId { get; set; }
+    public string? RemoteEndPoint { get; set; }
+    public string Message { get; set; } = string.Empty;
+}
+
+public sealed class RobotServerSentMessageItem
+{
+    public DateTimeOffset SentAt { get; set; }
+    public int ClientId { get; set; }
+    public string? RemoteEndPoint { get; set; }
+    public string Message { get; set; } = string.Empty;
+}
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/App.vue b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/App.vue
index 567aee1..10a7a1a 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/App.vue
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/App.vue
@@ -1,94 +1,169 @@
-<template>
-  <el-container class="app-container">
-    <el-header class="app-header">
-      <div class="header-content">
-        <router-link to="/" class="logo">
-          <el-icon :size="24"><Cpu /></el-icon>
-          <span>S7 PLC Simulator</span>
-        </router-link>
-        <div class="header-nav">
-          <router-link to="/protocol-templates" class="nav-link">鍗忚妯℃澘</router-link>
+锘�<template>
+  <el-container class="admin-layout">
+    <el-aside class="admin-aside" width="220px">
+      <div class="brand-area">
+        <el-icon :size="24" class="brand-icon"><Cpu /></el-icon>
+        <div class="brand-text">
+          <div class="brand-title">WCS 妯℃嫙骞冲彴</div>
+          <div class="brand-subtitle">S7 Simulator</div>
         </div>
       </div>
-    </el-header>
 
-    <el-main class="app-main">
-      <router-view />
-    </el-main>
+      <el-menu
+        class="aside-menu"
+        :default-active="activeMenu"
+        background-color="#1f2a37"
+        text-color="#c7d2fe"
+        active-text-color="#ffffff"
+        router
+      >
+        <el-menu-item index="/">
+          <el-icon><House /></el-icon>
+          <span>瀹炰緥绠$悊</span>
+        </el-menu-item>
+        <el-menu-item index="/protocol-templates">
+          <el-icon><Files /></el-icon>
+          <span>鍗忚妯℃澘</span>
+        </el-menu-item>
+        <el-menu-item index="/robot-clients">
+          <el-icon><Connection /></el-icon>
+          <span>鏈烘鎵嬪鎴风</span>
+        </el-menu-item>
+      </el-menu>
+    </el-aside>
 
-    <el-footer class="app-footer">
-      <span>&copy; 2026 - S7 PLC Simulator Management UI</span>
-    </el-footer>
+    <el-container>
+      <el-header class="admin-header">
+        <div class="header-left">
+          <div class="page-title">{{ pageTitle }}</div>
+          <div class="page-path">{{ route.path }}</div>
+        </div>
+      </el-header>
+
+      <el-main class="admin-main">
+        <div class="content-shell">
+          <router-view />
+        </div>
+      </el-main>
+    </el-container>
   </el-container>
 </template>
 
 <script setup lang="ts">
-import { Cpu } from '@element-plus/icons-vue'
+import { computed } from 'vue'
+import { useRoute } from 'vue-router'
+import { Connection, Cpu, Files, House } from '@element-plus/icons-vue'
+
+const route = useRoute()
+
+const activeMenu = computed(() => {
+  if (route.path.startsWith('/protocol-templates')) return '/protocol-templates'
+  if (route.path.startsWith('/robot-clients')) return '/robot-clients'
+  return '/'
+})
+
+const pageTitle = computed(() => {
+  if (route.path.startsWith('/create')) return '鍒涘缓瀹炰緥'
+  if (route.path.startsWith('/edit')) return '缂栬緫瀹炰緥'
+  if (route.path.startsWith('/details')) return '瀹炰緥璇︽儏'
+  if (route.path.startsWith('/protocol-templates')) return '鍗忚妯℃澘'
+  if (route.path.startsWith('/robot-clients')) return '鏈烘鎵嬪鎴风'
+  return '瀹炰緥绠$悊'
+})
 </script>
 
 <style scoped>
-.app-container {
-  min-height: 100vh;
+.admin-layout {
+  height: 100vh;
 }
 
-.app-header {
-  background: #409eff;
-  color: white;
-  padding: 0 20px;
+.admin-aside {
+  background: linear-gradient(180deg, #1f2a37 0%, #111827 100%);
+  border-right: 1px solid #263445;
+  display: flex;
+  flex-direction: column;
+}
+
+.brand-area {
+  height: 64px;
+  padding: 0 14px;
   display: flex;
   align-items: center;
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  border-bottom: 1px solid #2b3a4f;
+  color: #e5e7eb;
 }
 
-.header-content {
-  width: 100%;
-  max-width: 1400px;
-  margin: 0 auto;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
+.brand-icon {
+  margin-right: 10px;
 }
 
-.logo {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  color: white;
-  text-decoration: none;
-  font-size: 18px;
-  font-weight: 500;
+.brand-title {
+  font-size: 15px;
+  font-weight: 700;
+  line-height: 1.2;
 }
 
-.logo:hover {
-  color: white;
+.brand-subtitle {
+  font-size: 12px;
+  color: #94a3b8;
+  line-height: 1.2;
 }
 
-.header-nav {
-  display: flex;
-  gap: 12px;
-}
-
-.nav-link {
-  color: #fff;
-  text-decoration: none;
-}
-
-.app-main {
+.aside-menu {
+  border-right: none;
   flex: 1;
-  padding: 20px;
-  max-width: 1400px;
+}
+
+.admin-header {
+  height: 64px;
+  background: #ffffff;
+  border-bottom: 1px solid #e5e7eb;
+  display: flex;
+  align-items: center;
+  padding: 0 20px;
+}
+
+.header-left {
+  display: flex;
+  flex-direction: column;
+  gap: 2px;
+}
+
+.page-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #0f172a;
+}
+
+.page-path {
+  font-size: 12px;
+  color: #64748b;
+}
+
+.admin-main {
+  background: #f1f5f9;
+  padding: 14px;
+}
+
+.content-shell {
+  min-height: calc(100vh - 64px - 28px);
   width: 100%;
+  max-width: 1680px;
   margin: 0 auto;
+  padding: 2px;
 }
 
-.app-footer {
-  text-align: center;
-  color: #909399;
-  border-top: 1px solid #dcdfe6;
-  padding: 20px;
-}
+@media (max-width: 960px) {
+  .admin-aside {
+    width: 64px !important;
+  }
 
-a.router-link-active {
-  font-weight: bold;
+  .brand-text {
+    display: none;
+  }
+
+  .admin-header {
+    padding: 0 12px;
+  }
 }
 </style>
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts
index e6c9850..c45b917 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts
@@ -1,9 +1,12 @@
-import axios from 'axios'
+锘縤mport axios from 'axios'
 import type {
   InstanceListItem,
   InstanceState,
   InstanceConfig,
-  ProtocolTemplate
+  ProtocolTemplate,
+  RobotClientStartRequest,
+  RobotClientSendRequest,
+  RobotClientStatusResponse
 } from '../types'
 
 const api = axios.create({
@@ -19,7 +22,7 @@
   return response.data
 }
 
-// 鑾峰彇鎸囧畾瀹炰緥鐘舵��
+// 鑾峰彇瀹炰緥鐘舵��
 export async function getInstance(id: string): Promise<InstanceState | null> {
   try {
     const response = await api.get<InstanceState>('/SimulatorInstances/GetInstance', {
@@ -52,7 +55,7 @@
 // 鍒涘缓瀹炰緥
 export async function createInstance(config: InstanceConfig): Promise<InstanceState | null> {
   try {
-    const response = await api.post<InstanceState>('/SimulatorInstances/Create',  config )
+    const response = await api.post<InstanceState>('/SimulatorInstances/Create', config)
     return response.data
   } catch (error) {
     console.error('鍒涘缓瀹炰緥澶辫触:', error)
@@ -175,4 +178,35 @@
   }
 }
 
+// 鑾峰彇鏈烘鎵嬫湇鍔$杩愯鐘舵�侊紙鍖呭惈澶氬疄渚嬪拰鎺ユ敹娑堟伅鏃ュ織锛�
+export async function getRobotClientStatus(): Promise<RobotClientStatusResponse> {
+  const response = await api.get<RobotClientStatusResponse>('/RobotClients/status')
+  return response.data
+}
+
+// 鍚姩涓�涓満姊版墜鏈嶅姟绔疄渚�
+export async function startRobotClients(request: RobotClientStartRequest): Promise<RobotClientStatusResponse> {
+  const response = await api.post<RobotClientStatusResponse>('/RobotClients/start', request)
+  return response.data
+}
+
+// 鍋滄鏈烘鎵嬫湇鍔$锛宻erverId 涓虹┖鏃跺仠姝㈠叏閮�
+export async function stopRobotClients(serverId?: string): Promise<void> {
+  await api.post('/RobotClients/stop', null, {
+    params: { serverId }
+  })
+}
+
+// 鍙戦�佹満姊版墜娑堟伅锛堟寜鏈嶅姟绔疄渚嬪箍鎾垨鍗曞彂锛�
+export async function sendRobotClientMessage(request: RobotClientSendRequest): Promise<void> {
+  await api.post('/RobotClients/send', request)
+}
+
+// 娓呯┖鎸囧畾鏈嶅姟绔疄渚嬬殑鎺ユ敹娑堟伅鏃ュ織
+export async function clearRobotClientReceivedMessages(serverId: string): Promise<void> {
+  await api.post('/RobotClients/clear-received', null, {
+    params: { serverId }
+  })
+}
+
 export default api
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/router/index.ts b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/router/index.ts
index 766810e..cc0caaa 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/router/index.ts
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/router/index.ts
@@ -28,6 +28,11 @@
     path: '/protocol-templates',
     name: 'protocolTemplates',
     component: () => import('../views/ProtocolTemplatesView.vue')
+  },
+  {
+    path: '/robot-clients',
+    name: 'robotClients',
+    component: () => import('../views/RobotClientsView.vue')
   }
 ]
 
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/style.css b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/style.css
index 6c3eee6..13f7281 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/style.css
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/style.css
@@ -1,50 +1,135 @@
-/* Global Styles */
 :root {
-  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
+  --bg-page: #edf2f7;
+  --bg-panel: #ffffff;
+  --bg-soft: #f8fafc;
+  --text-main: #0f172a;
+  --text-sub: #64748b;
+  --border-main: #dbe2ea;
+  --brand-main: #0b5cab;
+  --brand-soft: #e8f2ff;
+  --ok: #16a34a;
+  --warn: #d97706;
+  --danger: #dc2626;
+  font-family: 'Noto Sans SC', 'Microsoft YaHei', 'PingFang SC', 'Helvetica Neue', sans-serif;
+}
+
+* {
+  box-sizing: border-box;
 }
 
 body {
   margin: 0;
   min-height: 100vh;
-  background: #f5f7fa;
+  color: var(--text-main);
+  background:
+    radial-gradient(circle at 0% 0%, #f6faff 0%, transparent 35%),
+    radial-gradient(circle at 100% 0%, #eef6ff 0%, transparent 38%),
+    var(--bg-page);
 }
 
-/* Status Colors - Element Plus */
+#app {
+  min-height: 100vh;
+}
+
+.admin-page {
+  display: flex;
+  flex-direction: column;
+  gap: 14px;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  flex-wrap: wrap;
+  gap: 12px;
+  padding: 16px 18px;
+  border: 1px solid var(--border-main);
+  border-radius: 12px;
+  background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
+}
+
+.page-header h2 {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin: 0;
+  font-size: 20px;
+}
+
+.text-muted {
+  margin: 4px 0 0 0;
+  color: var(--text-sub);
+  font-size: 13px;
+}
+
+.panel-card {
+  border-radius: 12px;
+  border: 1px solid var(--border-main);
+  overflow: hidden;
+}
+
+.section-block {
+  border: 1px solid var(--border-main);
+  border-radius: 12px;
+  background: var(--bg-panel);
+  overflow: hidden;
+}
+
+.section-head {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  gap: 10px;
+  padding: 12px 16px;
+  border-bottom: 1px solid #e6edf4;
+  background: linear-gradient(180deg, #ffffff 0%, #f9fbfe 100%);
+}
+
+.section-title {
+  margin: 0;
+  font-size: 15px;
+  font-weight: 600;
+  color: #0f172a;
+}
+
+.section-desc {
+  margin: 2px 0 0;
+  font-size: 12px;
+  color: var(--text-sub);
+}
+
+.section-body {
+  padding: 12px 14px;
+}
+
 .status-stopped {
-  border-left: 4px solid #909399;
+  border-left: 4px solid #94a3b8;
 }
 
 .status-starting {
-  border-left: 4px solid #409eff;
+  border-left: 4px solid var(--brand-main);
 }
 
 .status-running {
-  border-left: 4px solid #67c23a;
+  border-left: 4px solid var(--ok);
 }
 
 .status-stopping {
-  border-left: 4px solid #e6a23c;
+  border-left: 4px solid var(--warn);
 }
 
 .status-error {
-  border-left: 4px solid #f56c6c;
+  border-left: 4px solid var(--danger);
 }
 
-/* Loading Spinner Overlay */
-.spinner-overlay {
-  position: fixed;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  background-color: rgba(0, 0, 0, 0.5);
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  z-index: 9999;
+.loading-container {
+  text-align: center;
+  padding: 60px 0;
+  color: var(--text-sub);
 }
 
-/* Spin icon animation */
+.loading-icon,
 .spin-icon {
   animation: spin 1s linear infinite;
 }
@@ -58,30 +143,32 @@
   }
 }
 
-/* Card hover effect */
 .el-card {
-  transition: all 0.3s ease;
+  transition: all 0.2s ease;
 }
 
 .el-card:hover {
-  transform: translateY(-2px);
+  transform: translateY(-1px);
 }
 
-/* Custom scrollbar */
+.el-table {
+  --el-table-header-bg-color: #f3f7fb;
+}
+
 ::-webkit-scrollbar {
   width: 8px;
   height: 8px;
 }
 
 ::-webkit-scrollbar-track {
-  background: #f1f1f1;
+  background: #eef2f6;
 }
 
 ::-webkit-scrollbar-thumb {
-  background: #c0c4cc;
+  background: #b4beca;
   border-radius: 4px;
 }
 
 ::-webkit-scrollbar-thumb:hover {
-  background: #909399;
+  background: #8f9cab;
 }
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/types/index.ts b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/types/index.ts
index 63e0c17..85d6119 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/types/index.ts
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/types/index.ts
@@ -112,3 +112,58 @@
   version: string
   fields: ProtocolFieldMapping[]
 }
+
+export interface RobotClientStartRequest {
+  serverId: string
+  listenIp: string
+  listenPort: number
+  localPort: number
+}
+
+export interface RobotClientSendRequest {
+  serverId: string
+  clientId?: number | null
+  message: string
+}
+
+export interface RobotClientStatusItem {
+  clientId: number
+  remoteEndPoint: string | null
+  connected: boolean
+  connectedAt: string | null
+  lastReceivedMessage: string | null
+  lastError: string | null
+  lastReceivedAt: string | null
+  lastSentAt: string | null
+}
+
+export interface RobotServerReceivedMessageItem {
+  receivedAt: string
+  clientId: number
+  remoteEndPoint: string | null
+  message: string
+}
+
+export interface RobotServerSentMessageItem {
+  sentAt: string
+  clientId: number
+  remoteEndPoint: string | null
+  message: string
+}
+
+export interface RobotServerStatusItem {
+  serverId: string
+  running: boolean
+  listenIp: string
+  listenPort: number
+  localPort: number
+  connectedCount: number
+  clients: RobotClientStatusItem[]
+  receivedMessages: RobotServerReceivedMessageItem[]
+  sentMessages: RobotServerSentMessageItem[]
+}
+
+export interface RobotClientStatusResponse {
+  runningServerCount: number
+  servers: RobotServerStatusItem[]
+}
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue
index 88b6545..78e1e50 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue
@@ -1,5 +1,5 @@
 锘�<template>
-  <div>
+  <div class="admin-page">
     <div class="page-header">
       <div class="header-left">
         <h2>
@@ -16,7 +16,7 @@
 
     <el-row justify="center">
       <el-col :lg="24">
-        <el-card shadow="never">
+        <el-card shadow="never" class="panel-card">
           <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
             <!-- 鍩烘湰淇℃伅 -->
             <el-divider content-position="left">
@@ -315,27 +315,6 @@
 </script>
 
 <style scoped>
-.page-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: flex-start;
-  margin-bottom: 20px;
-  flex-wrap: wrap;
-  gap: 16px;
-}
-
-.header-left h2 {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  margin: 0 0 8px 0;
-}
-
-.text-muted {
-  color: #909399;
-  margin: 0;
-}
-
 .el-divider h3 {
   margin: 0;
   font-size: 16px;
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/DetailsView.vue b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/DetailsView.vue
index c336b5a..83ea82c 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/DetailsView.vue
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/DetailsView.vue
@@ -1,5 +1,6 @@
 锘�<template>
   <div
+    class="admin-page"
     v-loading.fullscreen.lock="startActionLoading"
     element-loading-text="姝e湪鍚姩瀹炰緥锛岃绋嶅��..."
   >
@@ -31,44 +32,64 @@
         </el-button>
       </div>
 
-      <el-row :gutter="20" class="status-cards">
-        <el-col :xs="12" :sm="6">
-          <el-card shadow="hover" class="status-card">
-            <el-statistic title="鐘舵��">
-              <template #default>
-                <el-tag :type="getStatusTagType(instance.status)" size="large">
-                  {{ getStatusText(instance.status) }}
-                </el-tag>
-              </template>
-            </el-statistic>
-          </el-card>
-        </el-col>
-        <el-col :xs="12" :sm="6">
-          <el-card shadow="hover" class="status-card">
-            <el-statistic title="杩炴帴瀹㈡埛绔�" :value="instance.clientCount">
-              <template #suffix>
-                <el-icon><User /></el-icon>
-              </template>
-            </el-statistic>
-          </el-card>
-        </el-col>
-        <el-col :xs="12" :sm="6">
-          <el-card shadow="hover" class="status-card">
-            <el-statistic title="鎬昏姹傛暟" :value="instance.totalRequests" />
-          </el-card>
-        </el-col>
-        <el-col :xs="12" :sm="6">
-          <el-card shadow="hover" class="status-card">
-            <el-statistic title="绔彛" :value="instance.port" />
-          </el-card>
-        </el-col>
-      </el-row>
+      <section class="section-block">
+        <div class="section-head">
+          <div>
+            <h3 class="section-title">淇℃伅鍖�</h3>
+            <p class="section-desc">瀹炰緥杩愯鐘舵�佷笌杩炴帴姒傝</p>
+          </div>
+        </div>
+        <div class="section-body">
+          <el-row :gutter="12" class="status-cards">
+            <el-col :xs="12" :sm="6">
+              <el-card shadow="hover" class="status-card panel-card">
+                <el-statistic title="鐘舵��">
+                  <template #default>
+                    <el-tag :type="getStatusTagType(instance.status)" size="large">
+                      {{ getStatusText(instance.status) }}
+                    </el-tag>
+                  </template>
+                </el-statistic>
+              </el-card>
+            </el-col>
+            <el-col :xs="12" :sm="6">
+              <el-card shadow="hover" class="status-card panel-card">
+                <el-statistic title="杩炴帴瀹㈡埛绔�" :value="instance.clientCount">
+                  <template #suffix>
+                    <el-icon><User /></el-icon>
+                  </template>
+                </el-statistic>
+              </el-card>
+            </el-col>
+            <el-col :xs="12" :sm="6">
+              <el-card shadow="hover" class="status-card panel-card">
+                <el-statistic title="鎬昏姹傛暟" :value="instance.totalRequests" />
+              </el-card>
+            </el-col>
+            <el-col :xs="12" :sm="6">
+              <el-card shadow="hover" class="status-card panel-card">
+                <el-statistic title="绔彛" :value="instance.port" />
+              </el-card>
+            </el-col>
+          </el-row>
+        </div>
+      </section>
 
-      <el-card class="mt-4" shadow="never">
+      <section class="section-block detail-section">
+        <div class="section-head">
+          <div>
+            <h3 class="section-title">鎿嶄綔鍖�</h3>
+            <p class="section-desc">宸︿晶瀹炰緥淇℃伅涓庢搷浣滐紝鍙充晶瀹炴椂 DB 鏁版嵁</p>
+          </div>
+        </div>
+        <div class="section-body">
+      <el-row :gutter="16" class="detail-main">
+        <el-col :xs="24" :lg="8">
+      <el-card class="panel-card" shadow="never">
         <template #header>
           <span class="card-header-title">鍩烘湰淇℃伅</span>
         </template>
-        <el-descriptions :column="2" border>
+        <el-descriptions :column="1" border>
           <el-descriptions-item label="瀹炰緥ID">{{ instance.instanceId }}</el-descriptions-item>
           <el-descriptions-item label="瀹炰緥鍚嶇О">{{ instance.name }}</el-descriptions-item>
           <el-descriptions-item label="PLC鍨嬪彿">{{ getPlcTypeText(instance.plcType) }}</el-descriptions-item>
@@ -79,17 +100,18 @@
           <el-descriptions-item v-if="instance.lastActivityTime" label="鏈�鍚庢椿鍔ㄦ椂闂�">
             {{ formatDate(instance.lastActivityTime) }}
           </el-descriptions-item>
-          <el-descriptions-item v-if="instance.errorMessage" label="閿欒淇℃伅" :span="2">
+          <el-descriptions-item v-if="instance.errorMessage" label="閿欒淇℃伅">
             <el-text type="danger">{{ instance.errorMessage }}</el-text>
           </el-descriptions-item>
         </el-descriptions>
       </el-card>
 
-      <el-card class="mt-4" shadow="never">
+      <el-card class="panel-card left-actions" shadow="never">
         <div class="action-buttons">
           <el-button
             v-if="instance.status === 'Stopped' || instance.status === 'Error'"
             type="success"
+           
             @click="handleStart"
           >
             <el-icon><VideoPlay /></el-icon>
@@ -98,6 +120,7 @@
           <el-button
             v-if="instance.status === 'Running'"
             type="warning"
+           
             @click="handleStop"
           >
             <el-icon><VideoPause /></el-icon>
@@ -114,13 +137,15 @@
         </div>
       </el-card>
 
-      <el-card class="mt-4" shadow="never">
+        </el-col>
+        <el-col :xs="24" :lg="16">
+      <el-card class="panel-card" shadow="never">
         <template #header>
           <div class="db-header">
             <span class="card-header-title">DB鍧楀疄鏃舵暟鎹�</span>
             <div class="db-toolbar">
               <el-switch v-model="autoRefreshDb" active-text="鑷姩鍒锋柊" />
-              <el-button size="small" @click="loadMemoryData(true)">鎵嬪姩鍒锋柊</el-button>
+              <el-button @click="loadMemoryData(true)">鎵嬪姩鍒锋柊</el-button>
             </div>
           </div>
         </template>
@@ -131,7 +156,7 @@
             <template #default>
               <div v-if="deviceDbViews.length === 0" class="text-muted">褰撳墠璁惧妯℃澘鏈尮閰嶅埌鍙樉绀虹殑DB鍧�</div>
               <div v-else>
-                <el-tabs type="border-card" class="db-tabs">
+                    <el-tabs type="border-card" class="db-tabs">
                   <el-tab-pane
                     v-for="view in deviceDbViews"
                     :key="view.templateDbNumber"
@@ -149,25 +174,27 @@
                         :key="`${view.templateDbNumber}-${group.key}`"
                       >
                         <template #label>
-                          <el-tag :type="getFieldGroupTagType(group.key)" size="small">{{ group.key }}</el-tag>
+                          <el-tag :type="getFieldGroupTagType(group.key)">{{ group.key }}</el-tag>
                         </template>
+                        <div class="field-table-wrap">
                         <el-table
                           :data="group.fields"
                           border
-                          size="small"
+                          class="field-table"
+                          table-layout="auto"
                           empty-text="褰撳墠鍒嗙粍鏃犲瓧娈垫槧灏�"
                         >
-                          <el-table-column prop="fieldKey" label="瀛楁" min-width="140" />
-                          <el-table-column prop="address" label="鍦板潃" width="130" />
-                          <el-table-column prop="mappedDb" label="鏄犲皠鍧�" width="120">
+                          <el-table-column prop="fieldKey" label="瀛楁" />
+                          <el-table-column prop="address" label="鍦板潃" />
+                          <el-table-column prop="mappedDb" label="鏄犲皠鍧�">
                             <template #default="{ row }">
-                              <el-tag :type="getDbTagType(row.mappedDb)" size="small">{{ row.mappedDb }}</el-tag>
+                              <el-tag :type="getDbTagType(row.mappedDb)">{{ row.mappedDb }}</el-tag>
                             </template>
                           </el-table-column>
-                          <el-table-column prop="dataType" label="绫诲瀷" width="90" />
-                          <el-table-column prop="direction" label="鏂瑰悜" width="130" />
-                          <el-table-column prop="value" label="褰撳墠鍊�" min-width="220" />
-                          <el-table-column label="淇敼鍊�" min-width="220">
+                          <el-table-column prop="dataType" label="绫诲瀷" />
+                          <el-table-column prop="direction" label="鏂瑰悜" />
+                          <el-table-column prop="value" label="褰撳墠鍊�" />
+                          <el-table-column label="淇敼鍊�">
                             <template #default="{ row }">
                               <el-switch
                                 v-if="row.dataType === 'Bool'"
@@ -181,17 +208,18 @@
                                 @change="markFieldDirty(row)"
                                 :disabled="!isFieldWritable(row)"
                                 :controls="false"
-                                style="width: 100%"
+                                class="editable-control"
                               />
                               <el-input
                                 v-else
                                 v-model="fieldEditValues[getFieldEditKey(row)]"
                                 @input="markFieldDirty(row)"
                                 :disabled="!isFieldWritable(row)"
+                                class="editable-control"
                               />
                             </template>
                           </el-table-column>
-                          <el-table-column label="鎿嶄綔" width="90" fixed="right">
+                          <el-table-column label="鎿嶄綔" width="88" fixed="right">
                             <template #default="{ row }">
                               <el-button
                                 type="primary"
@@ -205,26 +233,29 @@
                             </template>
                           </el-table-column>
                         </el-table>
+                        </div>
                       </el-tab-pane>
                     </el-tabs>
+                    <template v-else-if="view.fields.length > 0">
+                    <div class="field-table-wrap">
                     <el-table
-                      v-else-if="view.fields.length > 0"
                       :data="view.fields"
                       border
-                      size="small"
+                      class="field-table"
+                      table-layout="auto"
                       empty-text="褰撳墠DB鍧楁棤瀛楁鏄犲皠"
                     >
-                      <el-table-column prop="fieldKey" label="瀛楁" min-width="140" />
-                      <el-table-column prop="address" label="鍦板潃" width="130" />
-                      <el-table-column prop="mappedDb" label="鏄犲皠鍧�" width="120">
+                      <el-table-column prop="fieldKey" label="瀛楁" />
+                      <el-table-column prop="address" label="鍦板潃" />
+                      <el-table-column prop="mappedDb" label="鏄犲皠鍧�">
                         <template #default="{ row }">
-                          <el-tag :type="getDbTagType(row.mappedDb)" size="small">{{ row.mappedDb }}</el-tag>
+                          <el-tag :type="getDbTagType(row.mappedDb)">{{ row.mappedDb }}</el-tag>
                         </template>
                       </el-table-column>
-                      <el-table-column prop="dataType" label="绫诲瀷" width="90" />
-                      <el-table-column prop="direction" label="鏂瑰悜" width="130" />
-                      <el-table-column prop="value" label="褰撳墠鍊�" min-width="220" />
-                      <el-table-column label="淇敼鍊�" min-width="220">
+                      <el-table-column prop="dataType" label="绫诲瀷" />
+                      <el-table-column prop="direction" label="鏂瑰悜" />
+                      <el-table-column prop="value" label="褰撳墠鍊�" />
+                      <el-table-column label="淇敼鍊�">
                         <template #default="{ row }">
                           <el-switch
                             v-if="row.dataType === 'Bool'"
@@ -238,17 +269,18 @@
                             @change="markFieldDirty(row)"
                             :disabled="!isFieldWritable(row)"
                             :controls="false"
-                            style="width: 100%"
+                            class="editable-control"
                           />
                           <el-input
                             v-else
                             v-model="fieldEditValues[getFieldEditKey(row)]"
                             @input="markFieldDirty(row)"
                             :disabled="!isFieldWritable(row)"
+                            class="editable-control"
                           />
                         </template>
                       </el-table-column>
-                      <el-table-column label="鎿嶄綔" width="90" fixed="right">
+                      <el-table-column label="鎿嶄綔" width="88" fixed="right">
                         <template #default="{ row }">
                           <el-button
                             type="primary"
@@ -262,6 +294,8 @@
                         </template>
                       </el-table-column>
                     </el-table>
+                    </div>
+                    </template>
                     <div v-else class="text-muted">褰撳墠DB鍧楁棤瀛楁鏄犲皠</div>
 
                     <div class="card-header-title field-title">鍘熷鏁版嵁</div>
@@ -300,6 +334,10 @@
           />
         </div>
       </el-card>
+        </el-col>
+      </el-row>
+        </div>
+      </section>
     </div>
   </div>
 </template>
@@ -1065,48 +1103,8 @@
 </script>
 
 <style scoped>
-.page-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: flex-start;
-  margin-bottom: 20px;
-  flex-wrap: wrap;
-  gap: 16px;
-}
-
-.header-left h2 {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  margin: 0 0 8px 0;
-}
-
-.text-muted {
-  color: #909399;
-  margin: 0;
-}
-
-.loading-container {
-  text-align: center;
-  padding: 60px 0;
-  color: #909399;
-}
-
-.loading-icon {
-  animation: spin 1s linear infinite;
-}
-
-@keyframes spin {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}
-
 .status-cards {
-  margin-bottom: 20px;
+  margin-bottom: 8px;
 }
 
 .status-card {
@@ -1119,13 +1117,17 @@
 }
 
 .mt-4 {
-  margin-top: 16px;
+  margin-top: 14px;
 }
 
 .action-buttons {
   display: flex;
-  gap: 12px;
+  gap: 10px;
   flex-wrap: wrap;
+}
+
+.left-actions {
+  margin-top: 14px;
 }
 
 .db-header {
@@ -1142,7 +1144,7 @@
 
 .db-content {
   margin: 0;
-  max-height: 180px;
+  max-height: 168px;
   overflow: auto;
   white-space: pre-wrap;
   font-family: Consolas, Monaco, 'Courier New', monospace;
@@ -1168,11 +1170,11 @@
 }
 
 .db-tabs {
-  margin-top: 8px;
+  margin-top: 10px;
 }
 
 .data-view-tabs {
-  margin-top: 8px;
+  margin-top: 10px;
 }
 
 .db-raw-toolbar {
@@ -1189,4 +1191,35 @@
   margin-top: 12px;
   margin-bottom: 8px;
 }
+
+.field-table-wrap {
+  width: 100%;
+  overflow-x: auto;
+}
+
+:deep(.field-table) {
+  width: max-content;
+  min-width: 100%;
+}
+
+:deep(.editable-control) {
+  width: 100%;
+}
+
+:deep(.status-card .el-card__body) {
+  padding: 14px 16px;
+}
+
+:deep(.action-buttons .el-button) {
+  min-width: 82px;
+}
+
+:deep(.panel-card > .el-card__header) {
+  padding: 14px 18px;
+}
+
+:deep(.panel-card > .el-card__body) {
+  padding: 14px 18px;
+}
 </style>
+
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/EditView.vue b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/EditView.vue
index cf81d0f..ecc26b1 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/EditView.vue
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/EditView.vue
@@ -1,5 +1,5 @@
 锘�<template>
-  <div>
+  <div class="admin-page">
     <div v-if="loading" class="loading-container">
       <el-icon class="loading-icon" :size="40"><Loading /></el-icon>
       <p>鍔犺浇涓�...</p>
@@ -40,7 +40,7 @@
 
       <el-row justify="center">
         <el-col :lg="24">
-          <el-card shadow="never">
+          <el-card shadow="never" class="panel-card">
             <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
               <!-- 鍩烘湰淇℃伅 -->
               <el-divider content-position="left">
@@ -385,46 +385,6 @@
 </script>
 
 <style scoped>
-.page-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: flex-start;
-  margin-bottom: 20px;
-  flex-wrap: wrap;
-  gap: 16px;
-}
-
-.header-left h2 {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  margin: 0 0 8px 0;
-}
-
-.text-muted {
-  color: #909399;
-  margin: 0;
-}
-
-.loading-container {
-  text-align: center;
-  padding: 60px 0;
-  color: #909399;
-}
-
-.loading-icon {
-  animation: spin 1s linear infinite;
-}
-
-@keyframes spin {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}
-
 .form-tip {
   font-size: 12px;
   color: #909399;
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue
index e16d086..06cb505 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue
@@ -1,5 +1,6 @@
 锘�<template>
   <div
+    class="admin-page"
     v-loading.fullscreen.lock="startActionLoading"
     element-loading-text="姝e湪鍚姩瀹炰緥锛岃绋嶅��..."
   >
@@ -12,16 +13,43 @@
         <p class="text-muted">绠$悊鍜岀洃鎺� S7 PLC 妯℃嫙鍣ㄥ疄渚�</p>
       </div>
       <div class="header-right">
-        <div class="stats">
-          <span>杩愯涓�: {{ runningCount }} | 宸插仠姝�: {{ stoppedCount }}</span>
-          <span v-if="errorCount > 0" class="error-text">| 閿欒: {{ errorCount }}</span>
-        </div>
-        <el-button type="primary" @click="$router.push('/create')">
+        <el-button type="primary" class="create-btn" @click="$router.push('/create')">
           <el-icon><Plus /></el-icon>
           鍒涘缓瀹炰緥
         </el-button>
       </div>
     </div>
+
+    <section class="section-block">
+      <div class="section-head">
+        <div>
+          <h3 class="section-title">淇℃伅鍖�</h3>
+          <p class="section-desc">瀹炰緥杩愯鐘舵�佹�昏</p>
+        </div>
+      </div>
+      <div class="section-body">
+        <el-row :gutter="12" class="summary-row">
+          <el-col :xs="24" :sm="8">
+            <el-card shadow="hover" class="summary-card running-card">
+              <div class="summary-title">杩愯涓�</div>
+              <div class="summary-value">{{ runningCount }}</div>
+            </el-card>
+          </el-col>
+          <el-col :xs="24" :sm="8">
+            <el-card shadow="hover" class="summary-card stopped-card">
+              <div class="summary-title">宸插仠姝�</div>
+              <div class="summary-value">{{ stoppedCount }}</div>
+            </el-card>
+          </el-col>
+          <el-col :xs="24" :sm="8">
+            <el-card shadow="hover" class="summary-card error-card">
+              <div class="summary-title">閿欒瀹炰緥</div>
+              <div class="summary-value">{{ errorCount }}</div>
+            </el-card>
+          </el-col>
+        </el-row>
+      </div>
+    </section>
 
     <!-- Loading state -->
     <div v-if="loading && instances.length === 0" class="loading-container">
@@ -35,45 +63,75 @@
     </el-empty>
 
     <!-- Instances grid -->
-    <el-row v-else :gutter="20">
-      <el-col v-for="instance in instances" :key="instance.instanceId" :xs="24" :sm="12" :xl="8">
-        <el-card class="instance-card" :class="getStatusClass(instance.status)" shadow="hover">
-          <template #header>
-            <div class="card-header">
-              <span class="instance-id">{{ instance.instanceId }}</span>
-              <el-tag :type="getStatusTagType(instance.status)">
-                {{ getStatusText(instance.status) }}
-              </el-tag>
+    <section v-else class="section-block">
+      <div class="section-head">
+        <div>
+          <h3 class="section-title">鎿嶄綔鍖�</h3>
+          <p class="section-desc">瀹炰緥鍚姩銆佸仠姝€�佺紪杈戜笌璇︽儏鍏ュ彛</p>
+        </div>
+      </div>
+      <div class="section-body">
+        <el-row :gutter="14" class="instances-grid">
+          <el-col
+            v-for="instance in instances"
+            :key="instance.instanceId"
+            :xs="24"
+            :sm="12"
+            :md="12"
+            :lg="8"
+            :xl="6"
+          >
+            <el-card class="instance-card panel-card" :class="getStatusClass(instance.status)" shadow="hover">
+          <div class="card-glow"></div>
+
+          <div class="card-top">
+            <div class="card-title">
+              <div class="instance-id-line">
+                <span class="instance-id">{{ instance.instanceId }}</span>
+                <span class="instance-name">{{ instance.name || '鏈懡鍚嶅疄渚�' }}</span>
+                <span class="instance-sub">PLC</span>
+              </div>
             </div>
-          </template>
-
-          <div class="instance-info">
-            <el-descriptions :column="2" size="small">
-              <el-descriptions-item label="鍚嶇О">{{ instance.name || '-' }}</el-descriptions-item>
-              <el-descriptions-item label="PLC鍨嬪彿">{{ getPlcTypeText(instance.plcType) }}</el-descriptions-item>
-              <el-descriptions-item label="绔彛">{{ instance.port || '-' }}</el-descriptions-item>
-              <el-descriptions-item label="瀹㈡埛绔�">
-                <el-icon><User /></el-icon>
-                {{ instance.clientCount || 0 }}
-              </el-descriptions-item>
-              <el-descriptions-item v-if="instance.startTime" label="鍚姩鏃堕棿" :span="2">
-                {{ formatDate(instance.startTime) }}
-              </el-descriptions-item>
-            </el-descriptions>
-
-            <el-alert
-              v-if="instance.errorMessage"
-              type="error"
-              :closable="false"
-              class="mt-2"
-              show-icon
-            >
-              {{ instance.errorMessage }}
-            </el-alert>
+            <el-tag :type="getStatusTagType(instance.status)" effect="dark" round>
+              {{ getStatusText(instance.status) }}
+            </el-tag>
           </div>
 
-          <template #footer>
-            <div class="card-footer">
+          <div class="meta-row">
+              <div class="meta-chip">
+                <span class="chip-label">PLC</span>
+                <span class="chip-value">{{ getPlcTypeText(instance.plcType) }}</span>
+              </div>
+            <div class="meta-chip">
+              <span class="chip-label">绔彛</span>
+              <span class="chip-value">{{ instance.port || '-' }}</span>
+            </div>
+            <div class="meta-chip">
+              <span class="chip-label">瀹㈡埛绔�</span>
+              <span class="chip-value">
+                <el-icon><User /></el-icon>
+                {{ instance.clientCount || 0 }}
+              </span>
+            </div>
+          </div>
+
+          <div class="time-row">
+            <span class="time-label">鍚姩鏃堕棿</span>
+            <span class="time-value">{{ instance.startTime ? formatDate(instance.startTime) : '-' }}</span>
+          </div>
+
+          <el-alert
+            v-if="instance.errorMessage"
+            type="error"
+            :closable="false"
+            class="mt-2"
+            show-icon
+          >
+            {{ instance.errorMessage }}
+          </el-alert>
+
+          <div class="card-footer">
+            <div class="main-actions">
               <el-button
                 v-if="instance.status === 'Running'"
                 type="warning"
@@ -98,14 +156,16 @@
                 <el-icon><Edit /></el-icon>
                 缂栬緫
               </el-button>
-              <el-button type="danger" @click="handleDelete(instance.instanceId)">
-                <el-icon><Delete /></el-icon>
-              </el-button>
             </div>
-          </template>
-        </el-card>
-      </el-col>
-    </el-row>
+            <el-button class="delete-btn" type="danger" @click="handleDelete(instance.instanceId)">
+              <el-icon><Delete /></el-icon>
+            </el-button>
+          </div>
+            </el-card>
+          </el-col>
+        </el-row>
+      </div>
+    </section>
   </div>
 </template>
 
@@ -246,106 +306,220 @@
 </script>
 
 <style scoped>
-.page-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: flex-start;
-  margin-bottom: 20px;
-  flex-wrap: wrap;
-  gap: 16px;
-}
-
 .header-left h2 {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  margin: 0 0 8px 0;
-}
-
-.text-muted {
-  color: #909399;
   margin: 0;
 }
 
 .header-right {
   display: flex;
   align-items: center;
-  gap: 16px;
+  gap: 10px;
   flex-wrap: wrap;
 }
 
-.stats {
-  color: #606266;
-  font-size: 14px;
+.create-btn {
+  padding-inline: 18px;
 }
 
-.error-text {
-  color: #f56c6c;
+.summary-row {
+  margin-top: -2px;
+  margin-bottom: 2px;
 }
 
-.loading-container {
-  text-align: center;
-  padding: 60px 0;
-  color: #909399;
+.instances-grid {
+  max-width: 1500px;
 }
 
-.loading-icon {
-  animation: spin 1s linear infinite;
+.summary-card {
+  border-radius: 12px;
+  border: 1px solid #dbe2ea;
+  overflow: hidden;
 }
 
-@keyframes spin {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
+.summary-title {
+  color: #64748b;
+  font-size: 13px;
+  margin-bottom: 6px;
+}
+
+.summary-value {
+  font-size: 28px;
+  font-weight: 700;
+  line-height: 1;
+}
+
+.running-card {
+  background: linear-gradient(180deg, #f0fdf4 0%, #ffffff 100%);
+}
+
+.running-card .summary-value {
+  color: #15803d;
+}
+
+.stopped-card {
+  background: linear-gradient(180deg, #f8fafc 0%, #ffffff 100%);
+}
+
+.stopped-card .summary-value {
+  color: #334155;
+}
+
+.error-card {
+  background: linear-gradient(180deg, #fef2f2 0%, #ffffff 100%);
+}
+
+.error-card .summary-value {
+  color: #b91c1c;
 }
 
 .instance-card {
-  margin-bottom: 20px;
-  transition: all 0.3s;
+  margin-bottom: 10px;
+  position: relative;
+  border-radius: 12px;
+  border: 1px solid #dbe2ea;
+  transition: all 0.25s;
+  overflow: hidden;
 }
 
 .instance-card:hover {
-  transform: translateY(-4px);
+  transform: translateY(-3px);
+  box-shadow: 0 14px 26px rgba(15, 23, 42, 0.1);
 }
 
-.card-header {
+.card-glow {
+  position: absolute;
+  top: -56px;
+  right: -56px;
+  width: 100px;
+  height: 100px;
+  border-radius: 50%;
+  background: radial-gradient(circle, rgba(14, 116, 244, 0.16), transparent 70%);
+  pointer-events: none;
+}
+
+.card-title {
   display: flex;
-  justify-content: space-between;
-  align-items: center;
+  flex-direction: column;
+  gap: 1px;
+  min-width: 0;
 }
 
 .instance-id {
   font-weight: 600;
-  font-size: 16px;
+  font-size: 15px;
+  color: #0f172a;
+  white-space: nowrap;
 }
 
-.instance-info {
-  margin-bottom: 16px;
+.instance-name {
+  color: #64748b;
+  font-size: 12px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 
-.card-footer {
+.instance-id-line {
   display: flex;
+  align-items: baseline;
+  gap: 6px;
+  min-width: 0;
+}
+
+.instance-sub {
+  color: #94a3b8;
+  font-size: 10px;
+}
+
+.card-top {
+  margin-top: 2px;
+  display: flex;
+  justify-content: space-between;
   gap: 8px;
+  align-items: flex-start;
+}
+
+.meta-row {
+  margin-top: 8px;
+  display: flex;
+  gap: 6px;
   flex-wrap: wrap;
 }
 
-.card-footer .el-button {
-  flex: 1;
-  min-width: 60px;
+.meta-chip {
+  border: 1px solid #e2e8f0;
+  border-radius: 999px;
+  padding: 4px 8px;
+  background: #f8fafc;
+  display: inline-flex;
+  align-items: center;
+  gap: 6px;
 }
 
-.status-stopped { border-left: 4px solid #909399; }
-.status-starting { border-left: 4px solid #409eff; }
-.status-running { border-left: 4px solid #67c23a; }
-.status-stopping { border-left: 4px solid #e6a23c; }
-.status-error { border-left: 4px solid #f56c6c; }
+.chip-label {
+  font-size: 10px;
+  line-height: 1;
+  color: #64748b;
+  padding: 1px 5px;
+  border-radius: 999px;
+  background: #e2e8f0;
+}
+
+.chip-value {
+  font-size: 12px;
+  line-height: 1;
+  color: #0f172a;
+  display: inline-flex;
+  align-items: center;
+  gap: 4px;
+}
+
+.time-row {
+  margin-top: 7px;
+  margin-bottom: 8px;
+  display: flex;
+  justify-content: space-between;
+  gap: 8px;
+  font-size: 11px;
+}
+
+.time-label {
+  color: #64748b;
+}
+
+.time-value {
+  color: #0f172a;
+}
+
+.card-footer {
+  border-top: 1px dashed #dbe2ea;
+  padding-top: 8px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  gap: 10px;
+}
+
+.main-actions {
+  display: flex;
+  gap: 6px;
+  flex-wrap: wrap;
+}
+
+.main-actions .el-button {
+  border-radius: 8px;
+  height: 28px;
+  padding: 0 10px;
+}
+
+.delete-btn {
+  border-radius: 8px;
+  height: 28px;
+  padding: 0 10px;
+}
 
 .mt-2 {
   margin-top: 8px;
 }
 </style>
-
 
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/ProtocolTemplatesView.vue b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/ProtocolTemplatesView.vue
index 75f038f..be2a12f 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/ProtocolTemplatesView.vue
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/ProtocolTemplatesView.vue
@@ -1,5 +1,5 @@
 锘�<template>
-  <div>
+  <div class="admin-page">
     <div class="page-header">
       <div>
         <h2>鍗忚妯℃澘绠$悊</h2>
@@ -8,7 +8,8 @@
       <el-button type="primary" @click="openNewTemplate">鏂板缓妯℃澘</el-button>
     </div>
 
-    <el-table :data="templates" border>
+    <el-card shadow="never" class="panel-card">
+      <el-table :data="templates" border>
       <el-table-column prop="id" label="妯℃澘ID" width="240" />
       <el-table-column prop="name" label="鍚嶇О" min-width="240" />
       <el-table-column prop="version" label="鐗堟湰" width="140" />
@@ -21,7 +22,8 @@
           <el-button size="small" type="danger" @click="removeTemplate(row.id)">鍒犻櫎</el-button>
         </template>
       </el-table-column>
-    </el-table>
+      </el-table>
+    </el-card>
 
     <el-dialog v-model="dialogVisible" title="鍗忚妯℃澘" width="96vw" top="2vh" class="protocol-dialog">
       <el-form :model="editing" label-width="100px">
@@ -187,18 +189,6 @@
 </script>
 
 <style scoped>
-.page-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: flex-start;
-  margin-bottom: 16px;
-}
-
-.text-muted {
-  color: #909399;
-  margin: 4px 0 0 0;
-}
-
 .mt-2 {
   margin-top: 12px;
 }
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/RobotClientsView.vue b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/RobotClientsView.vue
new file mode 100644
index 0000000..693aa25
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/RobotClientsView.vue
@@ -0,0 +1,452 @@
+锘�<template>
+  <div class="admin-page robot-admin-page">
+    <div class="page-header">
+      <div>
+        <h2>鏈烘鎵嬪鎴风绠$悊鍙�</h2>
+        <p class="text-muted">澶氬疄渚嬭繛鎺ョ洰鏍囨湇鍔$銆佹秷鎭敹鍙戠洃鎺�</p>
+      </div>
+      <div class="toolbar-actions">
+        <el-button :loading="refreshing" @click="loadStatus">鍒锋柊</el-button>
+        <el-button type="danger" :loading="stoppingAll" @click="handleStopAll">鍋滄鍏ㄩ儴</el-button>
+      </div>
+    </div>
+
+    <el-row :gutter="12" class="stats-row">
+      <el-col :xs="24" :sm="8">
+        <el-card shadow="hover" class="stat-card">
+          <el-statistic title="杩愯瀹炰緥" :value="status?.runningServerCount ?? 0" />
+        </el-card>
+      </el-col>
+      <el-col :xs="24" :sm="8">
+        <el-card shadow="hover" class="stat-card">
+          <el-statistic title="瀹炰緥鎬绘暟" :value="status?.servers.length ?? 0" />
+        </el-card>
+      </el-col>
+      <el-col :xs="24" :sm="8">
+        <el-card shadow="hover" class="stat-card">
+          <el-statistic title="鍦ㄧ嚎杩炴帴鎬绘暟" :value="totalConnectedCount" />
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <el-card shadow="never" class="create-card">
+      <template #header>
+        <span>鏂板瀹㈡埛绔疄渚�</span>
+      </template>
+      <el-form :inline="true" :model="startForm" class="create-form">
+        <el-form-item label="瀹炰緥ID">
+          <el-input v-model="startForm.serverId" placeholder="robot-client-1" style="width: 180px" />
+        </el-form-item>
+        <el-form-item label="鏈嶅姟绔湴鍧�">
+          <el-input v-model="startForm.listenIp" placeholder="127.0.0.1" style="width: 160px" />
+        </el-form-item>
+        <el-form-item label="鏈嶅姟绔鍙�">
+          <el-input-number v-model="startForm.listenPort" :min="1" :max="65535" />
+        </el-form-item>
+        <el-form-item label="鏈湴绔彛">
+          <el-input-number v-model="startForm.localPort" :min="1" :max="65535" />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" :loading="starting" @click="handleStart">杩炴帴瀹炰緥</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <el-row :gutter="12" class="main-row">
+      <el-col :xs="24" :lg="8">
+        <el-card shadow="never" class="panel-card">
+          <template #header>
+            <span>瀹㈡埛绔疄渚嬪垪琛�</span>
+          </template>
+          <el-table
+            :data="status?.servers || []"
+            border
+            size="small"
+            highlight-current-row
+            :row-class-name="serverRowClassName"
+            @row-click="onServerRowClick"
+          >
+            <el-table-column prop="serverId" label="瀹炰緥ID" min-width="120" />
+            <el-table-column label="鐩爣鏈嶅姟绔�" min-width="130">
+              <template #default="{ row }">{{ row.listenIp }}:{{ row.listenPort }}</template>
+            </el-table-column>
+            <el-table-column prop="localPort" label="鏈湴绔彛" width="100" />
+            <el-table-column prop="connectedCount" label="杩炴帴" width="70" />
+            <el-table-column label="鎿嶄綔" width="90">
+              <template #default="{ row }">
+                <el-button link type="danger" @click.stop="handleStopOne(row.serverId)">鍋滄</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-card>
+      </el-col>
+
+      <el-col :xs="24" :lg="16">
+        <el-card v-if="selectedServer" shadow="never" class="panel-card">
+          <template #header>
+            <div class="panel-header">
+              <span>瀹炰緥璇︽儏锛歿{ selectedServer.serverId }}</span>
+              <el-tag :type="selectedServer.running ? 'success' : 'info'">
+                {{ selectedServer.running ? '杩愯涓�' : '宸插仠姝�' }}
+              </el-tag>
+            </div>
+          </template>
+
+          <el-descriptions :column="4" border class="desc-block">
+            <el-descriptions-item label="鏈嶅姟绔湴鍧�">{{ selectedServer.listenIp }}</el-descriptions-item>
+            <el-descriptions-item label="鏈嶅姟绔鍙�">{{ selectedServer.listenPort }}</el-descriptions-item>
+            <el-descriptions-item label="鏈湴绔彛">{{ selectedServer.localPort }}</el-descriptions-item>
+            <el-descriptions-item label="杩炴帴鐘舵��">{{ selectedServer.connectedCount > 0 ? '宸茶繛鎺�' : '鏈繛鎺�' }}</el-descriptions-item>
+          </el-descriptions>
+
+          <div class="message-actions">
+            <el-button type="primary" @click="openMessageCenter">
+              娑堟伅涓績
+            </el-button>
+          </div>
+
+          <el-card shadow="never" class="connection-card">
+            <template #header>
+              <span>杩炴帴鍒楄〃</span>
+            </template>
+            <el-table :data="selectedServer.clients || []" border size="small">
+              <el-table-column prop="clientId" label="杩炴帴ID" width="100" />
+              <el-table-column prop="remoteEndPoint" label="杩滅鍦板潃" min-width="170" />
+              <el-table-column label="鐘舵��" width="100">
+                <template #default="{ row }">
+                  <el-tag :type="row.connected ? 'success' : 'danger'">{{ row.connected ? '鍦ㄧ嚎' : '绂荤嚎' }}</el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column prop="connectedAt" label="杩炴帴鏃堕棿" min-width="170" />
+              <el-table-column prop="lastReceivedAt" label="鏈�杩戞帴鏀�" min-width="170" />
+              <el-table-column prop="lastSentAt" label="鏈�杩戝彂閫�" min-width="170" />
+              <el-table-column prop="lastError" label="鏈�鍚庨敊璇�" min-width="190" />
+            </el-table>
+          </el-card>
+        </el-card>
+
+        <el-empty v-else description="璇烽�夋嫨宸︿晶瀹㈡埛绔疄渚嬫煡鐪嬭鎯�" />
+      </el-col>
+    </el-row>
+
+    <el-dialog
+      v-model="messageCenterVisible"
+      title="娑堟伅涓績"
+      width="78vw"
+      destroy-on-close
+    >
+      <el-card shadow="never" class="message-send-card">
+        <template #header>
+          <span>鍙戦�佹寚浠�</span>
+        </template>
+        <div class="send-row">
+          <el-input v-model="sendMessage" placeholder="渚嬪 Pickbattery,1" />
+          <el-button type="primary" :loading="sending" @click="handleSend">鍙戦��</el-button>
+        </div>
+      </el-card>
+
+      <el-tabs v-model="messageTab">
+        <el-tab-pane
+          :label="`鎺ユ敹娑堟伅 (${selectedServer?.receivedMessages?.length || 0})`"
+          name="received"
+        >
+          <div class="message-toolbar">
+            <el-button
+              link
+              type="danger"
+              :loading="clearingMessages"
+              @click="handleClearMessages"
+            >
+              娓呯┖娑堟伅
+            </el-button>
+          </div>
+          <el-table :data="selectedServer?.receivedMessages || []" border size="small" max-height="430">
+            <el-table-column prop="receivedAt" label="鎺ユ敹鏃堕棿" min-width="170" />
+            <el-table-column prop="clientId" label="杩炴帴ID" width="100" />
+            <el-table-column prop="remoteEndPoint" label="杩滅鍦板潃" min-width="170" />
+            <el-table-column prop="message" label="娑堟伅鍐呭" min-width="250" />
+          </el-table>
+        </el-tab-pane>
+        <el-tab-pane
+          :label="`鍙戦�佹秷鎭� (${selectedServer?.sentMessages?.length || 0})`"
+          name="sent"
+        >
+          <el-table :data="selectedServer?.sentMessages || []" border size="small" max-height="430">
+            <el-table-column prop="sentAt" label="鍙戦�佹椂闂�" min-width="170" />
+            <el-table-column prop="clientId" label="杩炴帴ID" width="100" />
+            <el-table-column prop="remoteEndPoint" label="杩滅鍦板潃" min-width="170" />
+            <el-table-column prop="message" label="娑堟伅鍐呭" min-width="250" />
+          </el-table>
+        </el-tab-pane>
+      </el-tabs>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, onMounted, onUnmounted, ref } from 'vue'
+import { ElMessage } from 'element-plus'
+import {
+  clearRobotClientReceivedMessages,
+  getRobotClientStatus,
+  sendRobotClientMessage,
+  startRobotClients,
+  stopRobotClients
+} from '../api'
+import type {
+  RobotClientStartRequest,
+  RobotClientStatusResponse,
+  RobotServerStatusItem
+} from '../types'
+
+const startForm = ref<RobotClientStartRequest>({
+  serverId: 'robot-client-1',
+  listenIp: '127.0.0.1',
+  listenPort: 2000,
+  localPort: 2001
+})
+
+const status = ref<RobotClientStatusResponse | null>(null)
+const selectedServerId = ref('')
+
+const refreshing = ref(false)
+const starting = ref(false)
+const stoppingAll = ref(false)
+const sending = ref(false)
+const clearingMessages = ref(false)
+const messageCenterVisible = ref(false)
+const messageTab = ref<'received' | 'sent'>('received')
+
+const sendMessage = ref('')
+
+let timer: number | null = null
+
+const totalConnectedCount = computed(() =>
+  (status.value?.servers || []).reduce((sum, x) => sum + (x.connectedCount || 0), 0)
+)
+
+const selectedServer = computed<RobotServerStatusItem | null>(() => {
+  if (!status.value) return null
+  return status.value.servers.find(x => x.serverId === selectedServerId.value) || null
+})
+
+async function loadStatus() {
+  refreshing.value = true
+  try {
+    status.value = await getRobotClientStatus()
+    if ((status.value.servers || []).length > 0) {
+      const exists = status.value.servers.some(x => x.serverId === selectedServerId.value)
+      if (!exists) {
+        selectedServerId.value = status.value.servers[0].serverId
+      }
+    } else {
+      selectedServerId.value = ''
+    }
+  } catch (error) {
+    console.error(error)
+  } finally {
+    refreshing.value = false
+  }
+}
+
+function onServerRowClick(row: RobotServerStatusItem) {
+  selectedServerId.value = row.serverId
+}
+
+function serverRowClassName(args: { row: RobotServerStatusItem }) {
+  return args.row.serverId === selectedServerId.value ? 'is-selected-row' : ''
+}
+
+function openMessageCenter() {
+  if (!selectedServer.value) {
+    ElMessage.warning('璇峰厛閫夋嫨涓�涓鎴风瀹炰緥')
+    return
+  }
+
+  messageTab.value = 'received'
+  messageCenterVisible.value = true
+}
+
+async function handleStart() {
+  if (!startForm.value.serverId.trim()) {
+    ElMessage.warning('璇疯緭鍏ュ疄渚婭D')
+    return
+  }
+
+  starting.value = true
+  try {
+    status.value = await startRobotClients({
+      ...startForm.value,
+      serverId: startForm.value.serverId.trim()
+    })
+    selectedServerId.value = startForm.value.serverId.trim()
+    ElMessage.success('瀹㈡埛绔疄渚嬭繛鎺ユ垚鍔�')
+  } catch (error) {
+    console.error(error)
+    ElMessage.error('杩炴帴澶辫触锛岃妫�鏌ユ湇鍔$鍦板潃鍜岀鍙�')
+  } finally {
+    starting.value = false
+  }
+}
+
+async function handleStopAll() {
+  stoppingAll.value = true
+  try {
+    await stopRobotClients()
+    await loadStatus()
+    ElMessage.success('鍏ㄩ儴瀹㈡埛绔疄渚嬪凡鍋滄')
+  } catch (error) {
+    console.error(error)
+    ElMessage.error('鍋滄澶辫触锛岃鏌ョ湅鏃ュ織')
+  } finally {
+    stoppingAll.value = false
+  }
+}
+
+async function handleStopOne(serverId: string) {
+  try {
+    await stopRobotClients(serverId)
+    await loadStatus()
+    ElMessage.success(`瀹炰緥 ${serverId} 宸插仠姝)
+  } catch (error) {
+    console.error(error)
+    ElMessage.error('鍋滄瀹炰緥澶辫触')
+  }
+}
+
+async function handleSend() {
+  if (!selectedServer.value) {
+    ElMessage.warning('璇峰厛閫夋嫨涓�涓鎴风瀹炰緥')
+    return
+  }
+
+  if (!sendMessage.value.trim()) {
+    ElMessage.warning('璇疯緭鍏ュ彂閫佸唴瀹�')
+    return
+  }
+
+  sending.value = true
+  try {
+    await sendRobotClientMessage({
+      serverId: selectedServer.value.serverId,
+      clientId: null,
+      message: sendMessage.value.trim()
+    })
+    ElMessage.success('鍙戦�佹垚鍔�')
+  } catch (error) {
+    console.error(error)
+    ElMessage.error('鍙戦�佸け璐ワ紝璇锋鏌ヨ繛鎺ョ姸鎬�')
+  } finally {
+    sending.value = false
+  }
+}
+
+async function handleClearMessages() {
+  if (!selectedServer.value) {
+    ElMessage.warning('璇峰厛閫夋嫨涓�涓鎴风瀹炰緥')
+    return
+  }
+
+  clearingMessages.value = true
+  try {
+    await clearRobotClientReceivedMessages(selectedServer.value.serverId)
+    await loadStatus()
+    ElMessage.success('鎺ユ敹娑堟伅宸叉竻绌�')
+  } catch (error) {
+    console.error(error)
+    ElMessage.error('娓呯┖澶辫触锛岃鏌ョ湅鏃ュ織')
+  } finally {
+    clearingMessages.value = false
+  }
+}
+
+onMounted(async () => {
+  await loadStatus()
+  timer = window.setInterval(() => {
+    loadStatus()
+  }, 2000)
+})
+
+onUnmounted(() => {
+  if (timer !== null) {
+    clearInterval(timer)
+  }
+})
+</script>
+
+<style scoped>
+.robot-admin-page {
+  display: flex;
+  flex-direction: column;
+  gap: 14px;
+}
+
+.toolbar-actions {
+  display: flex;
+  gap: 8px;
+}
+
+.stats-row {
+  margin-bottom: 0;
+}
+
+.stat-card {
+  min-height: 92px;
+}
+
+.create-card,
+.panel-card {
+  border-radius: 8px;
+}
+
+.create-form {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px 12px;
+}
+
+.main-row {
+  margin-top: 0;
+}
+
+.panel-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.desc-block {
+  margin-bottom: 12px;
+}
+
+.connection-card {
+  margin-top: 8px;
+}
+
+.message-send-card {
+  margin-bottom: 8px;
+}
+
+.send-row {
+  display: flex;
+  gap: 8px;
+  align-items: center;
+  flex-wrap: wrap;
+}
+
+.message-actions {
+  display: flex;
+  gap: 10px;
+  margin-bottom: 8px;
+}
+
+.message-toolbar {
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 6px;
+}
+
+:deep(.is-selected-row td) {
+  background-color: #ecf5ff !important;
+}
+</style>
diff --git a/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json b/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json
index 3c0868f..cee9aa1 100644
--- a/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json
+++ b/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json
@@ -3,40 +3,16 @@
   "WorkspaceRootPath": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\",
   "Documents": [
     {
-      "AbsoluteMoniker": "D:0:0:{83F18A31-5983-4587-A0B2-414BF70E50B5}|WIDESEAWCS_TaskInfoService\\WIDESEAWCS_TaskInfoService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{83F18A31-5983-4587-A0B2-414BF70E50B5}|WIDESEAWCS_TaskInfoService\\WIDESEAWCS_TaskInfoService.csproj|solutionrelative:wideseawcs_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\conveyorlinenewjob\\commonconveyorlinenewjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\conveyorlinenewjob\\commonconveyorlinenewjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{861C4D0B-A478-48DB-A0FA-AE70F5BA210A}|WIDESEAWCS_Communicator\\WIDESEAWCS_Communicator.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_communicator\\siemens\\siemenss7communicator.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{861C4D0B-A478-48DB-A0FA-AE70F5BA210A}|WIDESEAWCS_Communicator\\WIDESEAWCS_Communicator.csproj|solutionrelative:wideseawcs_communicator\\siemens\\siemenss7communicator.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\conveyorlinenewjob\\conveyorlinedispatchhandler.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\conveyorlinenewjob\\conveyorlinedispatchhandler.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{6236BFFF-173D-44A8-9FC3-7C001EA30347}|WIDESEAWCS_QuartzJob\\WIDESEAWCS_QuartzJob.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_quartzjob\\service\\routerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{6236BFFF-173D-44A8-9FC3-7C001EA30347}|WIDESEAWCS_QuartzJob\\WIDESEAWCS_QuartzJob.csproj|solutionrelative:wideseawcs_quartzjob\\service\\routerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_common\\httpenum\\configkey.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|solutionrelative:wideseawcs_common\\httpenum\\configkey.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
-    },
-    {
-      "AbsoluteMoniker": "D:0:0:{BFFDD936-2E61-4D3A-ABFE-7CF77FE0B184}|WIDESEAWCS_Core\\WIDESEAWCS_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_core\\http\\http\\httpclienthelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{BFFDD936-2E61-4D3A-ABFE-7CF77FE0B184}|WIDESEAWCS_Core\\WIDESEAWCS_Core.csproj|solutionrelative:wideseawcs_core\\http\\http\\httpclienthelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+      "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\workflow\\robotworkfloworchestrator.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+      "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\workflow\\robotworkfloworchestrator.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
     },
     {
       "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
       "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
     },
     {
-      "AbsoluteMoniker": "D:0:0:{7F200FE8-CAF6-4131-BD25-8D438FE0ABAC}|WIDESEAWCS_Model\\WIDESEAWCS_Model.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_model\\models\\taskinfo\\dt_task_hty.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{7F200FE8-CAF6-4131-BD25-8D438FE0ABAC}|WIDESEAWCS_Model\\WIDESEAWCS_Model.csproj|solutionrelative:wideseawcs_model\\models\\taskinfo\\dt_task_hty.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+      "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotmessagehandler.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+      "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotmessagehandler.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
     }
   ],
   "DocumentGroupContainers": [
@@ -46,7 +22,7 @@
       "DocumentGroups": [
         {
           "DockedWidth": 200,
-          "SelectedChildIndex": 11,
+          "SelectedChildIndex": 3,
           "Children": [
             {
               "$type": "Bookmark",
@@ -62,116 +38,40 @@
             },
             {
               "$type": "Document",
-              "DocumentIndex": 3,
-              "Title": "ConveyorLineDispatchHandler.cs",
-              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\ConveyorLineNewJob\\ConveyorLineDispatchHandler.cs",
-              "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\ConveyorLineNewJob\\ConveyorLineDispatchHandler.cs",
-              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\ConveyorLineNewJob\\ConveyorLineDispatchHandler.cs",
-              "RelativeToolTip": "WIDESEAWCS_Tasks\\ConveyorLineNewJob\\ConveyorLineDispatchHandler.cs",
-              "ViewState": "AgIAAIgAAAAAAAAAAAAlwKAAAAAQAAAAAAAAAA==",
+              "DocumentIndex": 0,
+              "Title": "RobotWorkflowOrchestrator.cs",
+              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\Workflow\\RobotWorkflowOrchestrator.cs",
+              "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\Workflow\\RobotWorkflowOrchestrator.cs",
+              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\Workflow\\RobotWorkflowOrchestrator.cs*",
+              "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\Workflow\\RobotWorkflowOrchestrator.cs*",
+              "ViewState": "AgIAAAAAAAAAAAAAAAAAACMAAABzAAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-18T03:31:16.145Z",
+              "WhenOpened": "2026-03-18T09:21:38.852Z",
               "EditorCaption": ""
             },
             {
               "$type": "Document",
               "DocumentIndex": 2,
-              "Title": "SiemensS7Communicator.cs",
-              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Communicator\\Siemens\\SiemensS7Communicator.cs",
-              "RelativeDocumentMoniker": "WIDESEAWCS_Communicator\\Siemens\\SiemensS7Communicator.cs",
-              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Communicator\\Siemens\\SiemensS7Communicator.cs",
-              "RelativeToolTip": "WIDESEAWCS_Communicator\\Siemens\\SiemensS7Communicator.cs",
-              "ViewState": "AgIAANkBAAAAAAAAAAAewOsBAAAQAAAAAAAAAA==",
+              "Title": "RobotMessageHandler.cs",
+              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs",
+              "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs",
+              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs",
+              "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs",
+              "ViewState": "AgIAABMAAAAAAAAAAAAAwDIAAAAQAAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-18T03:25:37.718Z",
-              "EditorCaption": ""
+              "WhenOpened": "2026-03-18T09:10:02.533Z"
             },
             {
               "$type": "Document",
-              "DocumentIndex": 4,
-              "Title": "RouterService.cs",
-              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_QuartzJob\\Service\\RouterService.cs",
-              "RelativeDocumentMoniker": "WIDESEAWCS_QuartzJob\\Service\\RouterService.cs",
-              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_QuartzJob\\Service\\RouterService.cs",
-              "RelativeToolTip": "WIDESEAWCS_QuartzJob\\Service\\RouterService.cs",
-              "ViewState": "AgIAACYBAAAAAAAAAAAlwDkBAAAIAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-17T07:55:50.917Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 7,
+              "DocumentIndex": 1,
               "Title": "RobotJob.cs",
               "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
               "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
               "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
               "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
-              "ViewState": "AgIAADwAAAAAAAAAAADwv1UAAAAxAAAAAAAAAA==",
+              "ViewState": "AgIAAEoAAAAAAAAAAAAAwGAAAAA7AAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-17T02:11:28.683Z"
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 8,
-              "Title": "Dt_Task_Hty.cs",
-              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Model\\Models\\TaskInfo\\Dt_Task_Hty.cs",
-              "RelativeDocumentMoniker": "WIDESEAWCS_Model\\Models\\TaskInfo\\Dt_Task_Hty.cs",
-              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Model\\Models\\TaskInfo\\Dt_Task_Hty.cs",
-              "RelativeToolTip": "WIDESEAWCS_Model\\Models\\TaskInfo\\Dt_Task_Hty.cs",
-              "ViewState": "AgIAAAsAAAAAAAAAAAAwwAsAAAAmAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-13T02:59:26.007Z"
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 5,
-              "Title": "ConfigKey.cs",
-              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\HttpEnum\\ConfigKey.cs",
-              "RelativeDocumentMoniker": "WIDESEAWCS_Common\\HttpEnum\\ConfigKey.cs",
-              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\HttpEnum\\ConfigKey.cs",
-              "RelativeToolTip": "WIDESEAWCS_Common\\HttpEnum\\ConfigKey.cs",
-              "ViewState": "AgIAABkAAAAAAAAAAAAawCwAAAAIAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-12T01:55:15.084Z"
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 6,
-              "Title": "HttpClientHelper.cs",
-              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs",
-              "RelativeDocumentMoniker": "WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs",
-              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs",
-              "RelativeToolTip": "WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs",
-              "ViewState": "AgIAABAAAAAAAAAAAAAAAB8AAAASAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-12T01:54:05.934Z"
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 1,
-              "Title": "CommonConveyorLineNewJob.cs",
-              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\ConveyorLineNewJob\\CommonConveyorLineNewJob.cs",
-              "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\ConveyorLineNewJob\\CommonConveyorLineNewJob.cs",
-              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\ConveyorLineNewJob\\CommonConveyorLineNewJob.cs",
-              "RelativeToolTip": "WIDESEAWCS_Tasks\\ConveyorLineNewJob\\CommonConveyorLineNewJob.cs",
-              "ViewState": "AgIAADwAAAAAAAAAAAApwFEAAAAcAAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-11T09:29:57.419Z",
-              "EditorCaption": ""
-            },
-            {
-              "$type": "Document",
-              "DocumentIndex": 0,
-              "Title": "TaskService.cs",
-              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_TaskInfoService\\TaskService.cs",
-              "RelativeDocumentMoniker": "WIDESEAWCS_TaskInfoService\\TaskService.cs",
-              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_TaskInfoService\\TaskService.cs",
-              "RelativeToolTip": "WIDESEAWCS_TaskInfoService\\TaskService.cs",
-              "ViewState": "AgIAAG4CAAAAAAAAAAAAAIICAAB9AAAAAAAAAA==",
-              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-11T09:01:01.549Z",
-              "EditorCaption": ""
+              "WhenOpened": "2026-03-18T08:56:41.452Z"
             }
           ]
         }
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_DTO/TaskInfo/WMSTaskDTO.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_DTO/TaskInfo/WMSTaskDTO.cs
index cf1f52c..fbd91e7 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_DTO/TaskInfo/WMSTaskDTO.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_DTO/TaskInfo/WMSTaskDTO.cs
@@ -36,7 +36,7 @@
         /// <summary>
         /// 浠诲姟鐘舵��
         /// </summary>
-        public int TaskState { get; set; }
+        public int TaskStatus { get; set; }
 
         /// <summary>
         /// 璧风偣
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask.cs
index 7cf765d..cb2cc60 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask.cs
@@ -18,7 +18,7 @@
         /// <summary>
         /// 鏈哄櫒浜轰换鍔D
         /// </summary>
-        [SugarColumn(IsPrimaryKey = true, ColumnDescription = "鏈哄櫒浜轰换鍔D")]
+        [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "鏈哄櫒浜轰换鍔D")]
         public int RobotTaskId { get; set; }
 
         /// <summary>
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
index 3887e19..d5d6da7 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
@@ -72,11 +72,11 @@
       "110681": "Split"
     },
     "AddressRoadwayMap": { // 瀵瑰簲璁惧鍦板潃鏄犲皠
-      "11001": "HPRB1",
-      "11010": "HPRB1",
-      "11068": "ZYRB1",
-      "10010": "HPRB1",
-      "10030": "HPRB1"
+      "11001": "鎹㈢洏鏈烘鎵�",
+      "11010": "鎹㈢洏鏈烘鎵�",
+      "11068": "娉ㄦ恫缁勭洏鏈烘鎵�",
+      "10010": "鎹㈢洏鏈烘鎵�",
+      "10030": "鎹㈢洏鏈烘鎵�"
     },
     "AddressSourceLineNoMap": { // 瀵瑰簲杈撻�佺嚎缂栧彿鍦板潃鏄犲皠
       "11001": "10010",
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
index 465fcb5..f88a4e6 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -87,9 +87,10 @@
                     RobotSourceAddressPalletCode = stockDTO.SourcePalletNo,
                     RobotTargetAddressPalletCode = stockDTO.TargetPalletNo,
                     RobotTaskType = taskDTO.TaskType,
-                    RobotTaskState = taskDTO.TaskState,
+                    RobotTaskState = taskDTO.TaskStatus,
                     RobotGrade = taskDTO.Grade,
-                    Creater = "WMS"
+                    Creater = "WMS",
+                    RobotTaskTotalNum = 0,
                 };
 
                 BaseDal.AddData(task);
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
index 8622839..3dd7db2 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
@@ -144,7 +144,7 @@
                     Roadway = "SC01",
                     SourceAddress = sourceAddress,
                     TargetAddress = "SC01",
-                    TaskState = (int)TaskInStatusEnum.InNew,
+                    TaskStatus = (int)TaskInStatusEnum.InNew,
                     Id = 0,
                     TaskType = (int)TaskInboundTypeEnum.Inbound
                 };
@@ -399,7 +399,7 @@
             task.Modifier = "System";
             if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish)
             {
-                BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.鑷姩鍒犻櫎);
+                BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.鑷姩瀹屾垚);
             }
             else
             {
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
index b344986..190a8d6 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
@@ -39,7 +39,7 @@
                 {
                     await HandlePickFinishedStateAsync(task, ipAddress);
                 }
-                else if ((latestState.CurrentAction == "PutFinished" || latestState.CurrentAction == "AllPutFinished")
+                else if ((latestState.CurrentAction == "PutFinished" || latestState.CurrentAction == "AllPutFinished" || latestState.CurrentAction == null)
                     && latestState.OperStatus == "Homed"
                     && latestState.RobotArmObject == 0
                     && (task.RobotTaskState == TaskRobotStatusEnum.RobotPutFinish.GetHashCode()
diff --git a/Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/v18/DocumentLayout.backup.json b/Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/v18/DocumentLayout.backup.json
index b82eb6a..09fa9fe 100644
--- a/Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/v18/DocumentLayout.backup.json
+++ b/Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/v18/DocumentLayout.backup.json
@@ -7,12 +7,12 @@
       "RelativeMoniker": "D:0:0:{7D7534D4-51D9-46DC-A6B7-6430042F4E12}|WIDESEA_TaskInfoService\\WIDESEA_TaskInfoService.csproj|solutionrelative:widesea_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
     },
     {
-      "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
-    },
-    {
       "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\task\\wmstaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
       "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\task\\wmstaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+    },
+    {
+      "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+      "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
     },
     {
       "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\taskenum\\tasktypeenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
@@ -86,15 +86,16 @@
             },
             {
               "$type": "Document",
-              "DocumentIndex": 2,
+              "DocumentIndex": 1,
               "Title": "WMSTaskDTO.cs",
               "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\Task\\WMSTaskDTO.cs",
               "RelativeDocumentMoniker": "WIDESEA_DTO\\Task\\WMSTaskDTO.cs",
               "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\Task\\WMSTaskDTO.cs",
               "RelativeToolTip": "WIDESEA_DTO\\Task\\WMSTaskDTO.cs",
-              "ViewState": "AgIAAAYAAAAAAAAAAAAuwB8AAAArAAAAAAAAAA==",
+              "ViewState": "AgIAABgAAAAAAAAAAAAIwCkAAAAdAAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-17T07:42:09.48Z"
+              "WhenOpened": "2026-03-17T07:42:09.48Z",
+              "EditorCaption": ""
             },
             {
               "$type": "Document",
@@ -134,13 +135,13 @@
             },
             {
               "$type": "Document",
-              "DocumentIndex": 1,
+              "DocumentIndex": 2,
               "Title": "TaskController.cs",
               "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs",
               "RelativeDocumentMoniker": "WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs",
               "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs",
               "RelativeToolTip": "WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs",
-              "ViewState": "AgIAAHgAAAAAAAAAAADgv5cAAAAjAAAAAAAAAA==",
+              "ViewState": "AgIAAIoAAAAAAAAAAAAhwJsAAAAIAAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
               "WhenOpened": "2026-03-13T02:00:31.089Z",
               "EditorCaption": ""
@@ -262,7 +263,7 @@
               "RelativeDocumentMoniker": "WIDESEA_TaskInfoService\\TaskService.cs",
               "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_TaskInfoService\\TaskService.cs",
               "RelativeToolTip": "WIDESEA_TaskInfoService\\TaskService.cs",
-              "ViewState": "AgIAAGkCAAAAAAAAAAAkwHoCAAAIAAAAAAAAAA==",
+              "ViewState": "AgIAAGkCAAAAAAAAAAAkwHgCAAAWAAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
               "WhenOpened": "2026-02-06T06:34:59.734Z",
               "EditorCaption": ""
diff --git a/Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/v18/DocumentLayout.json b/Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/v18/DocumentLayout.json
index d7f56f6..d24497d 100644
--- a/Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/v18/DocumentLayout.json
+++ b/Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/v18/DocumentLayout.json
@@ -7,12 +7,12 @@
       "RelativeMoniker": "D:0:0:{7D7534D4-51D9-46DC-A6B7-6430042F4E12}|WIDESEA_TaskInfoService\\WIDESEA_TaskInfoService.csproj|solutionrelative:widesea_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
     },
     {
-      "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
-      "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
-    },
-    {
       "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\task\\wmstaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
       "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\task\\wmstaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+    },
+    {
+      "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+      "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
     },
     {
       "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\taskenum\\tasktypeenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
@@ -86,13 +86,13 @@
             },
             {
               "$type": "Document",
-              "DocumentIndex": 2,
+              "DocumentIndex": 1,
               "Title": "WMSTaskDTO.cs",
               "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\Task\\WMSTaskDTO.cs",
               "RelativeDocumentMoniker": "WIDESEA_DTO\\Task\\WMSTaskDTO.cs",
               "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\Task\\WMSTaskDTO.cs",
               "RelativeToolTip": "WIDESEA_DTO\\Task\\WMSTaskDTO.cs",
-              "ViewState": "AgIAAAYAAAAAAAAAAAAuwB8AAAArAAAAAAAAAA==",
+              "ViewState": "AgIAABgAAAAAAAAAAAAIwCkAAAAdAAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
               "WhenOpened": "2026-03-17T07:42:09.48Z"
             },
@@ -134,16 +134,15 @@
             },
             {
               "$type": "Document",
-              "DocumentIndex": 1,
+              "DocumentIndex": 2,
               "Title": "TaskController.cs",
               "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs",
               "RelativeDocumentMoniker": "WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs",
               "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs",
               "RelativeToolTip": "WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs",
-              "ViewState": "AgIAAHgAAAAAAAAAAADgv5cAAAAjAAAAAAAAAA==",
+              "ViewState": "AgIAAIoAAAAAAAAAAAAhwJsAAAAIAAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-13T02:00:31.089Z",
-              "EditorCaption": ""
+              "WhenOpened": "2026-03-13T02:00:31.089Z"
             },
             {
               "$type": "Document",
@@ -215,8 +214,7 @@
               "RelativeToolTip": "WIDESEA_BasicService\\LocationInfoService.cs",
               "ViewState": "AgIAAFcAAAAAAAAAAAAAwGgAAAARAAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
-              "WhenOpened": "2026-03-12T02:05:14.224Z",
-              "EditorCaption": ""
+              "WhenOpened": "2026-03-12T02:05:14.224Z"
             },
             {
               "$type": "Document",
@@ -262,7 +260,7 @@
               "RelativeDocumentMoniker": "WIDESEA_TaskInfoService\\TaskService.cs",
               "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_TaskInfoService\\TaskService.cs",
               "RelativeToolTip": "WIDESEA_TaskInfoService\\TaskService.cs",
-              "ViewState": "AgIAAKwCAAAAAAAAAAAgwL8CAAAAAAAAAAAAAA==",
+              "ViewState": "AgIAAAAAAAAAAAAAAAAAAHgCAAAWAAAAAAAAAA==",
               "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
               "WhenOpened": "2026-02-06T06:34:59.734Z",
               "EditorCaption": ""
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs
index 1271ec3..a4c4868 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs
@@ -101,6 +101,7 @@
         /// </summary>
         public async Task<WebResponseContent> ChangePalletAsync(StockDTO stock)
         {
+
             WebResponseContent content = new WebResponseContent();
             if (stock == null ||
                 string.IsNullOrWhiteSpace(stock.TargetPalletNo) ||
@@ -110,7 +111,7 @@
                 return content.Error("婧愭墭鐩樺彿涓庣洰鏍囨墭鐩樺彿鐩稿悓");
             }
 
-            var sourceStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.SourcePalletNo);
+            var sourceStock = await StockInfoService.Repository.QueryDataNavFirstAsync(s => s.PalletCode == stock.SourcePalletNo);
             if (sourceStock == null) return content.Error("婧愭墭鐩樹笉瀛樺湪");
 
             var targetStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.TargetPalletNo);
@@ -131,11 +132,11 @@
                 targetStock.Id = newId;
             }
 
-            var serialNumbers = stock.Details.Select(d => d.CellBarcode).Distinct().ToList();
+            var serialNumbers = stock.Details.Select(d => d.Channel).Distinct().ToList();
             if (!serialNumbers.Any()) return content.Error("鏈壘鍒版湁鏁堢殑搴忓垪鍙�");
 
             var detailEntities = StockInfoDetailService.Repository.QueryData(
-                d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.SerialNumber));
+                d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.InboundOrderRowNo));
             if (!detailEntities.Any()) return content.Error("鏈壘鍒版湁鏁堢殑搴撳瓨鏄庣粏");
 
             if (await StockInfoDetail_HtyService.Repository.AddDataAsync(CreateDetailHistory(detailEntities, "鎹㈢洏")) <= 0)
@@ -253,7 +254,9 @@
                 Creater = s.Creater,
                 CreateDate = s.CreateDate,
                 Modifier = s.Modifier,
-                ModifyDate = s.ModifyDate
+                ModifyDate = s.ModifyDate,
+                LocationId = s.LocationId,
+                OutboundDate = s.OutboundDate
             }).ToList();
         }
     }
diff --git "a/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\234\272\346\242\260\346\211\213\345\215\217\350\256\256/~$\344\272\244\344\272\222\346\265\201\347\250\213\350\241\250\0501\051.xlsx" "b/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\234\272\346\242\260\346\211\213\345\215\217\350\256\256/~$\344\272\244\344\272\222\346\265\201\347\250\213\350\241\250\0501\051.xlsx"
new file mode 100644
index 0000000..236d63d
--- /dev/null
+++ "b/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\234\272\346\242\260\346\211\213\345\215\217\350\256\256/~$\344\272\244\344\272\222\346\265\201\347\250\213\350\241\250\0501\051.xlsx"
Binary files differ

--
Gitblit v1.9.3