diff --git a/app/Http/Controllers/ChatController.php b/app/Http/Controllers/ChatController.php index d0f3cee..513db70 100644 --- a/app/Http/Controllers/ChatController.php +++ b/app/Http/Controllers/ChatController.php @@ -149,17 +149,29 @@ class ChatController extends Controller return response()->json(['status' => 'error'], 401); } - // 1. 心跳经验:通过 Redis 限制最小间隔(默认30秒),防止频繁点击刷经验 - $expCooldownKey = "heartbeat_exp:{$user->id}"; - $canGainExp = ! Redis::exists($expCooldownKey); + // 1. 心跳奖励:通过 Redis 限制最小间隔(默认30秒),防止频繁点击 + $cooldownKey = "heartbeat_exp:{$user->id}"; + $canGainReward = ! Redis::exists($cooldownKey); + $actualExpGain = 0; + $actualJjbGain = 0; - if ($canGainExp) { - $expGain = (int) Sysparam::getValue('exp_per_heartbeat', '1'); + if ($canGainReward) { + // 经验奖励(支持固定值 "1" 或范围 "1-10") + $expGain = $this->parseRewardValue(Sysparam::getValue('exp_per_heartbeat', '1')); $expMultiplier = $this->vipService->getExpMultiplier($user); - $user->exp_num += (int) round($expGain * $expMultiplier); + $actualExpGain = (int) round($expGain * $expMultiplier); + $user->exp_num += $actualExpGain; - // 设置冷却(30秒内不再给经验) - Redis::setex($expCooldownKey, 30, 1); + // 金币奖励(支持固定值 "1" 或范围 "1-5") + $jjbGain = $this->parseRewardValue(Sysparam::getValue('jjb_per_heartbeat', '0')); + if ($jjbGain > 0) { + $jjbMultiplier = $this->vipService->getJjbMultiplier($user); + $actualJjbGain = (int) round($jjbGain * $jjbMultiplier); + $user->jjb = ($user->jjb ?? 0) + $actualJjbGain; + } + + // 设置冷却(30秒内不再给奖励) + Redis::setex($cooldownKey, 30, 1); } // 2. 使用 sysparam 表中可配置的等级-经验阈值计算等级 @@ -263,6 +275,9 @@ class ChatController extends Controller 'status' => 'success', 'data' => [ 'exp_num' => $user->exp_num, + 'jjb' => $user->jjb ?? 0, + 'exp_gain' => $actualExpGain, + 'jjb_gain' => $actualJjbGain, 'user_level' => $user->user_level, 'leveled_up' => $leveledUp, 'is_max_level' => $user->user_level >= $superLevel, @@ -408,4 +423,31 @@ class ChatController extends Controller 'announcement' => $room->announcement, ]); } + + /** + * 解析奖励数值配置(支持固定值或范围格式) + * + * 支持格式: + * "5" → 固定返回 5 + * "1-10" → 随机返回 1~10 之间的整数 + * "0" → 返回 0(关闭该奖励) + * + * @param string $value 配置值 + * @return int 解析后的奖励数值 + */ + private function parseRewardValue(string $value): int + { + $value = trim($value); + + // 支持范围格式 "min-max" + if (str_contains($value, '-')) { + $parts = explode('-', $value, 2); + $min = max(0, (int) $parts[0]); + $max = max($min, (int) $parts[1]); + + return rand($min, $max); + } + + return max(0, (int) $value); + } } diff --git a/database/migrations/2026_02_27_004100_seed_jjb_per_heartbeat_sysparam.php b/database/migrations/2026_02_27_004100_seed_jjb_per_heartbeat_sysparam.php new file mode 100644 index 0000000..1ce1593 --- /dev/null +++ b/database/migrations/2026_02_27_004100_seed_jjb_per_heartbeat_sysparam.php @@ -0,0 +1,50 @@ +where('alias', 'jjb_per_heartbeat')->exists()) { + DB::table('sysparam')->insert([ + 'alias' => 'jjb_per_heartbeat', + 'body' => '1-3', + 'guidetxt' => '💰 每次心跳金币奖励(支持固定值如"1",或范围如"1-5";设为0关闭)', + ]); + } + + // 更新经验配置描述(说明支持范围格式) + DB::table('sysparam') + ->where('alias', 'exp_per_heartbeat') + ->update(['guidetxt' => '⚡ 每次心跳经验奖励(支持固定值如"1",或范围如"1-10";设为0关闭)']); + } + + /** + * 回滚:删除金币配置记录 + */ + public function down(): void + { + DB::table('sysparam')->where('alias', 'jjb_per_heartbeat')->delete(); + + DB::table('sysparam') + ->where('alias', 'exp_per_heartbeat') + ->update(['guidetxt' => '每次心跳经验值']); + } +}; diff --git a/resources/views/chat/partials/scripts.blade.php b/resources/views/chat/partials/scripts.blade.php index e2bc279..b058257 100644 --- a/resources/views/chat/partials/scripts.blade.php +++ b/resources/views/chat/partials/scripts.blade.php @@ -830,11 +830,18 @@ let levelInfo = ''; if (d.is_max_level) { - levelInfo = `级别(${d.user_level});累积经验(${d.exp_num});已满级。`; + levelInfo = `级别(${d.user_level});经验(${d.exp_num});金币(${d.jjb}枚);已满级。`; } else { - const requiredExp = d.user_level * d.user_level * 10; - const remaining = Math.max(0, requiredExp - d.exp_num); - levelInfo = `级别(${d.user_level});累积经验(${d.exp_num});还有(${remaining})升级。`; + levelInfo = `级别(${d.user_level});经验(${d.exp_num});金币(${d.jjb}枚)。`; + } + + // 本次获得的奖励提示 + let gainInfo = ''; + if (d.exp_gain > 0 || d.jjb_gain > 0) { + const parts = []; + if (d.exp_gain > 0) parts.push(`经验+${d.exp_gain}`); + if (d.jjb_gain > 0) parts.push(`金币+${d.jjb_gain}`); + gainInfo = `(本次: ${parts.join(', ')})`; } if (data.data.leveled_up) { @@ -850,7 +857,7 @@ const detailDiv = document.createElement('div'); detailDiv.className = 'msg-line'; detailDiv.innerHTML = - `【${levelTitle}存点】您的最新情况:${levelInfo}(${timeStr})`; + `【${levelTitle}存点】您的最新情况:${levelInfo} ${gainInfo}(${timeStr})`; container2.appendChild(detailDiv); if (autoScroll) container2.scrollTop = container2.scrollHeight; } else {