(string)$userId, 'login_ip' => $info['login_ip'], 'country' => $info['country'], 'browser' => $info['browser'], 'os' => $info['os'], 'status' => $status, 'logout_time' => null, 'online_duration' => null, 'user_agent' => $info['user_agent'], ]); } /** * 标记登出:更新最近一条未登出的成功登录记录 */ public static function markLogout($userId): void { $log = self::where('user_id', (string)$userId) ->where('status', self::STATUS_SUCCESS) ->whereNull('logout_time') ->orderByDesc('id') ->first(); if (!$log) { return; } $logoutAt = Carbon::now('Asia/Shanghai'); $loginAt = Carbon::parse($log->getRawOriginal('created_at') ?? $log->created_at) ->setTimezone('Asia/Shanghai'); $seconds = max(0, $logoutAt->getTimestamp() - $loginAt->getTimestamp()); $minutes = (int)ceil($seconds / 60); $log->logout_time = $logoutAt->format('Y-m-d H:i:s'); $log->online_duration = $minutes; $log->save(); } public function getStatusTextAttribute(): string { $status = (int)($this->attributes['status'] ?? self::STATUS_SUCCESS); return $status === self::STATUS_SUCCESS ? '登录成功' : '登录失败'; } public function getLogoutTimeAttribute($value): ?string { if (empty($value) || $value === '0000-00-00 00:00:00') { return null; } return Carbon::parse($value)->setTimezone('Asia/Shanghai')->format('Y-m-d H:i:s'); } // 获取用户未登录天数(最后第二次未登录的天数) public static function getNotLoginDays($memberId) { $list = self::where('user_id', $memberId) ->where('status', self::STATUS_SUCCESS) ->orderByDesc('id') ->limit(2) ->get() ->toArray(); if (count($list) < 2) { return 0; } if (date('Y-m-d', strtotime($list[0]['created_at'])) != date('Y-m-d')) { return 0; } $diff = strtotime($list[0]['created_at']) - strtotime($list[1]['created_at']); $days = ceil($diff / 86400); return abs($days); } }