fix(admin): 支付中心分页条改回四按钮式

AdminListPagination 的输出标记从 WP 原生 paginate_links() 换回「卡密管理」
原版的四按钮式:`« ‹ 第 X 页,共 Y 页 › »` +「每页 X 共Y」计数,没有数字页码
链接。七个页面调用点不变,外观统一为卡密管理那一套。

- 删除 $total_pages <= 1 早退:只要总数 > 0 就渲染分页条,单页时四枚按钮全
  disabled —— 与原版 render_pagenavi 行为一致
- 基准 URL 与页码夹取沿用现有实现(显式拼装、夹到 [1, total_pages]),
  这两处缺陷修复不动
- 标题属性由 esc_attr_e() 改为 esc_attr__():输出相同,且同文件与 dev harness
  都只用后者
- 新增私有静态 print_assets(),由 render() 调用并以 $assets_printed 保证每页
  只输出一次;内容只有 .tablenav-pages a.disabled { pointer-events: none; }
  及其注释。这些原生后台页面不加载主题 CSS,故随标记内联

清理 harness 中已无人调用的 number_format_i18n() 与 paginate_links() stub。

验证:tests/admin/ 76 项通过;tests/widget-system/ 458/459(仅剩与本次无关的
lazyload-contract 既有失败);用 git show HEAD~1 取出原 render_pagenavi() 与
新助手在 8 组输入(含单页、总数为 0、per_page 为 0、页码越界)下比对,规范化
空白后输出逐字节一致;harness 渲染售后面板确认四按钮标记与内联样式就位。
This commit is contained in:
2026-10-09 11:49:16 +08:00
parent 536ac67f3c
commit afd08885fc
4 changed files with 104 additions and 48 deletions
+4 -3
View File
@@ -13,8 +13,9 @@
* 3) ice_perpage 只在服务端被读取、默认每页条数偏大。条数小于默认值时永远只有一页,
* 四个按钮恒为 disabled —— 看上去就是「分页是坏的」。
*
* 现状:渲染已迁移到共享助手 AdminListPagination(WP 原生 paginate_links),
* 基准 URL 与页码夹取都在那里做。本文件只固化卡密管理仍特有的部分:
* 现状:渲染已迁移到共享助手 AdminListPagination,四按钮标记由助手统一输出
* (与这里原来那套逐行一致),基准 URL 与页码夹取也都在那里做。
* 本文件只固化卡密管理仍特有的部分:
* - ice_perpage 仍作为 URL 参数被尊重,且工具栏不新增「每页显示」控件;
* - 越界页码回退到最后一页并重查,不留空态死胡同;
* - 筛选参数白名单化拼装,排序与每页条数随链接带走。
@@ -55,7 +56,7 @@ test('渲染已迁移到共享助手 AdminListPagination', () => {
assert.doesNotMatch(page, /self::DEFAULT_PER_PAGE/);
assert.match(page, /AdminListPagination::DEFAULT_PER_PAGE/);
// 只服务自定义禁用按钮的 CSS 规则一并删除。
// 只服务自定义禁用按钮的 CSS 规则已随标记一起搬进助手。
assert.doesNotMatch(page, /\.tablenav-pages a\.disabled \{ pointer-events: none; \}/);
});
+34 -14
View File
@@ -1,7 +1,7 @@
'use strict';
/**
* 支付中心列表页分页契约(WP 原生 paginate_links,统一到 AdminListPagination)。
* 支付中心列表页分页契约(四按钮式,统一到 AdminListPagination)。
*
* 背景(本次收敛的缺陷):
* 1) 各页面的翻页基准 URL 写成 add_query_arg('paged', '%#%') —— 只有两个参数时
@@ -15,6 +15,8 @@
*
* 本契约固化:
* - 七个页面全部改走 AdminListPagination::render(),不再有各自的翻页实现;
* - 渲染标记是卡密管理那一套:« ‹ 第 X 页,共 Y 页 › » 四枚按钮 + 「每页 X 共Y」计数,
* 没有数字页码链接;只要总数 > 0 就渲染,单页时四枚按钮全 disabled;
* - 每页条数默认 20 且来自共享常量,不新增「每页显示」控件;
* - 每页都在查询前夹取页码,越界时重查,杜绝「空表且没有分页条」的死胡同;
* - 翻页链接显式带上当前筛选参数,不依赖 REQUEST_URI。
@@ -185,26 +187,44 @@ test('提现审核不把一次性动作参数带进翻页链接', () => {
}
});
test('共享助手自身:页码夹取、早退与显式基准 URL', () => {
test('共享助手自身:页码夹取、四按钮标记与显式基准 URL', () => {
assert.match(helper, /namespace AKSRT\\Admin\\Native;/);
assert.match(helper, /defined\('ABSPATH'\) \|\| exit;/);
// 空态与单页都不渲染。
// 总数为 0 或每页条数非法时不渲染;单页照样渲染(与原版 render_pagenavi 一致)。
assert.match(helper, /if \(\$total_count <= 0 \|\| \$per_page <= 0\) \{\s*return;\s*\}/);
assert.doesNotMatch(helper, /\$total_pages <= 1/, '单页也必须渲染分页条');
assert.match(helper, /\$total_pages\s*=\s*max\(1, \(int\) ceil\(\$total_count \/ \$per_page\)\);/);
assert.match(helper, /\$current_page = min\(max\(1, \$current_page\), \$total_pages\);/);
assert.match(helper, /if \(\$total_pages <= 1\) \{\s*return;\s*\}/);
// 基准 URL 显式拼装:add_query_arg 必带第三个参数(那正是两参数写法退回 REQUEST_URI 的根治点)。
assert.match(helper, /\$base = add_query_arg\(array_merge\(\['page' => \$page_slug\], \$query_args\), admin_url\('admin\.php'\)\);/);
assert.match(helper, /\$base = add_query_arg\('paged', '%#%', \$base\);/);
// 基准 URL 显式拼装:add_query_arg 必带第三个参数(两参数写法会退回 REQUEST_URI)。
assert.match(helper, /\$base\s*=\s*add_query_arg\(array_merge\(\['page' => \$page_slug\], \$query_args\), admin_url\('admin\.php'\)\);/);
assert.match(helper, /\$page_url = static function \(int \$page\) use \(\$base\): string \{/);
assert.match(helper, /return add_query_arg\('paged', \$page, \$base\);/);
assert.doesNotMatch(helper, /add_query_arg\('paged',\s*'[^']*'\s*\)/);
// 原生 WP 分页 + 总数提示。
assert.match(helper, /<div class="tablenav"><div class="tablenav-pages">/);
// 卡密管理式四按钮标记。
assert.match(helper, /<div class="tablenav bottom">/);
assert.match(helper, /<div class="tablenav-pages">/);
assert.match(helper, /<span class="displaying-num">/);
assert.match(helper, /number_format_i18n\(\$total_count\)/);
assert.match(helper, /echo paginate_links\(\[/);
assert.match(helper, /'prev_text' => '&laquo;',/);
assert.match(helper, /'next_text' => '&raquo;',/);
assert.match(helper, /phpcs:ignore WordPress\.Security\.EscapeOutput -- paginate_links 自行转义。/);
assert.match(helper, /每页 %1\$s 共%2\$s/);
assert.match(helper, /<span class="pagination-links">/);
assert.match(helper, /<span class="paging-input">/);
assert.match(helper, /第 %1\$s 页,共 %2\$s 页/);
assert.match(helper, /<span class="total-pages">/);
for (const cls of ['first-page', 'prev-page', 'next-page', 'last-page']) {
assert.match(helper, new RegExp(`class="${cls} button`), `缺少 ${cls} 按钮`);
}
assert.match(helper, /\$on_first = \$current_page <= 1;/);
assert.match(helper, /\$on_last\s*=\s*\$current_page >= \$total_pages;/);
assert.equal(count(helper, /\$on_first \? '#' :/g), 2, '第一页/上一页都要按 on_first 落到 #');
assert.equal(count(helper, /\$on_last \? '#' :/g), 2, '下一页/最后一页都要按 on_last 落到 #');
// 禁用的翻页按钮不可点击,否则 <a href="#"> 会把页面滚回顶部。
assert.match(helper, /\.tablenav-pages a\.disabled \{ pointer-events: none; \}/);
assert.match(helper, /private static \$assets_printed = false;/);
assert.match(helper, /private static function print_assets\(\): void \{/);
// 不再使用 WP 原生 paginate_links。
assert.doesNotMatch(helper, /echo paginate_links\(/);
});
-2
View File
@@ -55,8 +55,6 @@ function wp_die($m) { throw new Exception('wp_die: ' . $m); }
function get_userdata($id) { return $id > 0 ? (object) ['display_name' => 'User' . $id] : null; }
function get_the_title($id) { return 'Product' . $id; }
function is_admin() { return true; }
function number_format_i18n($n, $d = 0) { return number_format((float) $n, $d); }
function paginate_links($args = []) { return ''; }
}
namespace AKSRT\Ledger {