From 97e32572cfaf503fab088b512f18597b64f13e2b Mon Sep 17 00:00:00 2001 From: lkddi Date: Thu, 2 Apr 2026 18:35:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E7=9C=8B=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E8=B5=9A=E9=87=91=E5=B8=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在右侧导航新增「赚钱」入口(娱乐下方) - 新增 earn-panel 弹窗:风格与商店一致,800px 宽度 - 集成 FluidPlayer + VAST 广告(ExoClick) - 动态倒计时:实时监听视频 duration/currentTime - VAST 失败时自动回退保底视频,20s 超时保底放行 - 修复 AbortError:idle 时 video 不预播放,仅提供 fallback source - 删除不支持的 player.on('error') 调用 - 所有 overlay 改用绝对定位居中,修复 Alpine x-show 破坏 flex 问题 - EarnController:Redis 每日 10 次限额 + 冷却防刷 - 领取成功后广播全服系统消息(含金币+经验+快捷入口标签) - 移除神秘盒子相关 UI 代码 --- app/Http/Controllers/EarnController.php | 130 ++++++ resources/views/chat/frame.blade.php | 5 +- .../chat/partials/games/earn-panel.blade.php | 342 ++++++++++++++ .../chat/partials/games/mystery-box.blade.php | 423 +----------------- .../chat/partials/layout/toolbar.blade.php | 1 + routes/web.php | 3 + 6 files changed, 481 insertions(+), 423 deletions(-) create mode 100644 app/Http/Controllers/EarnController.php create mode 100644 resources/views/chat/partials/games/earn-panel.blade.php diff --git a/app/Http/Controllers/EarnController.php b/app/Http/Controllers/EarnController.php new file mode 100644 index 0000000..d6f647b --- /dev/null +++ b/app/Http/Controllers/EarnController.php @@ -0,0 +1,130 @@ +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' => '今日视频收益次数已达上限(每天最多10次),请明天再来。', + ]); + } + + // 3. 开始发放奖励并增加次数 + // 增量前可能需要锁机制,但简单的 incr 在并发也不容易超量很多,且有限流 + $newCount = Redis::incr($dailyCountKey); + + // 设置每日次数键在同一天结束时过期,留一点余量 + if ($newCount === 1) { + Redis::expire($dailyCountKey, 86400 * 2); + } + + // 配置:单次 5000 金币,500 经验 + $rewardCoins = 5000; + $rewardExp = 500; + + $user->increment('jjb', $rewardCoins); + $user->increment('exp_num', $rewardExp); + $user->refresh(); // 刷新模型以获取 increment 后的最新字段值 + + // 设置冷却时间 + Redis::setex($cooldownKey, $this->cooldownSeconds, 1); + + // 4. 检查是否升级 + $levelUp = false; + $newLevelName = ''; + + // 我们利用现有的 levelCache 或者根据 exp_num 和当前 user_level 判断 + // 因为这是一个常见的游戏房逻辑,通常判断用户当前经验是否大于下一级的经验要求 + // 简化起见,如果需要严格触发升级系统,可参考已有的升华逻辑。 + // (在此处简化为:只要给了经验,前端自然显示就好。部分框架逻辑可能不需要在此检查升降,而是下一次进入发言时自动算) + + $roomId = (int) $request->input('room_id', 0); + 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' => '#d97706', + 'action' => '', + 'sent_at' => now()->toDateTimeString(), + ]; + + $this->chatState->pushMessage($roomId, $sysMsg); + broadcast(new \App\Events\MessageSent($roomId, $sysMsg)); + } + + $remainingToday = $this->maxDailyLimit - $newCount; + + return response()->json([ + 'success' => true, + 'message' => "观看完毕!获得 {$rewardCoins} 金币 + {$rewardExp} 经验。今日还可观看 {$remainingToday} 次。", + 'new_jjb' => $user->jjb, // refresh 后的真实值 + 'level_up' => false, + 'new_level_name' => '', + ]); + } +} diff --git a/resources/views/chat/frame.blade.php b/resources/views/chat/frame.blade.php index 7bf6409..822cd23 100644 --- a/resources/views/chat/frame.blade.php +++ b/resources/views/chat/frame.blade.php @@ -15,6 +15,7 @@ {{ $room->name ?? '聊天室' }} - 飘落流星 + @php // 从 sysparam 读取权限等级配置 $levelWarn = (int) \App\Models\Sysparam::getValue('level_warn', '5'); @@ -112,7 +113,8 @@ weddingSetupUrl: (id) => `/wedding/${id}/setup`, claimEnvelopeUrl: (id, ceremonyId) => `/wedding/${id}/claim`, envelopeStatusUrl: (id) => `/wedding/${id}/envelope-status`, - } + }, + earnRewardUrl: "{{ route('earn.video_reward') }}" }; @vite(['resources/css/app.css', 'resources/js/app.js', 'resources/js/chat.js']) @@ -194,6 +196,7 @@ @include('chat.partials.games.fishing-panel') @include('chat.partials.games.game-hall') @include('chat.partials.games.gomoku-panel') + @include('chat.partials.games.earn-panel') {{-- 全屏特效系统:管理员烟花/下雨/雷电/下雪 --}} diff --git a/resources/views/chat/partials/games/earn-panel.blade.php b/resources/views/chat/partials/games/earn-panel.blade.php new file mode 100644 index 0000000..a753925 --- /dev/null +++ b/resources/views/chat/partials/games/earn-panel.blade.php @@ -0,0 +1,342 @@ +{{-- + 文件功能:观看广告赚钱面板 + 包含 ExoClick 广告展示和倒计时领奖逻辑,基于 Alpine.js + + @author ChatRoom Laravel + @version 1.0.0 +--}} + + + + + + + diff --git a/resources/views/chat/partials/games/mystery-box.blade.php b/resources/views/chat/partials/games/mystery-box.blade.php index d48869c..693f61e 100644 --- a/resources/views/chat/partials/games/mystery-box.blade.php +++ b/resources/views/chat/partials/games/mystery-box.blade.php @@ -1,422 +1 @@ -{{-- - 文件功能:神秘箱子游戏前台UI组件 - - 功能描述: - - 右下角悬浮提示标(检测到可领取箱子时显示,支持拖动移位) - - 监听聊天消息事件,识别公屏暗号提示后自动出现 - - 用户在聊天框输入暗号(由前端拦截 /mystery-box/claim 接口) - - 或点击悬浮图标展开快速输入界面 - - 开箱结果展示 toast 通知 ---}} - -{{-- ─── 神秘箱子悬浮提示(可拖动) ─── --}} -
- - {{-- 悬浮圆形按钮 --}} - - - {{-- 悬浮提示标签 --}} -
- 神秘箱 - - -
-
- -{{-- ─── 神秘箱子快捷输入面板 ─── --}} -
-
- -
- - {{-- ─── 顶部 ─── --}} -
- -
-
📦
-
-
-
- 输入暗号即可开箱,限时 - -
-
-
- - {{-- 倒计时进度条 --}} -
-
-
-
-
- - {{-- ─── 输入区 ─── --}} -
- {{-- 奖励提示 --}} -
-
-
- - {{-- 暗号输入框 --}} -
- -
- - {{-- 提交按钮 --}} - -
- - {{-- ─── 底部关闭 ─── --}} -
- -
-
-
-
- - - - +{{-- 神秘箱子的前台 UI 弹窗和悬浮提醒已按照用户要求彻底取消 --}} diff --git a/resources/views/chat/partials/layout/toolbar.blade.php b/resources/views/chat/partials/layout/toolbar.blade.php index fcdece8..1afbd1f 100644 --- a/resources/views/chat/partials/layout/toolbar.blade.php +++ b/resources/views/chat/partials/layout/toolbar.blade.php @@ -18,6 +18,7 @@
商店
存点
娱乐
+
赚钱
银行
婚姻
好友
diff --git a/routes/web.php b/routes/web.php index b67b62f..b0a7fbd 100644 --- a/routes/web.php +++ b/routes/web.php @@ -320,6 +320,9 @@ Route::middleware(['chat.auth'])->group(function () { Route::post('/feedback/{id}/reply', [FeedbackController::class, 'reply'])->middleware('throttle:10,1')->name('feedback.reply'); // 删除反馈(本人24小时内或管理员) Route::delete('/feedback/{id}', [FeedbackController::class, 'destroy'])->name('feedback.destroy'); + + // ---- 赚金币看视频等任务 ---- + Route::post('/earn/video-reward', [\App\Http\Controllers\EarnController::class, 'claimVideoReward'])->name('earn.video_reward'); }); // ═══════════════════════════════════════════════════════════════════