UserLogin.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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. 'login_domain',
  20. 'country',
  21. 'browser',
  22. 'os',
  23. 'platform',
  24. 'status',
  25. 'logout_time',
  26. 'online_duration',
  27. 'user_agent',
  28. ];
  29. // 登录日志需要展示登录时间
  30. protected $hidden = [];
  31. protected $appends = ['status_text', 'is_online', 'online_duration_live'];
  32. public const STATUS_FAIL = 0;
  33. public const STATUS_SUCCESS = 1;
  34. public function getStatusTextAttribute(): string
  35. {
  36. return (int)($this->attributes['status'] ?? self::STATUS_FAIL) === self::STATUS_SUCCESS
  37. ? '登录成功'
  38. : '登录失败';
  39. }
  40. public function getIsOnlineAttribute(): bool
  41. {
  42. if ((int)($this->attributes['status'] ?? self::STATUS_FAIL) !== self::STATUS_SUCCESS) {
  43. return false;
  44. }
  45. $logout = $this->attributes['logout_time'] ?? null;
  46. return empty($logout) || $logout === '0000-00-00 00:00:00';
  47. }
  48. /**
  49. * 展示用在线时长(分钟):
  50. * - 已登出:库内 online_duration
  51. * - 仍在线:按登录时间估算(不写库)
  52. * - 失败:null
  53. */
  54. public function getOnlineDurationLiveAttribute(): ?int
  55. {
  56. if ((int)($this->attributes['status'] ?? self::STATUS_FAIL) !== self::STATUS_SUCCESS) {
  57. return null;
  58. }
  59. $stored = $this->attributes['online_duration'] ?? null;
  60. if ($stored !== null && $stored !== '') {
  61. return (int)$stored;
  62. }
  63. if (!$this->is_online) {
  64. return null;
  65. }
  66. $rawCreated = $this->attributes['created_at'] ?? null;
  67. if (empty($rawCreated)) {
  68. return null;
  69. }
  70. $loginTs = strtotime((string)$rawCreated);
  71. if (!$loginTs) {
  72. return null;
  73. }
  74. return (int)ceil(max(0, time() - $loginTs) / 60);
  75. }
  76. public function getLogoutTimeAttribute($value): ?string
  77. {
  78. if (empty($value) || $value === '0000-00-00 00:00:00') {
  79. return null;
  80. }
  81. return Carbon::parse($value)->setTimezone('Asia/Shanghai')->format('Y-m-d H:i:s');
  82. }
  83. // 获取用户未登录天数(最后第二次登录间隔天数)
  84. public static function getNotLoginDays($memberId)
  85. {
  86. $list = self::where('user_id', $memberId)
  87. ->where('status', self::STATUS_SUCCESS)
  88. ->orderByDesc('id')
  89. ->limit(2)
  90. ->get()
  91. ->toArray();
  92. if (count($list) < 2) {
  93. return 0;
  94. }
  95. if (date('Y-m-d', strtotime($list[0]['created_at'])) != date('Y-m-d')) {
  96. return 0;
  97. }
  98. $diff = strtotime($list[0]['created_at']) - strtotime($list[1]['created_at']);
  99. $days = ceil($diff / 86400);
  100. return abs($days);
  101. }
  102. }