Files
st/web-app/public/scripts/auth.js

343 lines
9.9 KiB
JavaScript

/**
* 云酒馆 - 用户认证模块
* 处理用户登录和注册功能
*/
// ===== 配置 =====
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 };