diff --git a/app/Http/Controllers/Admin/PlanController.php b/app/Http/Controllers/Admin/PlanController.php index f697dfc..d65e4af 100644 --- a/app/Http/Controllers/Admin/PlanController.php +++ b/app/Http/Controllers/Admin/PlanController.php @@ -219,6 +219,28 @@ class PlanController extends Controller return redirect()->back()->with('success', '套餐状态已更新:' . ($this->statusLabels()[$plan->status] ?? $plan->status)); } + public function setPublished(Request $request, Plan $plan): RedirectResponse + { + $this->ensurePlatformAdmin($request); + + $data = $request->validate([ + 'published' => ['required', Rule::in(['0', '1'])], + ]); + + $published = (string) $data['published'] === '1'; + + if ($published) { + // 最小治理:发布动作仅写 published_at,不改变 status(避免误把草稿/停用套餐误启用)。 + $plan->published_at = $plan->published_at ?? now(); + } else { + $plan->published_at = null; + } + + $plan->save(); + + return redirect()->back()->with('success', $published ? '套餐已发布' : '套餐已取消发布'); + } + public function update(Request $request, Plan $plan): RedirectResponse { $this->ensurePlatformAdmin($request); diff --git a/resources/views/admin/plans/index.blade.php b/resources/views/admin/plans/index.blade.php index 7f4ee70..8fc7f0c 100644 --- a/resources/views/admin/plans/index.blade.php +++ b/resources/views/admin/plans/index.blade.php @@ -274,6 +274,16 @@ + +
+ @csrf + @php $isPublished = (bool) $plan->published_at; @endphp + + +
@empty diff --git a/routes/web.php b/routes/web.php index 00697e4..b318edb 100644 --- a/routes/web.php +++ b/routes/web.php @@ -144,6 +144,7 @@ Route::prefix('admin')->group(function () { Route::get('/plans/{plan}/edit', [PlanController::class, 'edit']); Route::post('/plans/{plan}', [PlanController::class, 'update']); Route::post('/plans/{plan}/set-status', [PlanController::class, 'setStatus']); + Route::post('/plans/{plan}/set-published', [PlanController::class, 'setPublished']); Route::get('/settings/system', [PlatformSettingController::class, 'system']); Route::post('/settings/system/{id}', [PlatformSettingController::class, 'updateSystem']); diff --git a/tests/Feature/AdminPlanSetPublishedTest.php b/tests/Feature/AdminPlanSetPublishedTest.php new file mode 100644 index 0000000..55f461e --- /dev/null +++ b/tests/Feature/AdminPlanSetPublishedTest.php @@ -0,0 +1,72 @@ +seed(); + + $this->post('/admin/login', [ + 'email' => 'platform.admin@demo.local', + 'password' => 'Platform@123456', + ])->assertRedirect('/admin'); + } + + public function test_platform_admin_can_set_plan_published_flag(): void + { + $this->loginAsPlatformAdmin(); + + $plan = Plan::query()->create([ + 'code' => 'publish_toggle_test', + 'name' => '发布状态切换测试', + 'billing_cycle' => 'monthly', + 'price' => 9, + 'list_price' => 9, + 'status' => 'draft', + 'sort' => 10, + 'published_at' => null, + ]); + + $this->post('/admin/plans/' . $plan->id . '/set-published', [ + 'published' => '1', + ])->assertRedirect(); + + $plan->refresh(); + $this->assertNotNull($plan->published_at); + + $this->post('/admin/plans/' . $plan->id . '/set-published', [ + 'published' => '0', + ])->assertRedirect(); + + $plan->refresh(); + $this->assertNull($plan->published_at); + } + + public function test_guest_cannot_set_plan_published_flag(): void + { + $this->seed(); + + $plan = Plan::query()->create([ + 'code' => 'publish_toggle_guest_test', + 'name' => '发布状态切换测试(guest)', + 'billing_cycle' => 'monthly', + 'price' => 9, + 'list_price' => 9, + 'status' => 'draft', + 'sort' => 10, + 'published_at' => null, + ]); + + $this->post('/admin/plans/' . $plan->id . '/set-published', [ + 'published' => '1', + ])->assertRedirect('/admin/login'); + } +}