Files
timeline/public/js/auth.js
2025-11-11 14:36:09 +08:00

344 lines
9.2 KiB
JavaScript

import state from './state.js';
import {
getToken,
setToken,
getUser,
setUser,
getCurrentServer,
setCurrentServer as persistCurrentServer,
clearAuth
} from './storage.js';
import { showToast } from './toast.js';
import { login, register, ApiError } from './api.js';
export default class AuthManager {
constructor(calendarView, serverManager) {
this.calendarView = calendarView;
this.serverManager = serverManager;
this.authModal = document.getElementById('authModal');
this.mainContainer = document.getElementById('mainContainer');
this.authTitle = document.getElementById('authTitle');
this.authUsername = document.getElementById('authUsername');
this.authPassword = document.getElementById('authPassword');
this.authServer = document.getElementById('authServer');
this.authMessage = document.getElementById('authMessage');
this.loginBtn = document.getElementById('loginBtn');
this.registerBtn = document.getElementById('registerBtn');
this.switchToRegister = document.getElementById('switchToRegister');
this.switchToLogin = document.getElementById('switchToLogin');
this.closeModalBtn = document.getElementById('closeAuthModal');
this.logoutBtn = document.getElementById('logoutBtn');
this.userDisplay = document.getElementById('userDisplay');
}
init() {
this.bindEvents();
this.updateAuthUI();
}
bindEvents() {
if (this.loginBtn) {
this.loginBtn.addEventListener('click', () => this.handleLogin());
}
if (this.registerBtn) {
this.registerBtn.addEventListener('click', () => this.handleRegister());
}
if (this.switchToRegister) {
this.switchToRegister.addEventListener('click', () => {
state.isLoginMode = false;
this.updateAuthUI();
});
}
if (this.switchToLogin) {
this.switchToLogin.addEventListener('click', () => {
state.isLoginMode = true;
this.updateAuthUI();
});
}
if (this.closeModalBtn) {
this.closeModalBtn.addEventListener('click', () => {
if (!state.token) {
showToast('请先登录后再关闭', 'error');
return;
}
this.hideAuthModal();
});
}
if (this.logoutBtn) {
this.logoutBtn.addEventListener('click', () => this.logout());
}
if (this.authPassword) {
this.authPassword.addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
state.isLoginMode ? this.handleLogin() : this.handleRegister();
}
});
}
}
async handleLogin() {
const server = this.getServerInput();
const username = (this.authUsername?.value || '').trim();
const password = this.authPassword?.value || '';
if (!server || !username || !password) {
this.showAuthMessage('请输入服务器、用户名和密码');
return;
}
try {
this.showAuthMessage('正在登录...', 'info');
const result = await login(server, username, password);
this.afterAuthSuccess(server, result.token, {
username: result.username,
userId: result.userId
});
showToast('登录成功', 'success');
} catch (error) {
this.handleAuthError(error);
}
}
async handleRegister() {
const server = this.getServerInput();
const username = (this.authUsername?.value || '').trim();
const password = this.authPassword?.value || '';
if (!server || !username || !password) {
this.showAuthMessage('请输入服务器、用户名和密码');
return;
}
if (username.length < 3) {
this.showAuthMessage('用户名至少需要3个字符');
return;
}
if (password.length < 6) {
this.showAuthMessage('密码至少需要6个字符');
return;
}
try {
this.showAuthMessage('正在注册...', 'info');
const result = await register(server, username, password);
this.afterAuthSuccess(server, result.token, {
username: result.username,
userId: result.userId
});
showToast('注册成功', 'success');
} catch (error) {
this.handleAuthError(error);
}
}
getServerInput() {
const value = this.authServer?.value.trim();
if (!value) {
this.showAuthMessage('请输入服务器地址');
return '';
}
try {
new URL(value);
return value;
} catch (error) {
this.showAuthMessage('无效的服务器地址格式');
return '';
}
}
afterAuthSuccess(server, token, user) {
state.currentServer = server;
state.token = token;
state.user = user;
persistCurrentServer(server);
setToken(server, token);
setUser(server, user);
if (this.serverManager) {
this.serverManager.ensureServerInList(server);
}
this.hideAuthModal();
this.showMainContainer();
this.updateUserDisplay();
if (this.serverManager) {
this.serverManager.setCurrentServer(server);
}
this.calendarView.loadData();
this.clearAuthForm();
this.clearAuthMessage();
}
handleAuthError(error) {
if (error instanceof ApiError) {
this.showAuthMessage(error.message || '操作失败');
return;
}
this.showAuthMessage('操作失败,请稍后再试');
}
clearAuthForm() {
if (this.authPassword) this.authPassword.value = '';
}
showAuthMessage(message, type = 'error') {
if (!this.authMessage) return;
this.authMessage.textContent = message;
this.authMessage.className = `auth-message ${type}`;
}
clearAuthMessage() {
if (!this.authMessage) return;
this.authMessage.textContent = '';
this.authMessage.className = 'auth-message';
}
updateAuthUI() {
if (!this.authTitle || !this.loginBtn || !this.registerBtn || !this.switchToLogin || !this.switchToRegister) {
return;
}
if (state.isLoginMode) {
this.authTitle.textContent = '登录';
this.loginBtn.style.display = 'block';
this.registerBtn.style.display = 'none';
this.switchToRegister.style.display = 'block';
this.switchToLogin.style.display = 'none';
} else {
this.authTitle.textContent = '注册';
this.loginBtn.style.display = 'none';
this.registerBtn.style.display = 'block';
this.switchToRegister.style.display = 'none';
this.switchToLogin.style.display = 'block';
}
}
showAuthModal(prefillServer) {
if (this.authModal) {
this.authModal.style.display = 'flex';
}
if (this.mainContainer) {
this.mainContainer.style.display = 'none';
}
const serverValue = prefillServer || state.currentServer || window.location.origin;
if (this.authServer) {
this.authServer.value = serverValue;
}
state.isLoginMode = true;
this.updateAuthUI();
this.clearAuthMessage();
}
hideAuthModal() {
if (this.authModal) {
this.authModal.style.display = 'none';
}
}
showMainContainer() {
if (this.mainContainer) {
this.mainContainer.style.display = 'block';
}
this.hideAuthModal();
}
hideMainContainer() {
if (this.mainContainer) {
this.mainContainer.style.display = 'none';
}
}
updateUserDisplay() {
if (this.userDisplay) {
this.userDisplay.textContent = state.user ? `用户: ${state.user.username}` : '未登录';
}
}
async handleServerSelection(server) {
if (!server) {
persistCurrentServer('');
state.currentServer = '';
state.token = '';
state.user = null;
this.calendarView.clearData();
this.hideMainContainer();
this.showAuthModal();
this.updateUserDisplay();
return;
}
persistCurrentServer(server);
state.currentServer = server;
const storedToken = getToken(server);
const storedUser = getUser(server);
if (storedToken && storedUser) {
state.token = storedToken;
state.user = storedUser;
this.showMainContainer();
this.updateUserDisplay();
this.calendarView.loadData();
this.hideAuthModal();
} else {
state.token = '';
state.user = null;
this.calendarView.clearData();
this.updateUserDisplay();
this.showAuthModal(server);
}
}
logout() {
if (state.currentServer) {
clearAuth(state.currentServer);
}
state.token = '';
state.user = null;
this.calendarView.clearData();
this.updateUserDisplay();
showToast('已退出登录', 'success');
this.hideMainContainer();
this.showAuthModal(state.currentServer || window.location.origin);
}
checkExistingSession() {
const storedServer = getCurrentServer();
if (storedServer) {
state.currentServer = storedServer;
if (this.serverManager) {
this.serverManager.ensureServerInList(storedServer);
this.serverManager.setCurrentServer(storedServer);
}
}
const storedToken = storedServer ? getToken(storedServer) : '';
const storedUser = storedServer ? getUser(storedServer) : null;
if (storedServer && storedToken && storedUser) {
state.token = storedToken;
state.user = storedUser;
this.showMainContainer();
this.updateUserDisplay();
this.calendarView.loadData();
} else {
this.hideMainContainer();
this.showAuthModal(storedServer || window.location.origin);
}
}
}