70 lines
2.0 KiB
TypeScript
70 lines
2.0 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
||
import { AlertCircle, Loader2 } from 'lucide-react';
|
||
|
||
interface RouteLoadingProps {
|
||
timeout?: number; // 超时时间(毫秒),默认10秒
|
||
}
|
||
|
||
/**
|
||
* 路由懒加载时的加载组件
|
||
*
|
||
* 功能:
|
||
* 1. 显示加载动画(使用 shadcn 风格)
|
||
* 2. 超时检测
|
||
* 3. 提供重试机制
|
||
* 4. 优化用户体验
|
||
*/
|
||
const RouteLoading: React.FC<RouteLoadingProps> = ({ timeout = 10000 }) => {
|
||
const [isTimeout, setIsTimeout] = useState(false);
|
||
|
||
useEffect(() => {
|
||
// 设置超时检测
|
||
const timer = setTimeout(() => {
|
||
setIsTimeout(true);
|
||
}, timeout);
|
||
|
||
return () => clearTimeout(timer);
|
||
}, [timeout]);
|
||
|
||
const handleReload = () => {
|
||
window.location.reload();
|
||
};
|
||
|
||
if (isTimeout) {
|
||
return (
|
||
<div className="flex min-h-[400px] flex-col items-center justify-center p-8">
|
||
<div className="text-center">
|
||
<div className="mb-4 flex justify-center">
|
||
<AlertCircle className="h-12 w-12 text-amber-500" />
|
||
</div>
|
||
<h3 className="mb-2 text-lg font-semibold text-slate-800">
|
||
加载时间过长
|
||
</h3>
|
||
<p className="mb-6 text-slate-600">
|
||
页面加载超时,可能是网络问题。
|
||
</p>
|
||
<button
|
||
onClick={handleReload}
|
||
className="rounded-md bg-blue-600 px-6 py-2 text-white transition-colors hover:bg-blue-700"
|
||
>
|
||
重新加载
|
||
</button>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className="flex min-h-[400px] flex-col items-center justify-center">
|
||
{/* ✅ 使用 shadcn 风格的 loading(lucide-react 图标) */}
|
||
<Loader2 className="h-12 w-12 animate-spin text-blue-600" />
|
||
<div className="mt-6 text-center text-slate-500">
|
||
<p className="text-base">正在加载页面</p>
|
||
<p className="mt-2 text-sm">请稍候...</p>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default RouteLoading;
|