hookehuyr

fix(user): 修复冷启动时接口抢在登录态前请求的竞态问题

- 新增 waitForLoginStatusReady 方法供外部等待登录态就绪
- checkLoginStatus 使用 Promise 缓存避免并发重复调用
- 首页 fetchHotArticles 调用前等待登录态初始化完成
- 清除首页残留的导航栏标题配置

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 /* 1 /*
2 * @Date: 2025-06-28 10:33:00 2 * @Date: 2025-06-28 10:33:00
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2026-01-30 10:07:28 4 + * @LastEditTime: 2026-05-28 17:28:54
5 * @FilePath: /manulife-weapp/src/app.config.js 5 * @FilePath: /manulife-weapp/src/app.config.js
6 * @Description: 小程序配置文件 6 * @Description: 小程序配置文件
7 */ 7 */
...@@ -57,7 +57,7 @@ export default { ...@@ -57,7 +57,7 @@ export default {
57 window: { 57 window: {
58 backgroundTextStyle: 'light', 58 backgroundTextStyle: 'light',
59 navigationBarBackgroundColor: '#fff', 59 navigationBarBackgroundColor: '#fff',
60 - navigationBarTitleText: '西园寺预约', 60 + navigationBarTitleText: '',
61 navigationBarTextStyle: 'black', 61 navigationBarTextStyle: 'black',
62 }, 62 },
63 // 开发环境开启调试模式 63 // 开发环境开启调试模式
......
...@@ -355,6 +355,10 @@ const hotArticlesLoading = ref(false); ...@@ -355,6 +355,10 @@ const hotArticlesLoading = ref(false);
355 const fetchHotArticles = async () => { 355 const fetchHotArticles = async () => {
356 try { 356 try {
357 hotArticlesLoading.value = true; 357 hotArticlesLoading.value = true;
358 +
359 + // 冷启动时先等登录态初始化完成,避免 week_hot 抢在 session 建立前发出请求
360 + await userStore.waitForLoginStatusReady();
361 +
358 const res = await weekHotAPI({ 362 const res = await weekHotAPI({
359 page: 0, 363 page: 0,
360 limit: 10 364 limit: 10
......
...@@ -29,9 +29,15 @@ export const useUserStore = defineStore('user', () => { ...@@ -29,9 +29,15 @@ export const useUserStore = defineStore('user', () => {
29 /** 加载状态 */ 29 /** 加载状态 */
30 const loading = ref(false) 30 const loading = ref(false)
31 31
32 + /** 登录态是否已经完成过首次检查 */
33 + const loginStatusChecked = ref(false)
34 +
32 /** 上次获取用户信息的时间戳(用于防抖) */ 35 /** 上次获取用户信息的时间戳(用于防抖) */
33 let lastFetchTime = 0 36 let lastFetchTime = 0
34 37
38 + /** 进行中的登录态检查 Promise,用于并发复用 */
39 + let loginStatusPromise = null
40 +
35 /** 防抖时间间隔(毫秒) */ 41 /** 防抖时间间隔(毫秒) */
36 const FETCH_DEBOUNCE_TIME = 5000 42 const FETCH_DEBOUNCE_TIME = 5000
37 43
...@@ -48,6 +54,11 @@ export const useUserStore = defineStore('user', () => { ...@@ -48,6 +54,11 @@ export const useUserStore = defineStore('user', () => {
48 * await userStore.checkLoginStatus() 54 * await userStore.checkLoginStatus()
49 */ 55 */
50 async function checkLoginStatus() { 56 async function checkLoginStatus() {
57 + if (loginStatusPromise) {
58 + return loginStatusPromise
59 + }
60 +
61 + loginStatusPromise = (async () => {
51 loading.value = true 62 loading.value = true
52 63
53 try { 64 try {
...@@ -83,6 +94,27 @@ export const useUserStore = defineStore('user', () => { ...@@ -83,6 +94,27 @@ export const useUserStore = defineStore('user', () => {
83 throw err 94 throw err
84 } finally { 95 } finally {
85 loading.value = false 96 loading.value = false
97 + loginStatusChecked.value = true
98 + loginStatusPromise = null
99 + }
100 + })()
101 +
102 + return loginStatusPromise
103 + }
104 +
105 + /**
106 + * 等待登录态初始化完成
107 + * @description 冷启动时复用 App.onLaunch 的登录态检查,避免页面抢跑请求
108 + * @returns {Promise<void>}
109 + */
110 + async function waitForLoginStatusReady() {
111 + if (loginStatusPromise) {
112 + await loginStatusPromise
113 + return
114 + }
115 +
116 + if (!loginStatusChecked.value) {
117 + await checkLoginStatus()
86 } 118 }
87 } 119 }
88 120
...@@ -235,12 +267,14 @@ export const useUserStore = defineStore('user', () => { ...@@ -235,12 +267,14 @@ export const useUserStore = defineStore('user', () => {
235 isOpenid, 267 isOpenid,
236 isLoggedIn, 268 isLoggedIn,
237 loading, 269 loading,
270 + loginStatusChecked,
238 271
239 // 计算属性 272 // 计算属性
240 tabBarBadges, 273 tabBarBadges,
241 274
242 // 方法 275 // 方法
243 checkLoginStatus, 276 checkLoginStatus,
277 + waitForLoginStatusReady,
244 fetchUserInfo, 278 fetchUserInfo,
245 login, 279 login,
246 logout 280 logout
......