// 认证工具类 - 参考Flutter的auth_provider.dart const apiClient = require('./api-client.js'); class AuthManager { constructor() { // 实现单例模式,防止重复创建实例 if (AuthManager._instance) { return AuthManager._instance; } this.isInitialized = false; this.loginPromise = null; // 防止并发登录 this.tokenRefreshPromise = null; // 防止并发刷新token this._app = null; // 缓存app实例 AuthManager._instance = this; } // 安全获取app实例 getApp() { if (!this._app) { try { this._app = getApp(); } catch (error) { console.error('获取app实例失败:', error); return null; } } return this._app; } // 初始化认证管理器 async init() { if (this.isInitialized) { return; } try { // 检查本地存储的用户信息 const userInfo = wx.getStorageSync('userInfo'); if (userInfo && userInfo.token) { // 检查token是否过期 if (this.isTokenValid(userInfo)) { // 恢复登录状态 const app = this.getApp(); if (app) { app.globalData.userInfo = userInfo; app.globalData.isLoggedIn = true; } apiClient.setToken(userInfo.token); } else { await this.refreshTokenIfNeeded(userInfo); } } else { } this.isInitialized = true; } catch (error) { console.error('认证管理器初始化失败:', error); this.clearAuthData(); this.isInitialized = true; } } // 检查token是否有效 isTokenValid(userInfo) { if (!userInfo || !userInfo.token || !userInfo.expiresAt) { return false; } // 检查是否过期(提前5分钟判断过期) const expiresAt = new Date(userInfo.expiresAt).getTime(); const now = Date.now(); const bufferTime = 5 * 60 * 1000; // 5分钟缓冲时间 return (expiresAt - now) > bufferTime; } // 检查是否已登录 isLoggedIn() { const app = this.getApp(); return app?.globalData?.isLoggedIn && !!app?.globalData?.userInfo?.token; } // 获取当前用户信息 getCurrentUser() { const app = this.getApp(); return app?.globalData?.userInfo?.user || null; } // 获取完整的认证信息(包含token) getFullUserInfo() { const app = this.getApp(); return app?.globalData?.userInfo || null; } // 获取当前token getCurrentToken() { const app = this.getApp(); return app?.globalData?.userInfo?.token || null; } // 静默登录检查 async ensureAuthenticated() { if (!this.isInitialized) { await this.init(); } if (this.isLoggedIn()) { return true; } return false; } // 刷新token async refreshTokenIfNeeded(userInfo) { // 防止并发刷新 if (this.tokenRefreshPromise) { return await this.tokenRefreshPromise; } if (!userInfo?.refreshToken) { this.clearAuthData(); return false; } this.tokenRefreshPromise = this._doRefreshToken(userInfo.refreshToken); try { const result = await this.tokenRefreshPromise; return result; } finally { this.tokenRefreshPromise = null; } } // 执行token刷新 async _doRefreshToken(refreshToken) { try { const response = await apiClient.refreshToken(refreshToken); if (response && response.data) { // 更新用户信息 const app = this.getApp(); const currentUserInfo = app?.globalData?.userInfo || {}; const updatedUserInfo = { ...currentUserInfo, token: response.data.access_token, refreshToken: response.data.refresh_token || refreshToken, expiresAt: response.data.expires_at * 1000, // 转换为毫秒时间戳 loginTime: Date.now() }; // 保存到本地存储 wx.setStorageSync('userInfo', updatedUserInfo); // 更新全局状态 if (app) { app.globalData.userInfo = updatedUserInfo; app.globalData.isLoggedIn = true; } // 更新API客户端token apiClient.setToken(response.data.access_token); return true; } else { throw new Error('刷新token响应格式错误'); } } catch (error) { console.error('Token刷新失败:', error); this.clearAuthData(); return false; } } // 登录成功后保存认证信息 async saveAuthData(loginData) { try { console.log('开始保存认证信息:', { hasAccessToken: !!loginData.access_token, hasRefreshToken: !!loginData.refresh_token, hasUser: !!loginData.user, userCustomId: loginData.user?.customId, expiresAt: loginData.expires_at, hasNeteaseIMAccid: !!loginData.neteaseIMAccid, hasNeteaseIMToken: !!loginData.neteaseIMToken }); // 先清除旧的认证数据 this.clearAuthData(); const userInfo = { token: loginData.access_token, refreshToken: loginData.refresh_token, user: loginData.user, expiresAt: loginData.expires_at * 1000, // 转换为毫秒时间戳 loginTime: Date.now(), // 🔥 保存 NIM 账号和密码 neteaseIMAccid: loginData.neteaseIMAccid, neteaseIMToken: loginData.neteaseIMToken }; // 保存到本地存储 wx.setStorageSync('userInfo', userInfo); // 更新全局状态 const app = this.getApp(); if (app) { app.globalData.userInfo = userInfo; app.globalData.isLoggedIn = true; } // 设置API客户端token apiClient.setToken(userInfo.token); console.log('认证信息保存成功,用户customId:', userInfo.user?.customId); console.log('NIM账号保存成功:', userInfo.neteaseIMAccid); // 验证保存是否成功 const savedInfo = wx.getStorageSync('userInfo'); console.log('验证保存结果:', { saved: !!savedInfo, customId: savedInfo?.user?.customId, hasToken: !!savedInfo?.token, hasNeteaseIMAccid: !!savedInfo?.neteaseIMAccid, hasNeteaseIMToken: !!savedInfo?.neteaseIMToken }); return true; } catch (error) { console.error('保存认证信息失败:', error); return false; } } // 清除认证数据 clearAuthData() { try { // 清除本地存储 wx.removeStorageSync('userInfo'); // 清除全局状态 const app = this.getApp(); if (app) { app.globalData.userInfo = null; app.globalData.isLoggedIn = false; } // 清除API客户端token apiClient.clearToken(); } catch (error) { console.error('清除认证数据失败:', error); } } // 登出 async logout() { try { // 调用登出API try { await apiClient.logout(); } catch (error) { console.error('服务端登出失败,继续本地清理:', error); } // 清除本地认证数据 this.clearAuthData(); return true; } catch (error) { console.error('登出失败:', error); // 即使失败也要清除本地数据 this.clearAuthData(); return false; } } // 检查登录状态 // autoRedirect: 可选,是否在未登录时自动跳转登录页,默认false requireAuth(autoRedirect = false) { if (!this.isLoggedIn()) { if (autoRedirect) { wx.reLaunch({ url: '/pages/login/login' }); } return false; } return true; } // 静默登录(小程序启动时调用) async silentLogin() { // 防止并发登录 if (this.loginPromise) { return await this.loginPromise; } this.loginPromise = this._doSilentLogin(); try { const result = await this.loginPromise; return result; } finally { this.loginPromise = null; } } // 执行静默登录 async _doSilentLogin() { try { // 先检查本地状态 if (!this.isInitialized) { await this.init(); } // 如果已经登录且token有效 const app = this.getApp(); const userInfo = app?.globalData?.userInfo; if (this.isLoggedIn() && this.isTokenValid(userInfo)) { return true; } // 尝试刷新token const storedUserInfo = userInfo || wx.getStorageSync('userInfo'); if (storedUserInfo?.refreshToken) { const refreshResult = await this.refreshTokenIfNeeded(storedUserInfo); if (refreshResult) { return true; } } return false; } catch (error) { console.error('静默登录异常:', error); this.clearAuthData(); return false; } } // 获取用户基本信息(用于页面显示) getUserDisplayInfo() { const user = this.getCurrentUser(); if (!user) { return null; } return { nickname: user.nickname || user.username || '未知用户', avatar: user.avatar || '', phone: user.phone || '', customId: user.customId || user.custom_id || '' }; } // 检查特定权限 hasPermission(permission) { const user = this.getCurrentUser(); if (!user) { return false; } // 这里可以根据实际需求检查用户权限 // 例如:user.permissions?.includes(permission) return true; } // 等待认证初始化完成 async waitForInitialization() { if (this.isInitialized) { return; } return new Promise((resolve) => { const checkInterval = setInterval(() => { if (this.isInitialized) { clearInterval(checkInterval); resolve(); } }, 100); }); } // 🔥 调试方法:检查当前认证状态 debugAuthStatus() { try { const app = this.getApp(); const globalUserInfo = app?.globalData?.userInfo; const storedUserInfo = wx.getStorageSync('userInfo'); const apiToken = apiClient.getToken(); console.log('1. 全局状态:', { isLoggedIn: app?.globalData?.isLoggedIn, hasGlobalUserInfo: !!globalUserInfo, globalCustomId: globalUserInfo?.user?.customId, globalToken: globalUserInfo?.token ? globalUserInfo.token.substring(0, 20) + '...' : null }); console.log('2. 本地存储:', { hasStoredUserInfo: !!storedUserInfo, storedCustomId: storedUserInfo?.user?.customId, storedToken: storedUserInfo?.token ? storedUserInfo.token.substring(0, 20) + '...' : null }); console.log('3. API客户端:', { hasApiToken: !!apiToken, apiToken: apiToken ? apiToken.substring(0, 20) + '...' : null }); } catch (error) { console.error('调试认证状态失败:', error); } } } // 创建全局实例 const authManager = new AuthManager(); // 导出认证管理器 module.exports = authManager;