/* ProxyAuto Pro - 主 JavaScript 文件 */ // Toast 通知 function showToast(type, message, duration = 4000) { const container = document.getElementById('toast-container'); const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.innerHTML = ` ${escapeHtml(message)} `; container.appendChild(toast); // 自动移除 setTimeout(() => { toast.style.opacity = '0'; toast.style.transform = 'translateX(20px)'; setTimeout(() => toast.remove(), 300); }, duration); } // HTML 转义 function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // 通用 API 请求函数 async function apiRequest(url, options = {}) { const defaultOptions = { headers: { 'Content-Type': 'application/json', }, }; const mergedOptions = { ...defaultOptions, ...options, headers: { ...defaultOptions.headers, ...options.headers, }, }; try { const response = await fetch(url, mergedOptions); const data = await response.json(); if (!response.ok) { throw new Error(data.message || `HTTP ${response.status}`); } return data; } catch (error) { throw error; } } // 格式化日期时间 function formatDateTime(isoString) { if (!isoString) return '--'; const date = new Date(isoString); return date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', }); } // 格式化时间 function formatTime(isoString) { if (!isoString) return '--'; const date = new Date(isoString); return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', second: '2-digit', }); } // 确认对话框 function confirmAction(message) { return confirm(message); } // 页面加载完成后的初始化 document.addEventListener('DOMContentLoaded', function() { // 可以在这里添加全局初始化逻辑 console.log('ProxyAuto Pro initialized'); }); // 移动端侧边栏切换 function toggleSidebar() { const sidebar = document.getElementById('sidebar'); const overlay = document.querySelector('.sidebar-overlay'); if (sidebar) { sidebar.classList.toggle('open'); if (overlay) { overlay.classList.toggle('active'); } } } // 格式化倒计时 function formatCountdown(seconds) { if (seconds <= 0) return '即将更换'; const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const secs = Math.floor(seconds % 60); if (hours > 0) { return `${hours}时${minutes}分${secs}秒`; } else if (minutes > 0) { return `${minutes}分${secs}秒`; } else { return `${secs}秒`; } } // 格式化24小时制时间 function formatTime24(isoString) { if (!isoString) return '--'; const date = new Date(isoString); const pad = n => n.toString().padStart(2, '0'); return `${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`; } // 更新所有倒计时 function updateCountdowns() { const countdownElements = document.querySelectorAll('[data-next-run]'); const now = Date.now(); countdownElements.forEach(el => { const nextRunTime = new Date(el.dataset.nextRun).getTime(); const remaining = Math.max(0, Math.floor((nextRunTime - now) / 1000)); const countdownSpan = el.querySelector('.countdown-value'); if (countdownSpan) { countdownSpan.textContent = formatCountdown(remaining); } }); } // 启动倒计时更新器 let countdownInterval = null; function startCountdownUpdater() { if (countdownInterval) clearInterval(countdownInterval); updateCountdowns(); countdownInterval = setInterval(updateCountdowns, 1000); } // 最小加载时间包装器 async function withMinLoadTime(promise, minMs = 500) { const start = Date.now(); const result = await promise; const elapsed = Date.now() - start; if (elapsed < minMs) { await new Promise(resolve => setTimeout(resolve, minMs - elapsed)); } return result; }