/** * 用户数据管理器 */ import { get, post, del } from '../utils/http'; export default class UserManager { constructor() { this.userId = null; this.openid = null; this.nickname = ''; this.avatarUrl = ''; this.token = ''; this.isLoggedIn = false; } /** * 检查是否已登录(只检查本地缓存) * @returns {boolean} 是否已登录 */ checkLogin() { const cached = wx.getStorageSync('userInfo'); if (cached && cached.userId && cached.token) { this.userId = cached.userId; this.openid = cached.openid; this.nickname = cached.nickname || '游客'; this.avatarUrl = cached.avatarUrl || ''; this.token = cached.token; this.isLoggedIn = true; return true; } return false; } /** * 初始化用户(只恢复缓存,不自动登录) */ async init() { // 只检查本地缓存,不自动登录 this.checkLogin(); } /** * 执行登录(供登录按钮调用) * @param {Object} userInfo - 微信用户信息(头像、昵称等),可选 */ async doLogin(userInfo = null) { try { // 获取登录code const { code } = await this.wxLogin(); // 调用后端登录接口,传入用户信息 const result = await post('/user/login', { code, userInfo: userInfo ? { nickname: userInfo.nickName, avatarUrl: userInfo.avatarUrl, gender: userInfo.gender || 0 } : null }); this.userId = result.userId; this.openid = result.openid; // 优先使用后端返回的,其次用授权获取的 this.nickname = result.nickname || (userInfo?.nickName) || '游客'; this.avatarUrl = result.avatarUrl || (userInfo?.avatarUrl) || ''; this.token = result.token || ''; this.isLoggedIn = true; // 缓存用户信息(包含 token) wx.setStorageSync('userInfo', { userId: this.userId, openid: this.openid, nickname: this.nickname, avatarUrl: this.avatarUrl, token: this.token }); return { userId: this.userId, nickname: this.nickname, avatarUrl: this.avatarUrl }; } catch (error) { console.error('登录失败:', error); throw error; } } /** * 退出登录 */ logout() { this.userId = null; this.openid = null; this.nickname = ''; this.avatarUrl = ''; this.token = ''; this.isLoggedIn = false; wx.removeStorageSync('userInfo'); } /** * 更新用户资料 */ async updateProfile(nickname, avatarUrl) { if (!this.isLoggedIn) return false; try { await post('/user/profile', { nickname, avatarUrl, gender: 0 }, { params: { userId: this.userId } }); // 更新本地数据 this.nickname = nickname; this.avatarUrl = avatarUrl; // 更新缓存(保留 token) wx.setStorageSync('userInfo', { userId: this.userId, openid: this.openid, nickname: this.nickname, avatarUrl: this.avatarUrl, token: this.token }); return true; } catch (e) { console.error('更新资料失败:', e); return false; } } /** * 微信登录(带超时) */ wxLogin() { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error('登录超时')); }, 5000); wx.login({ success: (res) => { clearTimeout(timeout); if (res.code) { resolve(res); } else { reject(new Error('获取code失败')); } }, fail: (err) => { clearTimeout(timeout); reject(err); } }); }); } /** * 获取用户游玩进度 */ async getProgress(storyId = null) { if (!this.isLoggedIn) return null; return await get('/user/progress', { userId: this.userId, storyId }); } /** * 保存用户进度 */ async saveProgress(storyId, currentNodeKey, isCompleted = false, endingReached = '') { if (!this.isLoggedIn) return; await post('/user/progress', { userId: this.userId, storyId, currentNodeKey, isCompleted, endingReached }); } /** * 点赞故事 */ async likeStory(storyId, isLiked) { if (!this.isLoggedIn) return; await post('/user/like', { userId: this.userId, storyId, isLiked }); } /** * 收藏故事 */ async collectStory(storyId, isCollected) { if (!this.isLoggedIn) return; await post('/user/collect', { userId: this.userId, storyId, isCollected }); } /** * 获取收藏列表 */ async getCollections() { if (!this.isLoggedIn) return []; return await get('/user/collections', { userId: this.userId }); } /** * 获取最近游玩的故事 */ async getRecentPlayed() { if (!this.isLoggedIn) return []; try { return await get('/user/recent-played', { userId: this.userId, limit: 10 }); } catch (e) { return []; } } /** * 获取AI创作历史 */ async getAIHistory() { if (!this.isLoggedIn) return []; try { return await get('/user/ai-history', { userId: this.userId, limit: 20 }); } catch (e) { return []; } } /** * 获取AI配额 */ async getAIQuota() { if (!this.isLoggedIn) return { daily: 3, used: 0, purchased: 0 }; try { return await get('/user/ai-quota', { userId: this.userId }); } catch (e) { return { daily: 3, used: 0, purchased: 0 }; } } /** * 获取我的作品 */ async getMyWorks() { if (!this.isLoggedIn) return []; try { return await get('/user/my-works', { userId: this.userId }); } catch (e) { return []; } } /** * 获取草稿箱 */ async getDrafts() { if (!this.isLoggedIn) return []; try { return await get('/user/drafts', { userId: this.userId }); } catch (e) { return []; } } // ========== 游玩记录相关 ========== /** * 保存游玩记录 */ async savePlayRecord(storyId, endingName, endingType, pathHistory) { if (!this.isLoggedIn) return null; try { return await post('/user/play-record', { userId: this.userId, storyId, endingName, endingType: endingType || '', pathHistory: pathHistory || [] }); } catch (e) { console.error('保存游玩记录失败:', e); return null; } } /** * 获取游玩记录列表 * @param {number} storyId - 可选,指定故事ID获取该故事的所有记录 */ async getPlayRecords(storyId = null) { if (!this.isLoggedIn) return []; try { const params = { userId: this.userId }; if (storyId) params.storyId = storyId; return await get('/user/play-records', params); } catch (e) { console.error('获取游玩记录失败:', e); return []; } } /** * 获取单条记录详情 */ async getPlayRecordDetail(recordId) { if (!this.isLoggedIn) return null; try { return await get(`/user/play-records/${recordId}`); } catch (e) { console.error('获取记录详情失败:', e); return null; } } // 删除游玩记录 async deletePlayRecord(recordId) { if (!this.isLoggedIn) return false; try { await del(`/user/play-records/${recordId}`); return true; } catch (e) { console.error('删除记录失败:', e); return false; } } }