diff --git a/app/Console/Commands/AutoSaveExp.php b/app/Console/Commands/AutoSaveExp.php index 6e02380..fca5cc9 100644 --- a/app/Console/Commands/AutoSaveExp.php +++ b/app/Console/Commands/AutoSaveExp.php @@ -293,13 +293,23 @@ class AutoSaveExp extends Command if ($openLog) { DB::table('position_duty_logs') ->where('id', $openLog->id) - ->update(['duration_seconds' => DB::raw('GREATEST(0, TIMESTAMPDIFF(SECOND, login_at, NOW()))')]); + ->update([ + 'duration_seconds' => DB::raw('GREATEST(0, TIMESTAMPDIFF(SECOND, login_at, NOW()))'), + 'updated_at' => now(), + ]); return; } - // ② 今日无开放日志 → 新建(login_at 优先用今日进房时间,跨天则用 now()) - $loginAt = ($user->in_time && $user->in_time->isToday()) + // ② 今日无开放日志 → 新建 + // 若今日已有已关闭的日志(是重建场景),必须用 now(),防止重用旧 in_time 累积膨胀 + $hasClosedToday = PositionDutyLog::query() + ->where('user_id', $user->id) + ->whereDate('login_at', today()) + ->whereNotNull('logout_at') + ->exists(); + + $loginAt = (! $hasClosedToday && $user->in_time && $user->in_time->isToday()) ? $user->in_time : now(); diff --git a/app/Http/Controllers/ChatController.php b/app/Http/Controllers/ChatController.php index 2469ae9..3f5c84d 100644 --- a/app/Http/Controllers/ChatController.php +++ b/app/Http/Controllers/ChatController.php @@ -1065,15 +1065,27 @@ class ChatController extends Controller if ($openLog) { DB::table('position_duty_logs') ->where('id', $openLog->id) - ->update(['duration_seconds' => DB::raw('GREATEST(0, TIMESTAMPDIFF(SECOND, login_at, NOW()))')]); + ->update([ + 'duration_seconds' => DB::raw('GREATEST(0, TIMESTAMPDIFF(SECOND, login_at, NOW()))'), + // DB::table raw update 不自动刷 updated_at,必须手动设置, + // 否则 CloseStaleDutyLogs 会误判此 session 为掉线而提前关闭。 + 'updated_at' => now(), + ]); return; } - // ② 今日是否已有任意日志(含已关闭的)? - // 若有:说明用户本次是重新进房,已经有历史记录,直接新建本次进房的日志段 - // 若无:说明今天第一次进房,新建,login_at 优先用 in_time - $loginAt = ($user->in_time && $user->in_time->isToday()) + // ② 若今日已有「已关闭」的日志段,说明是 CloseStaleDutyLogs 关闭后重建: + // 必须用 now() 作为 login_at,防止重用旧的 in_time(如今日 00:00)导致 + // 每次重建的 duration_seconds 都从午夜算起,累加成等差数列(产生 249h 等异常值)。 + // 只有今日首次创建(无任何历史日志段)时,才用 in_time 保留真实进房时刻。 + $hasClosedToday = PositionDutyLog::query() + ->where('user_id', $user->id) + ->whereDate('login_at', today()) + ->whereNotNull('logout_at') + ->exists(); + + $loginAt = (! $hasClosedToday && $user->in_time && $user->in_time->isToday()) ? $user->in_time : now(); diff --git a/resources/views/admin/appointments/duty-logs.blade.php b/resources/views/admin/appointments/duty-logs.blade.php index 3bf6b21..8ba2648 100644 --- a/resources/views/admin/appointments/duty-logs.blade.php +++ b/resources/views/admin/appointments/duty-logs.blade.php @@ -32,7 +32,7 @@
{{ gmdate('H', $logs->sum('duration_seconds')) }}h {{ gmdate('i', $logs->sum('duration_seconds')) }}m
-
累计在线时长(当前页)
+
累计在线时长(所有)
{{ $userPosition->total_rewarded_coins }}