id; $dateKey = now()->format('Y-m-d'); $dailyCountKey = "earn_video:count:{$userId}:{$dateKey}"; $cooldownKey = "earn_video:cooldown:{$userId}"; // 1. 检查冷却时间 if (Redis::exists($cooldownKey)) { return response()->json([ 'success' => false, 'message' => '操作过快,请稍后再试。', ]); } // 2. 检查每日最大次数 $todayCount = (int) Redis::get($dailyCountKey); if ($todayCount >= $this->maxDailyLimit) { return response()->json([ 'success' => false, 'message' => "今日视频收益次数已达上限(每天最多{$this->maxDailyLimit}次),请明天再来。", ]); } // 3. 增加今日次数计数 $newCount = Redis::incr($dailyCountKey); if ($newCount === 1) { Redis::expire($dailyCountKey, 86400 * 2); } // 4. 配置:单次 5000 金币,500 经验 $rewardCoins = 5000; $rewardExp = 500; $roomId = (int) $request->input('room_id', 0); // 参照钓鱼逻辑:通过 UserCurrencyService 写日志并变更金币/经验 $this->currencyService->change( $user, 'gold', $rewardCoins, CurrencySource::VIDEO_REWARD, "看视频赚取金币(第{$newCount}次)", $roomId, ); $this->currencyService->change( $user, 'exp', $rewardExp, CurrencySource::VIDEO_REWARD, "看视频赚取经验(第{$newCount}次)", $roomId, ); // 刷新模型以获取 service 原子更新后的最新字段值 $user->refresh(); // 5. 设置冷却时间 Redis::setex($cooldownKey, $this->cooldownSeconds, 1); // 6. 广播全服系统消息 if ($roomId > 0) { $promoTag = ' 💰 看视频赚金币'; $sysMsg = [ 'id' => $this->chatState->nextMessageId($roomId), 'room_id' => $roomId, 'from_user' => '系统播报', 'to_user' => '大家', 'content' => "👍 【{$user->username}】刚刚看视频赚取了 {$rewardCoins} 金币 + {$rewardExp} 经验!{$promoTag}", 'is_secret' => false, 'font_color' => '#16a34a', 'action' => '', 'sent_at' => now()->toDateTimeString(), ]; $this->chatState->pushMessage($roomId, $sysMsg); broadcast(new MessageSent($roomId, $sysMsg)); } $remainingToday = $this->maxDailyLimit - $newCount; return response()->json([ 'success' => true, 'message' => "观看完毕!获得 {$rewardCoins} 金币 + {$rewardExp} 经验。今日还可观看 {$remainingToday} 次。", 'new_jjb' => $user->jjb, 'level_up' => false, 'new_level_name' => '', ]); } }