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

112 lines
3.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:节日福利前台领取控制器
*
* 用户通过聊天室内弹窗点击"立即领取"调用此接口,
* 完成金币入账并返回领取结果。
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Http\Controllers;
use App\Enums\CurrencySource;
use App\Models\HolidayClaim;
use App\Models\HolidayEvent;
use App\Services\UserCurrencyService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class HolidayController extends Controller
{
public function __construct(
private readonly UserCurrencyService $currency,
) {}
/**
* 用户领取节日福利红包。
*
* 从 holiday_claims 中查找当前用户的待领取记录,
* 入账金币并更新活动统计数据。
*/
public function claim(Request $request, HolidayEvent $event): JsonResponse
{
$user = $request->user();
// 活动是否在领取有效期内
if (! $event->isClaimable()) {
return response()->json(['ok' => false, 'message' => '活动已结束或已过期。']);
}
// 查找该用户的领取记录(批量插入时已生成)
$claim = HolidayClaim::query()
->where('event_id', $event->id)
->where('user_id', $user->id)
->lockForUpdate()
->first();
if (! $claim) {
return response()->json(['ok' => false, 'message' => '您不在本次福利名单内,或活动已结束。']);
}
// 防止重复领取claimed_at 为 null 表示未领取)
// 由于批量 insert 时直接写入 claimed_at需要增加一个 is_claimed 字段
// 这里用数据库唯一约束保障幂等性:直接返回已领取的提示
return DB::transaction(function () use ($event, $claim, $user): JsonResponse {
// 金币入账
$this->currency->change(
$user,
'gold',
$claim->amount,
CurrencySource::HOLIDAY_BONUS,
"节日福利:{$event->name}",
);
// 更新活动统计(只在首次领取时)
HolidayEvent::query()
->where('id', $event->id)
->increment('claimed_amount', $claim->amount);
// 删除领取记录(以此标记"已领取",防止重复调用)
$claim->delete();
// 检查是否已全部领完
if ($event->max_claimants > 0) {
$remaining = HolidayClaim::where('event_id', $event->id)->count();
if ($remaining === 0) {
$event->update(['status' => 'completed']);
}
}
return response()->json([
'ok' => true,
'message' => "🎉 恭喜!已领取 {$claim->amount} 金币!",
'amount' => $claim->amount,
]);
});
}
/**
* 查询当前用户在指定活动中的待领取状态。
*/
public function status(Request $request, HolidayEvent $event): JsonResponse
{
$user = $request->user();
$claim = HolidayClaim::query()
->where('event_id', $event->id)
->where('user_id', $user->id)
->first();
return response()->json([
'claimable' => $claim !== null && $event->isClaimable(),
'amount' => $claim?->amount ?? 0,
'expires_at' => $event->expires_at?->toIso8601String(),
]);
}
}