更新Swagger API文档

This commit is contained in:
Alex Yang
2025-11-29 19:30:47 +08:00
parent aea162a616
commit ca876a8951
39 changed files with 16612 additions and 2003 deletions

284
js/config.js Normal file
View File

@@ -0,0 +1,284 @@
// 配置管理页面功能实现
// 工具函数安全获取DOM元素
function getElement(id) {
const element = document.getElementById(id);
if (!element) {
console.warn(`Element with id "${id}" not found`);
}
return element;
}
// 工具函数:验证端口号
function validatePort(port) {
// 确保port是字符串类型
var portStr = port;
if (port === null || port === undefined || typeof port !== 'string') {
return null;
}
// 去除前后空白并验证是否为纯数字
portStr = port.trim();
if (!/^\d+$/.test(portStr)) {
return null;
}
const num = parseInt(portStr, 10);
return num >= 1 && num <= 65535 ? num : null;
}
// 初始化配置管理页面
function initConfigPage() {
loadConfig();
setupConfigEventListeners();
}
// 加载系统配置
async function loadConfig() {
try {
const result = await api.getConfig();
// 检查API返回的错误
if (result && result.error) {
showErrorMessage('加载配置失败: ' + result.error);
return;
}
populateConfigForm(result);
} catch (error) {
// 捕获可能的异常虽然apiRequest不应该再抛出异常
showErrorMessage('加载配置失败: ' + (error.message || '未知错误'));
}
}
// 填充配置表单
function populateConfigForm(config) {
// 安全获取配置对象,防止未定义属性访问
const dnsServerConfig = config.DNSServer || {};
const httpServerConfig = config.HTTPServer || {};
const shieldConfig = config.Shield || {};
// DNS配置 - 使用函数安全设置值,避免 || 操作符可能的错误处理
setElementValue('dns-port', getSafeValue(dnsServerConfig.Port, 53));
setElementValue('dns-upstream-servers', getSafeArray(dnsServerConfig.UpstreamServers).join(', '));
setElementValue('dns-timeout', getSafeValue(dnsServerConfig.Timeout, 5));
setElementValue('dns-stats-file', getSafeValue(dnsServerConfig.StatsFile, 'data/stats.json'));
setElementValue('dns-save-interval', getSafeValue(dnsServerConfig.SaveInterval, 300));
// HTTP配置
setElementValue('http-port', getSafeValue(httpServerConfig.Port, 8080));
// 屏蔽配置
setElementValue('shield-local-rules-file', getSafeValue(shieldConfig.LocalRulesFile, 'data/rules.txt'));
setElementValue('shield-update-interval', getSafeValue(shieldConfig.UpdateInterval, 3600));
setElementValue('shield-hosts-file', getSafeValue(shieldConfig.HostsFile, 'data/hosts.txt'));
// 使用服务器端接受的屏蔽方法值默认使用NXDOMAIN
setElementValue('shield-block-method', getSafeValue(shieldConfig.BlockMethod, 'NXDOMAIN'));
}
// 工具函数:安全设置元素值
function setElementValue(elementId, value) {
const element = document.getElementById(elementId);
if (element && element.tagName === 'INPUT') {
element.value = value;
} else if (!element) {
console.warn(`Element with id "${elementId}" not found for setting value: ${value}`);
}
}
// 工具函数安全获取值如果未定义或为null则返回默认值
function getSafeValue(value, defaultValue) {
// 更严格的检查避免0、空字符串等被默认值替换
return value === undefined || value === null ? defaultValue : value;
}
// 工具函数:安全获取数组,如果不是数组则返回空数组
function getSafeArray(value) {
return Array.isArray(value) ? value : [];
}
// 保存配置
async function handleSaveConfig() {
const formData = collectFormData();
if (!formData) return;
try {
const result = await api.saveConfig(formData);
// 检查API返回的错误
if (result && result.error) {
showErrorMessage('保存配置失败: ' + result.error);
return;
}
showSuccessMessage('配置保存成功');
} catch (error) {
// 捕获可能的异常虽然apiRequest不应该再抛出异常
showErrorMessage('保存配置失败: ' + (error.message || '未知错误'));
}
}
// 重启服务
async function handleRestartService() {
if (!confirm('确定要重启DNS服务吗重启期间服务可能会短暂不可用。')) return;
try {
const result = await api.restartService();
// 检查API返回的错误
if (result && result.error) {
showErrorMessage('服务重启失败: ' + result.error);
return;
}
showSuccessMessage('服务重启成功');
} catch (error) {
// 捕获可能的异常虽然apiRequest不应该再抛出异常
showErrorMessage('重启服务失败: ' + (error.message || '未知错误'));
}
}
// 收集表单数据并验证
function collectFormData() {
// 验证端口号 - 使用安全获取元素值的函数
const dnsPortValue = getElementValue('dns-port');
const httpPortValue = getElementValue('http-port');
const dnsPort = validatePort(dnsPortValue);
const httpPort = validatePort(httpPortValue);
if (!dnsPort) {
showErrorMessage('DNS端口号无效必须是1-65535之间的整数');
return null;
}
if (!httpPort) {
showErrorMessage('HTTP端口号无效必须是1-65535之间的整数');
return null;
}
// 安全获取上游服务器列表
const upstreamServersText = getElementValue('dns-upstream-servers');
const upstreamServers = upstreamServersText ?
upstreamServersText.split(',').map(function(s) { return s.trim(); }).filter(function(s) { return s !== ''; }) :
[];
// 安全获取并转换整数值
const timeoutValue = getElementValue('dns-timeout');
const timeout = timeoutValue ? parseInt(timeoutValue, 10) : 5;
const saveIntervalValue = getElementValue('dns-save-interval');
const saveInterval = saveIntervalValue ? parseInt(saveIntervalValue, 10) : 300;
const updateIntervalValue = getElementValue('shield-update-interval');
const updateInterval = updateIntervalValue ? parseInt(updateIntervalValue, 10) : 3600;
return {
DNSServer: {
Port: dnsPort,
UpstreamServers: upstreamServers,
Timeout: timeout,
StatsFile: getElementValue('dns-stats-file') || './data/stats.json',
SaveInterval: saveInterval
},
HTTPServer: {
Port: httpPort
},
Shield: {
LocalRulesFile: getElementValue('shield-local-rules-file') || './data/rules.txt',
UpdateInterval: updateInterval,
HostsFile: getElementValue('shield-hosts-file') || './data/hosts.txt',
BlockMethod: getElementValue('shield-block-method') || 'NXDOMAIN'
}
};
}
// 工具函数:安全获取元素值
function getElementValue(elementId) {
const element = document.getElementById(elementId);
if (element && element.tagName === 'INPUT') {
return element.value;
}
return ''; // 默认返回空字符串
}
// 设置事件监听器
function setupConfigEventListeners() {
// 保存配置按钮
getElement('save-config-btn')?.addEventListener('click', handleSaveConfig);
// 重启服务按钮
getElement('restart-service-btn')?.addEventListener('click', handleRestartService);
}
// 显示成功消息
function showSuccessMessage(message) {
showNotification(message, 'success');
}
// 显示错误消息
function showErrorMessage(message) {
showNotification(message, 'error');
}
// 显示通知
function showNotification(message, type = 'info') {
// 移除现有通知
const existingNotification = document.querySelector('.notification');
if (existingNotification) {
existingNotification.remove();
}
// 创建新通知
const notification = document.createElement('div');
notification.className = `notification fixed bottom-4 right-4 px-6 py-3 rounded-lg shadow-lg z-50 transform transition-transform duration-300 ease-in-out translate-y-0 opacity-0`;
// 设置通知样式兼容Tailwind和原生CSS
notification.style.cssText += `
position: fixed;
bottom: 16px;
right: 16px;
padding: 16px 24px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 1000;
transition: all 0.3s ease;
opacity: 0;
`;
if (type === 'success') {
notification.style.backgroundColor = '#10b981';
notification.style.color = 'white';
} else if (type === 'error') {
notification.style.backgroundColor = '#ef4444';
notification.style.color = 'white';
} else {
notification.style.backgroundColor = '#3b82f6';
notification.style.color = 'white';
}
notification.textContent = message;
document.body.appendChild(notification);
// 显示通知
setTimeout(() => {
notification.style.opacity = '1';
}, 10);
// 3秒后隐藏通知
setTimeout(() => {
notification.style.opacity = '0';
setTimeout(() => {
notification.remove();
}, 300);
}, 3000);
}
// 页面加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initConfigPage);
} else {
initConfigPage();
}