UserLogin.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <?php
  2. namespace App\Models;
  3. use Carbon\Carbon;
  4. /**
  5. * 用户登录日志(只读侧:bot-28 后台查询)
  6. *
  7. * 写入在 melbet_sport-api 完成。
  8. * - user_id:仅真实用户 ID,失败且无用户时为空字符串
  9. * - login_account:尝试登录账号
  10. * - online_duration:仅登出后落库;未登出时接口通过 online_duration_live 估算
  11. */
  12. class UserLogin extends BaseModel
  13. {
  14. protected $table = 'user_login';
  15. protected $fillable = [
  16. 'user_id',
  17. 'login_account',
  18. 'login_ip',
  19. 'country',
  20. 'browser',
  21. 'os',
  22. 'status',
  23. 'logout_time',
  24. 'online_duration',
  25. 'user_agent',
  26. ];
  27. // 登录日志需要展示登录时间
  28. protected $hidden = [];
  29. protected $appends = ['status_text', 'is_online', 'online_duration_live'];
  30. public const STATUS_FAIL = 0;
  31. public const STATUS_SUCCESS = 1;
  32. public function getStatusTextAttribute(): string
  33. {
  34. return (int)($this->attributes['status'] ?? self::STATUS_FAIL) === self::STATUS_SUCCESS
  35. ? '登录成功'
  36. : '登录失败';
  37. }
  38. public function getIsOnlineAttribute(): bool
  39. {
  40. if ((int)($this->attributes['status'] ?? self::STATUS_FAIL) !== self::STATUS_SUCCESS) {
  41. return false;
  42. }
  43. $logout = $this->attributes['logout_time'] ?? null;
  44. return empty($logout) || $logout === '0000-00-00 00:00:00';
  45. }
  46. /**
  47. * 展示用在线时长(分钟):
  48. * - 已登出:库内 online_duration
  49. * - 仍在线:按登录时间估算(不写库)
  50. * - 失败:null
  51. */
  52. public function getOnlineDurationLiveAttribute(): ?int
  53. {
  54. if ((int)($this->attributes['status'] ?? self::STATUS_FAIL) !== self::STATUS_SUCCESS) {
  55. return null;
  56. }
  57. $stored = $this->attributes['online_duration'] ?? null;
  58. if ($stored !== null && $stored !== '') {
  59. return (int)$stored;
  60. }
  61. if (!$this->is_online) {
  62. return null;
  63. }
  64. $rawCreated = $this->attributes['created_at'] ?? null;
  65. if (empty($rawCreated)) {
  66. return null;
  67. }
  68. $loginTs = strtotime((string)$rawCreated);
  69. if (!$loginTs) {
  70. return null;
  71. }
  72. return (int)ceil(max(0, time() - $loginTs) / 60);
  73. }
  74. public function getLogoutTimeAttribute($value): ?string
  75. {
  76. if (empty($value) || $value === '0000-00-00 00:00:00') {
  77. return null;
  78. }
  79. return Carbon::parse($value)->setTimezone('Asia/Shanghai')->format('Y-m-d H:i:s');
  80. }
  81. // 获取用户未登录天数(最后第二次登录间隔天数)
  82. public static function getNotLoginDays($memberId)
  83. {
  84. $list = self::where('user_id', $memberId)
  85. ->where('status', self::STATUS_SUCCESS)
  86. ->orderByDesc('id')
  87. ->limit(2)
  88. ->get()
  89. ->toArray();
  90. if (count($list) < 2) {
  91. return 0;
  92. }
  93. if (date('Y-m-d', strtotime($list[0]['created_at'])) != date('Y-m-d')) {
  94. return 0;
  95. }
  96. $diff = strtotime($list[0]['created_at']) - strtotime($list[1]['created_at']);
  97. $days = ceil($diff / 86400);
  98. return abs($days);
  99. }
  100. }