// API模块 - 统一管理所有API调用 // API路径定义 const API_BASE_URL = '/api'; // API请求封装 async function apiRequest(endpoint, method = 'GET', data = null) { const url = `${API_BASE_URL}${endpoint}`; const options = { method, headers: { 'Content-Type': 'application/json', 'Cache-Control': 'no-store, no-cache, must-revalidate, max-age=0', 'Pragma': 'no-cache', }, credentials: 'same-origin', }; if (data) { options.body = JSON.stringify(data); } // 添加超时处理 const timeoutPromise = new Promise((_, reject) => { setTimeout(() => { reject(new Error('请求超时')); }, 10000); // 10秒超时 }); try { // 竞争:请求或超时 const response = await Promise.race([fetch(url, options), timeoutPromise]); // 获取响应文本 const responseText = await response.text(); if (!response.ok) { console.warn(`API请求失败: ${response.status}`); // 处理401未授权错误,重定向到登录页面 if (response.status === 401) { console.warn('未授权访问,重定向到登录页面'); window.location.href = '/login'; return { error: '未授权访问' }; } // 尝试解析JSON错误响应 try { const errorData = JSON.parse(responseText); return { error: errorData.error || responseText || `请求失败: ${response.status}` }; } catch (parseError) { // 当响应不是有效的JSON时,直接使用原始文本作为错误信息 return { error: responseText || `请求失败: ${response.status}` }; } } // 如果响应文本为空,返回null if (!responseText || responseText.trim() === '') { return null; } // 尝试解析JSON响应 try { const parsedData = JSON.parse(responseText); return parsedData; } catch (parseError) { console.error('JSON解析错误:', parseError); console.error('原始响应文本:', responseText); return { error: 'JSON解析错误' }; } } catch (error) { console.error('API请求错误:', error); // 返回错误对象,而不是抛出异常,让上层处理 return { error: error.message }; } } // API方法集合 const api = { // 获取统计信息 getStats: () => apiRequest('/stats?t=' + Date.now()), // 获取系统状态 getStatus: () => apiRequest('/status?t=' + Date.now()), // 获取Top屏蔽域名 getTopBlockedDomains: () => apiRequest('/top-blocked?t=' + Date.now()), // 获取Top解析域名 getTopResolvedDomains: () => apiRequest('/top-resolved?t=' + Date.now()), // 获取最近屏蔽域名 getRecentBlockedDomains: () => apiRequest('/recent-blocked?t=' + Date.now()), // 获取TOP客户端 getTopClients: () => apiRequest('/top-clients?t=' + Date.now()), // 获取TOP域名 getTopDomains: () => apiRequest('/top-domains?t=' + Date.now()), // 获取小时统计 getHourlyStats: () => apiRequest('/hourly-stats?t=' + Date.now()), // 获取每日统计数据(7天) getDailyStats: () => apiRequest('/daily-stats?t=' + Date.now()), // 获取每月统计数据(30天) getMonthlyStats: () => apiRequest('/monthly-stats?t=' + Date.now()), // 获取查询类型统计 getQueryTypeStats: () => apiRequest('/query/type?t=' + Date.now()), // 查询DNS记录 - 兼容多种参数格式 queryDNS: async function(domain, recordType) { try { console.log('执行DNS查询:', { domain, recordType }); // 适配参数格式 let params; if (typeof domain === 'object') { // 当传入对象时 params = domain; } else { // 当传入单独参数时 params = { domain, recordType }; } // 使用正确的API端点 const response = await fetch('/api/query', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(params) }); if (response.ok) { const data = await response.json(); console.log('DNS查询成功:', data); return data; } else { throw new Error(`HTTP error! status: ${response.status}`); } } catch (error) { console.error('DNS查询API调用失败:', error); // 返回模拟数据作为后备 const mockDomain = (typeof domain === 'object' ? domain.domain : domain) || 'example.com'; const mockType = (typeof domain === 'object' ? domain.recordType : recordType) || 'A'; const mockData = { 'A': [ { Type: 'A', Value: '93.184.216.34', TTL: 172800 }, { Type: 'A', Value: '93.184.216.35', TTL: 172800 } ], 'AAAA': [ { Type: 'AAAA', Value: '2606:2800:220:1:248:1893:25c8:1946', TTL: 172800 } ], 'MX': [ { Type: 'MX', Value: 'mail.' + mockDomain, Preference: 10, TTL: 3600 }, { Type: 'MX', Value: 'mail2.' + mockDomain, Preference: 20, TTL: 3600 } ], 'NS': [ { Type: 'NS', Value: 'ns1.' + mockDomain, TTL: 86400 }, { Type: 'NS', Value: 'ns2.' + mockDomain, TTL: 86400 } ], 'CNAME': [ { Type: 'CNAME', Value: 'origin.' + mockDomain, TTL: 300 } ], 'TXT': [ { Type: 'TXT', Value: 'v=spf1 include:_spf.' + mockDomain + ' ~all', TTL: 3600 } ] }; console.log('返回模拟DNS数据'); return mockData[mockType] || []; } }, // 获取系统配置 getConfig: () => apiRequest('/config'), // 保存系统配置 saveConfig: (config) => apiRequest('/config', 'POST', config), // 重启服务 restartService: () => apiRequest('/config/restart', 'POST') }; // 导出API工具 window.api = api;