diff --git a/resources/views/admin/orders/show.blade.php b/resources/views/admin/orders/show.blade.php index ed48e96..9aeaa32 100644 --- a/resources/views/admin/orders/show.blade.php +++ b/resources/views/admin/orders/show.blade.php @@ -7,6 +7,12 @@ @php $incomingBack = (string) request()->query('back', ''); $safeBackForLinks = \App\Support\BackUrl::sanitizeForLinks($incomingBack); + + // back 参数用于“返回上一页(保留上下文)”,但 back 本身不应再包含 back(避免无限嵌套导致 URL 膨胀) + $selfWithoutBack = \App\Support\BackUrl::selfWithoutBack(); + + // 去重降噪:仅在没有 incoming back 时,提供“返回订单列表(保留上下文)”入口 + $ordersIndexUrl = \App\Support\BackUrl::withBack('/admin/orders', $selfWithoutBack); @endphp
@if($safeBackForLinks) - ← 返回上一页(保留上下文) + 返回上一页(保留上下文) + @else + 返回订单列表(保留上下文) @endif - 返回订单列表
diff --git a/tests/Feature/AdminOrdersShowBackLinkDedupeTest.php b/tests/Feature/AdminOrdersShowBackLinkDedupeTest.php new file mode 100644 index 0000000..ae133bb --- /dev/null +++ b/tests/Feature/AdminOrdersShowBackLinkDedupeTest.php @@ -0,0 +1,104 @@ +seed(); + + $this->post('/admin/login', [ + 'email' => 'platform.admin@demo.local', + 'password' => 'Platform@123456', + ])->assertRedirect('/admin'); + } + + public function test_show_should_render_only_one_back_entry_when_incoming_back_present(): void + { + $this->loginAsPlatformAdmin(); + + $merchant = Merchant::query()->firstOrFail(); + + $order = Order::query()->create([ + 'merchant_id' => $merchant->id, + 'user_id' => null, + 'order_no' => 'O_SHOW_BACK_DEDUPE_0001', + 'status' => 'pending', + 'platform' => 'pc', + 'payment_channel' => 'manual', + 'payment_status' => 'unpaid', + 'device_type' => 'pc', + 'product_amount' => 10, + 'discount_amount' => 0, + 'shipping_amount' => 0, + 'pay_amount' => 10, + 'buyer_name' => '张三', + 'buyer_phone' => '13800000000', + 'buyer_email' => 'buyer@example.com', + 'remark' => 'test', + 'paid_at' => null, + 'shipped_at' => null, + 'completed_at' => null, + ]); + + $back = '/admin/orders?' . Arr::query(['status' => 'pending']); + + $res = $this->get('/admin/orders/' . $order->id . '?back=' . urlencode($back)); + $res->assertOk(); + + $res->assertSee('返回上一页(保留上下文)'); + $res->assertDontSee('返回订单列表(保留上下文)'); + $res->assertDontSee('返回订单列表', false); + } + + public function test_show_should_render_back_to_orders_index_with_context_when_no_incoming_back(): void + { + $this->loginAsPlatformAdmin(); + + $merchant = Merchant::query()->firstOrFail(); + + $order = Order::query()->create([ + 'merchant_id' => $merchant->id, + 'user_id' => null, + 'order_no' => 'O_SHOW_BACK_DEDUPE_0002', + 'status' => 'pending', + 'platform' => 'pc', + 'payment_channel' => 'manual', + 'payment_status' => 'unpaid', + 'device_type' => 'pc', + 'product_amount' => 10, + 'discount_amount' => 0, + 'shipping_amount' => 0, + 'pay_amount' => 10, + 'buyer_name' => '李四', + 'buyer_phone' => '13800000001', + 'buyer_email' => 'buyer2@example.com', + 'remark' => 'test', + 'paid_at' => null, + 'shipped_at' => null, + 'completed_at' => null, + ]); + + $res = $this->get('/admin/orders/' . $order->id); + $res->assertOk(); + + $res->assertSee('返回订单列表(保留上下文)'); + + $expectedBack = '/admin/orders/' . $order->id; + $expectedIndexUrl = '/admin/orders?' . Arr::query([ + 'back' => $expectedBack, + ]); + + $res->assertSee($expectedIndexUrl, false); + $res->assertDontSee('back%3D', false); + } +}