- 路由:GET/POST/PUT/PATCH/DELETE /admin/shop
- 控制器:Admin/ShopItemController(index/store/update/toggle/destroy)
- 视图:admin/shop/index.blade.php
- 表格展示所有商品(名称/类型色标/价格/有效期/排序/状态)
- Alpine.js 弹窗新增/编辑(支持全字段)
- 上下架一键切换(PATCH toggle)
- 删除按键(含二次确认)
- 侧边栏:VIP 下方新增「🛒 商店管理」链接
- 权限:superlevel 可查看/编辑;id=1 可新增/删除
114 lines
3.5 KiB
PHP
114 lines
3.5 KiB
PHP
<?php
|
||
|
||
/**
|
||
* 文件功能:后台商店商品管理控制器(站长功能)
|
||
*
|
||
* 提供商店商品的查看、编辑、切换上下架、删除等 CRUD 功能。
|
||
* 仅 superlevel 及以上可访问,id=1 超级站长才能新增/删除。
|
||
*
|
||
* @author ChatRoom Laravel
|
||
*
|
||
* @version 1.0.0
|
||
*/
|
||
|
||
namespace App\Http\Controllers\Admin;
|
||
|
||
use App\Http\Controllers\Controller;
|
||
use App\Models\ShopItem;
|
||
use Illuminate\Http\RedirectResponse;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Facades\Auth;
|
||
use Illuminate\View\View;
|
||
|
||
class ShopItemController extends Controller
|
||
{
|
||
/**
|
||
* 商品列表页(所有 superlevel 以上可查看)
|
||
*/
|
||
public function index(): View
|
||
{
|
||
$items = ShopItem::orderBy('sort_order')->orderBy('id')->get();
|
||
|
||
return view('admin.shop.index', compact('items'));
|
||
}
|
||
|
||
/**
|
||
* 新增商品(仅 id=1 超级站长)
|
||
*/
|
||
public function store(Request $request): RedirectResponse
|
||
{
|
||
abort_unless(Auth::id() === 1, 403);
|
||
|
||
$data = $this->validateItem($request);
|
||
ShopItem::create($data);
|
||
|
||
return redirect()->route('admin.shop.index')->with('success', '商品「'.$data['name'].'」创建成功!');
|
||
}
|
||
|
||
/**
|
||
* 更新商品信息
|
||
*
|
||
* @param ShopItem $shopItem 路由模型自动注入
|
||
*/
|
||
public function update(Request $request, ShopItem $shopItem): RedirectResponse
|
||
{
|
||
$data = $this->validateItem($request, $shopItem);
|
||
$shopItem->update($data);
|
||
|
||
return redirect()->route('admin.shop.index')->with('success', '商品「'.$shopItem->name.'」更新成功!');
|
||
}
|
||
|
||
/**
|
||
* 切换商品上下架状态
|
||
*
|
||
* @param ShopItem $shopItem 路由模型自动注入
|
||
*/
|
||
public function toggle(ShopItem $shopItem): RedirectResponse
|
||
{
|
||
$shopItem->update(['is_active' => ! $shopItem->is_active]);
|
||
$status = $shopItem->is_active ? '上架' : '下架';
|
||
|
||
return redirect()->route('admin.shop.index')->with('success', "「{$shopItem->name}」已{$status}。");
|
||
}
|
||
|
||
/**
|
||
* 删除商品(仅 id=1 超级站长)
|
||
*
|
||
* @param ShopItem $shopItem 路由模型自动注入
|
||
*/
|
||
public function destroy(ShopItem $shopItem): RedirectResponse
|
||
{
|
||
abort_unless(Auth::id() === 1, 403);
|
||
|
||
$name = $shopItem->name;
|
||
$shopItem->delete();
|
||
|
||
return redirect()->route('admin.shop.index')->with('success', "「{$name}」已删除。");
|
||
}
|
||
|
||
/**
|
||
* 统一验证商品表单(新增/编辑共用)
|
||
*
|
||
* @return array<string, mixed>
|
||
*/
|
||
private function validateItem(Request $request, ?ShopItem $item = null): array
|
||
{
|
||
return $request->validate([
|
||
'name' => 'required|string|max:100',
|
||
'slug' => ['required', 'string', 'max:100',
|
||
\Illuminate\Validation\Rule::unique('shop_items', 'slug')->ignore($item?->id),
|
||
],
|
||
'icon' => 'required|string|max:20',
|
||
'description' => 'nullable|string|max:500',
|
||
'price' => 'required|integer|min:0',
|
||
'type' => 'required|in:instant,duration,one_time,ring,auto_fishing',
|
||
'duration_days' => 'nullable|integer|min:0',
|
||
'duration_minutes' => 'nullable|integer|min:0',
|
||
'intimacy_bonus' => 'nullable|integer|min:0',
|
||
'charm_bonus' => 'nullable|integer|min:0',
|
||
'sort_order' => 'required|integer|min:0',
|
||
'is_active' => 'boolean',
|
||
]);
|
||
}
|
||
}
|