修复config.go中的URL错误
This commit is contained in:
@@ -115,28 +115,71 @@ function fetchHostsCount() {
|
||||
// 空实现,保留函数声明以避免引用错误
|
||||
}
|
||||
|
||||
// 通用API请求函数
|
||||
function apiRequest(endpoint, method = 'GET', data = null) {
|
||||
// 通用API请求函数 - 添加错误处理和重试机制
|
||||
function apiRequest(endpoint, method = 'GET', data = null, maxRetries = 3) {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
|
||||
const config = {
|
||||
method,
|
||||
headers
|
||||
headers,
|
||||
timeout: 10000, // 设置超时时间为10秒
|
||||
};
|
||||
|
||||
if (data && (method === 'POST' || method === 'PUT' || method === 'DELETE')) {
|
||||
config.body = JSON.stringify(data);
|
||||
}
|
||||
|
||||
return fetch(`${API_BASE_URL}${endpoint}`, config)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
});
|
||||
let retries = 0;
|
||||
|
||||
function makeRequest() {
|
||||
return fetch(`${API_BASE_URL}${endpoint}`, config)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
// 检查响应是否完整
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (contentType && contentType.includes('application/json')) {
|
||||
// 使用.text()先获取响应文本,处理可能的JSON解析错误
|
||||
return response.text().then(text => {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch (e) {
|
||||
console.error('JSON解析错误:', e, '响应文本:', text);
|
||||
// 针对ERR_INCOMPLETE_CHUNKED_ENCODING错误进行重试
|
||||
if (retries < maxRetries) {
|
||||
retries++;
|
||||
console.warn(`请求失败,正在进行第${retries}次重试...`);
|
||||
return new Promise(resolve => setTimeout(() => resolve(makeRequest()), 1000 * retries));
|
||||
}
|
||||
throw new Error('JSON解析失败且重试次数已达上限');
|
||||
}
|
||||
});
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('API请求错误:', error);
|
||||
|
||||
// 检查是否为网络错误或ERR_INCOMPLETE_CHUNKED_ENCODING相关错误
|
||||
if ((error.name === 'TypeError' && error.message.includes('Failed to fetch')) ||
|
||||
error.message.includes('incomplete chunked encoding')) {
|
||||
|
||||
if (retries < maxRetries) {
|
||||
retries++;
|
||||
console.warn(`网络错误,正在进行第${retries}次重试...`);
|
||||
return new Promise(resolve => setTimeout(() => resolve(makeRequest()), 1000 * retries));
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
return makeRequest();
|
||||
}
|
||||
|
||||
// 数字格式化函数
|
||||
|
||||
@@ -6,6 +6,67 @@ let domainDataCache = {
|
||||
let domainUpdateTimer = null;
|
||||
const DOMAIN_UPDATE_INTERVAL = 5000; // 域名排行更新间隔,设为5秒,比统计数据更新慢一些
|
||||
|
||||
// 初始化小型图表 - 修复Canvas重用问题
|
||||
function initMiniCharts() {
|
||||
// 获取所有图表容器
|
||||
const chartContainers = document.querySelectorAll('.chart-card canvas');
|
||||
|
||||
// 全局图表实例存储
|
||||
window.chartInstances = window.chartInstances || {};
|
||||
|
||||
chartContainers.forEach(canvas => {
|
||||
// 获取图表数据属性
|
||||
const chartId = canvas.id;
|
||||
const chartType = canvas.dataset.chartType || 'line';
|
||||
const chartData = JSON.parse(canvas.dataset.chartData || '{}');
|
||||
|
||||
// 设置图表上下文
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// 销毁已存在的图表实例,避免Canvas重用错误
|
||||
if (window.chartInstances[chartId]) {
|
||||
window.chartInstances[chartId].destroy();
|
||||
}
|
||||
|
||||
// 创建新图表
|
||||
window.chartInstances[chartId] = new Chart(ctx, {
|
||||
type: chartType,
|
||||
data: chartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
||||
padding: 10,
|
||||
cornerRadius: 4
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
grid: {
|
||||
color: 'rgba(0, 0, 0, 0.05)'
|
||||
}
|
||||
}
|
||||
},
|
||||
animation: {
|
||||
duration: 1000,
|
||||
easing: 'easeOutQuart'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化仪表盘面板
|
||||
function initDashboardPanel() {
|
||||
// 初始化小型图表
|
||||
@@ -20,6 +81,60 @@ function initDashboardPanel() {
|
||||
}
|
||||
// 启动域名排行的独立更新
|
||||
startDomainUpdate();
|
||||
|
||||
// 初始化响应式侧边栏
|
||||
initResponsiveSidebar();
|
||||
}
|
||||
|
||||
// 初始化响应式侧边栏
|
||||
function initResponsiveSidebar() {
|
||||
// 创建侧边栏切换按钮
|
||||
const toggleBtn = document.createElement('button');
|
||||
toggleBtn.className = 'sidebar-toggle';
|
||||
toggleBtn.innerHTML = '<i class="fas fa-bars"></i>';
|
||||
document.body.appendChild(toggleBtn);
|
||||
|
||||
// 侧边栏切换逻辑
|
||||
toggleBtn.addEventListener('click', function() {
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
sidebar.classList.toggle('open');
|
||||
|
||||
// 更新按钮图标
|
||||
const icon = toggleBtn.querySelector('i');
|
||||
if (sidebar.classList.contains('open')) {
|
||||
icon.className = 'fas fa-times';
|
||||
} else {
|
||||
icon.className = 'fas fa-bars';
|
||||
}
|
||||
});
|
||||
|
||||
// 在侧边栏打开时点击内容区域关闭侧边栏
|
||||
const content = document.querySelector('.content');
|
||||
content.addEventListener('click', function() {
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
const toggleBtn = document.querySelector('.sidebar-toggle');
|
||||
if (sidebar.classList.contains('open') && window.innerWidth <= 768) {
|
||||
sidebar.classList.remove('open');
|
||||
if (toggleBtn) {
|
||||
const icon = toggleBtn.querySelector('i');
|
||||
icon.className = 'fas fa-bars';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 窗口大小变化时调整侧边栏状态
|
||||
window.addEventListener('resize', function() {
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
const toggleBtn = document.querySelector('.sidebar-toggle');
|
||||
|
||||
if (window.innerWidth > 768) {
|
||||
sidebar.classList.remove('open');
|
||||
if (toggleBtn) {
|
||||
const icon = toggleBtn.querySelector('i');
|
||||
icon.className = 'fas fa-bars';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 加载仪表盘数据
|
||||
|
||||
Reference in New Issue
Block a user