// 路由页面代码模块加载失败的自愈处理。 // Vite 重启/依赖预构建刷新、发布后旧分包失效时,页面首次 import 会失败, // 稍后重试或整页刷新即可恢复,不需要用户手动按 F5。 const CHUNK_LOAD_ERROR = /Failed to fetch dynamically imported module|Importing a module script failed|Loading chunk .* failed|Outdated Optimize Dep/i export function isChunkLoadError(error) { if (!error) return false return CHUNK_LOAD_ERROR.test(error.message || String(error)) } export async function importWithRetry(loader, retries = 2, delay = 500) { for (let attempt = 0; ; attempt++) { try { return await loader() } catch (error) { if (attempt >= retries || !isChunkLoadError(error)) throw error await new Promise(resolve => setTimeout(resolve, delay * 2 ** attempt)) } } } const RELOAD_STATE_KEY = 'lims-chunk-load-reload' const RELOAD_WINDOW = 60 * 1000 const RELOAD_LIMIT = 3 // 重试后仍失败则自动整页刷新;60 秒内最多 3 次,避免真正故障时无限刷新。 export function autoReloadForChunkError() { const now = Date.now() let state = null try { state = JSON.parse(sessionStorage.getItem(RELOAD_STATE_KEY) || 'null') } catch (e) { state = null } if (!state || now - state.first > RELOAD_WINDOW) { state = { first: now, count: 0 } } if (state.count >= RELOAD_LIMIT) return false state.count += 1 try { sessionStorage.setItem(RELOAD_STATE_KEY, JSON.stringify(state)) } catch (e) { // 隐私模式等存储不可用时忽略,不影响刷新 } setTimeout(() => window.location.reload(), 500) return true }