fix(mp): 导航/请求健壮性 — reLaunch 去重 + 失败降级
- navigateToLogin 添加去重 + reLaunch 失败降级 redirectTo - request.ts safeReLaunch 添加目标页检测 + 失败降级 - 退出登录 reLaunch 失败降级 redirectTo - DoctorTabBar / 首页医生端跳转 reLaunch 失败降级 - 网络恢复时正确清理 toast 状态和定时器
This commit is contained in:
@@ -27,7 +27,9 @@ export default function DoctorTabBar({ active }: DoctorTabBarProps) {
|
|||||||
|
|
||||||
const handleTab = (tab: TabItem) => {
|
const handleTab = (tab: TabItem) => {
|
||||||
if (tab.key === activeKey) return;
|
if (tab.key === activeKey) return;
|
||||||
Taro.reLaunch({ url: tab.url });
|
Taro.reLaunch({ url: tab.url }).catch(() => {
|
||||||
|
Taro.redirectTo({ url: tab.url }).catch(() => {});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -370,7 +370,8 @@ export default function Index() {
|
|||||||
url: target,
|
url: target,
|
||||||
fail: () => {
|
fail: () => {
|
||||||
redirectingRef.current = false;
|
redirectingRef.current = false;
|
||||||
console.warn('跳转医生端失败,停留患者首页');
|
console.warn('跳转医生端失败,降级为 redirectTo');
|
||||||
|
Taro.redirectTo({ url: target }).catch(() => {});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const OFFLINE_MAX_MS = 30_000;
|
|||||||
let offlineDetectedAt = 0;
|
let offlineDetectedAt = 0;
|
||||||
let offlineSuppressMs = OFFLINE_SUPPRESS_MS;
|
let offlineSuppressMs = OFFLINE_SUPPRESS_MS;
|
||||||
let networkToastShown = false;
|
let networkToastShown = false;
|
||||||
|
let networkToastTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
let consecutiveNetErrors = 0;
|
let consecutiveNetErrors = 0;
|
||||||
|
|
||||||
function isOffline(): boolean {
|
function isOffline(): boolean {
|
||||||
@@ -44,7 +45,8 @@ function markOffline(): void {
|
|||||||
if (!networkToastShown) {
|
if (!networkToastShown) {
|
||||||
networkToastShown = true;
|
networkToastShown = true;
|
||||||
Taro.showToast({ title: '网络异常,请检查连接', icon: 'none', duration: 2000 });
|
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;
|
offlineDetectedAt = 0;
|
||||||
offlineSuppressMs = OFFLINE_SUPPRESS_MS;
|
offlineSuppressMs = OFFLINE_SUPPRESS_MS;
|
||||||
consecutiveNetErrors = 0;
|
consecutiveNetErrors = 0;
|
||||||
|
if (networkToastTimer) { clearTimeout(networkToastTimer); networkToastTimer = null; }
|
||||||
|
networkToastShown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function safeGet(key: string): string {
|
function safeGet(key: string): string {
|
||||||
@@ -157,9 +161,15 @@ async function doRefresh(): Promise<boolean> {
|
|||||||
let reLaunchPromise: Promise<void> | null = null;
|
let reLaunchPromise: Promise<void> | null = null;
|
||||||
|
|
||||||
function safeReLaunch(url: string): void {
|
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;
|
if (reLaunchPromise) return;
|
||||||
reLaunchPromise = Taro.reLaunch({ url }).then(() => {}, (err) => {
|
reLaunchPromise = Taro.reLaunch({ url }).then(() => {}, (err) => {
|
||||||
console.warn('[request] reLaunch failed:', err);
|
console.warn('[request] reLaunch failed:', err);
|
||||||
|
// reLaunch 失败时降级为 redirectTo
|
||||||
|
Taro.redirectTo({ url }).catch(() => {});
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
setTimeout(() => { reLaunchPromise = null; }, 2000);
|
setTimeout(() => { reLaunchPromise = null; }, 2000);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -293,6 +293,9 @@ export const useAuthStore = create<AuthState>((set, get) => ({
|
|||||||
});
|
});
|
||||||
resetAllStores();
|
resetAllStores();
|
||||||
set({ user: null, roles: [], currentPatient: null, patients: [] });
|
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(() => {});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -3,8 +3,26 @@ import Taro from '@tarojs/taro';
|
|||||||
const LOGIN_PAGE = '/pages/login/index';
|
const LOGIN_PAGE = '/pages/login/index';
|
||||||
const MAX_PAGE_STACK = 9;
|
const MAX_PAGE_STACK = 9;
|
||||||
|
|
||||||
|
// reLaunch 去重:避免 401 + 并发请求同时触发多个 reLaunch
|
||||||
|
let reLaunchPromise: Promise<void> | null = null;
|
||||||
|
|
||||||
export function navigateToLogin() {
|
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 {
|
export function safeNavigateTo(url: string): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user