From 1a376a255d909d0931afa88408963dcd127d3628 Mon Sep 17 00:00:00 2001 From: iven Date: Mon, 25 May 2026 13:45:12 +0800 Subject: [PATCH] =?UTF-8?q?fix(mp):=20=E5=AF=BC=E8=88=AA/=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=81=A5=E5=A3=AE=E6=80=A7=20=E2=80=94=20reLaunch=20?= =?UTF-8?q?=E5=8E=BB=E9=87=8D=20+=20=E5=A4=B1=E8=B4=A5=E9=99=8D=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - navigateToLogin 添加去重 + reLaunch 失败降级 redirectTo - request.ts safeReLaunch 添加目标页检测 + 失败降级 - 退出登录 reLaunch 失败降级 redirectTo - DoctorTabBar / 首页医生端跳转 reLaunch 失败降级 - 网络恢复时正确清理 toast 状态和定时器 --- .../src/components/ui/DoctorTabBar/index.tsx | 4 +++- apps/miniprogram/src/pages/index/index.tsx | 3 ++- apps/miniprogram/src/services/request.ts | 12 ++++++++++- apps/miniprogram/src/stores/auth.ts | 5 ++++- apps/miniprogram/src/utils/navigate.ts | 20 ++++++++++++++++++- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/apps/miniprogram/src/components/ui/DoctorTabBar/index.tsx b/apps/miniprogram/src/components/ui/DoctorTabBar/index.tsx index d0103e9..ec3d935 100644 --- a/apps/miniprogram/src/components/ui/DoctorTabBar/index.tsx +++ b/apps/miniprogram/src/components/ui/DoctorTabBar/index.tsx @@ -27,7 +27,9 @@ export default function DoctorTabBar({ active }: DoctorTabBarProps) { const handleTab = (tab: TabItem) => { if (tab.key === activeKey) return; - Taro.reLaunch({ url: tab.url }); + Taro.reLaunch({ url: tab.url }).catch(() => { + Taro.redirectTo({ url: tab.url }).catch(() => {}); + }); }; return ( diff --git a/apps/miniprogram/src/pages/index/index.tsx b/apps/miniprogram/src/pages/index/index.tsx index aeea7f4..58ec65d 100644 --- a/apps/miniprogram/src/pages/index/index.tsx +++ b/apps/miniprogram/src/pages/index/index.tsx @@ -370,7 +370,8 @@ export default function Index() { url: target, fail: () => { redirectingRef.current = false; - console.warn('跳转医生端失败,停留患者首页'); + console.warn('跳转医生端失败,降级为 redirectTo'); + Taro.redirectTo({ url: target }).catch(() => {}); }, }); } diff --git a/apps/miniprogram/src/services/request.ts b/apps/miniprogram/src/services/request.ts index 5deb21c..3585464 100644 --- a/apps/miniprogram/src/services/request.ts +++ b/apps/miniprogram/src/services/request.ts @@ -30,6 +30,7 @@ const OFFLINE_MAX_MS = 30_000; let offlineDetectedAt = 0; let offlineSuppressMs = OFFLINE_SUPPRESS_MS; let networkToastShown = false; +let networkToastTimer: ReturnType | null = null; let consecutiveNetErrors = 0; function isOffline(): boolean { @@ -44,7 +45,8 @@ function markOffline(): void { if (!networkToastShown) { networkToastShown = true; Taro.showToast({ title: '网络异常,请检查连接', icon: 'none', duration: 2000 }); - setTimeout(() => { networkToastShown = false; }, offlineSuppressMs); + if (networkToastTimer) clearTimeout(networkToastTimer); + networkToastTimer = setTimeout(() => { networkToastShown = false; networkToastTimer = null; }, offlineSuppressMs); } } @@ -52,6 +54,8 @@ function clearOffline(): void { offlineDetectedAt = 0; offlineSuppressMs = OFFLINE_SUPPRESS_MS; consecutiveNetErrors = 0; + if (networkToastTimer) { clearTimeout(networkToastTimer); networkToastTimer = null; } + networkToastShown = false; } function safeGet(key: string): string { @@ -157,9 +161,15 @@ async function doRefresh(): Promise { let reLaunchPromise: Promise | null = null; function safeReLaunch(url: string): void { + // 已在目标页,跳过(防止 DevTools reLaunch bug) + const pages = Taro.getCurrentPages(); + const currentPath = pages[pages.length - 1]?.path || ''; + if (currentPath.includes('pages/login')) return; if (reLaunchPromise) return; reLaunchPromise = Taro.reLaunch({ url }).then(() => {}, (err) => { console.warn('[request] reLaunch failed:', err); + // reLaunch 失败时降级为 redirectTo + Taro.redirectTo({ url }).catch(() => {}); }).then(() => { setTimeout(() => { reLaunchPromise = null; }, 2000); }); diff --git a/apps/miniprogram/src/stores/auth.ts b/apps/miniprogram/src/stores/auth.ts index f141d86..159db24 100644 --- a/apps/miniprogram/src/stores/auth.ts +++ b/apps/miniprogram/src/stores/auth.ts @@ -293,6 +293,9 @@ export const useAuthStore = create((set, get) => ({ }); resetAllStores(); set({ user: null, roles: [], currentPatient: null, patients: [] }); - Taro.reLaunch({ url: '/pages/index/index' }); + Taro.reLaunch({ url: '/pages/index/index' }).catch((err) => { + console.warn('[auth] reLaunch after logout failed:', err); + Taro.redirectTo({ url: '/pages/index/index' }).catch(() => {}); + }); }, })); diff --git a/apps/miniprogram/src/utils/navigate.ts b/apps/miniprogram/src/utils/navigate.ts index 69e39bc..8872738 100644 --- a/apps/miniprogram/src/utils/navigate.ts +++ b/apps/miniprogram/src/utils/navigate.ts @@ -3,8 +3,26 @@ import Taro from '@tarojs/taro'; const LOGIN_PAGE = '/pages/login/index'; const MAX_PAGE_STACK = 9; +// reLaunch 去重:避免 401 + 并发请求同时触发多个 reLaunch +let reLaunchPromise: Promise | null = null; + export function navigateToLogin() { - Taro.reLaunch({ url: LOGIN_PAGE }); + // 已在登录页,跳过 + const pages = Taro.getCurrentPages(); + const currentPath = pages[pages.length - 1]?.path || ''; + if (currentPath.includes('pages/login')) return; + + // 去重:上一个 reLaunch 还没完成就跳过 + if (reLaunchPromise) return; + reLaunchPromise = Taro.reLaunch({ url: LOGIN_PAGE }) + .catch((err) => { + console.warn('[navigate] reLaunch to login failed:', err); + // reLaunch 失败时降级为 redirectTo + Taro.redirectTo({ url: LOGIN_PAGE }).catch(() => {}); + }) + .then(() => { + setTimeout(() => { reLaunchPromise = null; }, 2000); + }); } export function safeNavigateTo(url: string): void {