|
|
@ -44,22 +44,42 @@ |
|
|
|
font-weight: bold; |
|
|
|
} |
|
|
|
|
|
|
|
.log-item > span { |
|
|
|
.log-item > span, .log-list-header > span { |
|
|
|
text-overflow: ellipsis; |
|
|
|
overflow: hidden; |
|
|
|
padding-right: 15px; |
|
|
|
} |
|
|
|
.log-timestamp { flex-basis: 20%; } |
|
|
|
.log-layer { flex-basis: 15%; } |
|
|
|
.log-direction { flex-basis: 15%; } |
|
|
|
.log-message { flex-basis: 40%; } |
|
|
|
.log-info { flex-basis: 10%; } |
|
|
|
|
|
|
|
/* 列宽定义:固定与弹性结合 */ |
|
|
|
.log-timestamp { flex: 0 0 170px; } /* 固定宽度 */ |
|
|
|
.log-layer { flex: 0 0 100px; } /* 固定宽度 */ |
|
|
|
.log-direction { flex: 0 0 120px; } /* 固定宽度 */ |
|
|
|
.log-info { flex: 0 0 80px; } /* 固定宽度 */ |
|
|
|
.log-message { |
|
|
|
flex: 1 1 0; /* 弹性增长和收缩,占据剩余空间 */ |
|
|
|
min-width: 150px; /* 保证最小宽度 */ |
|
|
|
} |
|
|
|
|
|
|
|
/* 日志列表标题栏 */ |
|
|
|
.log-list-header { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
padding: 8px 10px; |
|
|
|
padding-right: 27px; /* 10px base padding + 17px for a standard scrollbar */ |
|
|
|
background-color: #f8f9fa; |
|
|
|
font-weight: bold; |
|
|
|
border-bottom: 2px solid #dee2e6; |
|
|
|
color: #495057; |
|
|
|
font-size: 0.9em; |
|
|
|
white-space: nowrap; |
|
|
|
} |
|
|
|
|
|
|
|
/* 右侧日志详情 */ |
|
|
|
.log-detail-panel { |
|
|
|
flex-grow: 1; |
|
|
|
padding: 0 20px; |
|
|
|
overflow-y: auto; |
|
|
|
min-width: 250px; /* 保证最小宽度 */ |
|
|
|
} |
|
|
|
|
|
|
|
.log-detail-panel h4 { |
|
|
@ -89,6 +109,19 @@ |
|
|
|
line-height: 1.6; |
|
|
|
} |
|
|
|
|
|
|
|
/* 可拖动调整大小的分割线 */ |
|
|
|
.resizer { |
|
|
|
flex: 0 0 5px; |
|
|
|
background: #e9ecef; |
|
|
|
cursor: col-resize; |
|
|
|
transition: background-color 0.2s ease; |
|
|
|
} |
|
|
|
|
|
|
|
.resizer:hover, |
|
|
|
.resizer.is-dragging { |
|
|
|
background: #007bff; |
|
|
|
} |
|
|
|
|
|
|
|
#detail-placeholder { |
|
|
|
color: #999; |
|
|
|
text-align: center; |
|
|
@ -206,6 +239,14 @@ |
|
|
|
<div id="error-message" class="error-message"></div> |
|
|
|
<div id="info-message" class="info-message"></div> |
|
|
|
|
|
|
|
<div class="log-list-header"> |
|
|
|
<span class="log-timestamp">Timestamp</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> |
|
|
|
|
|
|
|
<div id="log-scroll-area"> |
|
|
|
<div id="log-content-area"></div> |
|
|
|
</div> |
|
|
@ -226,6 +267,9 @@ |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="resizer" id="drag-resizer"></div> |
|
|
|
|
|
|
|
<div class="log-detail-panel"> |
|
|
|
<div id="detail-placeholder"> |
|
|
|
<p>请从左侧选择一条日志以查看详情</p> |
|
|
@ -256,6 +300,8 @@ |
|
|
|
const resetLogsBtn = document.getElementById('reset-logs-btn'); |
|
|
|
const addTestDataBtn = document.getElementById('add-test-data-btn'); |
|
|
|
const reconnectBtn = document.getElementById('reconnect-btn'); |
|
|
|
const logListPanel = document.querySelector('.log-list-panel'); |
|
|
|
const resizer = document.getElementById('drag-resizer'); |
|
|
|
|
|
|
|
let allLogsData = []; |
|
|
|
let eventSource = null; |
|
|
@ -269,7 +315,8 @@ |
|
|
|
contentId: 'log-content-area', |
|
|
|
tag: 'div', |
|
|
|
rows_in_block: 50, |
|
|
|
blocks_in_cluster: 4 |
|
|
|
blocks_in_cluster: 4, |
|
|
|
no_data_text: "正在等待日志..." |
|
|
|
}); |
|
|
|
|
|
|
|
// 更新连接状态 |
|
|
@ -580,6 +627,48 @@ |
|
|
|
connectSSE(); |
|
|
|
}); |
|
|
|
|
|
|
|
// --- Resizer Logic --- |
|
|
|
let isResizing = false; |
|
|
|
|
|
|
|
resizer.addEventListener('mousedown', (e) => { |
|
|
|
isResizing = true; |
|
|
|
resizer.classList.add('is-dragging'); |
|
|
|
document.body.style.cursor = 'col-resize'; |
|
|
|
document.body.style.userSelect = 'none'; |
|
|
|
|
|
|
|
document.addEventListener('mousemove', onMouseMove); |
|
|
|
document.addEventListener('mouseup', onMouseUp); |
|
|
|
}); |
|
|
|
|
|
|
|
function onMouseMove(e) { |
|
|
|
if (!isResizing) return; |
|
|
|
|
|
|
|
const container = logListPanel.parentElement; |
|
|
|
const containerRect = container.getBoundingClientRect(); |
|
|
|
const newLeftWidth = e.clientX - containerRect.left; |
|
|
|
|
|
|
|
// Constraints |
|
|
|
const leftPanelMinWidth = 400; // in pixels |
|
|
|
const rightPanelMinWidth = 250; // in pixels |
|
|
|
const maxWidth = container.offsetWidth - rightPanelMinWidth - resizer.offsetWidth; |
|
|
|
|
|
|
|
if (newLeftWidth >= leftPanelMinWidth && newLeftWidth <= maxWidth) { |
|
|
|
logListPanel.style.flexBasis = `${newLeftWidth}px`; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function onMouseUp() { |
|
|
|
if (!isResizing) return; |
|
|
|
isResizing = false; |
|
|
|
resizer.classList.remove('is-dragging'); |
|
|
|
document.body.style.cursor = 'default'; |
|
|
|
document.body.style.userSelect = 'auto'; |
|
|
|
|
|
|
|
document.removeEventListener('mousemove', onMouseMove); |
|
|
|
document.removeEventListener('mouseup', onMouseUp); |
|
|
|
} |
|
|
|
// --- End Resizer Logic --- |
|
|
|
|
|
|
|
// 初始化连接 |
|
|
|
connectSSE(); |
|
|
|
}); |
|
|
|