// 登录与用户态管理:封装 wx.login + 后端 /api/auth/login。 // 后端在首次登录时自动创建用户;开发模式(未配置 WX_APPID)接受任意 code // 并返回稳定的虚拟 openid。 const { request, setUnauthorizedHandler } = require('./request'); const TOKEN_KEY = 'access_token'; const OPENID_KEY = 'openid'; const PROFILE_KEY = 'user_profile'; // 模块加载时注册 401 自动重新登录:成功后返回新的 token,失败返回 null。 setUnauthorizedHandler(async () => { try { await login(); return wx.getStorageSync(TOKEN_KEY); } catch (e) { return null; } }); function login() { return new Promise((resolve, reject) => { wx.login({ success(res) { const code = res.code || 'tourist'; request({ url: '/api/auth/login', method: 'POST', data: { code } }) .then((r) => { const token = r.token; const user = r.user || {}; wx.setStorageSync(TOKEN_KEY, token); if (user.openid) wx.setStorageSync(OPENID_KEY, user.openid); const profile = { nickname: user.nickname || '', avatar: user.avatar || '' }; wx.setStorageSync(PROFILE_KEY, profile); resolve(profile); }) .catch((err) => { wx.showToast({ title: '登录失败,请重试', icon: 'none' }); reject(err); }); }, fail() { // 拿不到 code 时降级为游客 code request({ url: '/api/auth/login', method: 'POST', data: { code: 'tourist' } }) .then((r) => { const token = r.token; const user = r.user || {}; wx.setStorageSync(TOKEN_KEY, token); if (user.openid) wx.setStorageSync(OPENID_KEY, user.openid); const profile = { nickname: user.nickname || '', avatar: user.avatar || '' }; wx.setStorageSync(PROFILE_KEY, profile); resolve(profile); }) .catch((err) => { wx.showToast({ title: '登录失败,请重试', icon: 'none' }); reject(err); }); } }); }); } // 确保已登录:有 token 直接返回,否则执行登录。 async function ensureLogin() { const token = getToken(); if (token) return token; await login(); return getToken(); } function getToken() { return wx.getStorageSync(TOKEN_KEY) || ''; } function getProfile() { return wx.getStorageSync(PROFILE_KEY) || { nickname: '', avatar: '' }; } function isLogin() { return !!getToken(); } function logout() { wx.removeStorageSync(TOKEN_KEY); wx.removeStorageSync(OPENID_KEY); wx.removeStorageSync(PROFILE_KEY); } function setProfile(p) { const profile = Object.assign({}, getProfile(), p || {}); wx.setStorageSync(PROFILE_KEY, profile); return profile; } // 更新昵称 / 头像,写回后端并刷新本地状态。 function updateProfile(dto) { return request({ url: '/api/users/me', method: 'PATCH', data: dto }) .then((user) => { const profile = { nickname: (user && user.nickname) || getProfile().nickname, avatar: (user && user.avatar) || getProfile().avatar }; wx.setStorageSync(PROFILE_KEY, profile); return profile; }); } module.exports = { login, ensureLogin, getToken, getProfile, isLogin, logout, setProfile, updateProfile };