优化修复
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -165,12 +165,16 @@ function processRealTimeData(stats) {
|
||||
let trendIcon = '---';
|
||||
|
||||
if (stats.avgResponseTime !== undefined && stats.avgResponseTime !== null) {
|
||||
// 存储当前值用于下次计算趋势
|
||||
const prevResponseTime = window.dashboardHistoryData.prevResponseTime || stats.avgResponseTime;
|
||||
window.dashboardHistoryData.prevResponseTime = stats.avgResponseTime;
|
||||
const prevResponseTime = window.dashboardHistoryData.prevResponseTime;
|
||||
|
||||
// 计算变化百分比
|
||||
if (prevResponseTime > 0) {
|
||||
// 首次加载时初始化历史数据,不计算趋势
|
||||
if (prevResponseTime === null) {
|
||||
window.dashboardHistoryData.prevResponseTime = stats.avgResponseTime;
|
||||
responsePercent = '0.0%';
|
||||
trendIcon = '•';
|
||||
trendClass = 'text-gray-500';
|
||||
} else {
|
||||
// 计算变化百分比
|
||||
const changePercent = ((stats.avgResponseTime - prevResponseTime) / prevResponseTime) * 100;
|
||||
responsePercent = Math.abs(changePercent).toFixed(1) + '%';
|
||||
|
||||
@@ -185,6 +189,9 @@ function processRealTimeData(stats) {
|
||||
trendIcon = '•';
|
||||
trendClass = 'text-gray-500';
|
||||
}
|
||||
|
||||
// 更新历史数据
|
||||
window.dashboardHistoryData.prevResponseTime = stats.avgResponseTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,26 +215,35 @@ function processRealTimeData(stats) {
|
||||
let trendIcon = '---';
|
||||
|
||||
if (stats.topQueryTypeCount !== undefined && stats.topQueryTypeCount !== null) {
|
||||
// 存储当前值用于下次计算趋势
|
||||
const prevTopQueryTypeCount = window.dashboardHistoryData.prevTopQueryTypeCount || stats.topQueryTypeCount;
|
||||
window.dashboardHistoryData.prevTopQueryTypeCount = stats.topQueryTypeCount;
|
||||
const prevTopQueryTypeCount = window.dashboardHistoryData.prevTopQueryTypeCount;
|
||||
|
||||
// 计算变化百分比
|
||||
if (prevTopQueryTypeCount > 0) {
|
||||
const changePercent = ((stats.topQueryTypeCount - prevTopQueryTypeCount) / prevTopQueryTypeCount) * 100;
|
||||
queryPercent = Math.abs(changePercent).toFixed(1) + '%';
|
||||
|
||||
// 设置趋势图标和颜色
|
||||
if (changePercent > 0) {
|
||||
trendIcon = '↑';
|
||||
trendClass = 'text-primary';
|
||||
} else if (changePercent < 0) {
|
||||
trendIcon = '↓';
|
||||
trendClass = 'text-secondary';
|
||||
} else {
|
||||
trendIcon = '•';
|
||||
trendClass = 'text-gray-500';
|
||||
// 首次加载时初始化历史数据,不计算趋势
|
||||
if (prevTopQueryTypeCount === null) {
|
||||
window.dashboardHistoryData.prevTopQueryTypeCount = stats.topQueryTypeCount;
|
||||
queryPercent = '0.0%';
|
||||
trendIcon = '•';
|
||||
trendClass = 'text-gray-500';
|
||||
} else {
|
||||
// 计算变化百分比
|
||||
if (prevTopQueryTypeCount > 0) {
|
||||
const changePercent = ((stats.topQueryTypeCount - prevTopQueryTypeCount) / prevTopQueryTypeCount) * 100;
|
||||
queryPercent = Math.abs(changePercent).toFixed(1) + '%';
|
||||
|
||||
// 设置趋势图标和颜色
|
||||
if (changePercent > 0) {
|
||||
trendIcon = '↑';
|
||||
trendClass = 'text-primary';
|
||||
} else if (changePercent < 0) {
|
||||
trendIcon = '↓';
|
||||
trendClass = 'text-secondary';
|
||||
} else {
|
||||
trendIcon = '•';
|
||||
trendClass = 'text-gray-500';
|
||||
}
|
||||
}
|
||||
|
||||
// 更新历史数据
|
||||
window.dashboardHistoryData.prevTopQueryTypeCount = stats.topQueryTypeCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,23 +261,33 @@ function processRealTimeData(stats) {
|
||||
let trendIcon = '---';
|
||||
|
||||
if (stats.activeIPs !== undefined) {
|
||||
const prevActiveIPs = window.dashboardHistoryData.prevActiveIPs || stats.activeIPs;
|
||||
window.dashboardHistoryData.prevActiveIPs = stats.activeIPs;
|
||||
const prevActiveIPs = window.dashboardHistoryData.prevActiveIPs;
|
||||
|
||||
if (prevActiveIPs > 0) {
|
||||
const changePercent = ((stats.activeIPs - prevActiveIPs) / prevActiveIPs) * 100;
|
||||
ipsPercent = Math.abs(changePercent).toFixed(1) + '%';
|
||||
|
||||
if (changePercent > 0) {
|
||||
trendIcon = '↑';
|
||||
trendClass = 'text-primary';
|
||||
} else if (changePercent < 0) {
|
||||
trendIcon = '↓';
|
||||
trendClass = 'text-secondary';
|
||||
} else {
|
||||
trendIcon = '•';
|
||||
trendClass = 'text-gray-500';
|
||||
// 首次加载时初始化历史数据,不计算趋势
|
||||
if (prevActiveIPs === null) {
|
||||
window.dashboardHistoryData.prevActiveIPs = stats.activeIPs;
|
||||
ipsPercent = '0.0%';
|
||||
trendIcon = '•';
|
||||
trendClass = 'text-gray-500';
|
||||
} else {
|
||||
if (prevActiveIPs > 0) {
|
||||
const changePercent = ((stats.activeIPs - prevActiveIPs) / prevActiveIPs) * 100;
|
||||
ipsPercent = Math.abs(changePercent).toFixed(1) + '%';
|
||||
|
||||
if (changePercent > 0) {
|
||||
trendIcon = '↑';
|
||||
trendClass = 'text-primary';
|
||||
} else if (changePercent < 0) {
|
||||
trendIcon = '↓';
|
||||
trendClass = 'text-secondary';
|
||||
} else {
|
||||
trendIcon = '•';
|
||||
trendClass = 'text-gray-500';
|
||||
}
|
||||
}
|
||||
|
||||
// 更新历史数据
|
||||
window.dashboardHistoryData.prevActiveIPs = stats.activeIPs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -275,17 +275,22 @@ async function getDomainInfo(domain) {
|
||||
function isDomainMatch(urlValue, targetDomain, categoryId) {
|
||||
console.log(' 开始匹配URL:', urlValue, '目标域名:', targetDomain, '类别ID:', categoryId);
|
||||
|
||||
// 规范化目标域名,去除末尾的点
|
||||
const normalizedTargetDomain = targetDomain.replace(/\.$/, '').toLowerCase();
|
||||
|
||||
try {
|
||||
// 尝试将URL值解析为完整URL
|
||||
console.log(' 尝试解析URL为完整URL');
|
||||
const url = new URL(urlValue);
|
||||
const hostname = url.hostname.toLowerCase();
|
||||
console.log(' 解析成功,主机名:', hostname);
|
||||
let hostname = url.hostname.toLowerCase();
|
||||
// 规范化主机名,去除末尾的点
|
||||
hostname = hostname.replace(/\.$/, '');
|
||||
console.log(' 解析成功,主机名:', hostname, '规范化目标域名:', normalizedTargetDomain);
|
||||
|
||||
// 根据类别ID选择匹配方式
|
||||
if (categoryId === 2) {
|
||||
// CDN类别,使用域名后缀匹配
|
||||
if (targetDomain.endsWith('.' + hostname) || targetDomain === hostname) {
|
||||
if (normalizedTargetDomain.endsWith('.' + hostname) || normalizedTargetDomain === hostname) {
|
||||
console.log(' CDN域名后缀匹配成功');
|
||||
return true;
|
||||
} else {
|
||||
@@ -294,7 +299,7 @@ function isDomainMatch(urlValue, targetDomain, categoryId) {
|
||||
}
|
||||
} else {
|
||||
// 其他类别,使用完整域名匹配
|
||||
if (hostname === targetDomain) {
|
||||
if (hostname === normalizedTargetDomain) {
|
||||
console.log(' 完整域名匹配成功');
|
||||
return true;
|
||||
} else {
|
||||
@@ -305,13 +310,15 @@ function isDomainMatch(urlValue, targetDomain, categoryId) {
|
||||
} catch (e) {
|
||||
console.log(' 解析URL失败,将其视为纯域名处理,错误信息:', e.message);
|
||||
// 如果是纯域名而不是完整URL
|
||||
const urlDomain = urlValue.toLowerCase();
|
||||
console.log(' 处理为纯域名:', urlDomain);
|
||||
let urlDomain = urlValue.toLowerCase();
|
||||
// 规范化纯域名,去除末尾的点
|
||||
urlDomain = urlDomain.replace(/\.$/, '');
|
||||
console.log(' 处理为纯域名:', urlDomain, '规范化目标域名:', normalizedTargetDomain);
|
||||
|
||||
// 根据类别ID选择匹配方式
|
||||
if (categoryId === 2) {
|
||||
// CDN类别,使用域名后缀匹配
|
||||
if (targetDomain.endsWith('.' + urlDomain) || targetDomain === urlDomain) {
|
||||
if (normalizedTargetDomain.endsWith('.' + urlDomain) || normalizedTargetDomain === urlDomain) {
|
||||
console.log(' CDN域名后缀匹配成功');
|
||||
return true;
|
||||
} else {
|
||||
@@ -320,7 +327,7 @@ function isDomainMatch(urlValue, targetDomain, categoryId) {
|
||||
}
|
||||
} else {
|
||||
// 其他类别,使用完整域名匹配
|
||||
if (urlDomain === targetDomain) {
|
||||
if (urlDomain === normalizedTargetDomain) {
|
||||
console.log(' 完整域名匹配成功');
|
||||
return true;
|
||||
} else {
|
||||
@@ -1485,20 +1492,20 @@ async function showLogDetailModal(log) {
|
||||
domainInfoDiv.className = 'col-span-1 md:col-span-2 space-y-1';
|
||||
domainInfoDiv.innerHTML = `
|
||||
<div class="text-xs text-gray-500">域名信息</div>
|
||||
<div class="text-sm font-medium text-gray-900 p-3 bg-gray-50 rounded-md border border-gray-200">
|
||||
<div class="text-sm font-medium text-gray-900 p-3 bg-gray-50 rounded-md border border-gray-200 w-full">
|
||||
${domainInfo ? `
|
||||
<div class="flex items-center mb-2">
|
||||
${domainInfo.icon ? `<img src="${domainInfo.icon}" alt="${domainInfo.name}" class="w-6 h-6 mr-2 rounded-sm" onerror="this.style.display='none'" />` : ''}
|
||||
<span class="text-base font-semibold">${domainInfo.name || '未知'}</span>
|
||||
<span class="text-base font-semibold flex-grow">${domainInfo.name || '未知'}</span>
|
||||
</div>
|
||||
<div class="ml-8 mt-1">
|
||||
<div class="flex items-center mb-1">
|
||||
<span class="text-gray-500 w-16">类别:</span>
|
||||
<span>${domainInfo.categoryName || '未知'}</span>
|
||||
<div class="mt-1">
|
||||
<div class="flex items-center mb-1 flex-wrap">
|
||||
<span class="text-gray-500 mr-2">类别:</span>
|
||||
<span class="flex-grow">${domainInfo.categoryName || '未知'}</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<span class="text-gray-500 w-16">所属公司:</span>
|
||||
<span>${domainInfo.company || '未知'}</span>
|
||||
<div class="flex items-center flex-wrap">
|
||||
<span class="text-gray-500 mr-2">所属单位:</span>
|
||||
<span class="flex-grow">${domainInfo.company || '未知'}</span>
|
||||
</div>
|
||||
</div>
|
||||
` : '无'}
|
||||
@@ -1615,16 +1622,59 @@ async function showLogDetailModal(log) {
|
||||
clientDetails.appendChild(clientDetailsTitle);
|
||||
clientDetails.appendChild(clientIPDiv);
|
||||
|
||||
// 操作按钮区域
|
||||
const actionButtons = document.createElement('div');
|
||||
actionButtons.className = 'pt-4 border-t border-gray-200 flex justify-end space-x-2';
|
||||
|
||||
// 根据域名状态显示不同的操作按钮
|
||||
if (result === 'blocked') {
|
||||
// 被拦截时显示放行按钮
|
||||
actionButtons.innerHTML = `
|
||||
<button class="px-4 py-2 bg-green-500 text-white rounded-md hover:bg-green-600 transition-colors text-sm" id="unblock-domain-btn">
|
||||
<i class="fa fa-unlock-alt mr-1"></i>放行
|
||||
</button>
|
||||
`;
|
||||
} else {
|
||||
// 未被拦截时显示拦截按钮
|
||||
actionButtons.innerHTML = `
|
||||
<button class="px-4 py-2 bg-red-500 text-white rounded-md hover:bg-red-600 transition-colors text-sm" id="block-domain-btn">
|
||||
<i class="fa fa-lock mr-1"></i>拦截
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
|
||||
// 组装内容
|
||||
content.appendChild(basicInfo);
|
||||
content.appendChild(responseDetails);
|
||||
content.appendChild(clientDetails);
|
||||
content.appendChild(actionButtons);
|
||||
|
||||
// 组装模态框
|
||||
modalContent.appendChild(header);
|
||||
modalContent.appendChild(content);
|
||||
modalContainer.appendChild(modalContent);
|
||||
|
||||
// 绑定操作按钮事件
|
||||
if (result === 'blocked') {
|
||||
const unblockBtn = modalContent.querySelector('#unblock-domain-btn');
|
||||
if (unblockBtn) {
|
||||
unblockBtn.addEventListener('click', async () => {
|
||||
await unblockDomain(domain);
|
||||
closeModal();
|
||||
loadLogs(); // 刷新日志列表
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const blockBtn = modalContent.querySelector('#block-domain-btn');
|
||||
if (blockBtn) {
|
||||
blockBtn.addEventListener('click', async () => {
|
||||
await blockDomain(domain);
|
||||
closeModal();
|
||||
loadLogs(); // 刷新日志列表
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 添加到页面
|
||||
document.body.appendChild(modalContainer);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user