/** * 识糖小课堂独立登录适配层。复用主小程序账号,但不依赖 tongji 其他页面代码。 */ export function useGameAuth(proxy) { let loginPromise = null function hasToken() { return !!String(uni.getStorageSync('token') || '').trim() } function clearToken() { uni.removeStorageSync('token') } function wxLoginCode() { return new Promise((resolve, reject) => { uni.login({ provider: 'weixin', success: (res) => res?.code ? resolve(res.code) : reject(new Error('微信登录未返回 code')), fail: reject }) }) } async function loginWithCode(code) { const res = await proxy.apiUrl({ url: '/api/login/mnpLogin', method: 'POST', data: { code } }, false) if (res?.code !== 1 || !res.data?.token) { clearToken() throw new Error(res?.msg || '登录失败') } uni.setStorageSync('token', res.data.token) uni.setStorageSync('userData', res.data) return true } async function verifyOrLogin() { if (hasToken()) { try { const res = await proxy.apiUrl({ url: '/api/user/info', method: 'POST' }, false) if (res?.code === 1 && res.data) { uni.setStorageSync('userData', res.data) return true } // 只有明确的登录失效才重新换取 token;其他业务错误先保留原登录。 if (res?.code !== -1) return true } catch (_) { // 断网不清除仍可能有效的 token,成绩由离线队列稍后补传。 return true } clearToken() } const code = await wxLoginCode() return loginWithCode(code) } async function ensureLoggedIn() { if (loginPromise) return loginPromise loginPromise = verifyOrLogin() .then(ok => !!ok) .catch(() => false) // 只合并同时发生的登录;成功结果不能永久缓存,否则 token 过期后无法恢复。 .finally(() => { loginPromise = null }) return loginPromise } return { ensureLoggedIn } }