cursor done.
This commit is contained in:
343
public/js/auth.js
Normal file
343
public/js/auth.js
Normal file
@@ -0,0 +1,343 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user