110 lines
3.9 KiB
TypeScript
110 lines
3.9 KiB
TypeScript
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; |