717 lines
23 KiB
JavaScript
717 lines
23 KiB
JavaScript
// main.js - 主脚本文件
|
|
|
|
// 页面数据缓存对象
|
|
const pageDataCache = {
|
|
// 页面初始化状态
|
|
initializedPages: {},
|
|
// 页面数据缓存
|
|
data: {
|
|
dashboard: {
|
|
timestamp: 0,
|
|
data: null,
|
|
expiry: 5 * 60 * 1000 // 5 分钟过期
|
|
},
|
|
logs: {
|
|
timestamp: 0,
|
|
data: null,
|
|
expiry: 5 * 60 * 1000 // 5 分钟过期
|
|
},
|
|
shield: {
|
|
timestamp: 0,
|
|
data: null,
|
|
expiry: 10 * 60 * 1000 // 10 分钟过期
|
|
},
|
|
hosts: {
|
|
timestamp: 0,
|
|
data: null,
|
|
expiry: 10 * 60 * 1000 // 10 分钟过期
|
|
},
|
|
gfwlist: {
|
|
timestamp: 0,
|
|
data: null,
|
|
expiry: 10 * 60 * 1000 // 10 分钟过期
|
|
},
|
|
about: {
|
|
timestamp: 0,
|
|
data: null,
|
|
expiry: 10 * 60 * 1000 // 10 分钟过期
|
|
},
|
|
threats: {
|
|
timestamp: 0,
|
|
data: null,
|
|
expiry: 5 * 60 * 1000 // 5 分钟过期
|
|
}
|
|
},
|
|
|
|
// 检查缓存是否有效
|
|
isCacheValid: function(page) {
|
|
const cache = this.data[page];
|
|
if (!cache || !cache.data) return false;
|
|
const now = Date.now();
|
|
return (now - cache.timestamp) < cache.expiry;
|
|
},
|
|
|
|
// 获取缓存数据
|
|
getCache: function(page) {
|
|
if (this.isCacheValid(page)) {
|
|
return this.data[page].data;
|
|
}
|
|
return null;
|
|
},
|
|
|
|
// 设置缓存数据
|
|
setCache: function(page, data) {
|
|
if (this.data[page]) {
|
|
this.data[page].data = data;
|
|
this.data[page].timestamp = Date.now();
|
|
}
|
|
},
|
|
|
|
// 清除缓存
|
|
clearCache: function(page) {
|
|
if (this.data[page]) {
|
|
this.data[page].data = null;
|
|
this.data[page].timestamp = 0;
|
|
}
|
|
},
|
|
|
|
// 标记页面已初始化
|
|
markPageInitialized: function(page) {
|
|
this.initializedPages[page] = true;
|
|
},
|
|
|
|
// 检查页面是否已初始化
|
|
isPageInitialized: function(page) {
|
|
return this.initializedPages[page] || false;
|
|
}
|
|
};
|
|
|
|
// 页面可见性状态
|
|
let isPageVisible = true;
|
|
|
|
// 全局 WebSocket 管理器 - 用于服务器状态更新
|
|
let serverStatusWebSocket = null;
|
|
let serverStatusReconnectTimer = null;
|
|
let isWebSocketProcessingPaused = false;
|
|
|
|
// 页面初始化函数 - 根据当前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('gfwlist-content'),
|
|
document.getElementById('query-content'),
|
|
document.getElementById('domain-content'),
|
|
document.getElementById('whois-content'),
|
|
document.getElementById('logs-content'),
|
|
document.getElementById('config-content'),
|
|
document.getElementById('about-content'),
|
|
document.getElementById('threats-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 管理',
|
|
'gfwlist': 'GFWList 管理',
|
|
'query': 'DNS 屏蔽查询',
|
|
'domain': '域名查询',
|
|
'whois': '域名信息',
|
|
'logs': '查询日志',
|
|
'config': '系统设置',
|
|
'about': '关于',
|
|
'threats': '威胁告警'
|
|
};
|
|
pageTitle.textContent = titles[hash] || '仪表盘';
|
|
}
|
|
|
|
// 页面特定初始化 - 使用setTimeout延迟调用,确保所有脚本文件都已加载完成
|
|
if (hash === 'shield') {
|
|
setTimeout(() => {
|
|
if (typeof initShieldPage === 'function') {
|
|
// 检查页面是否已经初始化
|
|
if (!pageDataCache.isPageInitialized('shield') || !pageDataCache.isCacheValid('shield')) {
|
|
initShieldPage();
|
|
pageDataCache.markPageInitialized('shield');
|
|
}
|
|
}
|
|
}, 0);
|
|
} else if (hash === 'hosts') {
|
|
setTimeout(() => {
|
|
if (typeof initHostsPage === 'function') {
|
|
// 检查页面是否已经初始化
|
|
if (!pageDataCache.isPageInitialized('hosts') || !pageDataCache.isCacheValid('hosts')) {
|
|
initHostsPage();
|
|
pageDataCache.markPageInitialized('hosts');
|
|
}
|
|
}
|
|
}, 0);
|
|
} else if (hash === 'gfwlist') {
|
|
setTimeout(() => {
|
|
if (typeof initGFWListPage === 'function') {
|
|
// 检查页面是否已经初始化
|
|
if (!pageDataCache.isPageInitialized('gfwlist') || !pageDataCache.isCacheValid('gfwlist')) {
|
|
initGFWListPage();
|
|
pageDataCache.markPageInitialized('gfwlist');
|
|
}
|
|
}
|
|
}, 0);
|
|
} else if (hash === 'logs') {
|
|
setTimeout(() => {
|
|
if (typeof initLogsPage === 'function') {
|
|
// 检查页面是否已经初始化
|
|
if (!pageDataCache.isPageInitialized('logs') || !pageDataCache.isCacheValid('logs')) {
|
|
initLogsPage();
|
|
pageDataCache.markPageInitialized('logs');
|
|
}
|
|
}
|
|
}, 0);
|
|
} else if (hash === 'dashboard') {
|
|
setTimeout(() => {
|
|
if (typeof loadDashboardData === 'function') {
|
|
// 检查页面是否已经初始化
|
|
if (!pageDataCache.isPageInitialized('dashboard') || !pageDataCache.isCacheValid('dashboard')) {
|
|
loadDashboardData();
|
|
pageDataCache.markPageInitialized('dashboard');
|
|
}
|
|
}
|
|
}, 0);
|
|
} else if (hash === 'about') {
|
|
setTimeout(() => {
|
|
if (typeof initAboutPage === 'function') {
|
|
// 检查页面是否已经初始化
|
|
if (!pageDataCache.isPageInitialized('about') || !pageDataCache.isCacheValid('about')) {
|
|
initAboutPage();
|
|
pageDataCache.markPageInitialized('about');
|
|
}
|
|
}
|
|
}, 0);
|
|
} else if (hash === 'threats') {
|
|
setTimeout(() => {
|
|
if (typeof initThreatsPage === 'function') {
|
|
// 检查页面是否已经初始化
|
|
if (!pageDataCache.isPageInitialized('threats') || !pageDataCache.isCacheValid('threats')) {
|
|
initThreatsPage();
|
|
pageDataCache.markPageInitialized('threats');
|
|
}
|
|
}
|
|
}, 0);
|
|
} else if (hash === 'whois') {
|
|
setTimeout(() => {
|
|
if (typeof initWhoisPage === 'function') {
|
|
initWhoisPage();
|
|
}
|
|
}, 0);
|
|
}
|
|
}
|
|
|
|
// 格式化运行时间
|
|
function formatUptime(milliseconds) {
|
|
const totalSeconds = Math.floor(milliseconds / 1000);
|
|
const days = Math.floor(totalSeconds / (24 * 60 * 60));
|
|
const hours = Math.floor((totalSeconds % (24 * 60 * 60)) / (60 * 60));
|
|
const minutes = Math.floor((totalSeconds % (60 * 60)) / 60);
|
|
const seconds = totalSeconds % 60;
|
|
|
|
if (days > 0) {
|
|
return `${days}天${hours}小时${minutes}分钟`;
|
|
} else if (hours > 0) {
|
|
return `${hours}小时${minutes}分钟${seconds}秒`;
|
|
} else if (minutes > 0) {
|
|
return `${minutes}分钟${seconds}秒`;
|
|
} else {
|
|
return `${seconds}秒`;
|
|
}
|
|
}
|
|
|
|
// 更新系统状态
|
|
function updateSystemStatus() {
|
|
api.getStatus()
|
|
.then(data => {
|
|
if (data.error) {
|
|
throw new Error(data.error);
|
|
}
|
|
const uptimeElement = document.getElementById('uptime');
|
|
if (uptimeElement) {
|
|
uptimeElement.textContent = `正常运行中 | ${formatUptime(data.uptime)}`;
|
|
uptimeElement.classList.remove('text-danger');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('更新系统状态失败:', error);
|
|
const uptimeElement = document.getElementById('uptime');
|
|
if (uptimeElement) {
|
|
uptimeElement.textContent = '连接异常';
|
|
uptimeElement.classList.add('text-danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
// 账户功能 - 下拉菜单、注销和修改密码
|
|
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 setupNavigation() {
|
|
// 侧边栏菜单项
|
|
const menuItems = document.querySelectorAll('nav a');
|
|
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('mobile-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();
|
|
}
|
|
});
|
|
}
|
|
|
|
// 主题切换功能
|
|
function setupThemeToggle() {
|
|
const themeToggle = document.getElementById('theme-toggle');
|
|
const body = document.body;
|
|
|
|
if (!themeToggle) return;
|
|
|
|
// 从localStorage加载主题偏好
|
|
const savedTheme = localStorage.getItem('theme');
|
|
if (savedTheme) {
|
|
body.classList.toggle('dark', savedTheme === 'dark');
|
|
updateThemeIcon(themeToggle, savedTheme === 'dark');
|
|
}
|
|
|
|
// 添加点击事件监听器
|
|
themeToggle.addEventListener('click', () => {
|
|
const isDark = body.classList.toggle('dark');
|
|
updateThemeIcon(themeToggle, isDark);
|
|
|
|
// 保存主题偏好到localStorage
|
|
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
|
});
|
|
}
|
|
|
|
// 更新主题图标
|
|
function updateThemeIcon(toggleElement, isDark) {
|
|
const icon = toggleElement.querySelector('i');
|
|
if (icon) {
|
|
if (isDark) {
|
|
icon.className = 'fa fa-sun-o text-sm sm:text-lg';
|
|
} else {
|
|
icon.className = 'fa fa-moon-o text-sm sm:text-lg';
|
|
}
|
|
}
|
|
}
|
|
|
|
// 建立 WebSocket 连接监听服务器状态
|
|
function connectServerStatusWebSocket() {
|
|
try {
|
|
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
const wsUrl = `${wsProtocol}//${window.location.host}/ws/stats`;
|
|
|
|
serverStatusWebSocket = new WebSocket(wsUrl);
|
|
|
|
serverStatusWebSocket.onopen = function() {
|
|
console.log('服务器状态 WebSocket 连接已建立');
|
|
if (serverStatusReconnectTimer) {
|
|
clearTimeout(serverStatusReconnectTimer);
|
|
serverStatusReconnectTimer = null;
|
|
}
|
|
};
|
|
|
|
serverStatusWebSocket.onmessage = function(event) {
|
|
if (isWebSocketProcessingPaused) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const data = JSON.parse(event.data);
|
|
if (data.type === 'stats_update' || data.type === 'initial_data') {
|
|
updateSystemStatusFromWebSocket(data.data);
|
|
}
|
|
} catch (error) {
|
|
console.error('处理服务器状态 WebSocket 消息失败:', error);
|
|
}
|
|
};
|
|
|
|
serverStatusWebSocket.onclose = function() {
|
|
console.warn('服务器状态 WebSocket 连接已关闭');
|
|
serverStatusWebSocket = null;
|
|
setupServerStatusReconnect();
|
|
};
|
|
|
|
serverStatusWebSocket.onerror = function(error) {
|
|
console.error('服务器状态 WebSocket 连接错误:', error);
|
|
};
|
|
|
|
} catch (error) {
|
|
console.error('创建服务器状态 WebSocket 连接失败:', error);
|
|
}
|
|
}
|
|
|
|
function setupServerStatusReconnect() {
|
|
if (serverStatusReconnectTimer) {
|
|
return;
|
|
}
|
|
|
|
serverStatusReconnectTimer = setTimeout(() => {
|
|
connectServerStatusWebSocket();
|
|
}, 5000);
|
|
}
|
|
|
|
function updateSystemStatusFromWebSocket(stats) {
|
|
if (!isPageVisible) {
|
|
return;
|
|
}
|
|
|
|
const uptimeElement = document.getElementById('uptime');
|
|
if (uptimeElement && stats.uptime) {
|
|
uptimeElement.textContent = `正常运行中 | ${formatUptime(stats.uptime)}`;
|
|
uptimeElement.classList.remove('text-danger');
|
|
}
|
|
}
|
|
|
|
function pauseWebSocketProcessing() {
|
|
isWebSocketProcessingPaused = true;
|
|
console.log('已暂停 WebSocket 数据处理');
|
|
}
|
|
|
|
function resumeWebSocketProcessing() {
|
|
isWebSocketProcessingPaused = false;
|
|
console.log('已恢复 WebSocket 数据处理');
|
|
}
|
|
|
|
function clearAllTimers() {
|
|
if (serverStatusReconnectTimer) {
|
|
clearTimeout(serverStatusReconnectTimer);
|
|
serverStatusReconnectTimer = null;
|
|
}
|
|
}
|
|
|
|
function handleVisibilityChange() {
|
|
if (document.visibilityState === 'visible') {
|
|
isPageVisible = true;
|
|
console.log('页面变为可见');
|
|
|
|
resumeWebSocketProcessing();
|
|
|
|
const hash = window.location.hash.substring(1);
|
|
|
|
if (hash && !pageDataCache.isCacheValid(hash)) {
|
|
console.log(`缓存已过期,重新加载${hash}页面数据`);
|
|
|
|
if (hash === 'dashboard' && typeof loadDashboardData === 'function') {
|
|
loadDashboardData();
|
|
} else if (hash === 'logs' && typeof loadLogs === 'function') {
|
|
loadLogs();
|
|
} else if (hash === 'shield' && typeof initShieldPage === 'function') {
|
|
initShieldPage();
|
|
} else if (hash === 'hosts' && typeof initHostsPage === 'function') {
|
|
initHostsPage();
|
|
} else if (hash === 'about' && typeof initAboutPage === 'function') {
|
|
initAboutPage();
|
|
} else if (hash === 'threats' && typeof initThreatsPage === 'function') {
|
|
initThreatsPage();
|
|
}
|
|
}
|
|
|
|
if (!serverStatusWebSocket) {
|
|
connectServerStatusWebSocket();
|
|
}
|
|
} else {
|
|
isPageVisible = false;
|
|
console.log('页面变为隐藏');
|
|
|
|
pauseWebSocketProcessing();
|
|
clearAllTimers();
|
|
}
|
|
}
|
|
|
|
// 初始化函数
|
|
function init() {
|
|
// 设置导航
|
|
setupNavigation();
|
|
|
|
// 设置账户功能
|
|
setupAccountFeatures();
|
|
|
|
// 设置主题切换
|
|
setupThemeToggle();
|
|
|
|
// 初始化页面
|
|
initPageByHash();
|
|
|
|
// 添加 hashchange 事件监听,处理浏览器前进/后退按钮
|
|
window.addEventListener('hashchange', initPageByHash);
|
|
|
|
// 添加页面可见性变化监听
|
|
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
|
|
// 建立 WebSocket 连接监听服务器状态(替代原来的 setInterval 轮询)
|
|
connectServerStatusWebSocket();
|
|
|
|
// 页面卸载时清理资源
|
|
window.addEventListener('beforeunload', () => {
|
|
if (serverStatusWebSocket) {
|
|
serverStatusWebSocket.close();
|
|
}
|
|
if (serverStatusReconnectTimer) {
|
|
clearTimeout(serverStatusReconnectTimer);
|
|
}
|
|
});
|
|
}
|
|
|
|
// 页面加载完成后执行初始化
|
|
window.addEventListener('DOMContentLoaded', init); |