first commit
This commit is contained in:
480
AIEC-server/js/auth-integration.js
Normal file
480
AIEC-server/js/auth-integration.js
Normal file
@ -0,0 +1,480 @@
|
||||
/**
|
||||
* 首页认证集成 - 处理登录状态检查和用户菜单
|
||||
*/
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user