@extends('admin.layouts.app') @section('title', '套餐管理') @section('page_title', '套餐管理') @section('content') @php // back 参数用于“返回上一页(保留上下文)”,但 back 本身不应再包含 back(避免无限嵌套导致 URL 膨胀) $selfWithoutBack = \App\Support\BackUrl::selfWithoutBack(); // 用于构建“从套餐页跳转到订阅/订单页后可返回套餐页”的链接 $makeSubscriptionUrl = function (array $query) use ($selfWithoutBack) { $query = $query + ['back' => $selfWithoutBack]; return '/admin/site-subscriptions?' . \Illuminate\Support\Arr::query($query); }; $makePlatformOrderUrl = function (array $query) use ($selfWithoutBack) { $query = $query + ['back' => $selfWithoutBack]; return '/admin/platform-orders?' . \Illuminate\Support\Arr::query($query); }; // back 安全护栏(全页通用): // - 仅允许站内相对路径(/ 开头) // - 拒绝引号/尖括号(由于本页大量 href 采用 `{!! !!}` 原样输出,必须严控注入风险) // - 拒绝 nested back=(避免 URL 膨胀/绕过) $incomingBack = (string) request()->query('back', ''); $safeBackForLinks = \App\Support\BackUrl::sanitizeForLinks($incomingBack); // 用于摘要卡等入口:保留当前 query 并覆盖字段,同时安全透传 back。 $safeFullUrlWithQuery = function (array $overrides = []) use ($safeBackForLinks) { return \App\Support\BackUrl::currentPathWithQuery($overrides, $safeBackForLinks); }; $planIndexUrl = \App\Support\BackUrl::withBack('/admin/plans', $safeBackForLinks); @endphp

快捷筛选

用于运营快速定位需要处理的套餐集合(口径基于筛选条件组合)。
@php // 快捷筛选:仅保留“上下文”字段(back/keyword),避免把其它筛选条件叠加导致空结果 $buildQuickFilterUrl = function (array $overrides) use ($safeBackForLinks) { return \App\Support\BackUrl::currentPathQuickFilter(['keyword'], $overrides, $safeBackForLinks); }; // “全部”:清空筛选,但保留安全 back(用于返回来源页) $allUrl = \App\Support\BackUrl::withBack('/admin/plans', $safeBackForLinks); @endphp
全部 启用中 停用 已发布 未发布

工具

@include('admin.components.filters_hidden_inputs', [ 'filters' => $filters ?? [], 'keys' => ['status', 'published', 'billing_cycle', 'keyword'], ])
@csrf
安全护栏:当库中已存在套餐时会自动阻止,避免污染运营数据。

筛选条件

点击收起/展开
@if($safeBackForLinks !== '') @endif

套餐总数

启用中套餐

月付套餐

年付套餐

已发布套餐

未发布套餐

关联订阅总量

关联平台订单总量

套餐列表

后续将从这里进入套餐详情、授权项与订阅联动。

@php $createPlanUrl = \App\Support\BackUrl::withBack('/admin/plans/create', $selfWithoutBack); @endphp 新建套餐
@forelse($plans as $plan) @empty @endforelse
ID 套餐名称 编码 计费周期 售价 划线价 状态 排序 发布时间 关联订阅 关联平台订单 操作
{{ $plan->id }} {{ $plan->name }}
{{ $plan->description ?: '暂无说明' }}
{{ $plan->code }} {{ $billingCycleLabels[$plan->billing_cycle] ?? $plan->billing_cycle }} ¥{{ number_format((float) $plan->price, 2) }} ¥{{ number_format((float) $plan->list_price, 2) }} {{ $statusLabels[$plan->status] ?? $plan->status }} {{ $plan->sort }} {{ optional($plan->published_at)->format('Y-m-d H:i:s') ?: '-' }} @php $subCount = (int) ($plan->subscriptions_count ?? 0); @endphp @if($subCount > 0) {{ $subCount }} 个 @else 0 @endif @php $orderCount = (int) ($plan->platform_orders_count ?? 0); @endphp @if($orderCount > 0) {{ $orderCount }} 单 @else 0 @endif @php $editPlanUrl = \App\Support\BackUrl::withBack('/admin/plans/' . $plan->id . '/edit', $selfWithoutBack); $createOrderUrl = \App\Support\BackUrl::withBack('/admin/platform-orders/create?' . \Illuminate\Support\Arr::query([ 'plan_id' => $plan->id, 'order_type' => 'new_purchase', ]), $selfWithoutBack); @endphp @php $renewalMissingSubscriptionUrl = $makePlatformOrderUrl([ 'plan_id' => $plan->id, 'renewal_missing_subscription' => '1', ]); @endphp
编辑 @if((string) ($plan->status ?? '') === 'active') 创建订单 @else 未启用:不建议下单 @endif 续费缺订阅
@csrf
@csrf @php $isPublished = (bool) $plan->published_at; @endphp
暂无套餐数据,当前阶段先把套餐主表与总台目录立起来,后续可继续接套餐创建、授权项与订阅关联。
{{ $plans->links('pagination.admin') }}
@endsection