|
|
@ -407,6 +407,74 @@ |
|
|
|
border-left: none; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* 列设置相关样式 */ |
|
|
|
.column-settings { |
|
|
|
position: relative; |
|
|
|
display: inline-block; |
|
|
|
} |
|
|
|
|
|
|
|
.column-settings-dropdown { |
|
|
|
position: absolute; |
|
|
|
bottom: 100%; /* Changed from top to bottom */ |
|
|
|
right: 0; |
|
|
|
margin-bottom: 4px; /* Add some space between button and menu */ |
|
|
|
background: white; |
|
|
|
border: 1px solid #ddd; |
|
|
|
border-radius: 4px; |
|
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1); |
|
|
|
z-index: 1000; |
|
|
|
min-width: 200px; |
|
|
|
display: none; |
|
|
|
padding: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.column-settings-dropdown.show { |
|
|
|
display: block; |
|
|
|
} |
|
|
|
|
|
|
|
.column-settings-header { |
|
|
|
font-weight: bold; |
|
|
|
padding: 4px 8px; |
|
|
|
border-bottom: 1px solid #eee; |
|
|
|
margin-bottom: 8px; |
|
|
|
color: #495057; |
|
|
|
font-size: 0.9em; |
|
|
|
} |
|
|
|
|
|
|
|
.column-option { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
padding: 4px 8px; |
|
|
|
cursor: pointer; |
|
|
|
border-radius: 3px; |
|
|
|
transition: background-color 0.2s; |
|
|
|
} |
|
|
|
|
|
|
|
.column-option:hover { |
|
|
|
background-color: #f8f9fa; |
|
|
|
} |
|
|
|
|
|
|
|
.column-option input[type="checkbox"] { |
|
|
|
margin-right: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.column-option label { |
|
|
|
cursor: pointer; |
|
|
|
font-size: 0.85em; |
|
|
|
color: #495057; |
|
|
|
margin: 0; |
|
|
|
flex: 1; |
|
|
|
} |
|
|
|
|
|
|
|
.column-option.disabled { |
|
|
|
opacity: 0.5; |
|
|
|
cursor: not-allowed; |
|
|
|
} |
|
|
|
|
|
|
|
.column-option.disabled:hover { |
|
|
|
background-color: transparent; |
|
|
|
} |
|
|
|
</style> |
|
|
|
|
|
|
|
<div class="container"> |
|
|
@ -469,6 +537,48 @@ |
|
|
|
<button class="btn-small" id="reset-logs-btn" title="重置日志">重置</button> |
|
|
|
<button class="btn-small" id="add-test-data-btn" title="添加测试数据">测试</button> |
|
|
|
<button class="btn-small" id="reconnect-btn" title="重新连接">重连</button> |
|
|
|
<div class="column-settings"> |
|
|
|
<button class="btn-small" id="column-settings-btn" title="列设置">列设置</button> |
|
|
|
<div class="column-settings-dropdown" id="column-settings-dropdown"> |
|
|
|
<div class="column-settings-header">显示/隐藏列</div> |
|
|
|
<div class="column-option"> |
|
|
|
<input type="checkbox" id="col-timestamp" checked> |
|
|
|
<label for="col-timestamp">时间戳</label> |
|
|
|
</div> |
|
|
|
<div class="column-option"> |
|
|
|
<input type="checkbox" id="col-layer" checked> |
|
|
|
<label for="col-layer">协议层</label> |
|
|
|
</div> |
|
|
|
<div class="column-option"> |
|
|
|
<input type="checkbox" id="col-direction" checked> |
|
|
|
<label for="col-direction">方向</label> |
|
|
|
</div> |
|
|
|
<div class="column-option"> |
|
|
|
<input type="checkbox" id="col-ueid" checked> |
|
|
|
<label for="col-ueid">UE ID</label> |
|
|
|
</div> |
|
|
|
<div class="column-option"> |
|
|
|
<input type="checkbox" id="col-rnti" checked> |
|
|
|
<label for="col-rnti">RNTI</label> |
|
|
|
</div> |
|
|
|
<div class="column-option"> |
|
|
|
<input type="checkbox" id="col-cell" checked> |
|
|
|
<label for="col-cell">Cell</label> |
|
|
|
</div> |
|
|
|
<div class="column-option"> |
|
|
|
<input type="checkbox" id="col-channel" checked> |
|
|
|
<label for="col-channel">Channel</label> |
|
|
|
</div> |
|
|
|
<div class="column-option"> |
|
|
|
<input type="checkbox" id="col-message" checked> |
|
|
|
<label for="col-message">消息</label> |
|
|
|
</div> |
|
|
|
<div class="column-option"> |
|
|
|
<input type="checkbox" id="col-info" checked> |
|
|
|
<label for="col-info">信息</label> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
@ -527,6 +637,19 @@ |
|
|
|
let sortField = 'timestamp'; // 当前排序字段 |
|
|
|
let sortDirection = 'desc'; // 当前排序方向:'asc' 或 'desc' |
|
|
|
|
|
|
|
// 列显示状态管理 |
|
|
|
let columnVisibility = { |
|
|
|
timestamp: true, |
|
|
|
layer: true, |
|
|
|
direction: true, |
|
|
|
ueid: true, |
|
|
|
rnti: true, |
|
|
|
cell: true, |
|
|
|
channel: true, |
|
|
|
message: true, |
|
|
|
info: true |
|
|
|
}; |
|
|
|
|
|
|
|
let clusterize = new Clusterize({ |
|
|
|
rows: [], |
|
|
|
scrollId: 'log-scroll-area', |
|
|
@ -702,6 +825,75 @@ |
|
|
|
refreshLogList(); |
|
|
|
} |
|
|
|
|
|
|
|
// 切换列显示状态 |
|
|
|
function toggleColumnVisibility(columnName, visible) { |
|
|
|
columnVisibility[columnName] = visible; |
|
|
|
updateColumnDisplay(); |
|
|
|
saveColumnSettings(); |
|
|
|
} |
|
|
|
|
|
|
|
// 更新列显示 |
|
|
|
function updateColumnDisplay() { |
|
|
|
// 更新标题栏 |
|
|
|
const headerSpans = document.querySelectorAll('.log-list-header > span'); |
|
|
|
headerSpans.forEach(span => { |
|
|
|
const columnClass = Array.from(span.classList).find(cls => cls.startsWith('log-')); |
|
|
|
if (columnClass) { |
|
|
|
const columnName = columnClass.replace('log-', ''); |
|
|
|
if (columnName === 'timestamp') { |
|
|
|
span.style.display = columnVisibility.timestamp ? 'flex' : 'none'; |
|
|
|
} else { |
|
|
|
span.style.display = columnVisibility[columnName] ? 'block' : 'none'; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 更新日志条目 |
|
|
|
const logItems = document.querySelectorAll('.log-item > span'); |
|
|
|
logItems.forEach(span => { |
|
|
|
const columnClass = Array.from(span.classList).find(cls => cls.startsWith('log-')); |
|
|
|
if (columnClass) { |
|
|
|
const columnName = columnClass.replace('log-', ''); |
|
|
|
if (columnName === 'timestamp') { |
|
|
|
span.style.display = columnVisibility.timestamp ? 'flex' : 'none'; |
|
|
|
} else { |
|
|
|
span.style.display = columnVisibility[columnName] ? 'block' : 'none'; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// 保存列设置到本地存储 |
|
|
|
function saveColumnSettings() { |
|
|
|
localStorage.setItem('logColumnSettings', JSON.stringify(columnVisibility)); |
|
|
|
} |
|
|
|
|
|
|
|
// 从本地存储加载列设置 |
|
|
|
function loadColumnSettings() { |
|
|
|
const saved = localStorage.getItem('logColumnSettings'); |
|
|
|
if (saved) { |
|
|
|
try { |
|
|
|
const savedSettings = JSON.parse(saved); |
|
|
|
columnVisibility = { ...columnVisibility, ...savedSettings }; |
|
|
|
} catch (error) { |
|
|
|
console.warn('加载列设置失败:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 更新列设置复选框状态 |
|
|
|
function updateColumnCheckboxes() { |
|
|
|
document.getElementById('col-timestamp').checked = columnVisibility.timestamp; |
|
|
|
document.getElementById('col-layer').checked = columnVisibility.layer; |
|
|
|
document.getElementById('col-direction').checked = columnVisibility.direction; |
|
|
|
document.getElementById('col-ueid').checked = columnVisibility.ueid; |
|
|
|
document.getElementById('col-rnti').checked = columnVisibility.rnti; |
|
|
|
document.getElementById('col-cell').checked = columnVisibility.cell; |
|
|
|
document.getElementById('col-channel').checked = columnVisibility.channel; |
|
|
|
document.getElementById('col-message').checked = columnVisibility.message; |
|
|
|
document.getElementById('col-info').checked = columnVisibility.info; |
|
|
|
} |
|
|
|
|
|
|
|
// 美化方向 |
|
|
|
function formatDirection(dir) { |
|
|
|
if (dir === 1) { |
|
|
@ -1083,6 +1275,65 @@ |
|
|
|
|
|
|
|
// 初始化排序状态 |
|
|
|
updateSortIcon(); |
|
|
|
|
|
|
|
// 初始化列设置 |
|
|
|
loadColumnSettings(); |
|
|
|
updateColumnCheckboxes(); |
|
|
|
updateColumnDisplay(); |
|
|
|
|
|
|
|
// 列设置相关事件 |
|
|
|
const columnSettingsBtn = document.getElementById('column-settings-btn'); |
|
|
|
const columnSettingsDropdown = document.getElementById('column-settings-dropdown'); |
|
|
|
|
|
|
|
// 列设置按钮点击事件 |
|
|
|
columnSettingsBtn.addEventListener('click', function(e) { |
|
|
|
e.stopPropagation(); |
|
|
|
columnSettingsDropdown.classList.toggle('show'); |
|
|
|
}); |
|
|
|
|
|
|
|
// 点击其他地方关闭下拉菜单 |
|
|
|
document.addEventListener('click', function(e) { |
|
|
|
if (!columnSettingsDropdown.contains(e.target) && !columnSettingsBtn.contains(e.target)) { |
|
|
|
columnSettingsDropdown.classList.remove('show'); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 列设置复选框事件 |
|
|
|
document.getElementById('col-timestamp').addEventListener('change', function() { |
|
|
|
toggleColumnVisibility('timestamp', this.checked); |
|
|
|
}); |
|
|
|
|
|
|
|
document.getElementById('col-layer').addEventListener('change', function() { |
|
|
|
toggleColumnVisibility('layer', this.checked); |
|
|
|
}); |
|
|
|
|
|
|
|
document.getElementById('col-direction').addEventListener('change', function() { |
|
|
|
toggleColumnVisibility('direction', this.checked); |
|
|
|
}); |
|
|
|
|
|
|
|
document.getElementById('col-ueid').addEventListener('change', function() { |
|
|
|
toggleColumnVisibility('ueid', this.checked); |
|
|
|
}); |
|
|
|
|
|
|
|
document.getElementById('col-rnti').addEventListener('change', function() { |
|
|
|
toggleColumnVisibility('rnti', this.checked); |
|
|
|
}); |
|
|
|
|
|
|
|
document.getElementById('col-cell').addEventListener('change', function() { |
|
|
|
toggleColumnVisibility('cell', this.checked); |
|
|
|
}); |
|
|
|
|
|
|
|
document.getElementById('col-channel').addEventListener('change', function() { |
|
|
|
toggleColumnVisibility('channel', this.checked); |
|
|
|
}); |
|
|
|
|
|
|
|
document.getElementById('col-message').addEventListener('change', function() { |
|
|
|
toggleColumnVisibility('message', this.checked); |
|
|
|
}); |
|
|
|
|
|
|
|
document.getElementById('col-info').addEventListener('change', function() { |
|
|
|
toggleColumnVisibility('info', this.checked); |
|
|
|
}); |
|
|
|
}); |
|
|
|
</script> |
|
|
|
} |
|
|
|