增加显示IP地理位置的功能
This commit is contained in:
@@ -10,6 +10,14 @@ let logsChart = null;
|
||||
let currentSortField = '';
|
||||
let currentSortDirection = 'desc'; // 默认降序
|
||||
|
||||
// IP地理位置缓存
|
||||
let ipGeolocationCache = {};
|
||||
const GEOLOCATION_CACHE_EXPIRY = 24 * 60 * 60 * 1000; // 缓存有效期24小时
|
||||
|
||||
// WebSocket连接和重连计时器
|
||||
let logsWsConnection = null;
|
||||
let logsWsReconnectTimer = null;
|
||||
|
||||
// 初始化查询日志页面
|
||||
function initLogsPage() {
|
||||
console.log('初始化查询日志页面');
|
||||
@@ -36,15 +44,15 @@ function initLogsPage() {
|
||||
// 清理资源
|
||||
function cleanupLogsResources() {
|
||||
// 清除WebSocket连接
|
||||
if (wsConnection) {
|
||||
wsConnection.close();
|
||||
wsConnection = null;
|
||||
if (logsWsConnection) {
|
||||
logsWsConnection.close();
|
||||
logsWsConnection = null;
|
||||
}
|
||||
|
||||
// 清除重连计时器
|
||||
if (wsReconnectTimer) {
|
||||
clearTimeout(wsReconnectTimer);
|
||||
wsReconnectTimer = null;
|
||||
if (logsWsReconnectTimer) {
|
||||
clearTimeout(logsWsReconnectTimer);
|
||||
logsWsReconnectTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,9 +198,14 @@ function updateSortIcons() {
|
||||
|
||||
// 加载日志统计数据
|
||||
function loadLogsStats() {
|
||||
fetch('/api/logs/stats')
|
||||
.then(response => response.json())
|
||||
// 使用封装的apiRequest函数进行API调用
|
||||
apiRequest('/logs/stats')
|
||||
.then(data => {
|
||||
if (data && data.error) {
|
||||
console.error('加载日志统计数据失败:', data.error);
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新统计卡片
|
||||
document.getElementById('logs-total-queries').textContent = data.totalQueries;
|
||||
document.getElementById('logs-avg-response-time').textContent = data.avgResponseTime.toFixed(2) + 'ms';
|
||||
@@ -216,32 +229,50 @@ function loadLogs() {
|
||||
}
|
||||
|
||||
// 构建请求URL
|
||||
let url = `/api/logs/query?limit=${logsPerPage}&offset=${(currentPage - 1) * logsPerPage}`;
|
||||
let endpoint = `/logs/query?limit=${logsPerPage}&offset=${(currentPage - 1) * logsPerPage}`;
|
||||
|
||||
// 添加过滤条件
|
||||
if (currentFilter) {
|
||||
url += `&result=${currentFilter}`;
|
||||
endpoint += `&result=${currentFilter}`;
|
||||
}
|
||||
|
||||
// 添加搜索条件
|
||||
if (currentSearch) {
|
||||
url += `&search=${encodeURIComponent(currentSearch)}`;
|
||||
endpoint += `&search=${encodeURIComponent(currentSearch)}`;
|
||||
}
|
||||
|
||||
// 添加排序条件
|
||||
if (currentSortField) {
|
||||
url += `&sort=${currentSortField}&direction=${currentSortDirection}`;
|
||||
endpoint += `&sort=${currentSortField}&direction=${currentSortDirection}`;
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
.then(response => response.json())
|
||||
// 使用封装的apiRequest函数进行API调用
|
||||
apiRequest(endpoint)
|
||||
.then(data => {
|
||||
if (data && data.error) {
|
||||
console.error('加载日志详情失败:', data.error);
|
||||
// 隐藏加载状态
|
||||
if (loadingEl) {
|
||||
loadingEl.classList.add('hidden');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 加载日志总数
|
||||
return fetch('/api/logs/count').then(response => response.json()).then(countData => {
|
||||
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;
|
||||
|
||||
@@ -358,7 +389,10 @@ function updateLogsTable(logs) {
|
||||
<div class="text-sm font-medium">${formattedTime}</div>
|
||||
<div class="text-xs text-gray-500 mt-1">${formattedDate}</div>
|
||||
</td>
|
||||
<td class="py-3 px-4 text-sm">${log.ClientIP}</td>
|
||||
<td class="py-3 px-4 text-sm">
|
||||
<div class="font-medium">${log.ClientIP}</div>
|
||||
<div class="text-xs text-gray-500 mt-1">${log.Location || '未知 未知'}</div>
|
||||
</td>
|
||||
<td class="py-3 px-4 text-sm">
|
||||
<div class="font-medium">${log.Domain}</div>
|
||||
<div class="text-xs text-gray-500 mt-1">类型: ${log.QueryType}, <span class="${statusClass}">${statusText}</span></div>
|
||||
@@ -396,9 +430,13 @@ function initLogsChart() {
|
||||
if (!ctx) return;
|
||||
|
||||
// 获取24小时统计数据
|
||||
fetch('/api/hourly-stats')
|
||||
.then(response => response.json())
|
||||
apiRequest('/hourly-stats')
|
||||
.then(data => {
|
||||
if (data && data.error) {
|
||||
console.error('初始化日志图表失败:', data.error);
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建图表
|
||||
logsChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
@@ -446,24 +484,29 @@ function initLogsChart() {
|
||||
function updateLogsChart(range) {
|
||||
if (!logsChart) return;
|
||||
|
||||
let url = '';
|
||||
let endpoint = '';
|
||||
switch (range) {
|
||||
case '24h':
|
||||
url = '/api/hourly-stats';
|
||||
endpoint = '/hourly-stats';
|
||||
break;
|
||||
case '7d':
|
||||
url = '/api/daily-stats';
|
||||
endpoint = '/daily-stats';
|
||||
break;
|
||||
case '30d':
|
||||
url = '/api/monthly-stats';
|
||||
endpoint = '/monthly-stats';
|
||||
break;
|
||||
default:
|
||||
url = '/api/hourly-stats';
|
||||
endpoint = '/hourly-stats';
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
.then(response => response.json())
|
||||
// 使用封装的apiRequest函数进行API调用
|
||||
apiRequest(endpoint)
|
||||
.then(data => {
|
||||
if (data && data.error) {
|
||||
console.error('更新日志图表失败:', data.error);
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新图表数据
|
||||
logsChart.data.labels = data.labels;
|
||||
logsChart.data.datasets[0].data = data.data;
|
||||
@@ -484,15 +527,15 @@ function connectLogsWebSocket() {
|
||||
console.log('正在连接WebSocket:', wsUrl);
|
||||
|
||||
// 创建WebSocket连接
|
||||
wsConnection = new WebSocket(wsUrl);
|
||||
logsWsConnection = new WebSocket(wsUrl);
|
||||
|
||||
// 连接打开事件
|
||||
wsConnection.onopen = function() {
|
||||
logsWsConnection.onopen = function() {
|
||||
console.log('WebSocket连接已建立');
|
||||
};
|
||||
|
||||
// 接收消息事件
|
||||
wsConnection.onmessage = function(event) {
|
||||
logsWsConnection.onmessage = function(event) {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
|
||||
@@ -507,16 +550,16 @@ function connectLogsWebSocket() {
|
||||
};
|
||||
|
||||
// 连接关闭事件
|
||||
wsConnection.onclose = function(event) {
|
||||
logsWsConnection.onclose = function(event) {
|
||||
console.warn('WebSocket连接已关闭,代码:', event.code);
|
||||
wsConnection = null;
|
||||
logsWsConnection = null;
|
||||
|
||||
// 设置重连
|
||||
setupLogsReconnect();
|
||||
};
|
||||
|
||||
// 连接错误事件
|
||||
wsConnection.onerror = function(error) {
|
||||
logsWsConnection.onerror = function(error) {
|
||||
console.error('WebSocket连接错误:', error);
|
||||
};
|
||||
|
||||
@@ -527,14 +570,14 @@ function connectLogsWebSocket() {
|
||||
|
||||
// 设置重连逻辑
|
||||
function setupLogsReconnect() {
|
||||
if (wsReconnectTimer) {
|
||||
if (logsWsReconnectTimer) {
|
||||
return; // 已经有重连计时器在运行
|
||||
}
|
||||
|
||||
const reconnectDelay = 5000; // 5秒后重连
|
||||
console.log(`将在${reconnectDelay}ms后尝试重新连接WebSocket`);
|
||||
|
||||
wsReconnectTimer = setTimeout(() => {
|
||||
logsWsReconnectTimer = setTimeout(() => {
|
||||
connectLogsWebSocket();
|
||||
}, reconnectDelay);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user