重构:提取 calculateNewLevel() 私有方法,增加在职职务等级保护逻辑

This commit is contained in:
2026-03-12 06:52:40 +08:00
parent 529a59551c
commit 174ee8241d
3 changed files with 164 additions and 98 deletions

View File

@@ -80,14 +80,14 @@ class ChatController extends Controller
// 获取当前在职职务信息(用于内容显示)
$activePosition = $user->activePosition;
$userData = [
'user_id' => $user->id,
'level' => $user->user_level,
'sex' => $user->sex,
'headface' => $user->headface,
'vip_icon' => $user->vipIcon(),
'vip_name' => $user->vipName(),
'vip_color' => $user->isVip() ? ($user->vipLevel?->color ?? '') : '',
'is_admin' => $user->user_level >= $superLevel,
'user_id' => $user->id,
'level' => $user->user_level,
'sex' => $user->sex,
'headface' => $user->headface,
'vip_icon' => $user->vipIcon(),
'vip_name' => $user->vipName(),
'vip_color' => $user->isVip() ? ($user->vipLevel?->color ?? '') : '',
'is_admin' => $user->user_level >= $superLevel,
'position_icon' => $activePosition?->position?->icon ?? '',
'position_name' => $activePosition?->position?->name ?? '',
];
@@ -419,16 +419,7 @@ class ChatController extends Controller
// 2. 使用 sysparam 表中可配置的等级-经验阈值计算等级
// 管理员superlevel 及以上)不参与自动升降级,等级由后台手动设置
$superLevel = (int) Sysparam::getValue('superlevel', '100');
$oldLevel = $user->user_level;
$leveledUp = false;
if ($oldLevel < $superLevel) {
$newLevel = Sysparam::calculateLevel($user->exp_num);
if ($newLevel !== $oldLevel && $newLevel < $superLevel) {
$user->user_level = $newLevel;
$leveledUp = ($newLevel > $oldLevel);
}
}
$leveledUp = $this->calculateNewLevel($user, $superLevel);
$user->save(); // 存点入库
@@ -506,12 +497,9 @@ class ChatController extends Controller
$user->refresh();
// 重新计算等级(经验可能因事件而变化,但管理员不参与自动升降级)
if ($user->user_level < $superLevel) {
$recalcLevel = Sysparam::calculateLevel($user->exp_num);
if ($recalcLevel !== $user->user_level && $recalcLevel < $superLevel) {
$user->user_level = $recalcLevel;
$user->save();
}
if ($this->calculateNewLevel($user, $superLevel)) {
$leveledUp = true; // 随机事件触发了升级,补充标记以便广播
$user->save();
}
// 广播随机事件消息到聊天室
@@ -576,11 +564,11 @@ class ChatController extends Controller
$onlineCount = count($this->chatState->getRoomUsers($room->id));
return [
'id' => $room->id,
'name' => $room->room_name,
'online' => $onlineCount,
'id' => $room->id,
'name' => $room->room_name,
'online' => $onlineCount,
'permit_level' => $room->permit_level ?? 0,
'door_open' => (bool) $room->door_open,
'door_open' => (bool) $room->door_open,
];
});
@@ -960,7 +948,7 @@ class ChatController extends Controller
->whereNull('logout_at')
->whereDate('login_at', today())
->update([
'logout_at' => now(),
'logout_at' => now(),
'duration_seconds' => DB::raw('GREATEST(0, TIMESTAMPDIFF(SECOND, login_at, NOW()))'),
]);
@@ -970,7 +958,7 @@ class ChatController extends Controller
->whereNull('logout_at')
->whereDate('login_at', '<', today())
->update([
'logout_at' => DB::raw('login_at'), // 时长 = 0
'logout_at' => DB::raw('login_at'), // 时长 = 0
'duration_seconds' => 0,
]);
}
@@ -1017,11 +1005,61 @@ class ChatController extends Controller
: now();
PositionDutyLog::create([
'user_id' => $user->id,
'user_id' => $user->id,
'user_position_id' => $activeUP->id,
'login_at' => $loginAt,
'ip_address' => request()->ip(),
'room_id' => $roomId,
'login_at' => $loginAt,
'ip_address' => request()->ip(),
'room_id' => $roomId,
]);
}
/**
* 根据经验值重新计算用户等级,申升减级均会直接修改 $user->user_level。
*
* PHP 对象引用传递,方法内对 $user 的修改会直接反映到调用方。
* 本方法不负责 save(),由调用方决定何时落库。
*
* @param \App\Models\User $user 当前用户模型
* @param int $superLevel 管理员等级阈值(达到后不参与自动升降级)
* @return bool 是否发生了升级true = 等级提升)
*/
private function calculateNewLevel(\App\Models\User $user, int $superLevel): bool
{
// 管理员等级由后台手动维护,不参与自动升降级
if ($user->user_level >= $superLevel) {
return false;
}
$newLevel = Sysparam::calculateLevel($user->exp_num);
// 等级无变化,或计算结果达到管理员阈值(异常情况),均跳过
if ($newLevel === $user->user_level || $newLevel >= $superLevel) {
return false;
}
$isLeveledUp = $newLevel > $user->user_level;
// 在职职务成员:等级保护逻辑
$activeUP = $user->activePosition;
if ($activeUP) {
$positionLevel = $activeUP->position->level ?? 0;
// 职务要求高于当前等级 → 强制补级到职务最低要求
if ($positionLevel > $user->user_level) {
$user->user_level = $positionLevel;
return true; // 等级提升,调用方需保存并广播
}
// 降级 且 降后等级低于职务要求 → 阻止
if (! $isLeveledUp && $newLevel < $positionLevel) {
return false;
}
}
// PHP 对象引用传递,这里对 $user->user_level 的修改将直接反映到调用方
$user->user_level = $newLevel;
return $isLeveledUp;
}
}

View File

@@ -126,7 +126,10 @@ class RedPacketController extends Controller
});
// 广播系统公告,含可点击「立即抢包」按钮
$btnHtml = '<button onclick="showRedPacketModal('
// 注意这里不能死命传 self::EXPIRE_SECONDS因为这句话会被存入数据库的历史记录。我们需要在取出来的时候能根据发包时间动态变化
// 啊等等!由于这条消息是直接静态写入 `chat_messages` 内容里的,这就意味着如果在这里计算,存进去的还是 300。
// 所以我们还是传 `self::EXPIRE_SECONDS` 作为总寿命,在前端逻辑里利用 `Date.now()` 和消息的 `sent_at` 来算出真实剩余倒计时更为严谨!
$btnHtml = '<button data-sent-at="'.time().'" onclick="showRedPacketModal('
.$envelope->id
.',\''.$user->username.'\','
.self::TOTAL_AMOUNT.','