import { useCallback, useEffect, useState } from "react" import { useReactTable, getCoreRowModel, flexRender, } from "@tanstack/react-table" import { Plus } from "lucide-react" import { Button } from "@/components/ui/button" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { CategoryFormDialog } from "@/components/category/CategoryFormDialog" import { DeleteCategoryDialog } from "@/components/category/DeleteCategoryDialog" import { getColumns } from "@/components/category/columns" import { fetchCategories, createCategory, updateCategory, deleteCategory, } from "@/lib/api/category-api" import type { Category, CategoryFormData } from "@/types/category" const PAGE_SIZE = 20 export default function CategoriesPage() { const [categories, setCategories] = useState([]) const [loading, setLoading] = useState(true) const [total, setTotal] = useState(0) const [page, setPage] = useState(1) // 对话框状态 const [formOpen, setFormOpen] = useState(false) const [editingCategory, setEditingCategory] = useState(null) const [deleteOpen, setDeleteOpen] = useState(false) const [deletingCategory, setDeletingCategory] = useState(null) const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE)) const loadCategories = useCallback(async () => { setLoading(true) try { const res = await fetchCategories({ page, limit: PAGE_SIZE, }) setCategories(res.data) setTotal(res.pagination.total) } catch { setCategories([]) setTotal(0) } finally { setLoading(false) } }, [page]) useEffect(() => { loadCategories() }, [loadCategories]) // 新建 / 编辑提交 async function handleFormSubmit(data: CategoryFormData) { if (editingCategory) { await updateCategory(editingCategory.id, data) } else { await createCategory(data) } await loadCategories() } // 删除提交 async function handleDelete() { if (!deletingCategory) return await deleteCategory(deletingCategory.id) setDeleteOpen(false) setDeletingCategory(null) await loadCategories() } // 打开编辑对话框 function openEdit(category: Category) { setEditingCategory(category) setFormOpen(true) } // 打开新建对话框 function openCreate() { setEditingCategory(null) setFormOpen(true) } // 打开删除对话框 function openDelete(category: Category) { setDeletingCategory(category) setDeleteOpen(true) } const columns = getColumns({ onEdit: openEdit, onDelete: openDelete, }) const table = useReactTable({ data: categories, columns, getCoreRowModel: getCoreRowModel(), }) return (
{/* 页面头部 */}

分类管理

{/* 表格 */}
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )} ))} ))} {loading ? ( 加载中... ) : categories.length === 0 ? ( 暂无分类数据 ) : ( table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext() )} ))} )) )}
{/* 分页 */} {totalPages > 1 && (
共 {total} 条,第 {page}/{totalPages} 页
)} {/* 对话框 */}
) }