/** * 云酒馆 - 用户认证模块 * 处理用户登录和注册功能 */ // ===== 配置 ===== const CONFIG = { API_BASE_URL: 'http://localhost:8888/app', TOKEN_KEY: 'st_access_token', REFRESH_TOKEN_KEY: 'st_refresh_token', USER_KEY: 'st_user_info', }; // ===== DOM 元素 ===== const elements = { tabs: document.querySelectorAll('.auth-tab'), loginForm: document.getElementById('loginForm'), registerForm: document.getElementById('registerForm'), messageBox: document.getElementById('messageBox'), loadingOverlay: document.getElementById('loadingOverlay'), passwordToggles: document.querySelectorAll('.password-toggle'), }; // ===== 初始化 ===== document.addEventListener('DOMContentLoaded', () => { initTabs(); initForms(); initPasswordToggles(); checkAutoLogin(); }); // ===== 标签页切换 ===== function initTabs() { elements.tabs.forEach(tab => { tab.addEventListener('click', () => { const tabName = tab.dataset.tab; switchTab(tabName); }); }); } function switchTab(tabName) { // 更新标签页状态 elements.tabs.forEach(tab => { tab.classList.toggle('active', tab.dataset.tab === tabName); }); // 更新表单显示 elements.loginForm.classList.toggle('active', tabName === 'login'); elements.registerForm.classList.toggle('active', tabName === 'register'); // 清空消息 hideMessage(); } // ===== 表单初始化 ===== function initForms() { // 登录表单 elements.loginForm.addEventListener('submit', async (e) => { e.preventDefault(); await handleLogin(); }); // 注册表单 elements.registerForm.addEventListener('submit', async (e) => { e.preventDefault(); await handleRegister(); }); } // ===== 密码显示/隐藏切换 ===== function initPasswordToggles() { elements.passwordToggles.forEach(toggle => { toggle.addEventListener('click', () => { const targetId = toggle.dataset.target; const input = document.getElementById(targetId); const icon = toggle.querySelector('i'); if (input.type === 'password') { input.type = 'text'; icon.classList.remove('fa-eye'); icon.classList.add('fa-eye-slash'); } else { input.type = 'password'; icon.classList.remove('fa-eye-slash'); icon.classList.add('fa-eye'); } }); }); } // ===== 登录处理 ===== async function handleLogin() { const username = document.getElementById('loginUsername').value.trim(); const password = document.getElementById('loginPassword').value; const rememberMe = document.getElementById('rememberMe').checked; // 验证输入 if (!username || !password) { showMessage('请填写完整的登录信息', 'error'); return; } showLoading(); try { const response = await fetch(`${CONFIG.API_BASE_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, password }), }); const data = await response.json(); if (data.code === 0) { // 登录成功 saveLoginData(data.data, rememberMe); showMessage('登录成功!正在跳转...', 'success'); // 延迟跳转到主页 setTimeout(() => { window.location.href = '/'; }, 1500); } else { // 登录失败 showMessage(data.msg || '登录失败,请检查用户名和密码', 'error'); } } catch (error) { console.error('登录错误:', error); showMessage('网络错误,请检查服务器连接', 'error'); } finally { hideLoading(); } } // ===== 注册处理 ===== async function handleRegister() { const username = document.getElementById('registerUsername').value.trim(); const password = document.getElementById('registerPassword').value; const passwordConfirm = document.getElementById('registerPasswordConfirm').value; const nickName = document.getElementById('registerNickname').value.trim(); const email = document.getElementById('registerEmail').value.trim(); // 验证输入 if (!username || !password || !passwordConfirm) { showMessage('请填写必填信息', 'error'); return; } if (username.length < 3 || username.length > 32) { showMessage('用户名长度应为 3-32 个字符', 'error'); return; } if (password.length < 6 || password.length > 32) { showMessage('密码长度应为 6-32 个字符', 'error'); return; } if (password !== passwordConfirm) { showMessage('两次输入的密码不一致', 'error'); return; } // 验证用户名格式 if (!/^[a-zA-Z0-9_]+$/.test(username)) { showMessage('用户名只能包含字母、数字和下划线', 'error'); return; } showLoading(); try { const requestBody = { username, password, nickName: nickName || username, // 如果没有昵称,使用用户名 }; // 如果填写了邮箱,添加到请求中 if (email) { requestBody.email = email; } const response = await fetch(`${CONFIG.API_BASE_URL}/auth/register`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(requestBody), }); const data = await response.json(); if (data.code === 0) { // 注册成功 showMessage('注册成功!请登录', 'success'); // 清空注册表单 elements.registerForm.reset(); // 切换到登录标签页,并填充用户名 setTimeout(() => { switchTab('login'); document.getElementById('loginUsername').value = username; document.getElementById('loginPassword').focus(); }, 1500); } else { // 注册失败 showMessage(data.msg || '注册失败,请稍后重试', 'error'); } } catch (error) { console.error('注册错误:', error); showMessage('网络错误,请检查服务器连接', 'error'); } finally { hideLoading(); } } // ===== 保存登录数据 ===== function saveLoginData(loginData, rememberMe) { const { token, refreshToken, user } = loginData; // 保存到 localStorage 或 sessionStorage const storage = rememberMe ? localStorage : sessionStorage; storage.setItem(CONFIG.TOKEN_KEY, token); storage.setItem(CONFIG.REFRESH_TOKEN_KEY, refreshToken); storage.setItem(CONFIG.USER_KEY, JSON.stringify(user)); } // ===== 自动登录检查 ===== function checkAutoLogin() { // 检查是否已经登录 const token = localStorage.getItem(CONFIG.TOKEN_KEY) || sessionStorage.getItem(CONFIG.TOKEN_KEY); if (token) { // 已登录,尝试验证 token 是否有效 verifyToken(token); } } // ===== 验证 Token ===== async function verifyToken(token) { try { const response = await fetch(`${CONFIG.API_BASE_URL}/auth/userinfo`, { method: 'GET', headers: { 'x-token': token, }, }); if (response.ok) { const data = await response.json(); if (data.code === 0) { // Token 有效,直接跳转到主页 showMessage('检测到已登录,正在跳转...', 'success'); setTimeout(() => { window.location.href = '/'; }, 1000); } } } catch (error) { console.error('Token 验证失败:', error); // Token 无效,清除存储 clearLoginData(); } } // ===== 清除登录数据 ===== function clearLoginData() { localStorage.removeItem(CONFIG.TOKEN_KEY); localStorage.removeItem(CONFIG.REFRESH_TOKEN_KEY); localStorage.removeItem(CONFIG.USER_KEY); sessionStorage.removeItem(CONFIG.TOKEN_KEY); sessionStorage.removeItem(CONFIG.REFRESH_TOKEN_KEY); sessionStorage.removeItem(CONFIG.USER_KEY); } // ===== 消息提示 ===== function showMessage(message, type = 'error') { elements.messageBox.textContent = message; elements.messageBox.className = `message-box show ${type}`; // 3秒后自动隐藏 setTimeout(() => { hideMessage(); }, 5000); } function hideMessage() { elements.messageBox.classList.remove('show'); } // ===== 加载动画 ===== function showLoading() { elements.loadingOverlay.classList.add('show'); } function hideLoading() { elements.loadingOverlay.classList.remove('show'); } // ===== 工具函数:获取当前登录用户 ===== export function getCurrentUser() { const userJson = localStorage.getItem(CONFIG.USER_KEY) || sessionStorage.getItem(CONFIG.USER_KEY); return userJson ? JSON.parse(userJson) : null; } // ===== 工具函数:获取 Token ===== export function getToken() { return localStorage.getItem(CONFIG.TOKEN_KEY) || sessionStorage.getItem(CONFIG.TOKEN_KEY); } // ===== 工具函数:登出 ===== export async function logout() { const token = getToken(); if (token) { try { await fetch(`${CONFIG.API_BASE_URL}/auth/logout`, { method: 'POST', headers: { 'x-token': token, }, }); } catch (error) { console.error('登出请求失败:', error); } } clearLoginData(); window.location.href = '/auth.html'; } // ===== 导出配置供其他模块使用 ===== export { CONFIG };