web修复

This commit is contained in:
Alex Yang
2025-11-24 02:16:06 +08:00
parent 63442c2b2a
commit 534878fa4d
5 changed files with 394 additions and 29 deletions

View File

@@ -23,13 +23,59 @@ function loadDashboardData() {
function loadHourlyStats() {
apiRequest('/api/hourly-stats')
.then(data => {
if (data && data.labels && data.data) {
// 只使用一组数据(假设是屏蔽请求数)
renderHourlyChart(data.labels, data.data, []);
// 处理不同可能的数据格式
if (data) {
// 优先处理用户提供的实际数据格式 {data: [], labels: []}
if (data.labels && data.data && Array.isArray(data.labels) && Array.isArray(data.data)) {
// 确保labels和data数组长度一致
if (data.labels.length === data.data.length) {
// 假设data数组包含的是屏蔽请求数据允许请求设为0
renderHourlyChart(data.labels, data.data, Array(data.data.length).fill(0));
return;
}
}
// 处理其他可能的数据格式
if (data.labels && data.blocked && data.allowed) {
// 完整数据格式:分别有屏蔽和允许的数据
renderHourlyChart(data.labels, data.blocked, data.allowed);
} else if (data.labels && data.data) {
// 简化数据格式:只有一组数据
renderHourlyChart(data.labels, data.data, Array(data.data.length).fill(0));
} else {
// 尝试直接使用数据对象的属性
const hours = [];
const blocked = [];
const allowed = [];
// 假设数据是按小时组织的对象
for (const key in data) {
if (data.hasOwnProperty(key)) {
hours.push(key);
// 尝试不同的数据结构访问方式
if (typeof data[key] === 'object' && data[key] !== null) {
blocked.push(data[key].Blocked || data[key].blocked || 0);
allowed.push(data[key].Allowed || data[key].allowed || 0);
} else {
blocked.push(data[key]);
allowed.push(0);
}
}
}
// 只在有数据时渲染
if (hours.length > 0) {
renderHourlyChart(hours, blocked, allowed);
}
}
}
})
.catch(error => {
console.error('获取24小时统计失败:', error);
// 显示默认空数据,避免图表区域空白
const emptyHours = Array.from({length: 24}, (_, i) => `${i}:00`);
const emptyData = Array(24).fill(0);
renderHourlyChart(emptyHours, emptyData, emptyData);
});
}
@@ -104,19 +150,45 @@ function renderHourlyChart(hours, blocked, allowed) {
function loadRequestsDistribution() {
apiRequest('/api/stats')
.then(data => {
if (data && data.dns) {
// 构造饼图所需的数据
const labels = ['允许请求', '屏蔽请求', '错误请求'];
const requestData = [
data.dns.Allowed || 0,
data.dns.Blocked || 0,
data.dns.Errors || 0
];
renderRequestsPieChart(labels, requestData);
// 构造饼图所需的数据,支持多种数据格式
const labels = ['允许请求', '屏蔽请求', '错误请求'];
let requestData = [0, 0, 0]; // 默认值
if (data) {
// 尝试多种可能的数据结构
if (data.dns) {
// 主要数据结构
requestData = [
data.dns.Allowed || data.dns.allowed || 0,
data.dns.Blocked || data.dns.blocked || 0,
data.dns.Errors || data.dns.errors || 0
];
} else if (data.Allowed !== undefined || data.Blocked !== undefined) {
// 直接在顶级对象中
requestData = [
data.Allowed || data.allowed || 0,
data.Blocked || data.blocked || 0,
data.Errors || data.errors || 0
];
} else if (data.requests) {
// 可能在requests属性中
requestData = [
data.requests.Allowed || data.requests.allowed || 0,
data.requests.Blocked || data.requests.blocked || 0,
data.requests.Errors || data.requests.errors || 0
];
}
}
// 渲染图表即使数据全为0也渲染避免空白
renderRequestsPieChart(labels, requestData);
})
.catch(error => {
console.error('获取请求类型分布失败:', error);
// 显示默认空数据的图表
const labels = ['允许请求', '屏蔽请求', '错误请求'];
const defaultData = [0, 0, 0];
renderRequestsPieChart(labels, defaultData);
});
}
@@ -173,21 +245,53 @@ function renderRequestsPieChart(labels, data) {
// 加载最常屏蔽的域名
function loadTopBlockedDomains() {
// 首先获取表格元素并显示加载状态
const tbody = document.getElementById('top-blocked-table')?.querySelector('tbody');
if (tbody) {
// 显示加载中状态
tbody.innerHTML = `<td colspan="100%" style="color: #7f8c8d; font-style: italic;">加载中...</td>`;
}
apiRequest('/api/top-blocked')
.then(data => {
renderTopBlockedDomains(data);
// 处理多种可能的数据格式,特别优化对用户提供格式的支持
let processedData = [];
console.log('最常屏蔽域名API返回数据:', data);
if (Array.isArray(data)) {
// 数组格式:直接使用,并过滤出有效的域名数据
processedData = data.filter(item => item && (item.domain || item.name || item.Domain || item.Name) && (item.count !== undefined || item.Count !== undefined || item.hits !== undefined || item.Hits !== undefined));
console.log('处理后的域名数据:', processedData);
} else if (data && data.domains && Array.isArray(data.domains)) {
// 嵌套在domains属性中
processedData = data.domains;
} else if (data && typeof data === 'object') {
// 对象格式:转换为数组
processedData = Object.keys(data).map(key => ({
domain: key,
count: data[key]
}));
}
renderTopBlockedDomains(processedData);
})
.catch(error => {
console.error('获取最常屏蔽域名失败:', error);
showError(document.getElementById('top-blocked-table').querySelector('tbody'), '获取数据失败');
// 显示默认空数据而不是错误消息,保持界面一致性
if (tbody) {
showEmpty(tbody, '获取数据失败');
}
});
}
// 渲染最常屏蔽的域名表格
function renderTopBlockedDomains(domains) {
const tbody = document.getElementById('top-blocked-table').querySelector('tbody');
const tbody = document.getElementById('top-blocked-table')?.querySelector('tbody');
if (!tbody) return;
console.log('准备渲染的域名数据:', domains);
if (!domains || domains.length === 0) {
showEmpty(tbody, '暂无屏蔽记录');
return;
@@ -196,27 +300,61 @@ function renderTopBlockedDomains(domains) {
tbody.innerHTML = '';
domains.forEach((domain, index) => {
if (!domain) return;
// 支持不同的字段名和格式,特别针对用户提供的数据格式优化
const domainName = domain.domain || domain.name || domain.Domain || domain.Name || '未知域名';
const count = domain.count !== undefined ? domain.count :
(domain.Count !== undefined ? domain.Count :
(domain.hits !== undefined ? domain.hits :
(domain.Hits !== undefined ? domain.Hits : 0)));
console.log(`渲染域名 ${index + 1}:`, {domainName, count});
const row = document.createElement('tr');
row.innerHTML = `
<td>${domain.domain}</td>
<td>${formatNumber(domain.count)}</td>
<td>${domainName}</td>
<td>${formatNumber(count)}</td>
`;
tbody.appendChild(row);
});
// 初始化表格排序
initTableSort('top-blocked-table');
if (typeof initTableSort === 'function') {
initTableSort('top-blocked-table');
}
}
// 加载最常解析的域名
function loadTopResolvedDomains() {
apiRequest('/api/top-resolved')
.then(data => {
renderTopResolvedDomains(data);
// 处理多种可能的数据格式
let processedData = [];
if (Array.isArray(data)) {
// 数组格式:直接使用
processedData = data;
} else if (data && data.domains && Array.isArray(data.domains)) {
// 嵌套在domains属性中
processedData = data.domains;
} else if (data && typeof data === 'object') {
// 对象格式:转换为数组
processedData = Object.keys(data).map(key => ({
domain: key,
count: data[key]
}));
}
renderTopResolvedDomains(processedData);
})
.catch(error => {
console.error('获取最常解析域名失败:', error);
showError(document.getElementById('top-resolved-table').querySelector('tbody'), '获取数据失败');
// 显示默认空数据而不是错误消息,保持界面一致性
const tbody = document.getElementById('top-resolved-table').querySelector('tbody');
if (tbody) {
showEmpty(tbody, '暂无解析记录');
}
});
}
@@ -233,10 +371,14 @@ function renderTopResolvedDomains(domains) {
tbody.innerHTML = '';
domains.forEach((domain, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${domain.domain}</td>
<td>${formatNumber(domain.count)}</td>
// 支持不同的字段名和格式
const domainName = domain.domain || domain.name || domain.Domain || domain.Name || '未知域名';
const count = domain.count || domain.Count || domain.hits || domain.Hits || 0;
const row = document.createElement('tr');
row.innerHTML = `
<td>${domainName}</td>
<td>${formatNumber(count)}</td>
`;
tbody.appendChild(row);
});