功能:id=1 超管无需职务即可发放奖励金币

前端(frame.blade.php):
- Auth::id()===1 时 myMaxReward=-1(不限),送金币按钮始终显示

后端(AdminCommandController::reward):
- isSuperAdmin=true 时跳过职务检查和①②③④限额校验
- 全局接收次数⑤对超管同样生效(防止刷奖励)
- 履职记录 user_position_id 允许 null(超管无职务时)
- 发放备注改用 positionName 变量(超管显示「超级管理员」)

顺带修复:②操作人单日累计统计之前误查 target_user_id,
已改为正确的 user_id(操作人自己今日已发总额)
This commit is contained in:
2026-03-01 11:43:51 +08:00
parent cc1278ffcb
commit 3d30d7e811
2 changed files with 64 additions and 49 deletions

View File

@@ -442,64 +442,73 @@ class AdminCommandController extends Controller
return response()->json(['status' => 'error', 'message' => '不能给自己发放奖励'], 422);
}
// 必须有在职职务且职务配置了 max_reward
$userPosition = $admin->activePosition;
if (! $userPosition) {
return response()->json(['status' => 'error', 'message' => '你当前没有在职职务,无权发放奖励'], 403);
}
$position = $userPosition->position;
if (! $position?->max_reward) {
return response()->json(['status' => 'error', 'message' => '你的职务未配置奖励权限'], 403);
}
// 目标用户必须存在
$target = User::where('username', $targetUsername)->first();
if (! $target) {
return response()->json(['status' => 'error', 'message' => '用户不存在'], 404);
}
// ① 单次上限校验
if ($amount > $position->max_reward) {
return response()->json([
'status' => 'error',
'message' => "单次奖励上限为 {$position->max_reward} 金币,请调整金额",
], 422);
}
// id=1 超级管理员:无需职务,无限额限制
$isSuperAdmin = $admin->id === 1;
$userPosition = null;
$position = null;
// ② 操作人单日累计上限校验
if ($position->daily_reward_limit) {
$todayTotal = PositionAuthorityLog::where('target_user_id', $target->id)
->where('action_type', 'reward')
->whereDate('created_at', today())
->sum('amount');
if (! $isSuperAdmin) {
// ① 必须有在职职务
$userPosition = $admin->activePosition;
if (! $userPosition) {
return response()->json(['status' => 'error', 'message' => '你当前没有在职职务,无权发放奖励'], 403);
}
if ($todayTotal + $amount > $position->daily_reward_limit) {
$remaining = max(0, $position->daily_reward_limit - $todayTotal);
$position = $userPosition->position;
// 职务 max_reward = 0 表示禁止null 表示不限,正整数表示有上限
if ($position?->max_reward === 0) {
return response()->json(['status' => 'error', 'message' => '你的职务未配置奖励权限'], 403);
}
// ② 单次上限校验max_reward > 0 时才限制null = 不限)
if ($position->max_reward && $amount > $position->max_reward) {
return response()->json([
'status' => 'error',
'message' => "今日剩余可发放额度为 {$remaining} 金币,超出单日上限({$position->daily_reward_limit}",
'message' => "单次奖励上限为 {$position->max_reward} 金币,请调整金额",
], 422);
}
// ③ 操作人单日累计上限校验
if ($position->daily_reward_limit) {
$todayTotal = PositionAuthorityLog::where('user_id', $admin->id)
->where('action_type', 'reward')
->whereDate('created_at', today())
->sum('amount');
if ($todayTotal + $amount > $position->daily_reward_limit) {
$remaining = max(0, $position->daily_reward_limit - $todayTotal);
return response()->json([
'status' => 'error',
'message' => "今日剩余可发放额度为 {$remaining} 金币,超出单日上限({$position->daily_reward_limit}",
], 422);
}
}
// ④ 职务级别:接收者每日次数上限
if ($position->recipient_daily_limit) {
$recipientCount = PositionAuthorityLog::where('target_user_id', $target->id)
->where('action_type', 'reward')
->whereDate('created_at', today())
->count();
if ($recipientCount >= $position->recipient_daily_limit) {
return response()->json([
'status' => 'error',
'message' => "{$targetUsername} 今日已由全体职务人员累计发放 {$recipientCount} 次奖励,已达每日上限({$position->recipient_daily_limit}",
], 422);
}
}
}
// ③ 同一接收者每日次数上限校验(统计今日所有职务持有者对该用户的累计发放次数
if ($position->recipient_daily_limit) {
$recipientCount = PositionAuthorityLog::where('target_user_id', $target->id)
->where('action_type', 'reward')
->whereDate('created_at', today())
->count();
if ($recipientCount >= $position->recipient_daily_limit) {
return response()->json([
'status' => 'error',
'message' => "{$targetUsername} 今日已由全体职务人员累计发放 {$recipientCount} 次奖励,已达每日上限({$position->recipient_daily_limit}",
], 422);
}
}
// ④ 全局系统级别:每位用户单日最多接收奖励次数(后台职务管理页统一配置)
// ⑤ 全局系统级别:每位用户单日最多接收奖励次数(所有操作人通用,含超管
$globalMax = (int) Sysparam::getValue('reward_recipient_daily_max', '0');
if ($globalMax > 0) {
$globalCount = PositionAuthorityLog::where('target_user_id', $target->id)
@@ -516,19 +525,20 @@ class AdminCommandController extends Controller
}
// 发放金币(通过 UserCurrencyService 原子性更新 + 写流水)
$positionName = $isSuperAdmin ? '超级管理员' : ($position->name ?? '职务');
$this->currencyService->change(
$target,
'gold',
$amount,
CurrencySource::POSITION_REWARD,
"{$admin->username}{$position->name})职务奖励",
"{$admin->username}{$positionName})职务奖励",
$roomId,
);
// 写履职记录PositionAuthorityLog
// 写履职记录PositionAuthorityLog;超管无职务时 user_position_id 留 null
PositionAuthorityLog::create([
'user_id' => $admin->id,
'user_position_id' => $userPosition->id,
'user_position_id' => $userPosition?->id,
'action_type' => 'reward',
'target_user_id' => $target->id,
'amount' => $amount,