UserActivityService.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. namespace App\Module\User\Services;
  3. use App\Module\LCache\Cache;
  4. use App\Module\User\Models\UserInfo;
  5. use Carbon\Carbon;
  6. use Illuminate\Support\Facades\Log;
  7. /**
  8. * 用户活动时间服务类
  9. *
  10. * 负责处理用户登录时间和活动时间的更新逻辑
  11. * 使用缓存机制避免频繁的数据库写入操作
  12. */
  13. class UserActivityService
  14. {
  15. /**
  16. * 缓存键前缀
  17. */
  18. const CACHE_PREFIX = 'user_activity:';
  19. /**
  20. * 缓存过期时间(秒)- 5分钟
  21. */
  22. const CACHE_TTL = 300;
  23. /**
  24. * 活动时间更新间隔(秒)- 1分钟
  25. * 只有距离上次更新超过此间隔才会真正更新数据库
  26. */
  27. const ACTIVITY_UPDATE_INTERVAL = 60;
  28. /**
  29. * 更新用户登录时间
  30. *
  31. * @param int $userId 用户ID
  32. * @param Carbon|null $loginTime 登录时间,默认为当前时间
  33. * @return bool
  34. */
  35. public static function updateLoginTime(int $userId, ?Carbon $loginTime = null): bool
  36. {
  37. try {
  38. $loginTime = $loginTime ?: Carbon::now();
  39. // 获取或创建用户信息记录
  40. $userInfo = UserInfo::firstOrCreate(
  41. ['user_id' => $userId],
  42. ['status' => \App\Module\User\Enums\STATUS2::Normal]
  43. );
  44. // 更新登录时间
  45. $userInfo->last_login_time = $loginTime;
  46. $userInfo->save();
  47. // 同时更新活动时间
  48. self::updateActivityTime($userId, $loginTime, true);
  49. Log::info('用户登录时间已更新', [
  50. 'user_id' => $userId,
  51. 'login_time' => $loginTime->toDateTimeString()
  52. ]);
  53. return true;
  54. } catch (\Exception $e) {
  55. Log::error('更新用户登录时间失败', [
  56. 'user_id' => $userId,
  57. 'error' => $e->getMessage()
  58. ]);
  59. return false;
  60. }
  61. }
  62. /**
  63. * 更新用户活动时间
  64. *
  65. * @param int $userId 用户ID
  66. * @param Carbon|null $activityTime 活动时间,默认为当前时间
  67. * @param bool $forceUpdate 是否强制更新,忽略缓存间隔
  68. * @return bool
  69. */
  70. public static function updateActivityTime(int $userId, ?Carbon $activityTime = null, bool $forceUpdate = false): bool
  71. {
  72. try {
  73. $activityTime = $activityTime ?: Carbon::now();
  74. $cacheKey = self::CACHE_PREFIX . 'last_update:' . $userId;
  75. // 检查缓存,避免频繁更新
  76. if (!$forceUpdate) {
  77. $lastUpdate = Cache::get($cacheKey);
  78. if ($lastUpdate && (time() - $lastUpdate) < self::ACTIVITY_UPDATE_INTERVAL) {
  79. // 距离上次更新时间太短,跳过本次更新
  80. return true;
  81. }
  82. }
  83. // 获取或创建用户信息记录
  84. $userInfo = UserInfo::firstOrCreate(
  85. ['user_id' => $userId],
  86. ['status' => \App\Module\User\Enums\STATUS2::Normal]
  87. );
  88. // 更新活动时间
  89. $userInfo->last_activity_time = $activityTime;
  90. $userInfo->save();
  91. // 更新缓存记录
  92. Cache::put($cacheKey, time(), self::CACHE_TTL);
  93. Log::debug('用户活动时间已更新', [
  94. 'user_id' => $userId,
  95. 'activity_time' => $activityTime->toDateTimeString(),
  96. 'force_update' => $forceUpdate
  97. ]);
  98. return true;
  99. } catch (\Exception $e) {
  100. Log::error('更新用户活动时间失败', [
  101. 'user_id' => $userId,
  102. 'error' => $e->getMessage()
  103. ]);
  104. return false;
  105. }
  106. }
  107. /**
  108. * 获取用户最后登录时间
  109. *
  110. * @param int $userId 用户ID
  111. * @return Carbon|null
  112. */
  113. public static function getLastLoginTime(int $userId): ?Carbon
  114. {
  115. $userInfo = UserInfo::where('user_id', $userId)->first();
  116. return $userInfo?->last_login_time;
  117. }
  118. /**
  119. * 获取用户最后活动时间
  120. *
  121. * @param int $userId 用户ID
  122. * @return Carbon|null
  123. */
  124. public static function getLastActivityTime(int $userId): ?Carbon
  125. {
  126. $userInfo = UserInfo::where('user_id', $userId)->first();
  127. return $userInfo?->last_activity_time;
  128. }
  129. /**
  130. * 批量更新用户活动时间
  131. * 用于定时任务或批量处理场景
  132. *
  133. * @param array $userActivities 用户活动数据 [['user_id' => 1, 'activity_time' => Carbon], ...]
  134. * @return int 成功更新的用户数量
  135. */
  136. public static function batchUpdateActivityTime(array $userActivities): int
  137. {
  138. $successCount = 0;
  139. foreach ($userActivities as $activity) {
  140. if (isset($activity['user_id']) && isset($activity['activity_time'])) {
  141. if (self::updateActivityTime($activity['user_id'], $activity['activity_time'], true)) {
  142. $successCount++;
  143. }
  144. }
  145. }
  146. Log::info('批量更新用户活动时间完成', [
  147. 'total' => count($userActivities),
  148. 'success' => $successCount
  149. ]);
  150. return $successCount;
  151. }
  152. /**
  153. * 清理过期的缓存数据
  154. *
  155. * @return void
  156. */
  157. public static function cleanExpiredCache(): void
  158. {
  159. // 这里可以实现清理逻辑,由于使用了TTL,缓存会自动过期
  160. // 如果需要主动清理,可以在这里实现
  161. Log::debug('用户活动缓存清理完成');
  162. }
  163. }