From 9107d4af4a9b0b11ddde80dfbe59002b7cb9f213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=9D=E5=8D=9C?= Date: Sat, 14 Mar 2026 21:02:25 +0000 Subject: [PATCH] fix(backurl): stabilize query append and support back-first links --- app/Support/BackUrl.php | 54 +++++++++++++++++-- .../admin/platform_orders/show.blade.php | 2 +- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/app/Support/BackUrl.php b/app/Support/BackUrl.php index c58fb50..f3219a6 100644 --- a/app/Support/BackUrl.php +++ b/app/Support/BackUrl.php @@ -74,6 +74,19 @@ class BackUrl * 用途:列表页“全部/返回来源”等需要清空筛选但保留 back 的场景。 */ public static function withBack(string $path, string $safeBackForLinks = ''): string + { + return self::appendBack($path, $safeBackForLinks, false); + } + + /** + * withBack 的变体:将 back 放到 query 的最前面(用于少数对 query 顺序有严格断言的页面/测试)。 + */ + public static function withBackFirst(string $path, string $safeBackForLinks = ''): string + { + return self::appendBack($path, $safeBackForLinks, true); + } + + private static function appendBack(string $path, string $safeBackForLinks = '', bool $preferFirst = false): string { $path = (string) $path; @@ -86,10 +99,26 @@ class BackUrl return $path; } - // 若 path 已带 query,则追加 &back=;否则追加 ?back= - $sep = str_contains($path, '?') ? '&' : '?'; + $backQuery = \Illuminate\Support\Arr::query(['back' => $safeBackForLinks]); - return $path . $sep . \Illuminate\Support\Arr::query(['back' => $safeBackForLinks]); + if (!str_contains($path, '?')) { + return $path . '?' . $backQuery; + } + + [$base, $qs] = explode('?', $path, 2); + $qs = trim((string) $qs); + $qs = trim($qs, "& "); + + // 处理类似 "/xx?" 或 "/xx?&" 的情况:视为无 query + if ($qs === '') { + return $base . '?' . $backQuery; + } + + if ($preferFirst) { + return $base . '?' . $backQuery . '&' . $qs; + } + + return $base . '?' . $qs . '&' . $backQuery; } /** @@ -114,6 +143,25 @@ class BackUrl return $url . '#' . $fragment; } + /** + * withBackFirst + fragment 的组合:用于少数对 query 顺序有严格断言的页面/测试。 + */ + public static function withBackFirstAndFragment(string $path, string $safeBackForLinks = '', string $fragment = ''): string + { + $url = self::withBackFirst($path, $safeBackForLinks); + + $fragment = ltrim((string) $fragment, '#'); + if ($fragment === '') { + return $url; + } + + if (!preg_match('/^[A-Za-z0-9_-]+$/', $fragment)) { + return $url; + } + + return $url . '#' . $fragment; + } + /** * 当前路径下的“快捷筛选”链接构造器: * - 仅保留指定上下文键(例如 merchant_id/plan_id/keyword/lead_id 等) diff --git a/resources/views/admin/platform_orders/show.blade.php b/resources/views/admin/platform_orders/show.blade.php index dae9109..9fab62f 100644 --- a/resources/views/admin/platform_orders/show.blade.php +++ b/resources/views/admin/platform_orders/show.blade.php @@ -327,7 +327,7 @@ 打开订阅详情 @php - $openSubSyncableUrl = \App\Support\BackUrl::withBackAndFragment( + $openSubSyncableUrl = \App\Support\BackUrl::withBackFirstAndFragment( '/admin/site-subscriptions/' . $order->siteSubscription->id . '?' . \Illuminate\Support\Arr::query([ 'order_sync_status' => 'syncable', ]),