From d61a04befadcb809f3183bebf8780dd8f7dafb66 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Fri, 10 Jul 2026 16:05:27 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E5=90=8E=E5=8F=B0=20Table=20?= =?UTF-8?q?=E5=88=86=E9=A1=B5=EF=BC=9A=E5=B8=B8=E5=BC=80=2010/20/50/100=20?= =?UTF-8?q?=E6=9D=A1=E6=95=B0=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 admin-pagination 工具,标准列表与云触手记录分别配置 - 用户/审计等页补齐 showSizeChanger,避免 total≤50 时无法切换 - ConfigProvider 默认开启条数切换 --- apps/frontend/src/main.tsx | 6 ++ .../src/pages/admin/AdminAuditLogsPage.tsx | 12 ++- .../admin/AdminCloudtentaclesRecordsPage.tsx | 20 ++-- .../pages/admin/AdminKuaishouIndustryPage.tsx | 12 ++- .../src/pages/admin/AdminOrdersPage.tsx | 13 ++- .../src/pages/admin/AdminTasksPage.tsx | 13 ++- .../src/pages/admin/AdminUsersPage.tsx | 12 ++- .../platform/AdminPlatformFulfillmentPage.tsx | 5 +- .../admin/platform/AdminPlatformShopsPage.tsx | 15 +-- apps/frontend/src/utils/admin-pagination.ts | 93 +++++++++++++++++++ 10 files changed, 160 insertions(+), 41 deletions(-) create mode 100644 apps/frontend/src/utils/admin-pagination.ts diff --git a/apps/frontend/src/main.tsx b/apps/frontend/src/main.tsx index eaa672db..9df4ac25 100644 --- a/apps/frontend/src/main.tsx +++ b/apps/frontend/src/main.tsx @@ -21,6 +21,12 @@ ReactDOM.createRoot(document.getElementById('root')!).render( }} scroll={{ x: 980 }} - pagination={{ + pagination={buildAdminTablePagination({ current: data?.pagination.page || page, pageSize: data?.pagination.pageSize || pageSize, total: data?.pagination.total || 0, - showTotal: (total) => `共 ${total} 条`, onChange: (nextPage, nextPageSize) => { setSearchParams( cleanParams({ ...filters, page: nextPage, pageSize: nextPageSize }), ) }, - }} + })} /> diff --git a/apps/frontend/src/pages/admin/AdminCloudtentaclesRecordsPage.tsx b/apps/frontend/src/pages/admin/AdminCloudtentaclesRecordsPage.tsx index 9bceb1b0..3215b21e 100644 --- a/apps/frontend/src/pages/admin/AdminCloudtentaclesRecordsPage.tsx +++ b/apps/frontend/src/pages/admin/AdminCloudtentaclesRecordsPage.tsx @@ -31,6 +31,10 @@ import { } from '@/services/admin' import type { AdminCloudtentaclesDeliveryRecordItem } from '@/types/admin' import { getAdminToken } from '@/utils/admin-auth' +import { + buildCloudtentaclesTablePagination, + CLOUDTENTACLES_DEFAULT_PAGE_SIZE, +} from '@/utils/admin-pagination' import { formatAdminDateTime } from '@/utils/admin-time' type RecordSourceOption = { @@ -43,9 +47,6 @@ type RecordSourceOption = { type DateRangeValue = [Dayjs | null, Dayjs | null] | null -const DEFAULT_PAGE_SIZE = 100 -const PAGE_SIZE_OPTIONS = [100, 200, 500, 1000] - export default function AdminCloudtentaclesRecordsPage() { const [loading, setLoading] = useState(false) const [sourceLoading, setSourceLoading] = useState(false) @@ -54,7 +55,7 @@ export default function AdminCloudtentaclesRecordsPage() { const [platformOrderId, setPlatformOrderId] = useState('') const [dateRange, setDateRange] = useState(createDefaultDateRange()) const [page, setPage] = useState(1) - const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE) + const [pageSize, setPageSize] = useState(CLOUDTENTACLES_DEFAULT_PAGE_SIZE) const [total, setTotal] = useState(0) const [items, setItems] = useState([]) const [sourceOptions, setSourceOptions] = useState([]) @@ -256,9 +257,9 @@ export default function AdminCloudtentaclesRecordsPage() { setPlatformOrderId('') setDateRange(nextDateRange) setPage(1) - setPageSize(DEFAULT_PAGE_SIZE) + setPageSize(CLOUDTENTACLES_DEFAULT_PAGE_SIZE) void loadRecords(1, { - pageSize: DEFAULT_PAGE_SIZE, + pageSize: CLOUDTENTACLES_DEFAULT_PAGE_SIZE, platformOrderId: '', dateRange: nextDateRange, }) @@ -357,17 +358,14 @@ export default function AdminCloudtentaclesRecordsPage() { dataSource={items} size="small" scroll={{ x: 1450 }} - pagination={{ + pagination={buildCloudtentaclesTablePagination({ current: page, pageSize, total, - pageSizeOptions: PAGE_SIZE_OPTIONS, - showSizeChanger: true, - showTotal: (nextTotal) => `共 ${nextTotal} 条`, onChange: (nextPage, nextPageSize) => { void loadRecords(nextPage, { pageSize: nextPageSize }) }, - }} + })} locale={{ emptyText: loading ? '发货记录加载中' : '当前筛选条件下暂无发货记录' }} /> diff --git a/apps/frontend/src/pages/admin/AdminKuaishouIndustryPage.tsx b/apps/frontend/src/pages/admin/AdminKuaishouIndustryPage.tsx index 136c4cb1..5f5d04d7 100644 --- a/apps/frontend/src/pages/admin/AdminKuaishouIndustryPage.tsx +++ b/apps/frontend/src/pages/admin/AdminKuaishouIndustryPage.tsx @@ -48,6 +48,11 @@ import type { AdminKuaishouIndustryVoucherToolPayload, } from '@/types/admin' import { hasAdminRole } from '@/utils/admin-auth' +import { + ADMIN_DEFAULT_PAGE_SIZE, + buildAdminLocalTablePagination, + buildAdminTablePagination, +} from '@/utils/admin-pagination' import { formatAdminDateTime } from '@/utils/admin-time' import { stringifyDisplayJson } from '@/utils/date-time' @@ -594,13 +599,12 @@ export default function AdminKuaishouIndustryPage() { dataSource={vouchers} loading={voucherLoading} scroll={{ x: 1180 }} - pagination={{ + pagination={buildAdminTablePagination({ current: voucherFilters.page, pageSize: voucherFilters.pageSize, total: voucherTotal, - showSizeChanger: true, onChange: (page, pageSize) => loadVouchers({ page, pageSize }), - }} + })} /> @@ -757,7 +761,7 @@ export default function AdminKuaishouIndustryPage() { columns={refundColumns} dataSource={refundRows} scroll={{ x: 1120 }} - pagination={{ pageSize: 10 }} + pagination={buildAdminLocalTablePagination({ pageSize: ADMIN_DEFAULT_PAGE_SIZE })} style={{ marginTop: 16 }} /> diff --git a/apps/frontend/src/pages/admin/AdminOrdersPage.tsx b/apps/frontend/src/pages/admin/AdminOrdersPage.tsx index af2263eb..cc95f488 100644 --- a/apps/frontend/src/pages/admin/AdminOrdersPage.tsx +++ b/apps/frontend/src/pages/admin/AdminOrdersPage.tsx @@ -10,6 +10,11 @@ import StatusTag from '@/components/admin/StatusTag' import { fetchAdminOrders } from '@/services/admin' import type { AdminOrderListItem } from '@/types/admin' import { adminPayStatusOptions } from '@/utils/admin-options' +import { + ADMIN_DEFAULT_PAGE_SIZE, + buildAdminTablePagination, + resolveAdminPageSize, +} from '@/utils/admin-pagination' import { formatAdminDateTime } from '@/utils/admin-time' type OrderFilterForm = { @@ -22,7 +27,7 @@ export default function AdminOrdersPage() { const navigate = useNavigate() const [searchParams, setSearchParams] = useSearchParams() const page = Number(searchParams.get('page') || 1) || 1 - const pageSize = Number(searchParams.get('pageSize') || 20) || 20 + const pageSize = resolveAdminPageSize(searchParams.get('pageSize'), ADMIN_DEFAULT_PAGE_SIZE) const filters = { platformOrderId: searchParams.get('platformOrderId') || '', payStatus: searchParams.get('payStatus') || '', @@ -141,16 +146,14 @@ export default function AdminOrdersPage() { columns={columns} dataSource={data?.items || []} scroll={{ x: 900 }} - pagination={{ + pagination={buildAdminTablePagination({ current: data?.pagination.page || page, pageSize: data?.pagination.pageSize || pageSize, total: data?.pagination.total || 0, - showSizeChanger: true, - showTotal: (total) => `共 ${total} 条`, onChange: (nextPage, nextPageSize) => { setSearchParams(cleanParams({ ...filters, page: nextPage, pageSize: nextPageSize })) }, - }} + })} /> diff --git a/apps/frontend/src/pages/admin/AdminTasksPage.tsx b/apps/frontend/src/pages/admin/AdminTasksPage.tsx index 041eb6a1..710c51a7 100644 --- a/apps/frontend/src/pages/admin/AdminTasksPage.tsx +++ b/apps/frontend/src/pages/admin/AdminTasksPage.tsx @@ -24,6 +24,11 @@ import { import type { AdminTaskActionResponse, AdminTaskListItem } from '@/types/admin' import { hasAdminRole } from '@/utils/admin-auth' import { adminTaskStatusOptions } from '@/utils/admin-options' +import { + ADMIN_DEFAULT_PAGE_SIZE, + buildAdminTablePagination, + resolveAdminPageSize, +} from '@/utils/admin-pagination' import { formatAdminDateTime } from '@/utils/admin-time' type TaskFilterForm = { @@ -50,7 +55,7 @@ export default function AdminTasksPage() { const [actionLoadingId, setActionLoadingId] = useState(null) const [lastClaimUrl, setLastClaimUrl] = useState('') const page = Number(searchParams.get('page') || 1) || 1 - const pageSize = Number(searchParams.get('pageSize') || 20) || 20 + const pageSize = resolveAdminPageSize(searchParams.get('pageSize'), ADMIN_DEFAULT_PAGE_SIZE) const canManageTaskLifecycle = hasAdminRole('operator') const canCloseTasks = hasAdminRole('support') const filters = { @@ -397,16 +402,14 @@ export default function AdminTasksPage() { columns={columns} dataSource={data?.items || []} scroll={{ x: 1500 }} - pagination={{ + pagination={buildAdminTablePagination({ current: data?.pagination.page || page, pageSize: data?.pagination.pageSize || pageSize, total: data?.pagination.total || 0, - showSizeChanger: true, - showTotal: (total) => `共 ${total} 条`, onChange: (nextPage, nextPageSize) => { setSearchParams(cleanParams({ ...filters, page: nextPage, pageSize: nextPageSize })) }, - }} + })} /> diff --git a/apps/frontend/src/pages/admin/AdminUsersPage.tsx b/apps/frontend/src/pages/admin/AdminUsersPage.tsx index 0fb67488..f7379796 100644 --- a/apps/frontend/src/pages/admin/AdminUsersPage.tsx +++ b/apps/frontend/src/pages/admin/AdminUsersPage.tsx @@ -38,6 +38,11 @@ import { import type { AdminRole, AdminUserListItem } from '@/types/admin' import { getAdminUserId, hasAdminRole } from '@/utils/admin-auth' import { adminUserRoleOptions, adminUserStatusOptions } from '@/utils/admin-options' +import { + ADMIN_DEFAULT_PAGE_SIZE, + buildAdminTablePagination, + resolveAdminPageSize, +} from '@/utils/admin-pagination' import { formatAdminDateTime } from '@/utils/admin-time' type UserFilterForm = { @@ -68,7 +73,7 @@ export default function AdminUsersPage() { const [creating, setCreating] = useState(false) const [actionLoadingId, setActionLoadingId] = useState(null) const page = Number(searchParams.get('page') || 1) || 1 - const pageSize = Number(searchParams.get('pageSize') || 20) || 20 + const pageSize = resolveAdminPageSize(searchParams.get('pageSize'), ADMIN_DEFAULT_PAGE_SIZE) const filters = { username: searchParams.get('username') || '', role: searchParams.get('role') || '', @@ -407,15 +412,14 @@ export default function AdminUsersPage() { dataSource={data?.items || []} locale={{ emptyText: }} scroll={{ x: 1060 }} - pagination={{ + pagination={buildAdminTablePagination({ current: data?.pagination.page || page, pageSize: data?.pagination.pageSize || pageSize, total: data?.pagination.total || 0, - showTotal: (total) => `共 ${total} 条`, onChange: (nextPage, nextPageSize) => { setSearchParams(cleanParams({ ...filters, page: nextPage, pageSize: nextPageSize })) }, - }} + })} /> diff --git a/apps/frontend/src/pages/admin/platform/AdminPlatformFulfillmentPage.tsx b/apps/frontend/src/pages/admin/platform/AdminPlatformFulfillmentPage.tsx index bcdb8e23..e05cb852 100644 --- a/apps/frontend/src/pages/admin/platform/AdminPlatformFulfillmentPage.tsx +++ b/apps/frontend/src/pages/admin/platform/AdminPlatformFulfillmentPage.tsx @@ -55,6 +55,7 @@ import type { AdminKuaishouFeifeiProductRule, } from '@/types/admin' import { hasAdminRole } from '@/utils/admin-auth' +import { buildAdminLocalTablePagination } from '@/utils/admin-pagination' type EditableOverrideRule = Omit & { normalizedProductName?: string @@ -666,7 +667,7 @@ function KuaishouFeifeiFulfillmentPanel() { rowKey={(row) => row.id || `${row.productName}-${row.productCode}`} columns={columns} dataSource={rules} - pagination={{ pageSize: 20, showSizeChanger: true }} + pagination={buildAdminLocalTablePagination()} scroll={{ x: 920, y: 520 }} locale={{ emptyText: '暂无 kuaishou-feifei 商品映射' }} className="platform-section-gap" @@ -1170,7 +1171,7 @@ function KuaishouCloudFulfillmentPanel() { ), }, ]} - pagination={{ pageSize: 20, showSizeChanger: true }} + pagination={buildAdminLocalTablePagination()} scroll={{ x: 1000, y: 420 }} locale={{ emptyText: '当前账号暂无可展示商品' }} /> diff --git a/apps/frontend/src/pages/admin/platform/AdminPlatformShopsPage.tsx b/apps/frontend/src/pages/admin/platform/AdminPlatformShopsPage.tsx index 6ea1d5f6..0143fe1d 100644 --- a/apps/frontend/src/pages/admin/platform/AdminPlatformShopsPage.tsx +++ b/apps/frontend/src/pages/admin/platform/AdminPlatformShopsPage.tsx @@ -77,6 +77,11 @@ import type { AdminScheduledJobsConfig, } from '@/types/admin' import { hasAdminRole } from '@/utils/admin-auth' +import { + ADMIN_DEFAULT_PAGE_SIZE, + buildAdminLocalTablePagination, + buildAdminTablePagination, +} from '@/utils/admin-pagination' import { formatAdminDateTime } from '@/utils/admin-time' type PlatformTab = @@ -441,14 +446,12 @@ function NinetyonePanel({ columns={columns} dataSource={data?.items || []} scroll={{ x: 1200 }} - pagination={{ + pagination={buildAdminTablePagination({ current: data?.page || 1, - pageSize: data?.pageSize || 20, + pageSize: data?.pageSize || ADMIN_DEFAULT_PAGE_SIZE, total: data?.total || 0, - showSizeChanger: true, - showTotal: (total) => `共 ${total} 条`, onChange: (nextPage, nextPageSize) => loadOrders(nextPage, nextPageSize), - }} + })} /> ) @@ -1469,7 +1472,7 @@ function KuaishouFeifeiPlatformPanel({ className="platform-section-gap" rowKey={(row) => row.id || row.productCode || row.productName} dataSource={source.productRules} - pagination={{ pageSize: 10, showSizeChanger: true }} + pagination={buildAdminLocalTablePagination()} scroll={{ x: 980 }} columns={[ { diff --git a/apps/frontend/src/utils/admin-pagination.ts b/apps/frontend/src/utils/admin-pagination.ts new file mode 100644 index 00000000..30da92d3 --- /dev/null +++ b/apps/frontend/src/utils/admin-pagination.ts @@ -0,0 +1,93 @@ +import type { TablePaginationConfig } from 'antd' + +/** 后台标准列表默认每页条数(与后端 normalizePageSize 默认 20 一致) */ +export const ADMIN_DEFAULT_PAGE_SIZE = 20 + +/** + * 标准列表可选页大小。 + * 后端 admin normalizePageSize 上限 100,故不包含更大档位。 + */ +export const ADMIN_PAGE_SIZE_OPTIONS = [10, 20, 50, 100] as const + +/** 云触手发货记录:上游接口更适合大批量拉取 */ +export const CLOUDTENTACLES_DEFAULT_PAGE_SIZE = 100 +export const CLOUDTENTACLES_PAGE_SIZE_OPTIONS = [100, 200, 500, 1000] as const + +export function formatAdminTotal(total: number) { + return `共 ${total} 条` +} + +/** 可复用到 Table.pagination 的标准选项(常开条数切换) */ +export const ADMIN_TABLE_PAGINATION_BASE: Pick< + TablePaginationConfig, + 'showSizeChanger' | 'pageSizeOptions' | 'showTotal' +> = { + showSizeChanger: true, + pageSizeOptions: [...ADMIN_PAGE_SIZE_OPTIONS], + showTotal: formatAdminTotal, +} + +/** + * 服务端分页列表(任务/订单/用户/审计等)。 + * 始终展示 10/20/50/100,避免 antd「total ≤ 50 不显示」默认行为。 + */ +export function buildAdminTablePagination(options: { + current?: number + page?: number + pageSize?: number + total?: number + onChange?: TablePaginationConfig['onChange'] +} & Partial): TablePaginationConfig { + const { current, page, pageSize, total, onChange, ...rest } = options + return { + ...ADMIN_TABLE_PAGINATION_BASE, + current: current ?? page ?? 1, + pageSize: pageSize ?? ADMIN_DEFAULT_PAGE_SIZE, + total: total ?? 0, + onChange, + ...rest, + } +} + +/** 纯前端本地表格分页 */ +export function buildAdminLocalTablePagination( + options: Partial = {}, +): TablePaginationConfig { + return { + ...ADMIN_TABLE_PAGINATION_BASE, + pageSize: ADMIN_DEFAULT_PAGE_SIZE, + ...options, + } +} + +/** 云触手发货记录分页(100–1000) */ +export function buildCloudtentaclesTablePagination(options: { + current?: number + page?: number + pageSize?: number + total?: number + onChange?: TablePaginationConfig['onChange'] +} & Partial): TablePaginationConfig { + const { current, page, pageSize, total, onChange, ...rest } = options + return { + showSizeChanger: true, + pageSizeOptions: [...CLOUDTENTACLES_PAGE_SIZE_OPTIONS], + showTotal: formatAdminTotal, + current: current ?? page ?? 1, + pageSize: pageSize ?? CLOUDTENTACLES_DEFAULT_PAGE_SIZE, + total: total ?? 0, + onChange, + ...rest, + } +} + +export function resolveAdminPageSize( + raw: unknown, + fallback: number = ADMIN_DEFAULT_PAGE_SIZE, +): number { + const parsed = Number(raw) + if (!Number.isFinite(parsed) || parsed <= 0) { + return fallback + } + return Math.min(100, Math.floor(parsed)) +}