// API 基础路径 const API_BASE = window.location.origin; // 存储认证 token let authToken = localStorage.getItem('auth_token'); // 页面加载时检查认证状态 document.addEventListener('DOMContentLoaded', function() { const currentPage = window.location.pathname; console.log('[DEBUG] Current page:', currentPage); console.log('[DEBUG] Auth token:', authToken ? 'exists' : 'none'); if (currentPage.includes('dashboard')) { console.log('[DEBUG] Loading dashboard...'); if (!authToken) { window.location.href = '/static/index.html'; return; } loadDashboard(); } else { // 登录页面(包括 /static/index.html, /, 或其他) console.log('[DEBUG] Loading login page...'); if (authToken) { console.log('[DEBUG] Already logged in, redirecting to dashboard...'); window.location.href = '/dashboard'; return; } setupLoginForm(); } }); // ========== 认证功能 ========== // 设置登录表单 function setupLoginForm() { console.log('[DEBUG] setupLoginForm called'); const loginForm = document.getElementById('loginForm'); console.log('[DEBUG] loginForm element:', loginForm); if (loginForm) { console.log('[DEBUG] Adding submit event listener to loginForm'); loginForm.addEventListener('submit', async (e) => { e.preventDefault(); console.log('[DEBUG] Form submitted!'); const username = document.getElementById('username').value; const password = document.getElementById('password').value; const errorDiv = document.getElementById('loginError'); console.log('[DEBUG] Attempting login with username:', username); try { console.log('[DEBUG] Sending request to:', `${API_BASE}/api/auth/login`); const response = await fetch(`${API_BASE}/api/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); const data = await response.json(); if (response.ok) { authToken = data.token; localStorage.setItem('auth_token', authToken); window.location.href = '/dashboard'; } else { errorDiv.textContent = data.error || '登录失败'; errorDiv.style.display = 'block'; } } catch (error) { errorDiv.textContent = '网络错误,请稍后重试'; errorDiv.style.display = 'block'; } }); } } // 登出 function logout() { if (confirm('确定要退出吗?')) { localStorage.removeItem('auth_token'); authToken = null; window.location.href = '/'; } } // 显示修改密码弹窗 function showChangePasswordModal() { document.getElementById('changePasswordModal').style.display = 'flex'; document.getElementById('changePasswordForm').reset(); document.getElementById('changePasswordError').style.display = 'none'; } // 关闭修改密码弹窗 function closeChangePasswordModal() { document.getElementById('changePasswordModal').style.display = 'none'; } // 修改密码 async function changePassword(oldPassword, newPassword) { try { const response = await apiRequest('/api/auth/password', { method: 'PUT', body: JSON.stringify({ old_password: oldPassword, new_password: newPassword }) }); if (response.ok) { showToast('密码修改成功', 'success'); closeChangePasswordModal(); return true; } else { const data = await response.json(); return { error: data.error || '密码修改失败' }; } } catch (error) { console.error('修改密码错误:', error); return { error: '网络错误,请重试' }; } } // 设置修改密码表单 function setupChangePasswordForm() { const form = document.getElementById('changePasswordForm'); if (form) { form.addEventListener('submit', async (e) => { e.preventDefault(); const oldPassword = document.getElementById('oldPassword').value; const newPassword = document.getElementById('newPassword').value; const confirmPassword = document.getElementById('confirmPassword').value; const errorDiv = document.getElementById('changePasswordError'); // 验证新密码长度 if (newPassword.length < 6) { errorDiv.textContent = '新密码至少需要6位字符'; errorDiv.style.display = 'block'; return; } // 验证两次密码是否一致 if (newPassword !== confirmPassword) { errorDiv.textContent = '两次输入的密码不一致'; errorDiv.style.display = 'block'; return; } const result = await changePassword(oldPassword, newPassword); if (result === true) { // 成功 } else if (result && result.error) { errorDiv.textContent = result.error; errorDiv.style.display = 'block'; } }); } } // API 请求封装 async function apiRequest(url, options = {}) { const headers = { 'Content-Type': 'application/json', ...options.headers }; if (authToken) { headers['Authorization'] = `Bearer ${authToken}`; } const response = await fetch(`${API_BASE}${url}`, { ...options, headers }); // 如果 401,跳转到登录页 if (response.status === 401) { localStorage.removeItem('auth_token'); authToken = null; window.location.href = '/'; return; } return response; } // ========== Dashboard 功能 ========== // 加载 Dashboard async function loadDashboard() { setupChangePasswordForm(); await loadUserInfo(); await loadStats(); await loadCookies(); } // 加载用户信息 async function loadUserInfo() { try { const response = await apiRequest('/api/auth/me'); if (response.ok) { const user = await response.json(); document.getElementById('currentUser').textContent = user.username; } } catch (error) { console.error('加载用户信息失败:', error); } } // 加载统计信息 async function loadStats() { try { const response = await apiRequest('/api/cookies/stats'); if (response.ok) { const stats = await response.json(); document.getElementById('totalCount').textContent = stats.total_count; document.getElementById('validCount').textContent = stats.valid_count; document.getElementById('invalidCount').textContent = stats.invalid_count; document.getElementById('totalUsage').textContent = stats.total_usage.toLocaleString(); } } catch (error) { console.error('加载统计信息失败:', error); } } // 加载 Cookie 列表 async function loadCookies() { try { const response = await apiRequest('/api/cookies'); if (response.ok) { const data = await response.json(); // API 返回的是数组而不是对象 renderCookieTable(Array.isArray(data) ? data : (data.cookies || [])); } } catch (error) { console.error('加载 Cookie 列表失败:', error); } } // 渲染 Cookie 表格 function renderCookieTable(cookies) { const tbody = document.getElementById('cookieTableBody'); const emptyState = document.getElementById('emptyState'); if (cookies.length === 0) { tbody.innerHTML = ''; emptyState.style.display = 'block'; return; } emptyState.style.display = 'none'; tbody.innerHTML = cookies.map((cookie, index) => ` ${index + 1} ${escapeHtml(cookie.name)} ${cookie.is_valid ? '✅ 有效' : '❌ 无效'} ${(cookie.usage_count || 0).toLocaleString()} ${cookie.priority || 0} ${formatTime(cookie.last_validated)}
`).join(''); } // 刷新 Cookie 列表 function refreshCookies() { loadCookies(); loadStats(); } // ========== Cookie 操作 ========== // 显示添加弹窗 function showAddModal() { document.getElementById('addModal').style.display = 'flex'; document.getElementById('addCookieForm').reset(); } // 关闭添加弹窗 function closeAddModal() { document.getElementById('addModal').style.display = 'none'; } // 添加 Cookie document.getElementById('addCookieForm')?.addEventListener('submit', async (e) => { e.preventDefault(); const formData = new FormData(e.target); const data = { name: formData.get('name'), api_key: formData.get('api_key'), session_key: formData.get('session_key') || '', priority: parseInt(formData.get('priority') || '0') }; try { const response = await apiRequest('/api/cookies', { method: 'POST', body: JSON.stringify(data) }); if (response.ok) { showToast('Cookie 添加成功', 'success'); closeAddModal(); refreshCookies(); } else { const error = await response.json(); showToast(error.error || '添加失败', 'error'); } } catch (error) { showToast('网络错误', 'error'); } }); // 显示编辑弹窗 async function editCookie(id) { try { const response = await apiRequest(`/api/cookies/${id}`); if (response.ok) { const cookie = await response.json(); document.getElementById('editCookieId').value = cookie.id; document.getElementById('editCookieName').value = cookie.name; document.getElementById('editApiKey').value = cookie.api_key || ''; document.getElementById('editSessionKey').value = cookie.session_key || ''; document.getElementById('editCookiePriority').value = cookie.priority || 0; document.getElementById('editModal').style.display = 'flex'; } } catch (error) { showToast('加载失败', 'error'); } } // 关闭编辑弹窗 function closeEditModal() { document.getElementById('editModal').style.display = 'none'; } // 更新 Cookie document.getElementById('editCookieForm')?.addEventListener('submit', async (e) => { e.preventDefault(); const id = document.getElementById('editCookieId').value; const formData = new FormData(e.target); const data = { name: formData.get('name'), api_key: formData.get('api_key'), session_key: formData.get('session_key') || '', priority: parseInt(formData.get('priority') || '0') }; try { const response = await apiRequest(`/api/cookies/${id}`, { method: 'PUT', body: JSON.stringify(data) }); if (response.ok) { showToast('Cookie 更新成功', 'success'); closeEditModal(); refreshCookies(); } else { const error = await response.json(); showToast(error.error || '更新失败', 'error'); } } catch (error) { showToast('网络错误', 'error'); } }); // 删除 Cookie async function deleteCookie(id) { if (!confirm('确定要删除这个 Cookie 吗?')) { return; } try { const response = await apiRequest(`/api/cookies/${id}`, { method: 'DELETE' }); if (response.ok) { showToast('Cookie 删除成功', 'success'); refreshCookies(); } else { const error = await response.json(); showToast(error.error || '删除失败', 'error'); } } catch (error) { showToast('网络错误', 'error'); } } // 验证单个 Cookie async function validateCookie(id) { try { showToast('正在验证...', 'success'); const response = await apiRequest(`/api/cookies/${id}/validate`, { method: 'POST' }); if (response.ok) { const result = await response.json(); showToast(result.is_valid ? '✅ Cookie 有效' : '❌ Cookie 无效', result.is_valid ? 'success' : 'error'); refreshCookies(); } else { const error = await response.json(); showToast(error.error || '验证失败', 'error'); } } catch (error) { showToast('网络错误', 'error'); } } // 批量验证所有 Cookie async function validateAll() { if (!confirm('确定要验证所有 Cookie 吗?这可能需要一些时间。')) { return; } try { showToast('正在批量验证...', 'success'); const response = await apiRequest('/api/cookies/validate/all', { method: 'POST' }); if (response.ok) { const result = await response.json(); showToast(`验证完成:${result.valid_count} 个有效,${result.invalid_count} 个无效`, 'success'); refreshCookies(); } else { const error = await response.json(); showToast(error.error || '验证失败', 'error'); } } catch (error) { showToast('网络错误', 'error'); } } // ========== 工具函数 ========== // 显示 Toast 通知 function showToast(message, type = 'success') { const toast = document.getElementById('toast'); toast.textContent = message; toast.className = `toast ${type}`; toast.style.display = 'block'; setTimeout(() => { toast.style.display = 'none'; }, 3000); } // 格式化时间 function formatTime(timeStr) { if (!timeStr) return '-'; const date = new Date(timeStr); const now = new Date(); const diff = Math.floor((now - date) / 1000); if (diff < 60) return '刚刚'; if (diff < 3600) return `${Math.floor(diff / 60)} 分钟前`; if (diff < 86400) return `${Math.floor(diff / 3600)} 小时前`; return `${Math.floor(diff / 86400)} 天前`; } // HTML 转义 function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; }