优化修复

This commit is contained in:
Alex Yang
2026-01-03 01:11:42 +08:00
parent 1dd1f15788
commit f247eaeaa8
16 changed files with 1288 additions and 315 deletions

View File

@@ -10,9 +10,11 @@ let logsChart = null;
let currentSortField = '';
let currentSortDirection = 'desc'; // 默认降序
// IP地理位置缓存
let ipGeolocationCache = {};
const GEOLOCATION_CACHE_EXPIRY = 24 * 60 * 60 * 1000; // 缓存有效期24小时
// IP地理位置缓存(检查是否已经存在,避免重复声明)
if (typeof ipGeolocationCache === 'undefined') {
var ipGeolocationCache = {};
var GEOLOCATION_CACHE_EXPIRY = 24 * 60 * 60 * 1000; // 缓存有效期24小时
}
// 获取IP地理位置信息
async function getIpGeolocation(ip) {
@@ -112,10 +114,12 @@ function isPrivateIP(ip) {
return false;
}
// 跟踪器数据库缓存
let trackersDatabase = null;
let trackersLoaded = false;
let trackersLoading = false;
// 跟踪器数据库缓存(检查是否已经存在,避免重复声明)
if (typeof trackersDatabase === 'undefined') {
var trackersDatabase = null;
var trackersLoaded = false;
var trackersLoading = false;
}
// 域名信息数据库缓存
let domainInfoDatabase = null;
@@ -477,6 +481,270 @@ function extractPrimaryDomain(domain) {
return result;
}
// 初始化列宽调节功能
function initResizableColumns() {
const table = document.querySelector('.resizable-table');
if (!table) return;
// 为每个表头添加调整手柄元素
function addResizeHandles() {
const headers = table.querySelectorAll('th');
headers.forEach(header => {
// 移除已存在的手柄
const existingHandle = header.querySelector('.resize-handle');
if (existingHandle) {
existingHandle.remove();
}
// 创建新的调整手柄
const resizeHandle = document.createElement('div');
resizeHandle.className = 'resize-handle';
resizeHandle.style.cssText = `
position: absolute;
top: 0;
right: 0;
width: 10px;
height: 100%;
cursor: col-resize;
background: rgba(59, 130, 246, 0.1);
z-index: 10;
transition: background-color 0.2s ease;
`;
// 添加悬停效果
resizeHandle.addEventListener('mouseenter', () => {
resizeHandle.style.background = 'rgba(59, 130, 246, 0.3)';
});
resizeHandle.addEventListener('mouseleave', () => {
if (!resizeHandle.classList.contains('dragging')) {
resizeHandle.style.background = 'rgba(59, 130, 246, 0.1)';
}
});
header.style.position = 'relative';
header.appendChild(resizeHandle);
});
}
// 计算列宽并设置固定宽度
function calculateAndSetColumnWidths() {
// 确保表格可见
table.style.visibility = 'visible';
// 保存当前表格布局
const originalLayout = table.style.tableLayout;
table.style.tableLayout = 'auto';
// 获取所有表头和数据行
const headers = table.querySelectorAll('th');
const rows = table.querySelectorAll('tbody tr');
// 计算每列的最大宽度
const columnWidths = [];
headers.forEach((header, index) => {
// 获取表头宽度
let maxWidth = header.offsetWidth;
// 遍历所有数据行,找到该列的最大宽度
rows.forEach(row => {
const cell = row.children[index];
if (cell) {
maxWidth = Math.max(maxWidth, cell.offsetWidth);
}
});
// 添加一些 padding
maxWidth += 20;
// 保存最大宽度
columnWidths[index] = maxWidth;
});
// 设置每列的固定宽度
headers.forEach((header, index) => {
const width = `${columnWidths[index]}px`;
header.style.width = width;
header.style.minWidth = width;
header.style.maxWidth = width;
// 找到对应的数据列并设置宽度
rows.forEach(row => {
const cell = row.children[index];
if (cell) {
cell.style.width = width;
cell.style.minWidth = width;
cell.style.maxWidth = width;
}
});
});
// 恢复表格布局
table.style.tableLayout = 'fixed';
}
// 保存列宽设置的函数
function saveColumnWidths() {
const headers = table.querySelectorAll('th');
const columnWidths = {};
headers.forEach((header, index) => {
columnWidths[index] = header.style.width;
});
localStorage.setItem('logsTableColumnWidths', JSON.stringify(columnWidths));
}
// 恢复列宽设置的函数
function restoreColumnWidths() {
const headers = table.querySelectorAll('th');
const savedWidths = localStorage.getItem('logsTableColumnWidths');
if (savedWidths) {
const columnWidths = JSON.parse(savedWidths);
// 设置表格布局为fixed
table.style.tableLayout = 'fixed';
headers.forEach((header, index) => {
if (columnWidths[index]) {
const width = columnWidths[index];
header.style.width = width;
header.style.minWidth = width;
header.style.maxWidth = width;
// 找到对应的数据列并设置宽度
const rows = table.querySelectorAll('tbody tr');
rows.forEach(row => {
const cell = row.children[index];
if (cell) {
cell.style.width = width;
cell.style.minWidth = width;
cell.style.maxWidth = width;
}
});
}
});
} else {
// 没有保存的宽度,计算并设置列宽
calculateAndSetColumnWidths();
}
}
// 恢复保存的列宽设置或计算初始列宽
restoreColumnWidths();
// 添加调整手柄
addResizeHandles();
// 拖拽状态变量
let currentHeader = null;
let startX = 0;
let startWidth = 0;
let isDragging = false;
// 鼠标按下事件
table.addEventListener('mousedown', (e) => {
const resizeHandle = e.target.closest('.resize-handle');
if (resizeHandle) {
currentHeader = resizeHandle.parentElement;
startX = e.clientX;
startWidth = currentHeader.offsetWidth;
isDragging = true;
// 添加拖拽状态类
currentHeader.classList.add('dragging');
resizeHandle.classList.add('dragging');
// 改变拖拽手柄样式
resizeHandle.style.background = 'rgba(59, 130, 246, 0.6)';
// 阻止默认事件和冒泡
e.preventDefault();
e.stopPropagation();
// 阻止文本选择
document.addEventListener('selectstart', preventSelect, { capture: true });
document.addEventListener('copy', preventCopy, { capture: true });
// 添加全局事件监听器
document.addEventListener('mousemove', onMouseMove, { capture: true });
document.addEventListener('mouseup', onMouseUp, { capture: true });
}
});
// 鼠标移动事件处理函数
function onMouseMove(e) {
if (!currentHeader) return;
// 阻止默认事件
e.preventDefault();
e.stopPropagation();
// 计算新宽度
const deltaX = e.clientX - startX;
const newWidth = Math.max(50, startWidth + deltaX);
// 设置新宽度
const width = `${newWidth}px`;
currentHeader.style.width = width;
currentHeader.style.minWidth = width;
currentHeader.style.maxWidth = width;
// 找到对应的数据列并设置宽度
const headers = table.querySelectorAll('th');
const index = Array.from(headers).indexOf(currentHeader);
const rows = table.querySelectorAll('tbody tr');
rows.forEach(row => {
const cell = row.children[index];
if (cell) {
cell.style.width = width;
cell.style.minWidth = width;
cell.style.maxWidth = width;
}
});
}
// 鼠标释放事件处理函数
function onMouseUp(e) {
if (!currentHeader) return;
// 阻止默认事件
e.preventDefault();
e.stopPropagation();
// 获取调整手柄
const resizeHandle = currentHeader.querySelector('.resize-handle');
// 移除拖拽状态类
currentHeader.classList.remove('dragging');
resizeHandle.classList.remove('dragging');
// 恢复拖拽手柄样式
resizeHandle.style.background = 'rgba(59, 130, 246, 0.1)';
// 保存列宽设置
saveColumnWidths();
// 重置状态
currentHeader = null;
isDragging = false;
// 移除事件监听器
document.removeEventListener('selectstart', preventSelect, { capture: true });
document.removeEventListener('copy', preventCopy, { capture: true });
document.removeEventListener('mousemove', onMouseMove, { capture: true });
document.removeEventListener('mouseup', onMouseUp, { capture: true });
}
// 阻止文本选择和复制
function preventSelect(e) {
e.preventDefault();
}
function preventCopy(e) {
e.preventDefault();
}
}
// 初始化查询日志页面
function initLogsPage() {
console.log('初始化查询日志页面');
@@ -499,6 +767,9 @@ function initLogsPage() {
// 建立WebSocket连接用于实时更新统计数据和图表
connectLogsWebSocket();
// 初始化列宽调节功能
initResizableColumns();
// 窗口大小改变时重新加载日志表格
window.addEventListener('resize', handleWindowResize);
@@ -723,7 +994,7 @@ function loadLogsStats() {
}
// 加载日志详情
function loadLogs() {
async function loadLogs() {
// 显示加载状态
const loadingEl = document.getElementById('logs-loading');
if (loadingEl) {
@@ -748,61 +1019,70 @@ function loadLogs() {
endpoint += `&sort=${currentSortField}&direction=${currentSortDirection}`;
}
// 使用封装的apiRequest函数进行API调用
apiRequest(endpoint)
.then(data => {
if (data && data.error) {
console.error('加载日志详情失败:', data.error);
// 隐藏加载状态
if (loadingEl) {
loadingEl.classList.add('hidden');
}
return;
}
// 加载日志总数
return apiRequest('/logs/count').then(countData => {
return { logs: data, count: countData.count };
});
})
.then(result => {
if (!result || !result.logs) {
console.error('加载日志详情失败: 无效的响应数据');
// 隐藏加载状态
if (loadingEl) {
loadingEl.classList.add('hidden');
}
return;
}
const logs = result.logs;
const totalLogs = result.count;
// 计算总页数
totalPages = Math.ceil(totalLogs / logsPerPage);
// 更新日志表格
updateLogsTable(logs);
// 绑定操作按钮事件
bindActionButtonsEvents();
// 更新分页信息
updateLogsPagination();
try {
// 使用封装的apiRequest函数进行API调用
const logsData = await apiRequest(endpoint);
if (logsData && logsData.error) {
console.error('加载日志详情失败:', logsData.error);
// 隐藏加载状态
if (loadingEl) {
loadingEl.classList.add('hidden');
}
})
.catch(error => {
console.error('加载日志详情失败:', error);
// 隐藏加载状态
if (loadingEl) {
loadingEl.classList.add('hidden');
}
});
return;
}
// 加载日志总数
const [logs, countData] = await Promise.all([
Promise.resolve(logsData || []), // 确保logsData是数组
apiRequest('/logs/count')
]);
// 确保logs是数组
const logsArray = Array.isArray(logs) ? logs : [];
// 确保countData是有效的
const totalLogs = countData && countData.count ? countData.count : logsArray.length;
// 计算总页数
totalPages = Math.ceil(totalLogs / logsPerPage);
// 更新日志表格
await updateLogsTable(logsArray);
// 绑定操作按钮事件
bindActionButtonsEvents();
// 更新分页信息
updateLogsPagination();
// 重新初始化列宽调节功能,确保新添加的行也能继承列宽设置
initResizableColumns();
// 隐藏加载状态
if (loadingEl) {
loadingEl.classList.add('hidden');
}
} catch (error) {
console.error('加载日志详情失败:', error);
// 隐藏加载状态
if (loadingEl) {
loadingEl.classList.add('hidden');
}
// 显示空状态
const tableBody = document.getElementById('logs-table-body');
if (tableBody) {
tableBody.innerHTML = `
<tr>
<td colspan="5" class="py-8 text-center text-gray-500 border-b border-gray-100">
<i class="fa fa-file-text-o text-4xl mb-2 text-gray-300"></i>
<div>暂无查询日志</div>
</td>
</tr>
`;
}
}
}
// 更新日志表格