first commit
This commit is contained in:
269
frontend/js/auth.js
Normal file
269
frontend/js/auth.js
Normal file
@@ -0,0 +1,269 @@
|
||||
class AuthManager {
|
||||
constructor() {
|
||||
// 动态设置API基础URL,支持file:///协议和localhost:3000访问
|
||||
this.apiBase = window.location.protocol === 'file:' ? 'http://localhost:3000/api' : '/api';
|
||||
this.initEventListeners();
|
||||
this.checkAuthStatus();
|
||||
}
|
||||
|
||||
async checkAuthStatus() {
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/me`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.user) {
|
||||
// 用户已登录,根据角色重定向到正确的仪表板
|
||||
const userRole = data.user.role;
|
||||
let redirectUrl = '/dashboard';
|
||||
|
||||
if (userRole === 'student') {
|
||||
redirectUrl = '/frontend/html/student_dashboard.html';
|
||||
} else if (userRole === 'teacher') {
|
||||
redirectUrl = '/frontend/html/teacher_dashboard.html';
|
||||
} else if (userRole === 'admin') {
|
||||
redirectUrl = '/frontend/html/admin_dashboard.html';
|
||||
}
|
||||
|
||||
// 如果当前页面是登录或注册页面,则重定向到仪表板
|
||||
const currentPath = window.location.pathname;
|
||||
if (currentPath.includes('login.html') || currentPath.includes('register.html')) {
|
||||
window.location.href = redirectUrl;
|
||||
}
|
||||
// 如果当前页面不是正确的仪表板页面,则重定向
|
||||
else if (!currentPath.includes(redirectUrl) &&
|
||||
currentPath !== '/' &&
|
||||
!currentPath.includes('index.html')) {
|
||||
window.location.href = redirectUrl;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('用户未登录');
|
||||
}
|
||||
}
|
||||
|
||||
initEventListeners() {
|
||||
// 登录表单提交
|
||||
const loginForm = document.getElementById('loginForm');
|
||||
if (loginForm) {
|
||||
loginForm.addEventListener('submit', (e) => this.handleLogin(e));
|
||||
}
|
||||
|
||||
// 注册表单提交
|
||||
const registerForm = document.getElementById('registerForm');
|
||||
if (registerForm) {
|
||||
registerForm.addEventListener('submit', (e) => this.handleRegister(e));
|
||||
}
|
||||
|
||||
// 登出按钮
|
||||
const logoutBtn = document.getElementById('logoutBtn');
|
||||
if (logoutBtn) {
|
||||
logoutBtn.addEventListener('click', (e) => this.handleLogout(e));
|
||||
}
|
||||
}
|
||||
|
||||
async handleLogin(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const form = e.target;
|
||||
const formData = new FormData(form);
|
||||
const data = Object.fromEntries(formData.entries());
|
||||
|
||||
const submitBtn = form.querySelector('button[type="submit"]');
|
||||
const originalText = submitBtn.innerHTML;
|
||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 登录中...';
|
||||
submitBtn.disabled = true;
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
this.showNotification('登录成功!正在跳转...', 'success');
|
||||
|
||||
// 根据用户角色跳转到不同的仪表板
|
||||
const userRole = result.user?.role;
|
||||
let redirectUrl = '/dashboard';
|
||||
|
||||
if (userRole === 'student') {
|
||||
redirectUrl = '/frontend/html/student_dashboard.html';
|
||||
} else if (userRole === 'teacher') {
|
||||
redirectUrl = '/frontend/html/teacher_dashboard.html';
|
||||
} else if (userRole === 'admin') {
|
||||
redirectUrl = '/frontend/html/admin_dashboard.html';
|
||||
}
|
||||
|
||||
// 延迟跳转以显示通知
|
||||
setTimeout(() => {
|
||||
window.location.href = redirectUrl;
|
||||
}, 1500);
|
||||
} else {
|
||||
this.showNotification(result.message || '登录失败', 'error');
|
||||
submitBtn.innerHTML = originalText;
|
||||
submitBtn.disabled = false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('登录错误:', error);
|
||||
this.showNotification('网络错误,请重试', 'error');
|
||||
submitBtn.innerHTML = originalText;
|
||||
submitBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
async handleRegister(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const form = e.target;
|
||||
const formData = new FormData(form);
|
||||
const data = Object.fromEntries(formData.entries());
|
||||
|
||||
// 验证密码
|
||||
if (data.password !== data.confirmPassword) {
|
||||
this.showNotification('两次输入的密码不一致', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const submitBtn = form.querySelector('button[type="submit"]');
|
||||
const originalText = submitBtn.innerHTML;
|
||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 注册中...';
|
||||
submitBtn.disabled = true;
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/register`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
this.showNotification('注册成功!正在跳转到登录页面...', 'success');
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '/html/login.html';
|
||||
}, 1500);
|
||||
} else {
|
||||
this.showNotification(result.message || '注册失败', 'error');
|
||||
submitBtn.innerHTML = originalText;
|
||||
submitBtn.disabled = false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('注册错误:', error);
|
||||
this.showNotification('网络错误,请重试', 'error');
|
||||
submitBtn.innerHTML = originalText;
|
||||
submitBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
async handleLogout(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (!confirm('确定要退出登录吗?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/logout`, {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
this.showNotification('已成功退出登录', 'success');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 1000);
|
||||
} else {
|
||||
this.showNotification('退出登录失败', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('退出登录错误:', error);
|
||||
this.showNotification('网络错误,请重试', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
showNotification(message, type = 'info') {
|
||||
// 移除现有的通知
|
||||
const existingNotification = document.querySelector('.notification');
|
||||
if (existingNotification) {
|
||||
existingNotification.remove();
|
||||
}
|
||||
|
||||
// 创建新的通知
|
||||
const notification = document.createElement('div');
|
||||
notification.className = `notification notification-${type}`;
|
||||
notification.innerHTML = `
|
||||
<i class="fas fa-${type === 'success' ? 'check-circle' : 'exclamation-circle'}"></i>
|
||||
<span>${message}</span>
|
||||
`;
|
||||
|
||||
// 样式
|
||||
notification.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : '#3b82f6'};
|
||||
color: white;
|
||||
padding: 15px 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
z-index: 1000;
|
||||
animation: slideIn 0.3s ease;
|
||||
`;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// 3秒后自动移除
|
||||
setTimeout(() => {
|
||||
notification.style.animation = 'slideOut 0.3s ease';
|
||||
setTimeout(() => notification.remove(), 300);
|
||||
}, 3000);
|
||||
|
||||
// 添加动画关键帧
|
||||
if (!document.querySelector('#notification-styles')) {
|
||||
const style = document.createElement('style');
|
||||
style.id = 'notification-styles';
|
||||
style.textContent = `
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes slideOut {
|
||||
from {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化认证管理器
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
window.authManager = new AuthManager();
|
||||
});
|
||||
Reference in New Issue
Block a user