405 lines
13 KiB
JavaScript
405 lines
13 KiB
JavaScript
// main.js - 主脚本文件
|
||
|
||
// 页面导航功能
|
||
function setupNavigation() {
|
||
// 侧边栏菜单项
|
||
const menuItems = document.querySelectorAll('nav a');
|
||
const contentSections = [
|
||
document.getElementById('dashboard-content'),
|
||
document.getElementById('shield-content'),
|
||
document.getElementById('hosts-content'),
|
||
document.getElementById('query-content'),
|
||
document.getElementById('logs-content'),
|
||
document.getElementById('config-content')
|
||
];
|
||
const pageTitle = document.getElementById('page-title');
|
||
|
||
menuItems.forEach((item, index) => {
|
||
item.addEventListener('click', (e) => {
|
||
// 允许浏览器自动更新地址栏中的hash,不阻止默认行为
|
||
|
||
// 移动端点击菜单项后自动关闭侧边栏
|
||
if (window.innerWidth < 768) {
|
||
closeSidebar();
|
||
}
|
||
});
|
||
});
|
||
|
||
// 移动端侧边栏切换
|
||
const toggleSidebar = document.getElementById('toggle-sidebar');
|
||
const closeSidebarBtn = document.getElementById('close-sidebar');
|
||
const sidebar = document.getElementById('sidebar');
|
||
const sidebarOverlay = document.getElementById('sidebar-overlay');
|
||
|
||
// 打开侧边栏函数
|
||
function openSidebar() {
|
||
console.log('Opening sidebar...');
|
||
if (sidebar) {
|
||
sidebar.classList.remove('-translate-x-full');
|
||
sidebar.classList.add('translate-x-0');
|
||
}
|
||
if (sidebarOverlay) {
|
||
sidebarOverlay.classList.remove('hidden');
|
||
sidebarOverlay.classList.add('block');
|
||
}
|
||
// 防止页面滚动
|
||
document.body.style.overflow = 'hidden';
|
||
console.log('Sidebar opened successfully');
|
||
}
|
||
|
||
// 关闭侧边栏函数
|
||
function closeSidebar() {
|
||
console.log('Closing sidebar...');
|
||
if (sidebar) {
|
||
sidebar.classList.add('-translate-x-full');
|
||
sidebar.classList.remove('translate-x-0');
|
||
}
|
||
if (sidebarOverlay) {
|
||
sidebarOverlay.classList.add('hidden');
|
||
sidebarOverlay.classList.remove('block');
|
||
}
|
||
// 恢复页面滚动
|
||
document.body.style.overflow = '';
|
||
console.log('Sidebar closed successfully');
|
||
}
|
||
|
||
// 切换侧边栏函数
|
||
function toggleSidebarVisibility() {
|
||
console.log('Toggling sidebar visibility...');
|
||
console.log('Current sidebar classes:', sidebar ? sidebar.className : 'sidebar not found');
|
||
if (sidebar && sidebar.classList.contains('-translate-x-full')) {
|
||
console.log('Sidebar is hidden, opening...');
|
||
openSidebar();
|
||
} else {
|
||
console.log('Sidebar is visible, closing...');
|
||
closeSidebar();
|
||
}
|
||
}
|
||
|
||
// 绑定切换按钮事件
|
||
if (toggleSidebar) {
|
||
toggleSidebar.addEventListener('click', toggleSidebarVisibility);
|
||
}
|
||
|
||
// 绑定关闭按钮事件
|
||
if (closeSidebarBtn) {
|
||
closeSidebarBtn.addEventListener('click', closeSidebar);
|
||
}
|
||
|
||
// 绑定遮罩层点击事件
|
||
if (sidebarOverlay) {
|
||
sidebarOverlay.addEventListener('click', closeSidebar);
|
||
}
|
||
|
||
// 移动端点击菜单项后自动关闭侧边栏
|
||
menuItems.forEach(item => {
|
||
item.addEventListener('click', () => {
|
||
// 检查是否是移动设备视图
|
||
if (window.innerWidth < 768) {
|
||
closeSidebar();
|
||
}
|
||
});
|
||
});
|
||
|
||
// 添加键盘事件监听,按ESC键关闭侧边栏
|
||
document.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Escape') {
|
||
closeSidebar();
|
||
}
|
||
});
|
||
}
|
||
|
||
// 页面初始化函数 - 根据当前hash值初始化对应页面
|
||
function initPageByHash() {
|
||
const hash = window.location.hash.substring(1);
|
||
|
||
// 隐藏所有内容区域
|
||
const contentSections = [
|
||
document.getElementById('dashboard-content'),
|
||
document.getElementById('shield-content'),
|
||
document.getElementById('hosts-content'),
|
||
document.getElementById('query-content'),
|
||
document.getElementById('logs-content'),
|
||
document.getElementById('config-content')
|
||
];
|
||
|
||
contentSections.forEach(section => {
|
||
if (section) {
|
||
section.classList.add('hidden');
|
||
}
|
||
});
|
||
|
||
// 显示当前页面内容
|
||
const currentSection = document.getElementById(`${hash}-content`);
|
||
if (currentSection) {
|
||
currentSection.classList.remove('hidden');
|
||
}
|
||
|
||
// 更新页面标题
|
||
const pageTitle = document.getElementById('page-title');
|
||
if (pageTitle) {
|
||
const titles = {
|
||
'dashboard': '仪表盘',
|
||
'shield': '屏蔽管理',
|
||
'hosts': 'Hosts管理',
|
||
'query': 'DNS屏蔽查询',
|
||
'logs': '查询日志',
|
||
'config': '系统设置'
|
||
};
|
||
pageTitle.textContent = titles[hash] || '仪表盘';
|
||
}
|
||
|
||
// 页面特定初始化 - 使用setTimeout延迟调用,确保所有脚本文件都已加载完成
|
||
if (hash === 'shield') {
|
||
setTimeout(() => {
|
||
if (typeof initShieldPage === 'function') {
|
||
initShieldPage();
|
||
}
|
||
}, 0);
|
||
} else if (hash === 'hosts') {
|
||
setTimeout(() => {
|
||
if (typeof initHostsPage === 'function') {
|
||
initHostsPage();
|
||
}
|
||
}, 0);
|
||
} else if (hash === 'logs') {
|
||
setTimeout(() => {
|
||
if (typeof initLogsPage === 'function') {
|
||
initLogsPage();
|
||
}
|
||
}, 0);
|
||
} else if (hash === 'dashboard') {
|
||
setTimeout(() => {
|
||
if (typeof loadDashboardData === 'function') {
|
||
loadDashboardData();
|
||
}
|
||
}, 0);
|
||
}
|
||
}
|
||
|
||
// 初始化函数
|
||
function init() {
|
||
// 设置导航
|
||
setupNavigation();
|
||
|
||
// 初始化页面
|
||
initPageByHash();
|
||
|
||
// 添加hashchange事件监听,处理浏览器前进/后退按钮
|
||
window.addEventListener('hashchange', initPageByHash);
|
||
|
||
// 定期更新系统状态
|
||
setInterval(updateSystemStatus, 5000);
|
||
}
|
||
|
||
// 更新系统状态
|
||
function updateSystemStatus() {
|
||
fetch('/api/status')
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
const uptimeElement = document.getElementById('uptime');
|
||
if (uptimeElement) {
|
||
uptimeElement.textContent = `正常运行中 | ${formatUptime(data.uptime)}`;
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('更新系统状态失败:', error);
|
||
const uptimeElement = document.getElementById('uptime');
|
||
if (uptimeElement) {
|
||
uptimeElement.textContent = '连接异常';
|
||
uptimeElement.classList.add('text-danger');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 格式化运行时间
|
||
function formatUptime(milliseconds) {
|
||
// 简化版的格式化,实际使用时需要根据API返回的数据格式调整
|
||
const seconds = Math.floor(milliseconds / 1000);
|
||
const minutes = Math.floor(seconds / 60);
|
||
const hours = Math.floor(minutes / 60);
|
||
const days = Math.floor(hours / 24);
|
||
|
||
if (days > 0) {
|
||
return `${days}天${hours % 24}小时`;
|
||
} else if (hours > 0) {
|
||
return `${hours}小时${minutes % 60}分钟`;
|
||
} else if (minutes > 0) {
|
||
return `${minutes}分钟${seconds % 60}秒`;
|
||
} else {
|
||
return `${seconds}秒`;
|
||
}
|
||
}
|
||
|
||
// 账户功能 - 下拉菜单、注销和修改密码
|
||
function setupAccountFeatures() {
|
||
// 下拉菜单功能
|
||
const accountDropdown = document.getElementById('account-dropdown');
|
||
const accountMenu = document.getElementById('account-menu');
|
||
const changePasswordBtn = document.getElementById('change-password-btn');
|
||
const logoutBtn = document.getElementById('logout-btn');
|
||
const changePasswordModal = document.getElementById('change-password-modal');
|
||
const closeModalBtn = document.getElementById('close-modal-btn');
|
||
const cancelChangePasswordBtn = document.getElementById('cancel-change-password');
|
||
const changePasswordForm = document.getElementById('change-password-form');
|
||
const passwordMismatch = document.getElementById('password-mismatch');
|
||
const newPassword = document.getElementById('new-password');
|
||
const confirmPassword = document.getElementById('confirm-password');
|
||
|
||
// 点击外部关闭下拉菜单
|
||
document.addEventListener('click', (e) => {
|
||
if (accountDropdown && !accountDropdown.contains(e.target)) {
|
||
accountMenu.classList.add('hidden');
|
||
}
|
||
});
|
||
|
||
// 点击账户区域切换下拉菜单
|
||
if (accountDropdown) {
|
||
accountDropdown.addEventListener('click', (e) => {
|
||
e.stopPropagation();
|
||
accountMenu.classList.toggle('hidden');
|
||
});
|
||
}
|
||
|
||
// 打开修改密码模态框
|
||
if (changePasswordBtn) {
|
||
changePasswordBtn.addEventListener('click', () => {
|
||
accountMenu.classList.add('hidden');
|
||
changePasswordModal.classList.remove('hidden');
|
||
document.body.style.overflow = 'hidden';
|
||
});
|
||
}
|
||
|
||
// 关闭修改密码模态框
|
||
function closeModal() {
|
||
changePasswordModal.classList.add('hidden');
|
||
document.body.style.overflow = '';
|
||
changePasswordForm.reset();
|
||
passwordMismatch.classList.add('hidden');
|
||
}
|
||
|
||
// 绑定关闭模态框事件
|
||
if (closeModalBtn) {
|
||
closeModalBtn.addEventListener('click', closeModal);
|
||
}
|
||
|
||
if (cancelChangePasswordBtn) {
|
||
cancelChangePasswordBtn.addEventListener('click', closeModal);
|
||
}
|
||
|
||
// 点击模态框外部关闭模态框
|
||
if (changePasswordModal) {
|
||
changePasswordModal.addEventListener('click', (e) => {
|
||
if (e.target === changePasswordModal) {
|
||
closeModal();
|
||
}
|
||
});
|
||
}
|
||
|
||
// 按ESC键关闭模态框
|
||
document.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Escape' && !changePasswordModal.classList.contains('hidden')) {
|
||
closeModal();
|
||
}
|
||
});
|
||
|
||
// 密码匹配验证
|
||
if (newPassword && confirmPassword) {
|
||
confirmPassword.addEventListener('input', () => {
|
||
if (newPassword.value !== confirmPassword.value) {
|
||
passwordMismatch.classList.remove('hidden');
|
||
} else {
|
||
passwordMismatch.classList.add('hidden');
|
||
}
|
||
});
|
||
|
||
newPassword.addEventListener('input', () => {
|
||
if (newPassword.value !== confirmPassword.value) {
|
||
passwordMismatch.classList.remove('hidden');
|
||
} else {
|
||
passwordMismatch.classList.add('hidden');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 修改密码表单提交
|
||
if (changePasswordForm) {
|
||
changePasswordForm.addEventListener('submit', async (e) => {
|
||
e.preventDefault();
|
||
|
||
// 验证密码匹配
|
||
if (newPassword.value !== confirmPassword.value) {
|
||
passwordMismatch.classList.remove('hidden');
|
||
return;
|
||
}
|
||
|
||
const formData = new FormData(changePasswordForm);
|
||
const data = {
|
||
currentPassword: formData.get('currentPassword'),
|
||
newPassword: formData.get('newPassword')
|
||
};
|
||
|
||
try {
|
||
const response = await fetch('/api/change-password', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify(data)
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result.status === 'success') {
|
||
// 密码修改成功
|
||
alert('密码修改成功');
|
||
closeModal();
|
||
} else {
|
||
// 密码修改失败
|
||
alert(result.error || '密码修改失败');
|
||
}
|
||
} catch (error) {
|
||
console.error('修改密码失败:', error);
|
||
alert('修改密码失败,请稍后重试');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 注销功能
|
||
if (logoutBtn) {
|
||
logoutBtn.addEventListener('click', async () => {
|
||
try {
|
||
await fetch('/api/logout', {
|
||
method: 'POST'
|
||
});
|
||
|
||
// 重定向到登录页面
|
||
window.location.href = '/login';
|
||
} catch (error) {
|
||
console.error('注销失败:', error);
|
||
alert('注销失败,请稍后重试');
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
// 初始化函数
|
||
function init() {
|
||
// 设置导航
|
||
setupNavigation();
|
||
|
||
// 设置账户功能
|
||
setupAccountFeatures();
|
||
|
||
// 初始化页面
|
||
initPageByHash();
|
||
|
||
// 添加hashchange事件监听,处理浏览器前进/后退按钮
|
||
window.addEventListener('hashchange', initPageByHash);
|
||
|
||
// 定期更新系统状态
|
||
setInterval(updateSystemStatus, 5000);
|
||
}
|
||
|
||
// 页面加载完成后执行初始化
|
||
window.addEventListener('DOMContentLoaded', init); |