平台订单列表:快捷筛选仅保留上下文字段避免互斥叠加

This commit is contained in:
萝卜
2026-03-13 23:48:13 +00:00
parent 8168b24215
commit 5023381816
2 changed files with 58 additions and 10 deletions

View File

@@ -77,10 +77,20 @@
// 快捷筛选:尽量保留当前筛选(站点/套餐/订阅ID/back 等),仅覆盖目标筛选字段,并清空 page。
$buildQuickFilterUrl = function (array $overrides) {
$path = '/' . ltrim(request()->path(), '/');
$q = request()->query();
// 强制清页码,避免“切筛选但还停留在老 page=xxx”导致空页
unset($q['page']);
// 快捷筛选的设计原则:
// - 保留“上下文”字段(站点/套餐/订阅/back/关键词)
// - 清理其它可能互斥/叠加导致空结果的筛选字段(例如 syncable_only/reconcile_mismatch 等)
// - 并且强制清空 page避免落到空页
$contextKeys = [
'merchant_id' => 1,
'plan_id' => 1,
'site_subscription_id' => 1,
'back' => 1,
'keyword' => 1,
];
$q = array_intersect_key(request()->query(), $contextKeys);
foreach ($overrides as $k => $v) {
if ($v === null) {

View File

@@ -19,19 +19,57 @@ class AdminPlatformOrderIndexQuickFilterLinksKeepContextTest extends TestCase
])->assertRedirect('/admin');
}
public function test_quick_filter_links_should_keep_context_and_clear_page(): void
public function test_quick_filter_links_should_keep_context_and_drop_other_filters(): void
{
$this->loginAsPlatformAdmin();
// 模拟:当前已筛选站点/套餐/订阅ID并且带 page/back
$res = $this->get('/admin/platform-orders?merchant_id=2&plan_id=3&site_subscription_id=4&page=9&back=%2Fadmin%2Fplans');
// 模拟:当前已筛选站点/套餐/订阅ID并且带一堆其它筛选(可能互斥),以及 page/back
$res = $this->get('/admin/platform-orders?merchant_id=2&plan_id=3&site_subscription_id=4&page=9&back=%2Fadmin%2Fplans&syncable_only=1&reconcile_mismatch=1&refund_inconsistent=1&receipt_status=has');
$res->assertOk();
// 以“待支付”为例:应保留 merchant_id/plan_id/site_subscription_id/back同时覆盖 payment_status=unpaid并清除 page
$res->assertSee('/admin/platform-orders?merchant_id=2&plan_id=3&site_subscription_id=4&back=%2Fadmin%2Fplans&payment_status=unpaid', false);
$res->assertDontSee('page=9', false);
$html = (string) $res->getContent();
preg_match_all('/href="([^"]+)"/', $html, $m);
$hrefs = $m[1] ?? [];
// 找到“待支付”的快捷筛选链接payment_status=unpaid 且不包含 status=pending避免匹配到“可BMPA处理”
$unpaidLinks = array_values(array_filter($hrefs, function ($u) {
return str_contains($u, '/admin/platform-orders')
&& str_contains($u, 'payment_status=unpaid')
&& !str_contains($u, 'status=pending');
}));
$this->assertGreaterThanOrEqual(1, count($unpaidLinks));
$parts = parse_url($unpaidLinks[0]);
parse_str($parts['query'] ?? '', $q);
// 应保留上下文merchant/plan/subscription/back并覆盖 payment_status
$this->assertSame('2', (string) ($q['merchant_id'] ?? ''));
$this->assertSame('3', (string) ($q['plan_id'] ?? ''));
$this->assertSame('4', (string) ($q['site_subscription_id'] ?? ''));
$this->assertSame('/admin/plans', (string) ($q['back'] ?? ''));
$this->assertSame('unpaid', (string) ($q['payment_status'] ?? ''));
// 并且:不应携带其它互斥筛选字段,避免叠加导致空结果
$this->assertArrayNotHasKey('page', $q);
$this->assertArrayNotHasKey('syncable_only', $q);
$this->assertArrayNotHasKey('reconcile_mismatch', $q);
$this->assertArrayNotHasKey('refund_inconsistent', $q);
$this->assertArrayNotHasKey('receipt_status', $q);
// “全部”应清空筛选,仅保留 back
$res->assertSee('/admin/platform-orders?back=%2Fadmin%2Fplans', false);
$allLinks = array_values(array_filter($hrefs, function ($u) {
if (!str_starts_with($u, '/admin/platform-orders')) {
return false;
}
$p = parse_url($u);
parse_str($p['query'] ?? '', $q2);
return (($q2['back'] ?? null) === '/admin/plans') && (count($q2) === 1);
}));
$this->assertGreaterThanOrEqual(1, count($allLinks));
}
}