feat: 订单列表支持分页查询,分页大小可选 20/50/100

- /api/orders/my 新增 page/page_size 参数,返回分页信息和全局状态统计
- 用户订单页:分页控件(首/上/下/末页)+ 分页大小选择,摘要卡片改为全局统计
- 管理员订单页:分页大小选择器(20/50/100)+ 首尾页跳转按钮
This commit is contained in:
erio
2026-03-01 20:04:49 +08:00
parent e4005da38e
commit 292c14b882
3 changed files with 210 additions and 70 deletions

View File

@@ -43,6 +43,7 @@ function AdminContent() {
const [orders, setOrders] = useState<AdminOrder[]>([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(20);
const [totalPages, setTotalPages] = useState(1);
const [statusFilter, setStatusFilter] = useState('');
const [loading, setLoading] = useState(true);
@@ -54,7 +55,7 @@ function AdminContent() {
if (!token) return;
setLoading(true);
try {
const params = new URLSearchParams({ token, page: String(page), page_size: '20' });
const params = new URLSearchParams({ token, page: String(page), page_size: String(pageSize) });
if (statusFilter) params.set('status', statusFilter);
const res = await fetch(`/api/admin/orders?${params}`);
@@ -75,7 +76,7 @@ function AdminContent() {
} finally {
setLoading(false);
}
}, [token, page, statusFilter]);
}, [token, page, pageSize, statusFilter]);
useEffect(() => {
fetchOrders();
@@ -198,14 +199,36 @@ function AdminContent() {
</div>
{/* Pagination */}
{totalPages > 1 && (
<div className="mt-4 flex items-center justify-between text-sm text-gray-500">
<span> {total} </span>
<div className="flex gap-2">
<div className="mt-4 flex flex-wrap items-center justify-between gap-3 text-sm text-gray-500">
<div className="flex items-center gap-2">
<span> {total} </span>
{[20, 50, 100].map((s) => (
<button
key={s}
onClick={() => { setPageSize(s); setPage(1); }}
className={`rounded border px-2.5 py-1 text-xs font-medium transition-colors ${
pageSize === s
? 'border-blue-500 bg-blue-50 text-blue-700'
: 'border-gray-300 text-gray-600 hover:bg-gray-100'
}`}
>
{s}
</button>
))}
</div>
{totalPages > 1 && (
<div className="flex items-center gap-1.5">
<button
onClick={() => setPage(1)}
disabled={page <= 1}
className="rounded border px-2.5 py-1 disabled:opacity-40 hover:bg-gray-100"
>
««
</button>
<button
onClick={() => setPage((p) => Math.max(1, p - 1))}
disabled={page <= 1}
className="rounded border px-3 py-1 disabled:opacity-50"
className="rounded border px-3 py-1 disabled:opacity-40 hover:bg-gray-100"
>
</button>
@@ -215,13 +238,20 @@ function AdminContent() {
<button
onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
disabled={page >= totalPages}
className="rounded border px-3 py-1 disabled:opacity-50"
className="rounded border px-3 py-1 disabled:opacity-40 hover:bg-gray-100"
>
</button>
<button
onClick={() => setPage(totalPages)}
disabled={page >= totalPages}
className="rounded border px-2.5 py-1 disabled:opacity-40 hover:bg-gray-100"
>
»»
</button>
</div>
</div>
)}
)}
</div>
{/* Order Detail */}
{detailOrder && <OrderDetail order={detailOrder} onClose={() => setDetailOrder(null)} />}