feat(admin): 支付中心列表页统一为 WP 原生分页

七个支付中心列表页(订单明细 / 售后服务 / 付费文章 / 优惠码 / 创作分成 /
提现审核 / 卡密管理)的分页收敛到共享助手 AdminListPagination,改用 WP 原生
paginate_links() 渲染。

- 基准 URL 显式以 page 参数 + 当前筛选参数拼装,不再让两个参数的
  add_query_arg('paged', ...) 退回 $_SERVER['REQUEST_URI']:链接不再随当前
  请求形态漂移,列条件也不再丢失
- 售后服务从写死的 limit => 100 改为 limit/offset 分页,总数接上原本零调用的
  AfterSaleService::count();after_sale_status 先按状态常量归一,保证 count()
  与 admin_list() 口径一致,分页条不说谎
- 每页 20 条,统一来自 AdminListPagination::DEFAULT_PER_PAGE
- 每页在查询前夹取页码,越界时回退到最后一页并重查,杜绝「空表且没有分页条」
  的死胡同;页码夹取与早退也一并收敛到助手
- 提现审核的翻页链接排除 retry_id / retry_key 两个一次性动作参数
- 订单明细的标签页与翻页链接共用同一份筛选参数,不再各写一份

清理死代码:五个页面里近乎复制的 render_pagination()(其中订单明细与提现审核
两份从未被调用)、两页重复的内联 paginate_links 块、卡密管理的 render_pagenavi()
及其 docblock、PayChargeCards::DEFAULT_PER_PAGE 常量,以及只服务自定义禁用
按钮的 .tablenav-pages a.disabled 规则。

验证:tests/admin/ 76 项通过(新增 pay-pages-pagination.test.cjs,重写
charge-cards-pagination.test.cjs);用 git show HEAD 取出原文件对比,订单明细
与售后服务两页在新旧实现下渲染输出逐字节相同。
This commit is contained in:
2026-10-08 22:22:08 +08:00
parent 83c164a427
commit 7b83893cf6
10 changed files with 516 additions and 242 deletions
+24 -19
View File
@@ -38,7 +38,7 @@ class PayProducts {
$pay_type = isset($_GET['pay_type']) ? sanitize_key((string) wp_unslash($_GET['pay_type'])) : '';
$search = isset($_GET['s']) ? sanitize_text_field((string) wp_unslash($_GET['s'])) : '';
$page_num = max(1, (int) ($_GET['paged'] ?? 1));
$per_page = 20;
$per_page = AdminListPagination::DEFAULT_PER_PAGE;
$type_labels = \AKSRT\Core\DomainModel::pay_type_labels();
unset($type_labels[\AKSRT\Core\DomainModel::PAY_TYPE_NO]);
@@ -51,9 +51,22 @@ class PayProducts {
]);
$posts = $query['posts'];
$total = $query['total'];
$total = (int) $query['total'];
$pages = max(1, (int) ceil($total / $per_page));
// 页码越界(手工改 URL、或筛选后总数变小)会让 WP_Query 停在空页上:表格空掉
// 且分页条不输出,只能手改 URL 退出。回退到最后一页重查一次。
if ($page_num > $pages) {
$page_num = $pages;
$query = $this->query_paid_posts([
'pay_type' => $pay_type,
'search' => $search,
'page' => $page_num,
'per_page' => $per_page,
]);
$posts = $query['posts'];
}
$sales_map = [];
if ($posts && class_exists('\AKSRT\Payment\OrderRepository')) {
$ids = array_map(static function ($p) {
@@ -146,8 +159,16 @@ class PayProducts {
echo '</tr>';
}
// 翻页链接显式带上当前筛选条件(不含 paged),口径与 render_filters() 的表单一致。
$query_args = array_filter([
'pay_type' => $pay_type !== '' ? $pay_type : null,
's' => $search !== '' ? $search : null,
], static function ($value): bool {
return $value !== null;
});
echo '</tbody></table>';
$this->render_pagination($pages, $page_num);
AdminListPagination::render(self::PAGE_SLUG, $total, $page_num, $per_page, $query_args);
$this->render_footer();
}
@@ -352,20 +373,4 @@ class PayProducts {
private function page_url(string $slug, array $args = []): string {
return add_query_arg(array_merge(['page' => $slug], $args), admin_url('admin.php'));
}
private function render_pagination(int $pages, int $page_num): void {
if ($pages <= 1) {
return;
}
echo '<div class="tablenav"><div class="tablenav-pages">';
echo paginate_links([
'base' => add_query_arg('paged', '%#%'),
'format' => '',
'prev_text' => '&laquo;',
'next_text' => '&raquo;',
'total' => $pages,
'current' => $page_num,
]);
echo '</div></div>';
}
}