Files
AIEC-new/AIEC-server/js/auth-integration.js
2025-10-17 09:31:28 +08:00

480 lines
16 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 首页认证集成 - 处理登录状态检查和用户菜单
*/
class HomeAuthIntegration {
constructor() {
this.currentUser = null;
this.isAuthenticated = false;
this.init();
}
/**
* 初始化
*/
async init() {
await this.checkAuthStatus();
this.setupEventListeners();
this.updateUI();
// 隐藏加载遮罩
const loader = document.getElementById('authCheckLoader');
if (loader) {
loader.style.display = 'none';
}
}
/**
* 检查认证状态
*/
async checkAuthStatus() {
try {
const authStatus = await AuthService.checkAuthStatus();
this.isAuthenticated = authStatus.isAuthenticated;
this.currentUser = authStatus.user;
// 如果用户已登录保存用户信息到localStorage供ChatManager使用
if (this.isAuthenticated && this.currentUser) {
localStorage.setItem('yundage_current_user', JSON.stringify(this.currentUser));
} else {
// 如果用户未登录,清除本地存储的用户信息
localStorage.removeItem('yundage_current_user');
}
console.log('Auth Status:', authStatus);
// 触发认证状态检查完成事件
window.dispatchEvent(new CustomEvent('authStatusChecked', {
detail: {
isAuthenticated: this.isAuthenticated,
user: this.currentUser
}
}));
// 路由保护逻辑
this.handleRouteProtection();
} catch (error) {
console.error('Failed to check auth status:', error);
this.isAuthenticated = false;
this.currentUser = null;
// 清除本地存储的用户信息
localStorage.removeItem('yundage_current_user');
// 即使检查失败也要触发事件
window.dispatchEvent(new CustomEvent('authStatusChecked', {
detail: {
isAuthenticated: false,
user: null,
error: error
}
}));
// 检查失败时也要处理路由保护
this.handleRouteProtection();
}
}
/**
* 处理路由保护
*/
handleRouteProtection() {
const currentPath = window.location.pathname;
const isAuthPage = currentPath.includes('/auth/pages/');
const isMainPage = currentPath.includes('/index.html') ||
currentPath === '/' ||
currentPath.endsWith('/yundage/') ||
currentPath.endsWith('/yundage');
// 如果在登录页面且已登录,跳转到首页
if (this.isAuthenticated && isAuthPage) {
console.log('已登录用户访问登录页面,跳转到首页');
setTimeout(() => {
window.location.href = '../../index.html';
}, 500);
return;
}
// 如果在主页且未登录,跳转到登录页面
if (!this.isAuthenticated && isMainPage) {
console.log('未登录用户访问主页,跳转到登录页面');
// 更新加载遮罩文字
const loader = document.getElementById('authCheckLoader');
if (loader) {
const loaderText = loader.querySelector('p');
if (loaderText) {
loaderText.textContent = '正在跳转到登录页面...';
}
}
// 显示提示
this.showNotification('请先登录', 'info');
// 短暂延迟后跳转
setTimeout(() => {
window.location.href = 'auth/pages/login.html?redirect=' + encodeURIComponent(window.location.href);
}, 500);
return;
}
}
/**
* 设置事件监听器
*/
setupEventListeners() {
// 用户菜单切换
const userMenuToggle = document.getElementById('userMenuToggle');
if (userMenuToggle) {
userMenuToggle.addEventListener('click', (e) => {
e.stopPropagation();
this.toggleUserMenu();
});
}
// 退出登录按钮
const logoutBtn = document.getElementById('logoutBtn');
if (logoutBtn) {
logoutBtn.addEventListener('click', (e) => {
e.preventDefault();
this.handleLogout();
});
}
// 点击页面其他地方关闭菜单
document.addEventListener('click', (e) => {
const userDropdown = document.getElementById('userDropdown');
const userMenuToggle = document.getElementById('userMenuToggle');
if (userDropdown && userMenuToggle) {
if (!userMenuToggle.contains(e.target) && !userDropdown.contains(e.target)) {
userDropdown.classList.add('hidden');
}
}
});
// 监听存储变化(其他标签页登录/登出)
window.addEventListener('storage', (e) => {
if (e.key === TokenManager.TOKEN_KEY || e.key === TokenManager.USER_KEY) {
this.handleStorageChange();
}
});
// 定期检查token状态
this.startTokenCheck();
}
/**
* 更新UI显示
*/
updateUI() {
const guestMenu = document.getElementById('guestMenu');
const userMenu = document.getElementById('userMenu');
const userName = document.getElementById('userName');
const userAccount = document.getElementById('userAccount');
if (this.isAuthenticated && this.currentUser) {
// 显示已登录状态
if (guestMenu) guestMenu.classList.add('hidden');
if (userMenu) userMenu.classList.remove('hidden');
// 更新用户信息显示
if (userName) {
userName.textContent = this.currentUser.username || this.currentUser.nickname || '用户';
}
if (userAccount) {
userAccount.textContent = this.currentUser.phone || this.currentUser.email || '';
}
// 更新用户头像(可选)
this.updateUserAvatar();
// 添加刷新按钮事件(如果存在)
this.setupRefreshButton();
} else {
// 显示未登录状态
if (guestMenu) guestMenu.classList.remove('hidden');
if (userMenu) userMenu.classList.add('hidden');
}
}
/**
* 设置刷新按钮
*/
setupRefreshButton() {
const refreshBtn = document.getElementById('refreshUserInfo');
if (refreshBtn && !refreshBtn._listenerAdded) {
refreshBtn._listenerAdded = true;
refreshBtn.addEventListener('click', async (e) => {
e.preventDefault();
await this.refreshUserInfo();
});
}
}
/**
* 刷新用户信息
*/
async refreshUserInfo() {
try {
console.log('手动刷新用户信息...');
const result = await AuthService.getUserInfo();
if (result.success && result.data) {
this.currentUser = result.data;
// 更新本地存储
localStorage.setItem('yundage_current_user', JSON.stringify(this.currentUser));
// 更新UI
this.updateUI();
// 显示成功提示
this.showNotification('用户信息已更新', 'success');
} else {
throw new Error(result.message || '获取用户信息失败');
}
} catch (error) {
console.error('刷新用户信息失败:', error);
// 特殊处理不同类型的错误
if (error.message.includes('403')) {
this.showNotification('没有权限访问此用户信息', 'warning');
} else if (error.message.includes('404')) {
this.showNotification('用户不存在', 'error');
} else {
this.showNotification('刷新失败:' + error.message, 'error');
}
}
}
/**
* 显示通知消息
*/
showNotification(message, type = 'info') {
// 创建通知元素
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 p-4 rounded-lg shadow-lg z-50 transition-all duration-300 transform translate-x-full`;
// 根据类型设置样式
const typeStyles = {
success: 'bg-green-500 text-white',
error: 'bg-red-500 text-white',
warning: 'bg-yellow-500 text-white',
info: 'bg-blue-500 text-white'
};
notification.className += ` ${typeStyles[type] || typeStyles.info}`;
notification.textContent = message;
// 添加到页面
document.body.appendChild(notification);
// 显示动画
setTimeout(() => {
notification.classList.remove('translate-x-full');
}, 100);
// 3秒后自动消失
setTimeout(() => {
notification.classList.add('translate-x-full');
setTimeout(() => {
notification.remove();
}, 300);
}, 3000);
}
/**
* 切换用户菜单显示
*/
toggleUserMenu() {
const userDropdown = document.getElementById('userDropdown');
if (userDropdown) {
userDropdown.classList.toggle('hidden');
}
}
/**
* 处理退出登录
*/
async handleLogout() {
try {
// 显示确认对话框
const confirmed = confirm('确定要退出登录吗?');
if (!confirmed) return;
// 执行登出
const result = await AuthService.logout();
if (result.success) {
this.isAuthenticated = false;
this.currentUser = null;
// 清除localStorage中的用户信息
localStorage.removeItem('yundage_current_user');
this.updateUI();
// 隐藏用户菜单
const userDropdown = document.getElementById('userDropdown');
if (userDropdown) {
userDropdown.classList.add('hidden');
}
// 显示成功提示
this.showNotification('已退出登录', 'success');
// 可选:刷新页面
setTimeout(() => {
window.location.reload();
}, 1000);
} else {
this.showNotification(result.message || '退出登录失败', 'error');
}
} catch (error) {
console.error('Logout error:', error);
this.showNotification('退出登录失败', 'error');
}
}
/**
* 处理存储变化(跨标签页同步)
*/
async handleStorageChange() {
await this.checkAuthStatus();
this.updateUI();
}
/**
* 更新用户头像
*/
updateUserAvatar() {
// 如果用户有头像,可以在这里更新头像显示
// 当前使用默认的太阳云朵图标
const userMenuToggle = document.getElementById('userMenuToggle');
if (userMenuToggle && this.currentUser && this.currentUser.avatar) {
// 可以在这里添加自定义头像逻辑
userMenuToggle.style.backgroundImage = `url(${this.currentUser.avatar})`;
userMenuToggle.style.backgroundSize = 'cover';
}
}
/**
* 显示通知消息
* @param {string} message - 消息内容
* @param {string} type - 消息类型success/error/info/warning
*/
showNotification(message, type = 'info') {
// 创建通知元素
const notification = document.createElement('div');
notification.className = `fixed top-20 right-4 z-50 px-4 py-3 rounded-lg shadow-lg max-w-sm transition-all duration-300 transform translate-x-full`;
// 设置样式
switch (type) {
case 'success':
notification.classList.add('bg-green-500', 'text-white');
break;
case 'error':
notification.classList.add('bg-red-500', 'text-white');
break;
case 'warning':
notification.classList.add('bg-yellow-500', 'text-white');
break;
default:
notification.classList.add('bg-blue-500', 'text-white');
}
notification.innerHTML = `
<div class="flex items-center gap-2">
<i class="fas fa-${type === 'success' ? 'check-circle' : type === 'error' ? 'exclamation-circle' : 'info-circle'}"></i>
<span>${message}</span>
<button class="ml-2 text-white hover:text-gray-200" onclick="this.parentElement.parentElement.remove()">
<i class="fas fa-times"></i>
</button>
</div>
`;
document.body.appendChild(notification);
// 显示动画
setTimeout(() => {
notification.classList.remove('translate-x-full');
}, 100);
// 自动隐藏
setTimeout(() => {
notification.classList.add('translate-x-full');
setTimeout(() => {
if (notification.parentElement) {
notification.remove();
}
}, 300);
}, 3000);
}
/**
* 开始token检查定时器
*/
startTokenCheck() {
// 每5分钟检查一次token状态
setInterval(async () => {
const isValid = TokenManager.isTokenValid();
if (this.isAuthenticated && !isValid) {
// Token已过期尝试刷新
const refreshResult = await AuthService.refreshToken();
if (!refreshResult.success) {
// 刷新失败,清除登录状态
this.isAuthenticated = false;
this.currentUser = null;
this.updateUI();
this.showNotification('登录已过期,请重新登录', 'warning');
}
}
}, 5 * 60 * 1000); // 5分钟
}
/**
* 检查是否需要登录才能使用某些功能
* @param {Function} callback - 需要登录后执行的回调函数
* @param {string} redirectUrl - 登录后的回跳地址
*/
requireAuth(callback, redirectUrl = null) {
if (this.isAuthenticated) {
callback();
} else {
// 未登录,跳转到登录页面
const loginUrl = redirectUrl
? `auth/pages/login.html?redirect=${encodeURIComponent(redirectUrl)}`
: 'auth/pages/login.html';
window.location.href = loginUrl;
}
}
/**
* 获取当前用户信息
* @returns {object|null} 用户信息
*/
getCurrentUser() {
return this.currentUser;
}
/**
* 检查是否已登录
* @returns {boolean} 是否已登录
*/
isLoggedIn() {
return this.isAuthenticated;
}
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {
window.homeAuth = new HomeAuthIntegration();
});
// 导出供其他模块使用
if (typeof module !== 'undefined' && module.exports) {
module.exports = HomeAuthIntegration;
}