App({ globalData: { token: "", user: null, expiresAt: 0 }, onLaunch() { this.globalData.token = wx.getStorageSync("pet_token") || ""; this.globalData.expiresAt = Number(wx.getStorageSync("pet_token_expires_at")) || 0; // Start immediately; pages await the same promise and display failures themselves. this.login().catch(() => {}); }, async login() { if (this.loginPromise) return this.loginPromise; if (this.globalData.token && (!this.globalData.expiresAt || this.globalData.expiresAt > Date.now() / 1000 + 60)) return this.globalData.token; this.loginPromise = (async () => { const { request } = require("./utils/api"); const refreshToken = wx.getStorageSync("pet_refresh_token"); if (refreshToken) { try { const pair = await request("/auth/refresh", "POST", { refresh_token: refreshToken }, false); return this.saveSession(pair); } catch (error) { if (error.status !== 401 && error.status !== 403) throw error; wx.removeStorageSync("pet_refresh_token"); } } const { code } = await new Promise((resolve, reject) => wx.login({ timeout: 10000, success: resolve, fail: () => reject(new Error("暂时无法连接微信,请重新连接")), }), ); if (!code) throw new Error("微信登录未取得凭证,请重新连接"); const data = await request("/auth/login", "POST", { code }, false); this.globalData.user = data.user; return this.saveSession(data); })().finally(() => { this.loginPromise = null; }); return this.loginPromise; }, saveSession(data) { if (!data || typeof data.token !== "string" || !data.token) throw new Error("登录未完成,请重新连接"); this.globalData.token = data.token; this.globalData.expiresAt = Number(data.expires_at) || 0; wx.setStorageSync("pet_token", data.token); wx.setStorageSync("pet_token_expires_at", this.globalData.expiresAt); if (data.refresh_token) wx.setStorageSync("pet_refresh_token", data.refresh_token); return data.token; }, });