|
|
@ -265,65 +265,23 @@ |
|
|
|
} |
|
|
|
|
|
|
|
/* Layer过滤器样式 */ |
|
|
|
.layer-filter-container { |
|
|
|
position: relative; |
|
|
|
margin-left: 8px; |
|
|
|
.layer-filter-section { |
|
|
|
background-color: #f8f9fa; |
|
|
|
border-bottom: 1px solid #dee2e6; |
|
|
|
padding: 8px 10px; |
|
|
|
} |
|
|
|
|
|
|
|
.layer-filter-trigger { |
|
|
|
padding: 4px 8px; |
|
|
|
border: 1px solid #ced4da; |
|
|
|
border-radius: 3px; |
|
|
|
background-color: #fff; |
|
|
|
cursor: pointer; |
|
|
|
.filter-header-row { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: center; |
|
|
|
gap: 4px; |
|
|
|
min-width: 80px; |
|
|
|
font-size: 0.8em; |
|
|
|
} |
|
|
|
|
|
|
|
.layer-filter-trigger:hover { |
|
|
|
border-color: #007bff; |
|
|
|
} |
|
|
|
|
|
|
|
.filter-text { |
|
|
|
font-size: 0.8em; |
|
|
|
} |
|
|
|
|
|
|
|
.filter-arrow { |
|
|
|
font-size: 0.8em; |
|
|
|
transition: transform 0.2s; |
|
|
|
} |
|
|
|
|
|
|
|
.layer-filter-container.open .filter-arrow { |
|
|
|
transform: rotate(180deg); |
|
|
|
} |
|
|
|
|
|
|
|
.layer-filter-dropdown { |
|
|
|
position: absolute; |
|
|
|
top: 100%; |
|
|
|
left: 0; |
|
|
|
width: 150px; |
|
|
|
background-color: #fff; |
|
|
|
border: 1px solid #ced4da; |
|
|
|
border-radius: 3px; |
|
|
|
max-height: 200px; |
|
|
|
overflow-y: auto; |
|
|
|
z-index: 9999; |
|
|
|
display: none; |
|
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1); |
|
|
|
margin-top: 2px; |
|
|
|
margin-bottom: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.layer-filter-container.open .layer-filter-dropdown { |
|
|
|
display: block !important; |
|
|
|
} |
|
|
|
|
|
|
|
.filter-header { |
|
|
|
padding: 8px 10px; |
|
|
|
background-color: #f8f9fa; |
|
|
|
border-bottom: 1px solid #dee2e6; |
|
|
|
.filter-label { |
|
|
|
font-size: 0.9em; |
|
|
|
font-weight: bold; |
|
|
|
color: #495057; |
|
|
|
} |
|
|
|
|
|
|
|
.select-all-label { |
|
|
@ -332,22 +290,27 @@ |
|
|
|
gap: 4px; |
|
|
|
font-size: 0.8em; |
|
|
|
cursor: pointer; |
|
|
|
color: #007bff; |
|
|
|
} |
|
|
|
|
|
|
|
.select-all-label:hover { |
|
|
|
color: #0056b3; |
|
|
|
} |
|
|
|
|
|
|
|
.select-all-label input { |
|
|
|
margin: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.filter-options { |
|
|
|
padding: 8px 10px; |
|
|
|
.filter-options-row { |
|
|
|
display: flex; |
|
|
|
flex-wrap: wrap; |
|
|
|
gap: 12px; |
|
|
|
} |
|
|
|
|
|
|
|
.filter-option { |
|
|
|
margin-bottom: 6px; |
|
|
|
} |
|
|
|
|
|
|
|
.filter-option:last-child { |
|
|
|
margin-bottom: 0; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
gap: 4px; |
|
|
|
} |
|
|
|
|
|
|
|
.filter-option label { |
|
|
@ -356,17 +319,24 @@ |
|
|
|
gap: 4px; |
|
|
|
font-size: 0.8em; |
|
|
|
cursor: pointer; |
|
|
|
padding: 2px 0; |
|
|
|
padding: 2px 6px; |
|
|
|
border-radius: 3px; |
|
|
|
transition: background-color 0.2s; |
|
|
|
} |
|
|
|
|
|
|
|
.filter-option label:hover { |
|
|
|
background-color: #f8f9fa; |
|
|
|
background-color: #e9ecef; |
|
|
|
} |
|
|
|
|
|
|
|
.filter-option input { |
|
|
|
margin: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.filter-option input:checked + span { |
|
|
|
font-weight: bold; |
|
|
|
color: #007bff; |
|
|
|
} |
|
|
|
|
|
|
|
.log-layer { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
@ -382,30 +352,25 @@ |
|
|
|
|
|
|
|
<div class="log-list-header"> |
|
|
|
<span class="log-timestamp">Timestamp</span> |
|
|
|
<span class="log-layer"> |
|
|
|
Layer |
|
|
|
<div class="layer-filter-container"> |
|
|
|
<div class="layer-filter-trigger" id="layer-filter-trigger"> |
|
|
|
<span class="filter-text">全部</span> |
|
|
|
<span class="filter-arrow">▼</span> |
|
|
|
</div> |
|
|
|
<div class="layer-filter-dropdown" id="layer-filter-dropdown"> |
|
|
|
<div class="filter-header"> |
|
|
|
<label class="select-all-label"> |
|
|
|
<input type="checkbox" id="select-all-layers"> 全选 |
|
|
|
</label> |
|
|
|
</div> |
|
|
|
<div class="filter-options" id="layer-filter-options"> |
|
|
|
<!-- 选项将动态生成 --> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</span> |
|
|
|
<span class="log-layer">Layer</span> |
|
|
|
<span class="log-direction">Direction</span> |
|
|
|
<span class="log-message">Message</span> |
|
|
|
<span class="log-info">Info</span> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- Layer过滤器区域 --> |
|
|
|
<div class="layer-filter-section"> |
|
|
|
<div class="filter-header-row"> |
|
|
|
<span class="filter-label">Layer过滤:</span> |
|
|
|
<label class="select-all-label"> |
|
|
|
<input type="checkbox" id="select-all-layers"> 全选 |
|
|
|
</label> |
|
|
|
</div> |
|
|
|
<div class="filter-options-row" id="layer-filter-options"> |
|
|
|
<!-- 选项将动态生成 --> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div id="log-scroll-area"> |
|
|
|
<div id="log-content-area"></div> |
|
|
|
</div> |
|
|
@ -460,11 +425,8 @@ |
|
|
|
const reconnectBtn = document.getElementById('reconnect-btn'); |
|
|
|
const logListPanel = document.querySelector('.log-list-panel'); |
|
|
|
const resizer = document.getElementById('drag-resizer'); |
|
|
|
const layerFilter = document.getElementById('layer-filter-dropdown'); |
|
|
|
const layerFilterTrigger = document.getElementById('layer-filter-trigger'); |
|
|
|
const layerFilterOptions = document.getElementById('layer-filter-options'); |
|
|
|
const selectAllLayers = document.getElementById('select-all-layers'); |
|
|
|
const filterText = document.querySelector('.filter-text'); |
|
|
|
|
|
|
|
let allLogsData = []; |
|
|
|
let availableLayers = new Set(['PHY', 'MAC', 'RLC', 'PDCP', 'RRC', 'NAS']); // 初始化标准LTE层 |
|
|
@ -484,19 +446,6 @@ |
|
|
|
no_data_text: "正在等待日志..." |
|
|
|
}); |
|
|
|
|
|
|
|
// 更新过滤器显示文本 |
|
|
|
function updateFilterText() { |
|
|
|
if (selectedLayers.size === 0) { |
|
|
|
filterText.textContent = '全部'; |
|
|
|
} else if (selectedLayers.size === availableLayers.size) { |
|
|
|
filterText.textContent = '全部'; |
|
|
|
} else if (selectedLayers.size === 1) { |
|
|
|
filterText.textContent = Array.from(selectedLayers)[0]; |
|
|
|
} else { |
|
|
|
filterText.textContent = `${selectedLayers.size}个层`; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 更新全选复选框状态 |
|
|
|
function updateSelectAllState() { |
|
|
|
if (availableLayers.size === 0) { |
|
|
@ -526,7 +475,7 @@ |
|
|
|
options.push(`<div class="filter-option"> |
|
|
|
<label> |
|
|
|
<input type="checkbox" value="${layer}"${isChecked}> |
|
|
|
${layer} |
|
|
|
<span>${layer}</span> |
|
|
|
</label> |
|
|
|
</div>`); |
|
|
|
}); |
|
|
@ -536,8 +485,7 @@ |
|
|
|
// 重新绑定事件 |
|
|
|
bindFilterEvents(); |
|
|
|
|
|
|
|
// 更新显示文本和全选状态 |
|
|
|
updateFilterText(); |
|
|
|
// 更新全选状态 |
|
|
|
updateSelectAllState(); |
|
|
|
} |
|
|
|
|
|
|
@ -551,7 +499,6 @@ |
|
|
|
} else { |
|
|
|
selectedLayers.delete(this.value); |
|
|
|
} |
|
|
|
updateFilterText(); |
|
|
|
updateSelectAllState(); |
|
|
|
refreshLogList(); |
|
|
|
}); |
|
|
@ -831,30 +778,9 @@ |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
// 切换下拉框显示状态 |
|
|
|
function toggleFilterDropdown() { |
|
|
|
const container = layerFilterTrigger.parentElement; |
|
|
|
console.log('Toggling dropdown, current state:', container.classList.contains('open')); |
|
|
|
container.classList.toggle('open'); |
|
|
|
console.log('Dropdown state after toggle:', container.classList.contains('open')); |
|
|
|
} |
|
|
|
|
|
|
|
// 关闭下拉框 |
|
|
|
function closeFilterDropdown() { |
|
|
|
const container = layerFilterTrigger.parentElement; |
|
|
|
container.classList.remove('open'); |
|
|
|
} |
|
|
|
|
|
|
|
// 事件监听器 |
|
|
|
layerFilterTrigger.addEventListener('click', function(e) { |
|
|
|
console.log('Layer filter trigger clicked'); |
|
|
|
e.stopPropagation(); |
|
|
|
toggleFilterDropdown(); |
|
|
|
}); |
|
|
|
|
|
|
|
// 全选/取消全选 |
|
|
|
selectAllLayers.addEventListener('change', function() { |
|
|
|
console.log('Select all changed:', this.checked); |
|
|
|
const isChecked = selectAllLayers.checked; |
|
|
|
if (isChecked) { |
|
|
|
// 全选 |
|
|
@ -868,18 +794,6 @@ |
|
|
|
refreshLogList(); |
|
|
|
}); |
|
|
|
|
|
|
|
// 点击外部关闭下拉框 |
|
|
|
document.addEventListener('click', function(e) { |
|
|
|
if (!layerFilterTrigger.contains(e.target) && !layerFilter.contains(e.target)) { |
|
|
|
closeFilterDropdown(); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 阻止下拉框内部点击事件冒泡 |
|
|
|
layerFilter.addEventListener('click', function(e) { |
|
|
|
e.stopPropagation(); |
|
|
|
}); |
|
|
|
|
|
|
|
// 事件委托处理点击事件 |
|
|
|
contentArea.addEventListener('click', function(e) { |
|
|
|
const item = e.target.closest('.log-item'); |
|
|
@ -995,14 +909,6 @@ |
|
|
|
|
|
|
|
// 初始化Layer过滤器,显示标准LTE层 |
|
|
|
updateLayerFilter(); |
|
|
|
|
|
|
|
// 调试信息 |
|
|
|
console.log('Layer filter elements found:', { |
|
|
|
trigger: layerFilterTrigger, |
|
|
|
dropdown: layerFilter, |
|
|
|
options: layerFilterOptions, |
|
|
|
selectAll: selectAllLayers |
|
|
|
}); |
|
|
|
}); |
|
|
|
</script> |
|
|
|
} |
|
|
|