Files
chatroom/app/Http/Controllers/ShopController.php

164 lines
5.7 KiB
PHP
Raw Normal View History

<?php
/**
* 文件功能:商店控制器
* 提供商品列表查询、商品购买(含赠送特效广播)、改名卡使用 三个接口
*/
namespace App\Http\Controllers;
use App\Events\EffectBroadcast;
use App\Events\MessageSent;
use App\Models\ShopItem;
use App\Services\ShopService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ShopController extends Controller
{
/**
* 注入商店服务
*/
public function __construct(
private readonly ShopService $shopService,
) {}
/**
* 获取商店商品列表及当前用户状态
*
* 返回字段items商品列表、user_jjb当前金币
* active_week_effect当前周卡、has_rename_card是否持有改名卡
*/
public function items(): JsonResponse
{
$user = Auth::user();
$items = ShopItem::active()->map(fn ($item) => [
'id' => $item->id,
'name' => $item->name,
'slug' => $item->slug,
'description' => $item->description,
'icon' => $item->icon,
'price' => $item->price,
'type' => $item->type,
'duration_days' => $item->duration_days,
]);
return response()->json([
'items' => $items,
'user_jjb' => $user->jjb ?? 0,
'active_week_effect' => $this->shopService->getActiveWeekEffect($user),
'has_rename_card' => $this->shopService->hasRenameCard($user),
]);
}
/**
* 购买商品
*
* 单次特效卡额外支持:
* - recipient 接收者用户名(传 "all" 或留空则全员可见)
* - message 公屏赠言(可选)
*
* @param Request $request item_id, recipient?, message?
*/
public function buy(Request $request): JsonResponse
{
$request->validate(['item_id' => 'required|integer|exists:shop_items,id']);
$item = ShopItem::find($request->item_id);
if (! $item->is_active) {
return response()->json(['status' => 'error', 'message' => '该商品已下架。'], 400);
}
$result = $this->shopService->buyItem(Auth::user(), $item);
if (! $result['ok']) {
return response()->json(['status' => 'error', 'message' => $result['message']], 400);
}
$response = ['status' => 'success', 'message' => $result['message']];
// ── 单次特效卡:广播给指定用户或全员 ────────────────────────
if (isset($result['play_effect'])) {
$user = Auth::user();
$roomId = (int) $request->room_id;
$recipient = trim($request->input('recipient', '')); // 空字符串 = 全员
$message = trim($request->input('message', ''));
// recipient 为空或 "all" 表示全员
$targetUsername = ($recipient === '' || $recipient === 'all') ? null : $recipient;
// 广播特效事件(全员频道)
broadcast(new EffectBroadcast(
roomId: $roomId,
type: $result['play_effect'],
operator: $user->username,
targetUsername: $targetUsername,
giftMessage: $message ?: null,
))->toOthers();
// 同时前端也需要播放(自己也要看到)
$response['play_effect'] = $result['play_effect'];
$response['target_username'] = $targetUsername;
$response['gift_message'] = $message ?: null;
// 公屏系统消息
if ($roomId > 0) {
$icons = [
'fireworks' => '🎆',
'rain' => '🌧',
'lightning' => '⚡',
'snow' => '❄️',
];
// 赠礼消息文案(简洁精美)
$icon = $icons[$result['play_effect']] ?? '✨';
$toStr = $targetUsername ? "{$targetUsername}" : '全体聊友';
$remarkPart = $message ? "{$message}" : '';
$sysContent = "{$icon} {$user->username} 送了一张【{$item->name}】给 {$toStr}{$remarkPart}";
// 广播系统消息到公屏(字段名与前端 appendMessage() 保持一致)
$sysMsgEvent = new MessageSent(
roomId: $roomId,
message: [
'id' => 0,
'room_id' => $roomId,
'from_user' => '系统传音', // 触发金色左边框样式(已有处理分支)
'to_user' => '大家',
'content' => $sysContent,
'font_color' => '#cc6600',
'sent_at' => now()->format('H:i:s'),
'is_secret' => false,
'action' => null,
]
);
broadcast($sysMsgEvent);
}
}
// 返回最新金币余额
$response['jjb'] = Auth::user()->fresh()->jjb;
return response()->json($response);
}
/**
* 使用改名卡修改昵称
*
* @param Request $request new_name
*/
public function rename(Request $request): JsonResponse
{
$request->validate([
'new_name' => 'required|string|min:1|max:10',
]);
$result = $this->shopService->useRenameCard(Auth::user(), $request->new_name);
if (! $result['ok']) {
return response()->json(['status' => 'error', 'message' => $result['message']], 400);
}
return response()->json(['status' => 'success', 'message' => $result['message']]);
}
}