Files
leaudit-platform-frontend/app/components/ui/SkeletonScreen.tsx
T

129 lines
3.7 KiB
TypeScript

// import React from 'react';
interface SkeletonBarProps {
width?: string;
height?: string;
className?: string;
}
// 基础骨架条
export function SkeletonBar({ width = 'w-full', height = 'h-5', className = '' }: SkeletonBarProps) {
return (
<div className={`${width} ${height} bg-gray-200 rounded-md animate-pulse ${className}`}></div>
);
}
// 通用骨架屏
export function SkeletonScreen() {
return (
<div className="flex flex-col gap-4">
<SkeletonBar height="h-10" />
<SkeletonBar height="h-10" />
<SkeletonBar height="h-10" />
</div>
);
}
// 数字统计骨架
export function NumberSkeleton({ className = '' }: { className?: string }) {
return (
<SkeletonBar width="w-12" height="h-5" className={className} />
);
}
// 表格行骨架屏
interface TableRowSkeletonProps {
count?: number;
className?: string;
}
export function TableRowSkeleton({ count = 5, className = '' }: TableRowSkeletonProps) {
return (
<div className={`py-2 ${className}`}>
{Array(count).fill(0).map((_, index) => (
<div key={index} className="flex items-center p-4 border-b border-gray-100">
<div className="w-[30%] flex">
<SkeletonBar width="w-10" height="h-10" />
<div className="ml-2">
<SkeletonBar width="w-48" className="mb-2" />
<SkeletonBar width="w-32" height="h-3" />
</div>
</div>
<div className="w-[12%]">
<SkeletonBar width="w-20" height="h-6" />
</div>
<div className="w-[12%]">
<SkeletonBar width="w-24" className="mb-1" />
<SkeletonBar width="w-16" height="h-3" />
</div>
<div className="w-[12%]">
<SkeletonBar width="w-16" height="h-5" className="mb-1" />
<SkeletonBar width="w-16" height="h-5" />
</div>
<div className="w-[20%]">
<SkeletonBar width="w-32" className="mb-1" />
<SkeletonBar width="w-24" />
</div>
<div className="w-[14%]">
<SkeletonBar width="w-16" height="h-8" />
</div>
</div>
))}
</div>
);
}
// 自定义列宽的表格行骨架屏
interface CustomTableRowSkeletonProps {
count?: number;
columns: Array<{
width: string;
rows?: Array<{
width: string;
height?: string;
className?: string;
}>;
}>;
className?: string;
}
export function CustomTableRowSkeleton({ count = 5, columns, className = '' }: CustomTableRowSkeletonProps) {
return (
<div className={`py-2 ${className}`}>
{Array(count).fill(0).map((_, rowIndex) => (
<div key={rowIndex} className="flex items-center p-4 border-b border-gray-100">
{columns.map((column, colIndex) => (
<div key={colIndex} className={`${column.width}`}>
{column.rows ? (
column.rows.map((row, rowIdx) => (
<SkeletonBar
key={rowIdx}
width={row.width}
height={row.height || 'h-4'}
className={`${rowIdx < column.rows!.length - 1 ? 'mb-1' : ''} ${row.className || ''}`}
/>
))
) : (
<SkeletonBar width="w-full" />
)}
</div>
))}
</div>
))}
</div>
);
}
// 加载指示器
export function LoadingIndicator({ text = '正在加载数据...' }: { text?: string }) {
return (
<div className="py-4 flex justify-center items-center">
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-green-700 mr-2"></div>
<span className="text-sm text-gray-500">{text}</span>
</div>
);
}