You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

240 lines
11 KiB

@{
ViewData["Title"] = "LTE WebSocket 客户端管理";
}
<div class="text-center">
<h1 class="display-4">LTE WebSocket 客户端管理</h1>
<p>基于 .NET 8 的 LTE WebSocket 客户端实现</p>
</div>
<!-- 消息提示 -->
@if (TempData["Message"] != null)
{
<div class="alert alert-success alert-dismissible fade show" role="alert">
@TempData["Message"]
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
}
@if (TempData["Error"] != null)
{
<div class="alert alert-danger alert-dismissible fade show" role="alert">
@TempData["Error"]
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
}
<!-- 连接统计信息 -->
<div class="row mb-4">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">连接统计信息</h5>
</div>
<div class="card-body">
@if (ViewBag.ConnectionStats != null)
{
var stats = ViewBag.ConnectionStats as LTEMvcApp.Services.ConnectionStatistics;
<div class="row">
<div class="col-md-3">
<div class="text-center">
<h4 class="text-primary">@(stats?.TotalClients ?? 0)</h4>
<p class="text-muted">总客户端数</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<h4 class="text-success">@(stats?.ConnectedClients ?? 0)</h4>
<p class="text-muted">已连接</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<h4 class="text-warning">@(stats?.DisconnectedClients ?? 0)</h4>
<p class="text-muted">未连接</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<h4 class="text-info">@(stats?.TotalLogs ?? 0)</h4>
<p class="text-muted">总日志数</p>
</div>
</div>
</div>
}
else
{
<p class="text-muted">暂无统计信息</p>
}
</div>
</div>
</div>
</div>
<!-- 客户端管理 -->
<div class="row mb-4">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">客户端管理</h5>
</div>
<div class="card-body">
<!-- 快速操作按钮 -->
<div class="row mb-3">
<div class="col-md-12">
<form method="post" style="display: inline;">
<button type="submit" asp-action="AddTestClient" class="btn btn-primary me-2">
<i class="bi bi-plus-circle"></i> 添加测试客户端
</button>
</form>
<form method="post" style="display: inline;">
<button type="submit" asp-action="StartTestClient" class="btn btn-success me-2">
<i class="bi bi-play-circle"></i> 启动测试客户端
</button>
</form>
<form method="post" style="display: inline;">
<button type="submit" asp-action="StopTestClient" class="btn btn-danger me-2">
<i class="bi bi-stop-circle"></i> 停止测试客户端
</button>
</form>
<a href="@Url.Action("WebSocketTest")" class="btn btn-info">
<i class="bi bi-gear"></i> WebSocket 测试
</a>
</div>
</div>
<!-- 客户端配置列表 -->
@if (ViewBag.ClientConfigs != null && ((List<LTEMvcApp.Models.ClientConfig>)ViewBag.ClientConfigs).Count > 0)
{
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>客户端名称</th>
<th>地址</th>
<th>状态</th>
<th>SSL</th>
<th>启用</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@foreach (var config in ViewBag.ClientConfigs as List<LTEMvcApp.Models.ClientConfig>)
{
var stats = ViewBag.ConnectionStats as LTEMvcApp.Services.ConnectionStatistics;
var clientStates = stats?.ClientStates ?? new Dictionary<string, LTEMvcApp.Models.ClientState>();
var state = clientStates.GetValueOrDefault(config.Name, LTEMvcApp.Models.ClientState.Stop);
<tr>
<td>@config.Name</td>
<td>@(config.Ssl ? "wss://" : "ws://")@config.Address</td>
<td>
<span class="badge @(state == LTEMvcApp.Models.ClientState.Connected ? "bg-success" :
state == LTEMvcApp.Models.ClientState.Connecting ? "bg-warning" :
state == LTEMvcApp.Models.ClientState.Error ? "bg-danger" : "bg-secondary")">
@state
</span>
</td>
<td>
<i class="bi @(config.Ssl ? "bi-check-circle-fill text-success" : "bi-x-circle-fill text-muted")"></i>
</td>
<td>
<i class="bi @(config.Enabled ? "bi-check-circle-fill text-success" : "bi-x-circle-fill text-muted")"></i>
</td>
<td>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-outline-primary" onclick="startClient('@config.Name')">
<i class="bi bi-play"></i>
</button>
<button type="button" class="btn btn-outline-danger" onclick="stopClient('@config.Name')">
<i class="bi bi-stop"></i>
</button>
<button type="button" class="btn btn-outline-info" onclick="viewLogs('@config.Name')">
<i class="bi bi-list-ul"></i>
</button>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
}
else
{
<div class="text-center text-muted">
<i class="bi bi-info-circle" style="font-size: 2rem;"></i>
<p class="mt-2">暂无客户端配置</p>
<p>点击"添加测试客户端"按钮来创建第一个客户端配置</p>
</div>
}
</div>
</div>
</div>
</div>
<!-- API 信息 -->
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">API 接口</h5>
</div>
<div class="card-body">
<p>以下API接口可用于程序化控制WebSocket客户端:</p>
<ul class="list-unstyled">
<li><code>GET /api/websocket/clients</code> - 获取所有客户端状态</li>
<li><code>GET /api/websocket/configs</code> - 获取所有客户端配置</li>
<li><code>POST /api/websocket/configs</code> - 添加客户端配置</li>
<li><code>POST /api/websocket/clients/{name}/start</code> - 启动客户端</li>
<li><code>POST /api/websocket/clients/{name}/stop</code> - 停止客户端</li>
<li><code>GET /api/websocket/clients/{name}/logs</code> - 获取客户端日志</li>
<li><code>GET /api/websocket/statistics</code> - 获取连接统计信息</li>
</ul>
</div>
</div>
</div>
</div>
@section Scripts {
<script>
function startClient(clientName) {
fetch(`/api/websocket/clients/${encodeURIComponent(clientName)}/start`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(data => {
alert(data.message || '操作成功');
location.reload();
})
.catch(error => {
console.error('Error:', error);
alert('操作失败');
});
}
function stopClient(clientName) {
fetch(`/api/websocket/clients/${encodeURIComponent(clientName)}/stop`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(data => {
alert(data.message || '操作成功');
location.reload();
})
.catch(error => {
console.error('Error:', error);
alert('操作失败');
});
}
function viewLogs(clientName) {
window.open(`/api/websocket/clients/${encodeURIComponent(clientName)}/logs?limit=100`, '_blank');
}
</script>
}