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.
564 lines
23 KiB
564 lines
23 KiB
@{
|
|
ViewData["Title"] = "统计配置管理";
|
|
}
|
|
|
|
<style>
|
|
/* 页面整体布局 */
|
|
.config-container {
|
|
max-height: calc(100vh - 280px);
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* 表单容器 */
|
|
.config-form {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
padding: 0.75rem;
|
|
}
|
|
|
|
/* 自定义滚动条 */
|
|
.config-form::-webkit-scrollbar {
|
|
width: 6px;
|
|
}
|
|
|
|
.config-form::-webkit-scrollbar-track {
|
|
background: #f1f1f1;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.config-form::-webkit-scrollbar-thumb {
|
|
background: #c1c1c1;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.config-form::-webkit-scrollbar-thumb:hover {
|
|
background: #a8a8a8;
|
|
}
|
|
|
|
/* 表单样式 */
|
|
.form-group {
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
|
|
.form-group label {
|
|
font-weight: 600;
|
|
color: #495057;
|
|
margin-bottom: 0.25rem;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.form-control {
|
|
border-radius: 0.375rem;
|
|
border: 1px solid #ced4da;
|
|
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
|
padding: 0.375rem 0.75rem;
|
|
}
|
|
|
|
.form-control:focus {
|
|
border-color: #80bdff;
|
|
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
|
}
|
|
|
|
/* 表格样式 */
|
|
.table-responsive {
|
|
border-radius: 0.5rem;
|
|
overflow: hidden;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.table {
|
|
margin-bottom: 0;
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.table th {
|
|
background-color: #343a40;
|
|
color: white;
|
|
font-weight: 600;
|
|
border: none;
|
|
padding: 0.5rem;
|
|
}
|
|
|
|
.table td {
|
|
vertical-align: middle;
|
|
border-color: #dee2e6;
|
|
padding: 0.5rem;
|
|
}
|
|
|
|
/* 按钮样式 */
|
|
.btn {
|
|
border-radius: 0.375rem;
|
|
font-weight: 500;
|
|
transition: all 0.2s;
|
|
padding: 0.375rem 0.75rem;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.btn:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.form-check {
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.form-check-input:checked {
|
|
background-color: #007bff;
|
|
border-color: #007bff;
|
|
}
|
|
|
|
.section-title {
|
|
color: #495057;
|
|
font-weight: 600;
|
|
margin-bottom: 0.5rem;
|
|
padding-bottom: 0.25rem;
|
|
border-bottom: 2px solid #e9ecef;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
/* 按钮区域 */
|
|
.button-area {
|
|
flex-shrink: 0;
|
|
background: white;
|
|
border-top: 1px solid #dee2e6;
|
|
padding: 0.5rem 0.75rem;
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
/* 配置卡片样式 */
|
|
.config-card {
|
|
border: 1px solid #e9ecef;
|
|
border-radius: 0.5rem;
|
|
background: #f8f9fa;
|
|
padding: 1rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.config-card-header {
|
|
display: flex;
|
|
justify-content: between;
|
|
align-items: center;
|
|
margin-bottom: 1rem;
|
|
padding-bottom: 0.5rem;
|
|
border-bottom: 1px solid #dee2e6;
|
|
}
|
|
|
|
.config-card-title {
|
|
font-weight: 600;
|
|
color: #495057;
|
|
margin: 0;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.config-options {
|
|
display: flex;
|
|
gap: 1rem;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.config-option {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
/* 响应式调整 */
|
|
@@media (max-width: 768px) {
|
|
.config-container {
|
|
max-height: calc(100vh - 240px);
|
|
}
|
|
|
|
.button-area {
|
|
padding: 0.4rem 0.6rem;
|
|
}
|
|
|
|
.config-form {
|
|
padding: 0.6rem;
|
|
}
|
|
|
|
.config-options {
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
}
|
|
}
|
|
|
|
@@media (max-width: 576px) {
|
|
.config-container {
|
|
max-height: calc(100vh - 220px);
|
|
}
|
|
|
|
.button-area {
|
|
padding: 0.3rem 0.5rem;
|
|
}
|
|
|
|
.config-form {
|
|
padding: 0.5rem;
|
|
}
|
|
|
|
.btn {
|
|
font-size: 0.8rem;
|
|
padding: 0.3rem 0.6rem;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">
|
|
<i class="fas fa-cogs"></i> 统计配置管理
|
|
</h3>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="config-container">
|
|
<div class="config-form">
|
|
<!-- 客户端配置 -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-server"></i> 客户端统计配置
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<span class="badge bg-info" id="clientCount">0</span> 个客户端
|
|
</div>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="loadClientList()">
|
|
<i class="fas fa-sync-alt"></i> 重新加载客户端
|
|
</button>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-hover">
|
|
<thead class="table-dark">
|
|
<tr>
|
|
<th>客户端名称</th>
|
|
<th>IP地址</th>
|
|
<th>Samples</th>
|
|
<th>RF</th>
|
|
<th>状态</th>
|
|
<th>描述</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="clientConfigTableBody">
|
|
<!-- 客户端配置数据将通过JavaScript动态填充 -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 配置信息 -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-info-circle"></i> 配置说明
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6>配置优先级:</h6>
|
|
<ol>
|
|
<li><strong>客户端特定配置</strong> - 如果客户端有特定的配置且启用,则使用该配置</li>
|
|
<li><strong>系统默认值</strong> - 如果客户端没有特定配置,则使用系统默认值(samples=false, rf=false)</li>
|
|
</ol>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6>参数说明:</h6>
|
|
<ul>
|
|
<li><strong>Samples</strong> - 控制是否收集详细的采样数据,可能影响性能</li>
|
|
<li><strong>RF</strong> - 控制是否收集射频相关数据,包含信号质量等信息</li>
|
|
<li><strong>启用配置</strong> - 控制该客户端配置是否生效</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@section Scripts {
|
|
<script>
|
|
// 页面加载时初始化
|
|
$(document).ready(function() {
|
|
loadClientList();
|
|
});
|
|
|
|
// 加载客户端列表并生成配置表格
|
|
function loadClientList() {
|
|
console.log('加载客户端列表...');
|
|
$.get('/api/config', function(response) {
|
|
if (response && response.length > 0) {
|
|
const tbody = document.getElementById('clientConfigTableBody');
|
|
tbody.innerHTML = '';
|
|
|
|
response.forEach(function(client) {
|
|
const row = document.createElement('tr');
|
|
row.innerHTML = `
|
|
<td><strong>${client.name}</strong></td>
|
|
<td><code>${client.address}</code></td>
|
|
<td>
|
|
<div class="form-check d-flex justify-content-center">
|
|
<input class="form-check-input" type="checkbox" id="samples_${client.name}"
|
|
onchange="updateConfig('${client.name}', 'samples', this.checked)">
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="form-check d-flex justify-content-center">
|
|
<input class="form-check-input" type="checkbox" id="rf_${client.name}"
|
|
onchange="updateConfig('${client.name}', 'rf', this.checked)">
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="form-check d-flex justify-content-center">
|
|
<input class="form-check-input" type="checkbox" id="enabled_${client.name}" checked
|
|
onchange="updateConfig('${client.name}', 'enabled', this.checked)">
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm" id="desc_${client.name}"
|
|
placeholder="配置描述" onblur="updateConfig('${client.name}', 'description', this.value)">
|
|
</td>
|
|
<td>
|
|
<div class="btn-group btn-group-sm">
|
|
<button class="btn btn-success" onclick="saveClientConfig('${client.name}')" title="保存">
|
|
<i class="fas fa-save"></i>
|
|
</button>
|
|
<button class="btn btn-info" onclick="loadClientConfig('${client.name}')" title="加载">
|
|
<i class="fas fa-download"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
`;
|
|
tbody.appendChild(row);
|
|
});
|
|
|
|
document.getElementById('clientCount').textContent = response.length;
|
|
console.log('客户端列表已加载,共', response.length, '个客户端');
|
|
|
|
// 加载所有客户端的现有配置
|
|
loadAllClientConfigs();
|
|
} else {
|
|
console.log('没有找到客户端配置');
|
|
document.getElementById('clientCount').textContent = '0';
|
|
}
|
|
}).fail(function(xhr, status, error) {
|
|
console.error('加载客户端列表错误:', error);
|
|
showAlert('danger', '加载客户端列表失败: ' + error);
|
|
});
|
|
}
|
|
|
|
// 更新配置(实时保存到服务器)
|
|
function updateConfig(clientName, field, value) {
|
|
console.log(`更新配置: ${clientName} - ${field} = ${value}`);
|
|
|
|
if (field === 'samples') {
|
|
// 更新Samples参数
|
|
$.ajax({
|
|
url: `/api/config/statistics/${encodeURIComponent(clientName)}/samples`,
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(value),
|
|
success: function(response) {
|
|
if (response.success) {
|
|
console.log(`客户端 ${clientName} Samples参数已更新`);
|
|
} else {
|
|
console.error('更新Samples参数失败:', response.message);
|
|
showAlert('danger', `更新Samples参数失败: ${response.message}`);
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error('更新Samples参数错误:', error);
|
|
showAlert('danger', `更新Samples参数错误: ${error}`);
|
|
}
|
|
});
|
|
} else if (field === 'rf') {
|
|
// 更新RF参数
|
|
$.ajax({
|
|
url: `/api/config/statistics/${encodeURIComponent(clientName)}/rf`,
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(value),
|
|
success: function(response) {
|
|
if (response.success) {
|
|
console.log(`客户端 ${clientName} RF参数已更新`);
|
|
} else {
|
|
console.error('更新RF参数失败:', response.message);
|
|
showAlert('danger', `更新RF参数失败: ${response.message}`);
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error('更新RF参数错误:', error);
|
|
showAlert('danger', `更新RF参数错误: ${error}`);
|
|
}
|
|
});
|
|
} else if (field === 'enabled') {
|
|
// 更新启用状态
|
|
saveClientConfig(clientName);
|
|
} else if (field === 'description') {
|
|
// 更新描述
|
|
saveClientConfig(clientName);
|
|
}
|
|
}
|
|
|
|
// 加载客户端配置
|
|
function loadClientConfig(clientName) {
|
|
console.log('加载客户端统计配置:', clientName);
|
|
$.get(`/api/config/statistics/${encodeURIComponent(clientName)}`, function(response) {
|
|
if (response.success && response.data) {
|
|
const config = response.data;
|
|
document.getElementById(`samples_${clientName}`).checked = config.enableSamples;
|
|
document.getElementById(`rf_${clientName}`).checked = config.enableRf;
|
|
document.getElementById(`enabled_${clientName}`).checked = config.isEnabled;
|
|
document.getElementById(`desc_${clientName}`).value = config.description || '';
|
|
console.log('客户端配置已加载:', config);
|
|
showAlert('success', `客户端 ${clientName} 配置已加载`);
|
|
} else {
|
|
console.log('客户端配置未找到,使用默认值');
|
|
// 使用默认值
|
|
document.getElementById(`samples_${clientName}`).checked = false;
|
|
document.getElementById(`rf_${clientName}`).checked = false;
|
|
document.getElementById(`enabled_${clientName}`).checked = true;
|
|
document.getElementById(`desc_${clientName}`).value = '';
|
|
showAlert('info', `客户端 ${clientName} 使用默认配置`);
|
|
}
|
|
}).fail(function(xhr, status, error) {
|
|
console.error('加载客户端配置错误:', error);
|
|
showAlert('danger', `加载客户端 ${clientName} 配置失败: ${error}`);
|
|
});
|
|
}
|
|
|
|
// 保存客户端配置
|
|
function saveClientConfig(clientName) {
|
|
const config = {
|
|
clientName: clientName,
|
|
ipAddress: '', // 将从客户端列表获取
|
|
enableSamples: document.getElementById(`samples_${clientName}`).checked,
|
|
enableRf: document.getElementById(`rf_${clientName}`).checked,
|
|
isEnabled: document.getElementById(`enabled_${clientName}`).checked,
|
|
description: document.getElementById(`desc_${clientName}`).value
|
|
};
|
|
|
|
// 从已加载的客户端列表中获取IP地址
|
|
const tbody = document.getElementById('clientConfigTableBody');
|
|
const rows = tbody.getElementsByTagName('tr');
|
|
for (let row of rows) {
|
|
const nameCell = row.querySelector('td:first-child strong');
|
|
if (nameCell && nameCell.textContent === clientName) {
|
|
const ipCell = row.querySelector('td:nth-child(2) code');
|
|
if (ipCell) {
|
|
config.ipAddress = ipCell.textContent;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
console.log('保存客户端统计配置:', config);
|
|
$.ajax({
|
|
url: `/api/config/statistics/${encodeURIComponent(clientName)}`,
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(config),
|
|
success: function(response) {
|
|
console.log('客户端配置保存响应:', response);
|
|
if (response.success) {
|
|
showAlert('success', `客户端 ${clientName} 配置已保存`);
|
|
} else {
|
|
showAlert('danger', `保存失败: ${response.message}`);
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error('保存客户端配置错误:', error);
|
|
showAlert('danger', `保存失败: ${error}`);
|
|
}
|
|
});
|
|
}
|
|
|
|
// 加载所有客户端配置
|
|
function loadAllClientConfigs() {
|
|
console.log('加载所有客户端配置...');
|
|
// 从WebSocketManagerService获取所有统计配置
|
|
$.get('/Statistics/GetAllClientStatisticsConfigs', function(response) {
|
|
if (response.success) {
|
|
const configs = response.data;
|
|
const configDict = {};
|
|
|
|
// 将配置转换为字典,方便查找
|
|
configs.forEach(function(config) {
|
|
configDict[config.clientName] = config;
|
|
});
|
|
|
|
// 更新表格中的配置
|
|
const tbody = document.getElementById('clientConfigTableBody');
|
|
const rows = tbody.getElementsByTagName('tr');
|
|
|
|
for (let row of rows) {
|
|
const nameCell = row.querySelector('td:first-child strong');
|
|
if (nameCell) {
|
|
const clientName = nameCell.textContent;
|
|
const config = configDict[clientName];
|
|
|
|
if (config) {
|
|
row.querySelector(`#samples_${clientName}`).checked = config.enableSamples;
|
|
row.querySelector(`#rf_${clientName}`).checked = config.enableRf;
|
|
row.querySelector(`#enabled_${clientName}`).checked = config.isEnabled;
|
|
row.querySelector(`#desc_${clientName}`).value = config.description || '';
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log('所有客户端配置已加载,共', configs.length, '个配置');
|
|
} else {
|
|
console.error('加载配置列表失败:', response.message);
|
|
}
|
|
}).fail(function(xhr, status, error) {
|
|
console.error('加载配置列表错误:', error);
|
|
});
|
|
}
|
|
|
|
// 显示提示信息
|
|
function showAlert(type, message) {
|
|
const alertHtml = `
|
|
<div class="alert alert-${type} alert-dismissible fade show" role="alert">
|
|
${message}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
</div>
|
|
`;
|
|
|
|
// 移除现有的提示
|
|
$('.alert').remove();
|
|
|
|
// 添加新提示到页面顶部
|
|
$('.container').prepend(alertHtml);
|
|
|
|
// 3秒后自动消失
|
|
setTimeout(function() {
|
|
$('.alert').fadeOut();
|
|
}, 3000);
|
|
}
|
|
</script>
|
|
}
|