casualroom/apps/fenghuo/web/components/articles/article-table.tsx

118 lines
4.0 KiB
TypeScript
Raw Normal View History

2025-07-28 07:50:50 +08:00
import { Checkbox } from '@nice/ui/components/checkbox';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@nice/ui/components/table';
import { Skeleton } from '@nice/ui/components/skeleton';
import { IconFileText } from '@tabler/icons-react';
import { ArticleRow } from './article-row';
import { ArticleQuickEdit } from './article-quick-edit';
import { useArticlesContext } from './context';
import React from 'react';
interface ArticleTableProps {
hasFilters?: boolean; // 是否有筛选条件,用于显示不同的空状态信息
}
// 新增骨架屏组件
function ArticleTableSkeleton() {
return (
<>
{Array.from({ length: 5 }).map((_, i) => (
<TableRow key={i} className="border-b-0">
<TableCell>
<Skeleton className="h-4 w-4" />
</TableCell>
<TableCell>
<div className="space-y-2">
<Skeleton className="h-4 w-64" />
<Skeleton className="h-3 w-48" />
</div>
</TableCell>
<TableCell>
<Skeleton className="h-6 w-20 rounded-full" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-24" />
</TableCell>
<TableCell>
<Skeleton className="h-8 w-8 rounded-full" />
</TableCell>
<TableCell>
<div className="space-y-2">
<Skeleton className="h-3 w-24" />
<Skeleton className="h-3 w-16" />
</div>
</TableCell>
<TableCell>
<div className="space-y-2">
<Skeleton className="h-3 w-24" />
<Skeleton className="h-3 w-16" />
</div>
</TableCell>
<TableCell>
<div className="flex justify-center gap-2">
<Skeleton className="h-7 w-7" />
<Skeleton className="h-7 w-7" />
</div>
</TableCell>
</TableRow>
))}
</>
);
}
export function ArticleTable({ hasFilters = false }: ArticleTableProps) {
const { articles, selectedArticles, quickEditId, handleSelectAll, isLoading } = useArticlesContext();
const isAllSelected = articles.length > 0 && articles.every((article) => selectedArticles.includes(article.id));
return (
<div className="overflow-auto flex-1">
<Table>
<TableHeader className="bg-muted/30 sticky top-0 z-10">
<TableRow className="border-b border-border hover:bg-transparent">
<TableHead className="w-12 py-4">
<Checkbox checked={isAllSelected} onCheckedChange={handleSelectAll} />
</TableHead>
<TableHead className="w-[45%] py-4 font-semibold"></TableHead>
<TableHead className="py-4 font-semibold"></TableHead>
<TableHead className="py-4 font-semibold"></TableHead>
<TableHead className="py-4 font-semibold"></TableHead>
<TableHead className="py-4 font-semibold"></TableHead>
<TableHead className="py-4 font-semibold"></TableHead>
<TableHead className="w-24 py-4 font-semibold text-center"></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{isLoading ? (
<ArticleTableSkeleton />
) : articles.length > 0 ? (
articles.map((article) => (
<React.Fragment key={article.id}>
<ArticleRow article={article} />
{quickEditId === article.id && <ArticleQuickEdit article={article} />}
</React.Fragment>
))
) : (
<TableRow>
<TableCell colSpan={8} className="h-64 text-center">
<div className="flex flex-col items-center gap-3">
<div className="w-16 h-16 bg-muted/20 rounded-full flex items-center justify-center">
<IconFileText className="h-8 w-8 text-muted-foreground/50" />
</div>
<div className="space-y-1">
<div className="text-sm font-medium text-muted-foreground">
{hasFilters ? '没有找到符合条件的文章' : '还没有文章'}
</div>
<div className="text-xs text-muted-foreground">
{hasFilters ? '请尝试调整搜索条件' : '点击"新建文章"开始创作吧'}
</div>
</div>
</div>
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
);
}