diff --git a/easyflow-ui-admin/app/src/router/guard.ts b/easyflow-ui-admin/app/src/router/guard.ts index cdb309a..9db1514 100644 --- a/easyflow-ui-admin/app/src/router/guard.ts +++ b/easyflow-ui-admin/app/src/router/guard.ts @@ -1,20 +1,22 @@ -import type { Router } from 'vue-router'; +import type {Router} from 'vue-router'; -import { LOGIN_PATH } from '@easyflow/constants'; -import { preferences } from '@easyflow/preferences'; -import { useAccessStore, useUserStore } from '@easyflow/stores'; -import { startProgress, stopProgress } from '@easyflow/utils'; +import {LOGIN_PATH} from '@easyflow/constants'; +import {preferences} from '@easyflow/preferences'; +import {useAccessStore, useUserStore} from '@easyflow/stores'; +import {startProgress, stopProgress} from '@easyflow/utils'; -import { accessRoutes, coreRouteNames } from '#/router/routes'; -import { useAuthStore } from '#/store'; +import {accessRoutes, coreRouteNames} from '#/router/routes'; +import {useAuthStore} from '#/store'; -import { generateAccess } from './access'; +import {generateAccess} from './access'; interface NetworkConnectionLike { effectiveType?: string; saveData?: boolean; } +const CHUNK_ERROR_RELOAD_KEY = '__easyflow_chunk_error_reload_path__'; + function isSlowNetworkConnection() { if (typeof navigator === 'undefined') { return false; @@ -35,6 +37,46 @@ function isSlowNetworkConnection() { return ['2g', '3g', 'slow-2g'].includes(connection.effectiveType ?? ''); } +function isDynamicImportChunkError(error: unknown) { + const message = String((error as Error | undefined)?.message ?? error ?? ''); + if (!message) { + return false; + } + return ( + /Loading chunk/i.test(message) || + /Importing a module script failed/i.test(message) || + /Failed to fetch dynamically imported module/i.test(message) || + /dynamically imported module/i.test(message) + ); +} + +function setupChunkErrorGuard(router: Router) { + router.onError((error, to) => { + if (!isDynamicImportChunkError(error)) { + return; + } + const fullPath = to?.fullPath; + if (!fullPath) { + return; + } + + const lastReloadPath = sessionStorage.getItem(CHUNK_ERROR_RELOAD_KEY); + if (lastReloadPath === fullPath) { + sessionStorage.removeItem(CHUNK_ERROR_RELOAD_KEY); + return; + } + sessionStorage.setItem(CHUNK_ERROR_RELOAD_KEY, fullPath); + window.location.assign(fullPath); + }); + + router.isReady().finally(() => { + const reloadedPath = sessionStorage.getItem(CHUNK_ERROR_RELOAD_KEY); + if (reloadedPath && router.currentRoute.value.fullPath === reloadedPath) { + sessionStorage.removeItem(CHUNK_ERROR_RELOAD_KEY); + } + }); +} + function shouldUseRouteProgress() { if (preferences.transition.progress) { return true; @@ -61,10 +103,11 @@ function setupCommonGuard(router: Router) { return true; }); - router.afterEach((to) => { + router.afterEach((to, _from, failure) => { // 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行 - - loadedPaths.add(to.path); + if (!failure) { + loadedPaths.add(to.path); + } // 关闭页面加载进度条 if (shouldUseRouteProgress()) { @@ -161,6 +204,8 @@ function createRouterGuard(router: Router) { setupCommonGuard(router); /** 权限访问 */ setupAccessGuard(router); + /** chunk加载错误兜底 */ + setupChunkErrorGuard(router); } export { createRouterGuard }; diff --git a/easyflow-ui-admin/packages/effects/layouts/src/basic/content/content.vue b/easyflow-ui-admin/packages/effects/layouts/src/basic/content/content.vue index 056a009..8a42b0f 100644 --- a/easyflow-ui-admin/packages/effects/layouts/src/basic/content/content.vue +++ b/easyflow-ui-admin/packages/effects/layouts/src/basic/content/content.vue @@ -1,17 +1,16 @@