fix(payment): 修复卡密管理分页:页码夹取、显式基准 URL、补齐每页条数入口
- render_pagenavi():页码先夹到 [1, total_pages],禁用状态由 $on_first / $on_last 一次导出。旧写法是一串 if/elseif,页码越界时三个分支一个都不命中, 上一页与下一页同时停在 '#':既不打 disabled 也点不动。 - 翻页链接改用显式基准 URL(page_url + 当前筛选参数),不再依赖 add_query_arg() 默认取 $_SERVER['REQUEST_URI'] 的行为; status / type / other / s / orderby / desc / ice_perpage 随链接带走。 - render_list():页码越界(手改 URL、或筛选后总数变小)时回退到最后一页重查, 消除「空白表格 + 一个分页控件都没有」的死胡同。 - 新增「每页显示」选择器(ice_perpage)。该参数此前只有服务端读取、界面上没有 任何入口能改,条数小于默认每页条数时永远只有一页,分页条恒为 disabled。 - 禁用按钮加 pointer-events:none,避免点空还滚回页首。 - 新增 tests/admin/charge-cards-pagination.test.cjs(6 条契约)。 验证:容器内真实渲染 7 组 URL(默认 / 每页 5 / 第 2 页 / paged=2 越界 / paged=99 越界 / 带 status 筛选 / 非预设每页 7),无头 Chrome 截图核对版式; node --test 三套 18/18 通过;负向对照(还原旧写法)按要求失败 2 条;php -l 通过。
This commit is contained in:
@@ -59,6 +59,7 @@
|
||||
/tests/admin/*
|
||||
!/tests/admin/charge-cards-page-contract.test.cjs
|
||||
!/tests/admin/charge-cards-dependency.test.cjs
|
||||
!/tests/admin/charge-cards-pagination.test.cjs
|
||||
!/tests/front-submit/
|
||||
/tests/front-submit/*
|
||||
!/tests/front-submit/video-cover-contract.test.cjs
|
||||
|
||||
@@ -21,6 +21,12 @@ class PayChargeCards {
|
||||
public const NONCE = 'aksrt_card_pass_page';
|
||||
public const EXPORT_AJAX_ACTION = 'aksrt_card_pass_export';
|
||||
|
||||
/** 每页条数默认值;列表页可由 ice_perpage 覆盖。 */
|
||||
public const DEFAULT_PER_PAGE = 30;
|
||||
|
||||
/** 「每页显示」下拉的可选值。 */
|
||||
private const PER_PAGE_CHOICES = [10, 20, 30, 50, 100];
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
/** @var string 当前页面 URL */
|
||||
@@ -116,7 +122,7 @@ class PayChargeCards {
|
||||
$orderby = isset($_GET['orderby']) ? sanitize_key((string) wp_unslash($_GET['orderby'])) : 'modified_time';
|
||||
$order = isset($_GET['desc']) ? (strtoupper((string) wp_unslash($_GET['desc'])) === 'ASC' ? 'ASC' : 'DESC') : 'DESC';
|
||||
$paged = max(1, (int) ($_GET['paged'] ?? 1));
|
||||
$per_page = max(1, min(100, (int) ($_REQUEST['ice_perpage'] ?? 30)));
|
||||
$per_page = max(1, min(100, (int) ($_REQUEST['ice_perpage'] ?? self::DEFAULT_PER_PAGE)));
|
||||
|
||||
// 参考主题:status=0 表示未使用;本主题规范状态为 active。
|
||||
if ($status === '0' || $status === 'active') {
|
||||
@@ -152,21 +158,37 @@ class PayChargeCards {
|
||||
</div>
|
||||
</form>';
|
||||
|
||||
echo '<div class="order-header"><ul class="subsubsub">' . $but_html . '</ul>' . $search . '</div>';
|
||||
// 当前筛选参数(不含 paged)。分页链接与「每页显示」表单都显式带上它,
|
||||
// 不再依赖 add_query_arg() 默认取 $_SERVER['REQUEST_URI'](链接会随环境漂移,且列条件容易丢)。
|
||||
$query_args = $this->list_query_args($status, $type, $other, $s, $orderby, $order, $per_page);
|
||||
|
||||
$result = $svc->get_list([
|
||||
echo '<div class="order-header"><ul class="subsubsub">' . $but_html . '</ul>'
|
||||
. '<div class="order-header-right">' . $this->per_page_selector($per_page, $query_args) . $search . '</div></div>';
|
||||
|
||||
$filters = [
|
||||
'status' => $status,
|
||||
'type' => $type,
|
||||
'other' => $other,
|
||||
'search' => $s,
|
||||
'orderby' => $orderby,
|
||||
'order' => $order,
|
||||
'limit' => $per_page,
|
||||
'offset' => ($paged - 1) * $per_page,
|
||||
]);
|
||||
];
|
||||
|
||||
$result = $svc->get_list($filters + ['limit' => $per_page, 'offset' => ($paged - 1) * $per_page]);
|
||||
$items = (array) ($result['items'] ?? []);
|
||||
$count_all = (int) ($result['total'] ?? 0);
|
||||
|
||||
// 页码越界(手工改 URL、或筛选后总数变小)会让 offset 落到数据之外,
|
||||
// 表现为「空白表格 + 一个分页控件都没有」的死胡同,只能靠手改 URL 退出。
|
||||
// 这里回退到最后一页重查一次,保证越界页码也能拿到数据与分页条。
|
||||
$max_page = max(1, (int) ($result['max_pages'] ?? 1));
|
||||
if (!$items && $count_all > 0 && $paged > $max_page) {
|
||||
$paged = $max_page;
|
||||
$result = $svc->get_list($filters + ['limit' => $per_page, 'offset' => ($paged - 1) * $per_page]);
|
||||
$items = (array) ($result['items'] ?? []);
|
||||
$count_all = (int) ($result['total'] ?? $count_all);
|
||||
}
|
||||
|
||||
if (!$items) {
|
||||
echo '<div class="clear"></div>';
|
||||
echo '<table class="widefat fixed striped posts table table-bordered" style="min-width: 1000px;">';
|
||||
@@ -279,7 +301,7 @@ class PayChargeCards {
|
||||
echo '</form>';
|
||||
echo '<div class="clear"></div>';
|
||||
|
||||
$this->render_pagenavi($count_all, $per_page);
|
||||
$this->render_pagenavi($count_all, $per_page, $query_args);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
@@ -996,47 +1018,116 @@ class PayChargeCards {
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页(参考主题 zibpay_admin_pagenavi 同款结构与禁用逻辑)。
|
||||
* 列表筛选参数(不含 paged / page),用于构造翻页链接与「每页显示」表单。
|
||||
* 显式列条件而不是依赖 add_query_arg() 默认取 $_SERVER['REQUEST_URI']:
|
||||
* 后者把链接绑到当前请求上,一旦请求形态变化(POST、代理改写)就会丢条件。
|
||||
*
|
||||
* @return array<string,string>
|
||||
*/
|
||||
private function render_pagenavi(int $total_count, int $number_per_page = 15): void {
|
||||
private function list_query_args(string $status, string $type, string $other, string $s, string $orderby, string $order, int $per_page): array {
|
||||
$args = [];
|
||||
if ($status !== '') {
|
||||
$args['status'] = $status;
|
||||
}
|
||||
if ($type !== '') {
|
||||
$args['type'] = $type;
|
||||
}
|
||||
if ($other !== '') {
|
||||
$args['other'] = $other;
|
||||
}
|
||||
if ($s !== '') {
|
||||
$args['s'] = $s;
|
||||
}
|
||||
if ($orderby !== '' && $orderby !== 'modified_time') {
|
||||
$args['orderby'] = $orderby;
|
||||
}
|
||||
if ($order === 'ASC') {
|
||||
$args['desc'] = 'ASC';
|
||||
}
|
||||
if ($per_page !== self::DEFAULT_PER_PAGE) {
|
||||
$args['ice_perpage'] = (string) $per_page;
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* 「每页显示」选择器。
|
||||
*
|
||||
* 服务端一直支持 ice_perpage,但界面上没有任何地方能改它 —— 每页条数恒等于默认值,
|
||||
* 于是数据量小于默认每页条数时永远只有一页,四个翻页按钮恒为 disabled,
|
||||
* 看起来就是「分页是坏的」。补上这个入口之后,条数、页码才有意义。
|
||||
*
|
||||
* @param array<string,string> $query_args 当前筛选参数(ice_perpage 由本表单自己提供)。
|
||||
*/
|
||||
private function per_page_selector(int $per_page, array $query_args): string {
|
||||
$choices = self::PER_PAGE_CHOICES;
|
||||
if (!in_array($per_page, $choices, true)) {
|
||||
$choices[] = $per_page;
|
||||
sort($choices);
|
||||
}
|
||||
|
||||
$hidden = '<input type="hidden" name="page" value="' . esc_attr(self::PAGE_SLUG) . '">';
|
||||
foreach ($query_args as $key => $value) {
|
||||
if ($key === 'ice_perpage') {
|
||||
continue;
|
||||
}
|
||||
$hidden .= '<input type="hidden" name="' . esc_attr((string) $key) . '" value="' . esc_attr((string) $value) . '">';
|
||||
}
|
||||
|
||||
$options = '';
|
||||
foreach ($choices as $choice) {
|
||||
$options .= '<option value="' . esc_attr((string) $choice) . '"' . selected($per_page, $choice, false) . '>' . esc_html((string) $choice) . '</option>';
|
||||
}
|
||||
|
||||
return '<form class="aksrt-perpage-form" method="get" action="' . esc_url(admin_url('admin.php')) . '">'
|
||||
. $hidden
|
||||
. '<label class="screen-reader-text" for="aksrt-perpage">' . esc_html__('每页显示条数', 'aksrt') . '</label>'
|
||||
. '<span class="aksrt-perpage-label">' . esc_html__('每页显示', 'aksrt') . '</span>'
|
||||
. '<select id="aksrt-perpage" name="ice_perpage" onchange="this.form.submit();">' . $options . '</select>'
|
||||
. '<button type="submit" class="button">' . esc_html__('应用', 'aksrt') . '</button>'
|
||||
. '</form>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页(参考主题 zibpay_admin_pagenavi 同款结构与禁用逻辑)。
|
||||
*
|
||||
* 与参考实现的两处差异,均为缺陷修复:
|
||||
* 1) 页码先夹到 [1, total_pages]。历史写法在此处会出现「第 2 页 / 共 1 页」这类越界状态,
|
||||
* 四个分支一个都不命中,上一页/下一页同时停在 '#',按钮既不禁用也点不动。
|
||||
* 2) 链接基于显式基准 URL(page_url + 当前筛选条件),不再依赖 REQUEST_URI。
|
||||
*
|
||||
* @param array<string,string> $query_args 当前筛选参数(不含 paged)。
|
||||
*/
|
||||
private function render_pagenavi(int $total_count, int $number_per_page, array $query_args = []): void {
|
||||
if ($total_count <= 0 || $number_per_page <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current_page = max(1, (int) ($_GET['paged'] ?? 1));
|
||||
$total_pages = (int) ceil($total_count / $number_per_page);
|
||||
$total_pages = max(1, (int) ceil($total_count / $number_per_page));
|
||||
$current_page = min(max(1, (int) ($_GET['paged'] ?? 1)), $total_pages);
|
||||
|
||||
$first_page_url = add_query_arg('paged', 1);
|
||||
$last_page_url = add_query_arg('paged', $total_pages);
|
||||
$prev_page_url = '#';
|
||||
$next_page_url = '#';
|
||||
$base = $query_args ? add_query_arg($query_args, $this->page_url) : $this->page_url;
|
||||
$page_url = static function (int $page) use ($base): string {
|
||||
return add_query_arg('paged', $page, $base);
|
||||
};
|
||||
|
||||
if ($current_page > 1 && $current_page < $total_pages) {
|
||||
$prev_page_url = add_query_arg('paged', $current_page - 1);
|
||||
$next_page_url = add_query_arg('paged', $current_page + 1);
|
||||
} elseif (1 == $current_page) {
|
||||
$first_page_url = '#';
|
||||
if ($total_pages > 1) {
|
||||
$next_page_url = add_query_arg('paged', $current_page + 1);
|
||||
} else {
|
||||
$next_page_url = '#';
|
||||
$last_page_url = '#';
|
||||
}
|
||||
} elseif ($current_page == $total_pages) {
|
||||
$prev_page_url = add_query_arg('paged', $current_page - 1);
|
||||
$next_page_url = '#';
|
||||
$last_page_url = '#';
|
||||
}
|
||||
$on_first = $current_page <= 1;
|
||||
$on_last = $current_page >= $total_pages;
|
||||
|
||||
$first_page_url = $on_first ? '#' : $page_url(1);
|
||||
$prev_page_url = $on_first ? '#' : $page_url($current_page - 1);
|
||||
$next_page_url = $on_last ? '#' : $page_url($current_page + 1);
|
||||
$last_page_url = $on_last ? '#' : $page_url($total_pages);
|
||||
?>
|
||||
<div class="tablenav bottom">
|
||||
<div class="tablenav-pages">
|
||||
<span class="displaying-num"><?php printf(esc_html__('每页 %1$s 共%2$s', 'aksrt'), esc_html((string) $number_per_page), esc_html((string) $total_count)); ?></span>
|
||||
<span class="pagination-links">
|
||||
<a class="first-page button<?php echo 1 == $current_page ? ' disabled' : ''; ?>" title="<?php esc_attr_e('前往第一页', 'aksrt'); ?>" href="<?php echo esc_url($first_page_url); ?>">«</a>
|
||||
<a class="prev-page button<?php echo 1 == $current_page ? ' disabled' : ''; ?>" title="<?php esc_attr_e('前往上一页', 'aksrt'); ?>" href="<?php echo esc_url($prev_page_url); ?>">‹</a>
|
||||
<a class="first-page button<?php echo $on_first ? ' disabled' : ''; ?>" title="<?php esc_attr_e('前往第一页', 'aksrt'); ?>" href="<?php echo esc_url($first_page_url); ?>">«</a>
|
||||
<a class="prev-page button<?php echo $on_first ? ' disabled' : ''; ?>" title="<?php esc_attr_e('前往上一页', 'aksrt'); ?>" href="<?php echo esc_url($prev_page_url); ?>">‹</a>
|
||||
<span class="paging-input"><?php printf(esc_html__('第 %1$s 页,共 %2$s 页', 'aksrt'), esc_html((string) $current_page), '<span class="total-pages">' . esc_html((string) $total_pages) . '</span>'); ?></span>
|
||||
<a class="next-page button<?php echo $current_page == $total_pages ? ' disabled' : ''; ?>" title="<?php esc_attr_e('前往下一页', 'aksrt'); ?>" href="<?php echo esc_url($next_page_url); ?>">›</a>
|
||||
<a class="last-page button<?php echo $current_page == $total_pages ? ' disabled' : ''; ?>" title="<?php esc_attr_e('前往最后一页', 'aksrt'); ?>" href="<?php echo esc_url($last_page_url); ?>">»</a>
|
||||
<a class="next-page button<?php echo $on_last ? ' disabled' : ''; ?>" title="<?php esc_attr_e('前往下一页', 'aksrt'); ?>" href="<?php echo esc_url($next_page_url); ?>">›</a>
|
||||
<a class="last-page button<?php echo $on_last ? ' disabled' : ''; ?>" title="<?php esc_attr_e('前往最后一页', 'aksrt'); ?>" href="<?php echo esc_url($last_page_url); ?>">»</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1049,6 +1140,12 @@ class PayChargeCards {
|
||||
<style>
|
||||
.order-header { display: flex; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; margin-top: 8px; }
|
||||
.order-header .subsubsub { margin: 6px 0; }
|
||||
.order-header-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
||||
.aksrt-perpage-form { display: flex; align-items: center; gap: 6px; margin: 0; }
|
||||
.aksrt-perpage-form select { min-width: 64px; }
|
||||
/* 禁用的翻页按钮已经无法跳转,但 <a href="#"> 仍会把页面滚回顶部;
|
||||
这里直接让它们不可点击,避免「点了没反应还跳回页首」的错觉。 */
|
||||
.tablenav-pages a.disabled { pointer-events: none; }
|
||||
/* 排序箭头对齐:宿主做成零尺寸 inline-block —— 空 inline-block 的基线即其下边缘,
|
||||
会与文字基线对齐,于是箭头可用 bottom 精确锚定到「基线以上 N em」。
|
||||
箭头盒中心等于 bottom 值(translateY(50%) 抵消自身高度,与盒子高度无关):
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* 「卡密管理」分页契约。
|
||||
*
|
||||
* 背景(已修复的缺陷):
|
||||
* 1) 翻页链接此前写作 add_query_arg('paged', N) —— 只有两个参数时 WordPress 会落到
|
||||
* $_SERVER['REQUEST_URI'],链接绑在当前请求上,随请求形态漂移,列条件也容易丢。
|
||||
* 2) render_pagenavi() 的 URL 推导是一串 if/elseif。页码越界时(例如 per_page 缩小后
|
||||
* URL 里还留着 paged=2,而总数只剩 1 页)三个分支一个都不命中,上一页/下一页
|
||||
* 同时停在 '#':按钮既不打 disabled 也点不动,还停在「第 1 页」状态无法自洽。
|
||||
* 极端情况下 offset 落到数据之外,表格直接变空态并且连分页条都不输出,只能手改 URL 退出。
|
||||
* 3) ice_perpage 只在服务端被读取,界面上没有任何入口能改每页条数。条数小于默认每页条数时
|
||||
* 永远只有一页,四个按钮恒为 disabled —— 看上去就是「分页是坏的」。
|
||||
*
|
||||
* 本契约固化三件事:
|
||||
* - 页码先夹到 [1, total_pages],禁用状态由夹取后的页码推导;
|
||||
* - 翻页链接基于显式基准 URL(page_url + 当前筛选参数),不再依赖 REQUEST_URI;
|
||||
* - 列表页提供「每页显示」选择器(name=ice_perpage),并把筛选参数带进翻页链接。
|
||||
*/
|
||||
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const test = require('node:test');
|
||||
|
||||
const root = path.resolve(__dirname, '..', '..');
|
||||
const page = fs.readFileSync(path.join(root, 'src/Admin/Native/PayChargeCards.php'), 'utf8');
|
||||
|
||||
const count = (src, pattern) => (src.match(pattern) || []).length;
|
||||
|
||||
const slice = (from, to) => {
|
||||
const start = page.indexOf(from);
|
||||
const end = page.indexOf(to);
|
||||
if (start === -1 || end === -1 || end <= start) {
|
||||
throw new Error(`切片失败:${from} → ${to}`);
|
||||
}
|
||||
return page.slice(start, end);
|
||||
};
|
||||
|
||||
const list = slice('private function render_list(', 'private function render_add_form(');
|
||||
const args = slice('private function list_query_args(', 'private function per_page_selector(');
|
||||
const perpage = slice('private function per_page_selector(', 'private function render_pagenavi(');
|
||||
const pager = slice('private function render_pagenavi(', 'private function print_assets(');
|
||||
|
||||
test('翻页链接使用显式基准 URL,不再依赖 REQUEST_URI', () => {
|
||||
// 反面写法:只有两个参数的 add_query_arg —— 会退回到 $_SERVER['REQUEST_URI']。
|
||||
assert.doesNotMatch(page, /add_query_arg\('paged',\s*[^,)]+\)/);
|
||||
|
||||
assert.match(pager, /\$base\s*=\s*\$query_args\s*\?\s*add_query_arg\(\$query_args,\s*\$this->page_url\)\s*:\s*\$this->page_url;/);
|
||||
assert.match(pager, /add_query_arg\('paged',\s*\$page,\s*\$base\)/);
|
||||
assert.equal(count(pager, /add_query_arg\('paged'/g), 1, '翻页 URL 只应有一个构造点');
|
||||
});
|
||||
|
||||
test('页码夹取到有效范围,禁用状态由夹取后的页码推导', () => {
|
||||
assert.match(pager, /\$total_pages\s*=\s*max\(1,\s*\(int\)\s*ceil\(\$total_count \/ \$number_per_page\)\)/);
|
||||
assert.match(pager, /\$current_page\s*=\s*min\(max\(1,\s*\(int\)\s*\(\$_GET\['paged'\] \?\? 1\)\),\s*\$total_pages\)/);
|
||||
|
||||
// 越界时 if/elseif 全不命中的分支结构不得回归。
|
||||
assert.match(pager, /\$on_first\s*=\s*\$current_page <= 1;/);
|
||||
assert.match(pager, /\$on_last\s*=\s*\$current_page >= \$total_pages;/);
|
||||
assert.equal(count(pager, /\$on_first \? '#' :/g), 2, '第一页/上一页都要按 on_first 落到 #');
|
||||
assert.equal(count(pager, /\$on_last \? '#' :/g), 2, '下一页/最后一页都要按 on_last 落到 #');
|
||||
assert.doesNotMatch(pager, /\$current_page == \$total_pages\b/);
|
||||
assert.doesNotMatch(pager, /\$prev_page_url\s*=\s*'#';/);
|
||||
});
|
||||
|
||||
test('越界页码回退到最后一页,不再出现无分页条的死胡同', () => {
|
||||
assert.match(list, /\$max_page\s*=\s*max\(1,\s*\(int\)\s*\(\$result\['max_pages'\] \?\? 1\)\)/);
|
||||
assert.match(list, /if \(!\$items && \$count_all > 0 && \$paged > \$max_page\)/);
|
||||
assert.match(list, /\$paged\s*=\s*\$max_page;/);
|
||||
// 回退之后必须重查,否则表格依旧是空的。
|
||||
assert.equal(count(list, /\$svc->get_list\(/g), 2);
|
||||
// 分页条必须在空态分支之后渲染,否则空态 return 会把分页条一起吞掉。
|
||||
assert.ok(list.indexOf('render_pagenavi(') > list.indexOf('未找到对应内容'), '分页渲染必须晚于空态处理');
|
||||
});
|
||||
|
||||
test('每页条数由界面提供,且与筛选参数保持一致', () => {
|
||||
assert.match(page, /public const DEFAULT_PER_PAGE = 30;/);
|
||||
assert.match(list, /\(int\) \(\$_REQUEST\['ice_perpage'\] \?\? self::DEFAULT_PER_PAGE\)/);
|
||||
|
||||
assert.match(perpage, /method="get"/);
|
||||
assert.match(perpage, /name="ice_perpage"/);
|
||||
assert.match(perpage, /name="page" value="' \. esc_attr\(self::PAGE_SLUG\)/);
|
||||
assert.match(perpage, /selected\(\$per_page, \$choice, false\)/);
|
||||
assert.match(perpage, /onchange="this\.form\.submit\(\);"/);
|
||||
// 非预设值也要出现在下拉里,否则当前状态无法回显、一提交就被重置。
|
||||
assert.match(perpage, /if \(!in_array\(\$per_page, \$choices, true\)\) \{/);
|
||||
|
||||
assert.match(list, /\$query_args = \$this->list_query_args\(/);
|
||||
assert.match(list, /per_page_selector\(\$per_page, \$query_args\)/);
|
||||
assert.match(list, /render_pagenavi\(\$count_all, \$per_page, \$query_args\)/);
|
||||
});
|
||||
|
||||
test('筛选参数白名单化拼装,排序与每页条数随链接带走', () => {
|
||||
for (const key of ['status', 'type', 'other', 's', 'orderby', 'desc', 'ice_perpage']) {
|
||||
assert.match(args, new RegExp(`\\$args\\['${key}'\\] =`), `缺少 ${key}`);
|
||||
}
|
||||
// 默认值不进 URL,避免链接里塞满无意义参数。
|
||||
assert.match(args, /\$orderby !== 'modified_time'/);
|
||||
assert.match(args, /\$order === 'ASC'/);
|
||||
assert.match(args, /\$per_page !== self::DEFAULT_PER_PAGE/);
|
||||
// paged 由 render_pagenavi 单独追加,不能混进基准参数里(否则会被自己覆盖)。
|
||||
assert.doesNotMatch(args, /\$args\['paged'\]/);
|
||||
});
|
||||
|
||||
test('禁用的翻页按钮不可点击,避免点空还滚回页首', () => {
|
||||
assert.match(page, /\.tablenav-pages a\.disabled \{ pointer-events: none; \}/);
|
||||
});
|
||||
Reference in New Issue
Block a user