页面加载的平滑效果添加
This commit is contained in:
parent
09478a1b58
commit
a4729f7b5c
@ -36,7 +36,7 @@ export default defineConfig({
|
||||
baseNavigator: true,
|
||||
},
|
||||
dynamicImport: {
|
||||
loading: '@/components/PageLoading/index',
|
||||
loading: '@/components/SmartLoading/index',
|
||||
},
|
||||
targets: {
|
||||
ie: 11,
|
||||
|
||||
17
src/app.ts
17
src/app.ts
@ -7,6 +7,7 @@
|
||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
*/
|
||||
import globalState from './globalState';
|
||||
import { routePreloader } from './utils/routePreloader';
|
||||
|
||||
// import { getMicroAppRouteComponent } from 'umi';
|
||||
|
||||
@ -29,6 +30,22 @@ export const qiankun = {
|
||||
}
|
||||
|
||||
|
||||
// 应用启动时的初始化配置
|
||||
export async function getInitialState() {
|
||||
// 预加载关键路由以优化首屏加载
|
||||
setTimeout(() => {
|
||||
routePreloader.preloadCriticalRoutes().then(() => {
|
||||
console.log('关键路由预加载完成');
|
||||
}).catch(error => {
|
||||
console.warn('关键路由预加载失败:', error);
|
||||
});
|
||||
}, 1000); // 延迟1秒后开始预加载,避免影响首屏渲染
|
||||
|
||||
return {
|
||||
preloadEnabled: true,
|
||||
};
|
||||
}
|
||||
|
||||
// export const patchRoutes = ({ routes }: any) => {
|
||||
// console.info('routes', routes);
|
||||
// routes[0].routes[1].routes[0].routes.forEach((item: any, index: number) => {
|
||||
|
||||
65
src/components/LoadingExample/index.tsx
Normal file
65
src/components/LoadingExample/index.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { Button, Space, Card } from 'antd';
|
||||
import SkeletonLoading from '../SkeletonLoading';
|
||||
import SmartLoading from '../SmartLoading';
|
||||
|
||||
/**
|
||||
* 加载组件使用示例
|
||||
* 展示不同场景下的骨架屏效果
|
||||
*/
|
||||
const LoadingExample: React.FC = () => {
|
||||
return (
|
||||
<div style={{ padding: 24 }}>
|
||||
<h2>加载组件示例</h2>
|
||||
|
||||
<Space direction="vertical" size="large" style={{ width: '100%' }}>
|
||||
{/* 页面级骨架屏 */}
|
||||
<Card title="页面级骨架屏" size="small">
|
||||
<div style={{ height: 400, overflow: 'hidden' }}>
|
||||
<SkeletonLoading type="page" />
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 表格骨架屏 */}
|
||||
<Card title="表格骨架屏" size="small">
|
||||
<div style={{ height: 300, overflow: 'hidden' }}>
|
||||
<SkeletonLoading type="table" rows={5} />
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 表单骨架屏 */}
|
||||
<Card title="表单骨架屏" size="small">
|
||||
<div style={{ height: 300, overflow: 'hidden' }}>
|
||||
<SkeletonLoading type="form" rows={4} />
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 卡片网格骨架屏 */}
|
||||
<Card title="卡片网格骨架屏" size="small">
|
||||
<div style={{ height: 300, overflow: 'hidden' }}>
|
||||
<SkeletonLoading type="card" rows={4} />
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 智能加载组件 */}
|
||||
<Card title="智能加载组件(根据路由自动选择)" size="small">
|
||||
<div style={{ height: 200, overflow: 'hidden' }}>
|
||||
<SmartLoading />
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 在Suspense中使用 */}
|
||||
<Card title="在Suspense中使用" size="small">
|
||||
<Suspense fallback={<SkeletonLoading type="page" />}>
|
||||
<div style={{ padding: 20, textAlign: 'center' }}>
|
||||
<h3>这里是延迟加载的内容</h3>
|
||||
<p>骨架屏会在内容加载完成后自动消失</p>
|
||||
</div>
|
||||
</Suspense>
|
||||
</Card>
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoadingExample;
|
||||
7
src/components/PageLoading/index.less
Normal file
7
src/components/PageLoading/index.less
Normal file
@ -0,0 +1,7 @@
|
||||
.page-loading-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
}
|
||||
@ -1,5 +1,13 @@
|
||||
import { PageLoading } from '@ant-design/pro-layout';
|
||||
// import { PageLoading } from '@ant-design/pro-layout';
|
||||
|
||||
// loading components from code split
|
||||
// https://umijs.org/plugin/umi-plugin-react.html#dynamicimport
|
||||
export default PageLoading;
|
||||
// // loading components from code split
|
||||
// // https://umijs.org/plugin/umi-plugin-react.html#dynamicimport
|
||||
// export default PageLoading;
|
||||
import React from 'react';
|
||||
import SkeletonLoading from '../SkeletonLoading';
|
||||
|
||||
const PageLoading: React.FC = () => {
|
||||
return <SkeletonLoading type="page" />;
|
||||
};
|
||||
|
||||
export default PageLoading;
|
||||
163
src/components/SkeletonLoading/index.less
Normal file
163
src/components/SkeletonLoading/index.less
Normal file
@ -0,0 +1,163 @@
|
||||
.skeleton-page-container {
|
||||
padding: 24px;
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
|
||||
.skeleton-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
padding: 16px 24px;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
|
||||
.skeleton-header-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.skeleton-content {
|
||||
.skeleton-filter-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
padding: 16px 24px;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.skeleton-table-card {
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.skeleton-table-container {
|
||||
padding: 16px;
|
||||
|
||||
.skeleton-table-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.skeleton-table-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #f9f9f9;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.skeleton-card-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 16px;
|
||||
padding: 16px;
|
||||
|
||||
.skeleton-card {
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
}
|
||||
|
||||
.skeleton-form-container {
|
||||
padding: 24px;
|
||||
|
||||
.skeleton-form-title {
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.skeleton-form-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.skeleton-form-label {
|
||||
width: 120px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.skeleton-form-control {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.skeleton-form-actions {
|
||||
margin-top: 32px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
// 骨架屏动画优化
|
||||
.ant-skeleton-element {
|
||||
.ant-skeleton-input {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.ant-skeleton-button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式设计
|
||||
@media (max-width: 768px) {
|
||||
.skeleton-page-container {
|
||||
padding: 12px;
|
||||
|
||||
.skeleton-header {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
align-items: stretch;
|
||||
|
||||
.skeleton-header-actions {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.skeleton-content {
|
||||
.skeleton-filter-bar {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
align-items: stretch;
|
||||
|
||||
.ant-skeleton-input {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.skeleton-card-container {
|
||||
grid-template-columns: 1fr;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.skeleton-form-container {
|
||||
padding: 12px;
|
||||
|
||||
.skeleton-form-row {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
|
||||
.skeleton-form-label {
|
||||
width: 100%;
|
||||
margin-right: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
110
src/components/SkeletonLoading/index.tsx
Normal file
110
src/components/SkeletonLoading/index.tsx
Normal file
@ -0,0 +1,110 @@
|
||||
import React from 'react';
|
||||
import { Skeleton, Card } from 'antd';
|
||||
import './index.less';
|
||||
|
||||
interface SkeletonLoadingProps {
|
||||
type?: 'page' | 'table' | 'card' | 'form';
|
||||
rows?: number;
|
||||
}
|
||||
|
||||
const SkeletonLoading: React.FC<SkeletonLoadingProps> = ({
|
||||
type = 'page',
|
||||
rows = 3
|
||||
}) => {
|
||||
const renderPageSkeleton = () => (
|
||||
<div className="skeleton-page-container">
|
||||
<div className="skeleton-header">
|
||||
<Skeleton.Input style={{ width: 200, height: 32 }} active />
|
||||
<div className="skeleton-header-actions">
|
||||
<Skeleton.Button style={{ width: 80 }} active />
|
||||
<Skeleton.Button style={{ width: 80 }} active />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="skeleton-content">
|
||||
<div className="skeleton-filter-bar">
|
||||
<Skeleton.Input style={{ width: 150, marginRight: 16 }} active />
|
||||
<Skeleton.Input style={{ width: 150, marginRight: 16 }} active />
|
||||
<Skeleton.Button style={{ width: 60 }} active />
|
||||
</div>
|
||||
|
||||
<Card className="skeleton-table-card">
|
||||
<Skeleton active paragraph={{ rows: 6 }} />
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderTableSkeleton = () => (
|
||||
<div className="skeleton-table-container">
|
||||
<div className="skeleton-table-header">
|
||||
{Array.from({ length: 5 }).map((_, index) => (
|
||||
<Skeleton.Input
|
||||
key={index}
|
||||
style={{ width: `${Math.random() * 50 + 80}px`, marginRight: 16 }}
|
||||
active
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{Array.from({ length: rows }).map((_, index) => (
|
||||
<div key={index} className="skeleton-table-row">
|
||||
{Array.from({ length: 5 }).map((_, cellIndex) => (
|
||||
<Skeleton.Input
|
||||
key={cellIndex}
|
||||
style={{ width: `${Math.random() * 60 + 60}px`, marginRight: 16 }}
|
||||
active
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderCardSkeleton = () => (
|
||||
<div className="skeleton-card-container">
|
||||
{Array.from({ length: rows }).map((_, index) => (
|
||||
<Card key={index} className="skeleton-card">
|
||||
<Skeleton active avatar paragraph={{ rows: 2 }} />
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderFormSkeleton = () => (
|
||||
<div className="skeleton-form-container">
|
||||
<Card>
|
||||
<div className="skeleton-form-title">
|
||||
<Skeleton.Input style={{ width: 150 }} active />
|
||||
</div>
|
||||
{Array.from({ length: rows }).map((_, index) => (
|
||||
<div key={index} className="skeleton-form-row">
|
||||
<div className="skeleton-form-label">
|
||||
<Skeleton.Input style={{ width: 80 }} active />
|
||||
</div>
|
||||
<div className="skeleton-form-control">
|
||||
<Skeleton.Input style={{ width: '100%' }} active />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="skeleton-form-actions">
|
||||
<Skeleton.Button style={{ width: 80, marginRight: 8 }} active />
|
||||
<Skeleton.Button style={{ width: 80 }} active />
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
|
||||
switch (type) {
|
||||
case 'table':
|
||||
return renderTableSkeleton();
|
||||
case 'card':
|
||||
return renderCardSkeleton();
|
||||
case 'form':
|
||||
return renderFormSkeleton();
|
||||
case 'page':
|
||||
default:
|
||||
return renderPageSkeleton();
|
||||
}
|
||||
};
|
||||
|
||||
export default SkeletonLoading;
|
||||
68
src/components/SmartLoading/index.tsx
Normal file
68
src/components/SmartLoading/index.tsx
Normal file
@ -0,0 +1,68 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'umi';
|
||||
import SkeletonLoading from '../SkeletonLoading';
|
||||
import { routePreloader } from '@/utils/routePreloader';
|
||||
|
||||
interface SmartLoadingProps {
|
||||
fallback?: React.ReactNode;
|
||||
enablePreload?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能加载组件
|
||||
* 根据路由类型自动选择合适的骨架屏,并支持路由预加载
|
||||
*/
|
||||
const SmartLoading: React.FC<SmartLoadingProps> = ({
|
||||
fallback,
|
||||
enablePreload = true
|
||||
}) => {
|
||||
const location = useLocation();
|
||||
const [loadingType, setLoadingType] = useState<'page' | 'table' | 'form' | 'card'>('page');
|
||||
|
||||
useEffect(() => {
|
||||
// 根据路径判断页面类型,选择合适的骨架屏
|
||||
const path = location.pathname;
|
||||
|
||||
if (path.includes('list') || path.includes('table')) {
|
||||
setLoadingType('table');
|
||||
} else if (path.includes('form') || path.includes('edit') || path.includes('add')) {
|
||||
setLoadingType('form');
|
||||
} else if (path.includes('card') || path.includes('dashboard')) {
|
||||
setLoadingType('card');
|
||||
} else {
|
||||
setLoadingType('page');
|
||||
}
|
||||
|
||||
// 预加载相关路由
|
||||
if (enablePreload) {
|
||||
routePreloader.preloadBasedOnUserBehavior(path);
|
||||
}
|
||||
}, [location.pathname, enablePreload]);
|
||||
|
||||
// 如果提供了自定义fallback,使用它
|
||||
if (fallback) {
|
||||
return <>{fallback}</>;
|
||||
}
|
||||
|
||||
// 根据页面类型返回对应的骨架屏
|
||||
return <SkeletonLoading type={loadingType} rows={getRowsByType(loadingType)} />;
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据加载类型获取合适的行数
|
||||
*/
|
||||
function getRowsByType(type: string): number {
|
||||
switch (type) {
|
||||
case 'table':
|
||||
return 8; // 表格通常显示更多行
|
||||
case 'form':
|
||||
return 5; // 表单通常5-6个字段
|
||||
case 'card':
|
||||
return 6; // 卡片网格通常6个
|
||||
case 'page':
|
||||
default:
|
||||
return 4; // 默认4行
|
||||
}
|
||||
}
|
||||
|
||||
export default SmartLoading;
|
||||
@ -24,6 +24,51 @@ body {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
// 骨架屏优化样式
|
||||
.ant-skeleton {
|
||||
.ant-skeleton-content {
|
||||
|
||||
.ant-skeleton-title,
|
||||
.ant-skeleton-paragraph>li {
|
||||
background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 50%, #f2f2f2 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: loading 1.4s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-skeleton-avatar {
|
||||
background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 50%, #f2f2f2 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: loading 1.4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.ant-skeleton-input,
|
||||
.ant-skeleton-button {
|
||||
background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 50%, #f2f2f2 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: loading 1.4s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading {
|
||||
0% {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 页面切换动画优化
|
||||
.ant-layout-content {
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
|
||||
&.loading {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
list-style: none;
|
||||
|
||||
188
src/utils/routePreloader.ts
Normal file
188
src/utils/routePreloader.ts
Normal file
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* 路由预加载工具
|
||||
* 优化首屏加载和用户体验
|
||||
*/
|
||||
|
||||
interface PreloadOptions {
|
||||
delay?: number; // 延迟预加载时间(ms)
|
||||
priority?: 'high' | 'low' | 'auto'; // 预加载优先级
|
||||
onlyOnIdle?: boolean; // 仅在浏览器空闲时预加载
|
||||
}
|
||||
|
||||
class RoutePreloader {
|
||||
private preloadedRoutes = new Set<string>();
|
||||
private preloadPromises = new Map<string, Promise<any>>();
|
||||
|
||||
/**
|
||||
* 预加载指定路由
|
||||
* @param routePath 路由路径
|
||||
* @param importFunction 动态导入函数
|
||||
* @param options 预加载选项
|
||||
*/
|
||||
async preloadRoute(
|
||||
routePath: string,
|
||||
importFunction: () => Promise<any>,
|
||||
options: PreloadOptions = {}
|
||||
) {
|
||||
const { delay = 0, onlyOnIdle = true } = options;
|
||||
|
||||
// 避免重复预加载
|
||||
if (this.preloadedRoutes.has(routePath)) {
|
||||
return this.preloadPromises.get(routePath);
|
||||
}
|
||||
|
||||
const preloadPromise = new Promise<any>((resolve) => {
|
||||
const executePreload = () => {
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
const module = await importFunction();
|
||||
this.preloadedRoutes.add(routePath);
|
||||
resolve(module);
|
||||
} catch (error) {
|
||||
console.warn(`预加载路由失败: ${routePath}`, error);
|
||||
resolve(null);
|
||||
}
|
||||
}, delay);
|
||||
};
|
||||
|
||||
if (onlyOnIdle && 'requestIdleCallback' in window) {
|
||||
// 在浏览器空闲时执行预加载
|
||||
requestIdleCallback(executePreload, { timeout: 5000 });
|
||||
} else {
|
||||
executePreload();
|
||||
}
|
||||
});
|
||||
|
||||
this.preloadPromises.set(routePath, preloadPromise);
|
||||
return preloadPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量预加载路由
|
||||
* @param routes 路由配置数组
|
||||
*/
|
||||
async preloadRoutes(routes: Array<{
|
||||
path: string;
|
||||
import: () => Promise<any>;
|
||||
options?: PreloadOptions;
|
||||
}>) {
|
||||
const promises = routes.map(({ path, import: importFn, options }) =>
|
||||
this.preloadRoute(path, importFn, options)
|
||||
);
|
||||
|
||||
return Promise.allSettled(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* 预加载首屏关键路由
|
||||
*/
|
||||
async preloadCriticalRoutes() {
|
||||
const criticalRoutes = [
|
||||
{
|
||||
path: '/dashboard/analysis',
|
||||
import: () => import('@/pages/busniess/Analysis'),
|
||||
options: { priority: 'high' as const, delay: 100 }
|
||||
},
|
||||
{
|
||||
path: '/dashboard/workplace',
|
||||
import: () => import('@/pages/dashboard/workplace'),
|
||||
options: { priority: 'high' as const, delay: 200 }
|
||||
},
|
||||
{
|
||||
path: '/busniessproject/list',
|
||||
import: () => import('@/pages/BussinessProject/list'),
|
||||
options: { priority: 'high' as const, delay: 300 }
|
||||
}
|
||||
];
|
||||
|
||||
return this.preloadRoutes(criticalRoutes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于用户行为预加载路由
|
||||
* @param currentPath 当前路径
|
||||
*/
|
||||
async preloadBasedOnUserBehavior(currentPath: string) {
|
||||
// 根据当前页面预测用户可能访问的页面
|
||||
const predictions = this.getPredictedRoutes(currentPath);
|
||||
|
||||
const routesToPreload = predictions.map(path => ({
|
||||
path,
|
||||
import: () => this.getRouteImport(path),
|
||||
options: { priority: 'low' as const, delay: 1000, onlyOnIdle: true }
|
||||
}));
|
||||
|
||||
return this.preloadRoutes(routesToPreload);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当前路径预测用户可能访问的路由
|
||||
*/
|
||||
private getPredictedRoutes(currentPath: string): string[] {
|
||||
const routeMap: Record<string, string[]> = {
|
||||
'/dashboard/analysis': [
|
||||
'/busniessproject/list',
|
||||
'/dashboard/workplace',
|
||||
'/basicManage/brand'
|
||||
],
|
||||
'/busniessproject/list': [
|
||||
'/busniessproject/detail',
|
||||
'/contract/list',
|
||||
'/busniess/paymentConfirm'
|
||||
],
|
||||
'/basicManage/brand': [
|
||||
'/basicManage/serverpart',
|
||||
'/basicManage/merchants',
|
||||
'/basicManage/commodity'
|
||||
],
|
||||
// 可以根据实际业务流程继续添加
|
||||
};
|
||||
|
||||
return routeMap[currentPath] || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取路由对应的动态导入函数
|
||||
*/
|
||||
private async getRouteImport(path: string) {
|
||||
// 这里需要根据实际的路由映射来返回对应的import函数
|
||||
const routeImportMap: Record<string, () => Promise<any>> = {
|
||||
'/dashboard/analysis': () => import('@/pages/busniess/Analysis'),
|
||||
'/dashboard/workplace': () => import('@/pages/dashboard/workplace'),
|
||||
'/busniessproject/list': () => import('@/pages/BussinessProject/list'),
|
||||
'/busniessproject/detail': () => import('@/pages/BussinessProject/detail'),
|
||||
'/contract/list': () => import('@/pages/contract/list'),
|
||||
'/basicManage/brand': () => import('@/pages/basicManage/Brand'),
|
||||
'/basicManage/serverpart': () => import('@/pages/basicManage/Serverpart'),
|
||||
'/basicManage/merchants': () => import('@/pages/basicManage/Merchats'),
|
||||
'/basicManage/commodity': () => import('@/pages/basicManage/Commodity/list'),
|
||||
};
|
||||
|
||||
const importFn = routeImportMap[path];
|
||||
if (importFn) {
|
||||
return importFn();
|
||||
}
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理预加载缓存
|
||||
*/
|
||||
clearCache() {
|
||||
this.preloadedRoutes.clear();
|
||||
this.preloadPromises.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// 创建单例实例
|
||||
export const routePreloader = new RoutePreloader();
|
||||
|
||||
// 导出预加载钩子
|
||||
export const useRoutePreloader = () => {
|
||||
return {
|
||||
preloadRoute: routePreloader.preloadRoute.bind(routePreloader),
|
||||
preloadCriticalRoutes: routePreloader.preloadCriticalRoutes.bind(routePreloader),
|
||||
preloadBasedOnUserBehavior: routePreloader.preloadBasedOnUserBehavior.bind(routePreloader),
|
||||
};
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user