perf: prefetch ai pages and soften route loading
This commit is contained in:
@@ -13,6 +13,7 @@ import { normalizeHomePath } from '#/utils/legacy-home';
|
|||||||
|
|
||||||
import { generateAccess } from './access';
|
import { generateAccess } from './access';
|
||||||
import { isLightTabRoute } from './light-menu';
|
import { isLightTabRoute } from './light-menu';
|
||||||
|
import { prefetchAiPlatformPages } from './prefetch';
|
||||||
|
|
||||||
function filterLightTabHistory<T extends { tabs?: unknown[] }>(history: T) {
|
function filterLightTabHistory<T extends { tabs?: unknown[] }>(history: T) {
|
||||||
const tabs = Array.isArray(history.tabs) ? history.tabs : [];
|
const tabs = Array.isArray(history.tabs) ? history.tabs : [];
|
||||||
@@ -197,6 +198,7 @@ function setupAccessGuard(router: Router) {
|
|||||||
accessStore.setAccessMenus(accessibleMenus);
|
accessStore.setAccessMenus(accessibleMenus);
|
||||||
accessStore.setAccessRoutes(accessibleRoutes);
|
accessStore.setAccessRoutes(accessibleRoutes);
|
||||||
accessStore.setIsAccessChecked(true);
|
accessStore.setIsAccessChecked(true);
|
||||||
|
prefetchAiPlatformPages();
|
||||||
|
|
||||||
// 子应用根路径重定向(/app/hr -> /app/hr/xxx)
|
// 子应用根路径重定向(/app/hr -> /app/hr/xxx)
|
||||||
if (appContextStore.isSubApp) {
|
if (appContextStore.isSubApp) {
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
type IdleCallbackHandle = number;
|
||||||
|
|
||||||
|
type IdleCallbackOptions = {
|
||||||
|
timeout?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type WindowWithIdleCallback = Window & {
|
||||||
|
requestIdleCallback?: (
|
||||||
|
callback: () => void,
|
||||||
|
options?: IdleCallbackOptions,
|
||||||
|
) => IdleCallbackHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
let prefetched = false;
|
||||||
|
|
||||||
|
const prefetchTasks = [
|
||||||
|
() => import('#/views/ai-platform/agent/index.vue'),
|
||||||
|
() => import('#/views/_core/agent-chat/index.vue'),
|
||||||
|
() => import('#/views/ai-platform/workflow/index.vue'),
|
||||||
|
() => import('#/views/ai-platform/workflow-runs/index.vue'),
|
||||||
|
() => import('#/views/ai-platform/model/index.vue'),
|
||||||
|
() => import('#/views/ai-platform/knowledge/index.vue'),
|
||||||
|
];
|
||||||
|
|
||||||
|
function scheduleIdle(callback: () => void) {
|
||||||
|
const browserWindow = window as WindowWithIdleCallback;
|
||||||
|
|
||||||
|
if (browserWindow.requestIdleCallback) {
|
||||||
|
browserWindow.requestIdleCallback(callback, { timeout: 3000 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setTimeout(callback, 1200);
|
||||||
|
}
|
||||||
|
|
||||||
|
function prefetchAiPlatformPages() {
|
||||||
|
if (prefetched || typeof window === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefetched = true;
|
||||||
|
scheduleIdle(() => {
|
||||||
|
void Promise.allSettled(prefetchTasks.map((task) => task()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export { prefetchAiPlatformPages };
|
||||||
@@ -5,41 +5,73 @@ import { preferences } from '@vben/preferences';
|
|||||||
|
|
||||||
function useContentSpinner() {
|
function useContentSpinner() {
|
||||||
const spinning = ref(false);
|
const spinning = ref(false);
|
||||||
const startTime = ref(0);
|
const visibleStartTime = ref(0);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const minShowTime = 500; // 最小显示时间
|
const showDelay = 220;
|
||||||
|
const minVisibleTime = 160;
|
||||||
const enableLoading = computed(() => preferences.transition.loading);
|
const enableLoading = computed(() => preferences.transition.loading);
|
||||||
|
let pending = false;
|
||||||
|
let showTimer: ReturnType<typeof setTimeout> | undefined;
|
||||||
|
let hideTimer: ReturnType<typeof setTimeout> | undefined;
|
||||||
|
|
||||||
// 结束加载动画
|
const clearTimers = () => {
|
||||||
const onEnd = () => {
|
clearTimeout(showTimer);
|
||||||
|
clearTimeout(hideTimer);
|
||||||
|
showTimer = undefined;
|
||||||
|
hideTimer = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onStart = () => {
|
||||||
if (!enableLoading.value) {
|
if (!enableLoading.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const processTime = performance.now() - startTime.value;
|
|
||||||
if (processTime < minShowTime) {
|
pending = true;
|
||||||
setTimeout(() => {
|
clearTimers();
|
||||||
|
showTimer = setTimeout(() => {
|
||||||
|
if (!pending) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
visibleStartTime.value = performance.now();
|
||||||
|
spinning.value = true;
|
||||||
|
}, showDelay);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEnd = () => {
|
||||||
|
pending = false;
|
||||||
|
clearTimeout(showTimer);
|
||||||
|
showTimer = undefined;
|
||||||
|
|
||||||
|
if (!enableLoading.value || !spinning.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const visibleTime = performance.now() - visibleStartTime.value;
|
||||||
|
if (visibleTime < minVisibleTime) {
|
||||||
|
hideTimer = setTimeout(() => {
|
||||||
spinning.value = false;
|
spinning.value = false;
|
||||||
}, minShowTime - processTime);
|
hideTimer = undefined;
|
||||||
|
}, minVisibleTime - visibleTime);
|
||||||
} else {
|
} else {
|
||||||
spinning.value = false;
|
spinning.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 路由前置守卫
|
|
||||||
router.beforeEach((to) => {
|
router.beforeEach((to) => {
|
||||||
if (to.meta.loaded || !enableLoading.value || to.meta.iframeSrc) {
|
if (to.meta.loaded || !enableLoading.value || to.meta.iframeSrc) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
startTime.value = performance.now();
|
|
||||||
spinning.value = true;
|
onStart();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 路由后置守卫
|
|
||||||
router.afterEach((to) => {
|
router.afterEach((to) => {
|
||||||
if (to.meta.loaded || !enableLoading.value || to.meta.iframeSrc) {
|
if (to.meta.loaded || !enableLoading.value || to.meta.iframeSrc) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnd();
|
onEnd();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user