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.
 
 
 

300 lines
15 KiB

@{
ViewData["Title"] = "测试客户端配置";
var testConfig = ViewBag.TestConfig as LTEMvcApp.Models.ClientConfig;
// 只保留不含 EVENT 的日志层
var allLayers = LTEMvcApp.Models.LogLayerTypes.AllLayers.Where(l => l != "EVENT").ToArray();
var layerConfigs = new Dictionary<string, LTEMvcApp.Models.LogLayerConfig>();
if (testConfig?.Logs?.ContainsKey("layers") == true && testConfig.Logs["layers"] is System.Text.Json.JsonElement layersElement)
{
var layers = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, LTEMvcApp.Models.LogLayerConfig>>(layersElement.GetRawText(), new System.Text.Json.JsonSerializerOptions { PropertyNameCaseInsensitive = true })
?? new Dictionary<string, LTEMvcApp.Models.LogLayerConfig>();
foreach (var layerName in allLayers)
{
if (layers.TryGetValue(layerName, out var config))
{
layerConfigs[layerName] = config;
}
else
{
layerConfigs[layerName] = new LTEMvcApp.Models.LogLayerConfig { Level = LTEMvcApp.Models.LogLayerTypes.GetDefaultLevel(layerName) };
}
}
}
else
{
foreach (var layerName in allLayers)
{
layerConfigs[layerName] = new LTEMvcApp.Models.LogLayerConfig { Level = LTEMvcApp.Models.LogLayerTypes.GetDefaultLevel(layerName) };
}
}
}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">测试客户端配置</h3>
</div>
<div class="card-body">
<form id="testClientConfigForm">
<!-- 基本配置 -->
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="name">客户端名称</label>
<input type="text" class="form-control" id="name" name="name" value="@testConfig?.Name" required>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="address">服务器地址</label>
<input type="text" class="form-control" id="address" name="address" value="@testConfig?.Address" placeholder="192.168.13.12:9001">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="password">密码</label>
<input type="password" class="form-control" id="password" name="password" value="@testConfig?.Password">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="reconnectDelay">重连延迟 (毫秒)</label>
<input type="number" class="form-control" id="reconnectDelay" name="reconnectDelay" value="@testConfig?.ReconnectDelay">
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="enabled" name="enabled" @(testConfig?.Enabled == true ? "checked" : "")>
<label class="form-check-label" for="enabled">启用</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="ssl" name="ssl" @(testConfig?.Ssl == true ? "checked" : "")>
<label class="form-check-label" for="ssl">使用SSL</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="readonly" name="readonly" @(testConfig?.Readonly == true ? "checked" : "")>
<label class="form-check-label" for="readonly">只读模式</label>
</div>
</div>
</div>
<!-- 日志层配置 -->
<div class="row mt-4">
<div class="col-md-12">
<h5>日志层配置</h5>
<div class="table-responsive">
<table class="table table-bordered table-sm">
<thead class="table-dark">
<tr>
<th>日志层</th>
<th>级别</th>
<th>过滤器</th>
<th>最大大小</th>
<th>包含负载</th>
</tr>
</thead>
<tbody>
@foreach (var layer in allLayers)
{
var config = layerConfigs[layer];
<tr>
<td><strong>@layer</strong></td>
<td>
<select class="form-control form-control-sm" name="layers[@layer][level]">
@foreach (var logLevel in LTEMvcApp.Models.LogLayerTypes.LogLevels)
{
if (logLevel == config.Level)
{
<option value="@logLevel" selected>@logLevel.ToUpper()</option>
}
else
{
<option value="@logLevel">@logLevel.ToUpper()</option>
}
}
</select>
</td>
<td>
<select class="form-control form-control-sm" name="layers[@layer][filter]">
@foreach (var logLevel in LTEMvcApp.Models.LogLayerTypes.LogLevels)
{
if (logLevel == config.Filter)
{
<option value="@logLevel" selected>@logLevel.ToUpper()</option>
}
else
{
<option value="@logLevel">@logLevel.ToUpper()</option>
}
}
</select>
</td>
<td>
<input type="number" class="form-control form-control-sm" name="layers[@layer][max_size]" value="@config.MaxSize" min="1" max="1000">
</td>
<td>
<div class="form-check">
<input type="checkbox" class="form-check-input" name="layers[@layer][payload]" @(config.Payload ? "checked" : "")>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
<!-- 操作按钮 -->
<div class="row mt-4">
<div class="col-md-12">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> 保存配置
</button>
<button type="button" class="btn btn-success" onclick="startTestClient()">
<i class="fas fa-play"></i> 启动测试客户端
</button>
<button type="button" class="btn btn-danger" onclick="stopTestClient()">
<i class="fas fa-stop"></i> 停止测试客户端
</button>
<a href="@Url.Action("ClientMessages", "Home", new { clientName = testConfig?.Name })" class="btn btn-info">
<i class="fas fa-list"></i> 查看消息队列
</a>
<button type="button" class="btn btn-secondary" onclick="resetToDefaults()">
<i class="fas fa-undo"></i> 重置为默认值
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@section Scripts {
<script>
$(document).ready(function() {
$('#testClientConfigForm').on('submit', function(e) {
e.preventDefault();
saveTestClientConfig();
});
});
function saveTestClientConfig() {
var formData = {
name: $('#name').val(),
address: $('#address').val(),
password: $('#password').val(),
reconnectDelay: parseInt($('#reconnectDelay').val()) || 15000,
enabled: $('#enabled').is(':checked'),
ssl: $('#ssl').is(':checked'),
readonly: $('#readonly').is(':checked'),
logs: {
layers: {}
}
};
// 构建日志层配置
var layers = @Html.Raw(Json.Serialize(allLayers));
layers.forEach(function(layer) {
var level = $(`select[name="layers[${layer}][level]"]`).val();
var filter = $(`select[name="layers[${layer}][filter]"]`).val();
var maxSize = parseInt($(`input[name="layers[${layer}][max_size]"]`).val()) || 1;
var payload = $(`input[name="layers[${layer}][payload]"]`).is(':checked');
formData.logs.layers[layer] = {
level: level,
maxSize: maxSize,
payload: payload,
filter: filter
};
});
$.ajax({
url: '/api/websocket/test-client-config',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(formData),
success: function(response) {
alert('配置保存成功!');
location.reload();
},
error: function(xhr) {
alert('保存配置失败:' + xhr.responseText);
}
});
}
function startTestClient() {
$.ajax({
url: '/api/websocket/test-client/start',
type: 'POST',
success: function(response) {
alert('测试客户端启动成功!');
},
error: function(xhr) {
alert('启动测试客户端失败:' + xhr.responseText);
}
});
}
function stopTestClient() {
$.ajax({
url: '/api/websocket/test-client/stop',
type: 'POST',
success: function(response) {
alert('测试客户端停止成功!');
},
error: function(xhr) {
alert('停止测试客户端失败:' + xhr.responseText);
}
});
}
function resetToDefaults() {
if (confirm('确定要重置为默认配置吗?')) {
// 重置为默认值
var defaultLevels = {
'PHY': 'info', 'MAC': 'info', 'RLC': 'info', 'PDCP': 'warn',
'RRC': 'debug', 'NAS': 'debug', 'S1AP': 'debug', 'NGAP': 'debug',
'GTPU': 'info', 'X2AP': 'debug', 'XnAP': 'info', 'M2AP': 'info'
};
Object.keys(defaultLevels).forEach(function(layer) {
$(`select[name="layers[${layer}][level]"]`).val(defaultLevels[layer]);
$(`select[name="layers[${layer}][filter]"]`).val('warn');
$(`input[name="layers[${layer}][max_size]"]`).val(1);
$(`input[name="layers[${layer}][payload]"]`).prop('checked', false);
});
// 设置一些层的 payload 为 true
['PHY', 'MAC', 'RRC', 'NAS'].forEach(function(layer) {
$(`input[name="layers[${layer}][payload]"]`).prop('checked', true);
});
alert('已重置为默认配置!');
}
}
</script>
}