功能:自动存点增加金币奖励 + VIP 加成
- heartbeat 增加金币奖励逻辑,读取 jjb_per_heartbeat 配置
- 支持固定值('5')和范围('1-10')两种奖励配置格式
- VIP 会员自动应用经验和金币加成倍率
- 前端手动存点显示金币余额和本次获得的奖励增量
- 新增迁移文件插入 jjb_per_heartbeat 配置项(默认 1-3)
- 更新 exp_per_heartbeat 描述说明支持范围格式
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:向 sysparam 表插入金币奖励和经验奖励相关配置项
|
||||
*
|
||||
* 新增 jjb_per_heartbeat(每次心跳金币奖励)配置,
|
||||
* 并更新 exp_per_heartbeat 的描述以说明支持范围格式。
|
||||
*
|
||||
* @author ChatRoom Laravel
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* 插入金币奖励配置记录,更新经验描述
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// 金币奖励配置(默认0=关闭,可设为 "1" 或 "1-5" 范围格式)
|
||||
if (! DB::table('sysparam')->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' => '每次心跳经验值']);
|
||||
}
|
||||
};
|
||||
@@ -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 =
|
||||
`<span style="color: green;">【${levelTitle}存点】您的最新情况:${levelInfo}</span><span class="msg-time">(${timeStr})</span>`;
|
||||
`<span style="color: green;">【${levelTitle}存点】您的最新情况:${levelInfo} ${gainInfo}</span><span class="msg-time">(${timeStr})</span>`;
|
||||
container2.appendChild(detailDiv);
|
||||
if (autoScroll) container2.scrollTop = container2.scrollHeight;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user