import { HttpUtil } from './HttpUtil'; import { StorageManager } from './StorageManager'; import { WxSDK } from './WxSDK'; import { API_ENDPOINTS, API_TIMEOUT } from '../config/ApiConfig'; import { ApiEnvelope, WxLoginData, GameData } from '../types/ApiTypes'; /** * 认证管理器 * 单例模式,负责微信登录和 JWT token 管理 */ export class AuthManager { private static _instance: AuthManager | null = null; private _userId: string = ''; private _isLoggedIn: boolean = false; /** 服务端返回的已完成关卡 ID(登录后暂存,等 LevelDataManager 就绪后同步) */ private _completedLevelIds: string[] = []; /** 服务端返回的已完成关卡数量,用于称号体系计算 */ private _completedLevelCount: number = 0; static get instance(): AuthManager { if (!this._instance) { this._instance = new AuthManager(); } return this._instance; } private constructor() {} get isLoggedIn(): boolean { return this._isLoggedIn; } get userId(): string { return this._userId; } get completedLevelIds(): string[] { return this._completedLevelIds; } get completedLevelCount(): number { return this._completedLevelCount; } addCompletedLevelCount(delta: number = 1): void { this._completedLevelCount = Math.max(0, this._completedLevelCount + delta); } /** * 初始化认证:尝试恢复 token 或执行微信登录 */ async initialize(): Promise { const savedToken = StorageManager.getToken(); if (savedToken) { HttpUtil.setAuthToken(savedToken); try { const valid = await this.validateToken(); if (valid) { console.log('[AuthManager] Token 恢复成功'); return true; } } catch { console.warn('[AuthManager] 本地 token 无效,重新登录'); } } return this.wxLogin(); } private async wxLogin(): Promise { try { let code: string; if (WxSDK.isWechat()) { code = await WxSDK.login(); } else { console.warn('[AuthManager] 非微信环境,使用开发模式 mock code'); code = 'dev_mock_code'; } const response = await HttpUtil.post>( API_ENDPOINTS.WX_LOGIN, { code }, API_TIMEOUT.DEFAULT ); if (!response.success || !response.data) { console.error('[AuthManager] 登录失败:', response.message); return false; } const { token, user } = response.data; HttpUtil.setAuthToken(token); StorageManager.setToken(token); this._userId = user.id; this._isLoggedIn = true; // 登录响应中 stamina 是原始数值(不含实时恢复),先存储默认体力 // 后续通过 game-data 接口获取完整 StaminaInfo console.log(`[AuthManager] 登录成功,用户: ${user.id},体力: ${user.stamina}`); // 获取通关进度和完整体力信息 await this.fetchGameData(); return true; } catch (err) { console.error('[AuthManager] 登录异常:', err); return false; } } private async validateToken(): Promise { const gameData = await this._fetchGameData(); if (!gameData) return false; this._userId = gameData.user.id; this._isLoggedIn = true; StorageManager.setStamina(gameData.user.stamina); this._completedLevelIds = gameData.completedLevelIds; this._completedLevelCount = this._resolveCompletedLevelCount(gameData); console.log(`[AuthManager] Token 验证成功,体力: ${gameData.user.stamina.current}/${gameData.user.stamina.max},已完成: ${this._completedLevelCount} 关`); return true; } /** * 登录成功后获取游戏数据(体力 + 通关进度) */ private async fetchGameData(): Promise { const gameData = await this._fetchGameData(); if (gameData) { this._completedLevelIds = gameData.completedLevelIds; this._completedLevelCount = this._resolveCompletedLevelCount(gameData); StorageManager.setStamina(gameData.user.stamina); } } /** * 从服务端获取游戏数据(共用方法) */ private async _fetchGameData(): Promise { try { const response = await HttpUtil.get>( API_ENDPOINTS.USER_GAME_DATA, API_TIMEOUT.SHORT ); return (response.success && response.data) ? response.data : null; } catch { console.warn('[AuthManager] 获取游戏数据失败'); return null; } } private _resolveCompletedLevelCount(gameData: GameData): number { return gameData.completedLevelCount ?? gameData.completedLevelIds.length; } }