UrsActiveUserService.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. <?php
  2. namespace App\Module\UrsPromotion\Services;
  3. use App\Module\UrsPromotion\Models\UrsUserMapping;
  4. use App\Module\User\Models\User;
  5. use Illuminate\Support\Facades\DB;
  6. use Illuminate\Support\Facades\Log;
  7. use Carbon\Carbon;
  8. /**
  9. * URS活跃用户服务
  10. *
  11. * 负责管理URS用户的活跃状态,包括活跃状态检查、更新和统计
  12. */
  13. class UrsActiveUserService
  14. {
  15. /**
  16. * 活跃用户定义:最近15天有活动的用户
  17. */
  18. const ACTIVE_DAYS_THRESHOLD = 15;
  19. /**
  20. * 更新单个用户的活跃状态
  21. *
  22. * @param int $ursUserId URS用户ID
  23. * @return bool
  24. */
  25. public static function updateUserActiveStatus(int $ursUserId): bool
  26. {
  27. try {
  28. // 获取用户映射关系
  29. $mapping = UrsUserMapping::where('urs_user_id', $ursUserId)
  30. ->where('status', UrsUserMapping::STATUS_VALID)
  31. ->with('user')
  32. ->first();
  33. if (!$mapping || !$mapping->user) {
  34. Log::warning('URS用户映射关系不存在或农场用户不存在', [
  35. 'urs_user_id' => $ursUserId
  36. ]);
  37. return false;
  38. }
  39. // 检查用户活跃状态
  40. $isActive = self::checkUserActivity($mapping->user);
  41. $activeDaysCount = self::calculateActiveDaysCount($mapping->user);
  42. // 更新活跃状态
  43. $mapping->update([
  44. 'is_active' => $isActive ? UrsUserMapping::ACTIVE_YES : UrsUserMapping::ACTIVE_NO,
  45. 'last_activity_check' => now(),
  46. 'active_days_count' => $activeDaysCount,
  47. ]);
  48. Log::info('URS用户活跃状态更新成功', [
  49. 'urs_user_id' => $ursUserId,
  50. 'farm_user_id' => $mapping->user_id,
  51. 'is_active' => $isActive,
  52. 'active_days_count' => $activeDaysCount
  53. ]);
  54. return true;
  55. } catch (\Exception $e) {
  56. Log::error('URS用户活跃状态更新失败', [
  57. 'urs_user_id' => $ursUserId,
  58. 'error' => $e->getMessage()
  59. ]);
  60. return false;
  61. }
  62. }
  63. /**
  64. * 批量更新用户活跃状态
  65. *
  66. * @param int $limit 每次处理的用户数量限制
  67. * @return array 更新结果统计
  68. */
  69. public static function batchUpdateActiveStatus(int $limit = 1000): array
  70. {
  71. $stats = [
  72. 'total_processed' => 0,
  73. 'successful_updates' => 0,
  74. 'failed_updates' => 0,
  75. 'active_users' => 0,
  76. 'inactive_users' => 0,
  77. ];
  78. try {
  79. // 获取需要检查的用户
  80. $mappings = UrsUserMapping::getUsersNeedActivityCheck($limit);
  81. $stats['total_processed'] = $mappings->count();
  82. Log::info('开始批量更新URS用户活跃状态', [
  83. 'total_users' => $stats['total_processed'],
  84. 'limit' => $limit
  85. ]);
  86. foreach ($mappings as $mapping) {
  87. try {
  88. if (!$mapping->user) {
  89. $stats['failed_updates']++;
  90. continue;
  91. }
  92. // 检查用户活跃状态
  93. $isActive = self::checkUserActivity($mapping->user);
  94. $activeDaysCount = self::calculateActiveDaysCount($mapping->user);
  95. // 更新活跃状态
  96. $mapping->update([
  97. 'is_active' => $isActive ? UrsUserMapping::ACTIVE_YES : UrsUserMapping::ACTIVE_NO,
  98. 'last_activity_check' => now(),
  99. 'active_days_count' => $activeDaysCount,
  100. ]);
  101. $stats['successful_updates']++;
  102. if ($isActive) {
  103. $stats['active_users']++;
  104. } else {
  105. $stats['inactive_users']++;
  106. }
  107. } catch (\Exception $e) {
  108. $stats['failed_updates']++;
  109. Log::error('单个用户活跃状态更新失败', [
  110. 'urs_user_id' => $mapping->urs_user_id,
  111. 'error' => $e->getMessage()
  112. ]);
  113. }
  114. }
  115. Log::info('批量更新URS用户活跃状态完成', $stats);
  116. } catch (\Exception $e) {
  117. Log::error('批量更新URS用户活跃状态失败', [
  118. 'error' => $e->getMessage(),
  119. 'stats' => $stats
  120. ]);
  121. }
  122. return $stats;
  123. }
  124. /**
  125. * 检查用户活跃状态
  126. *
  127. * @param User $user 农场用户对象
  128. * @return bool
  129. */
  130. public static function checkUserActivity(User $user): bool
  131. {
  132. if (!$user->last_activity_time) {
  133. return false;
  134. }
  135. $threshold = Carbon::now()->subDays(self::ACTIVE_DAYS_THRESHOLD);
  136. return $user->last_activity_time >= $threshold;
  137. }
  138. /**
  139. * 计算用户活跃天数
  140. *
  141. * @param User $user 农场用户对象
  142. * @return int
  143. */
  144. public static function calculateActiveDaysCount(User $user): int
  145. {
  146. if (!$user->last_activity_time) {
  147. return 0;
  148. }
  149. $daysSinceLastActivity = Carbon::now()->diffInDays($user->last_activity_time);
  150. // 如果在活跃期内,返回1,否则返回0
  151. return $daysSinceLastActivity <= self::ACTIVE_DAYS_THRESHOLD ? 1 : 0;
  152. }
  153. /**
  154. * 获取活跃用户统计信息
  155. *
  156. * @return array
  157. */
  158. public static function getActiveUserStats(): array
  159. {
  160. return UrsUserMapping::getActiveUserStats();
  161. }
  162. /**
  163. * 获取指定URS用户的活跃团队成员
  164. *
  165. * @param int $ursUserId URS用户ID
  166. * @return array
  167. */
  168. public static function getActiveTeamMembers(int $ursUserId): array
  169. {
  170. // 获取用户的推荐关系
  171. $teamMembers = UrsReferralService::getTeamMembers($ursUserId, 3); // 获取三代团队
  172. if (empty($teamMembers)) {
  173. return [
  174. 'active_direct_count' => 0,
  175. 'active_total_count' => 0,
  176. 'active_members' => []
  177. ];
  178. }
  179. // 提取所有团队成员的URS用户ID
  180. $allMemberIds = [];
  181. foreach ($teamMembers as $level => $members) {
  182. $allMemberIds = array_merge($allMemberIds, array_column($members, 'urs_user_id'));
  183. }
  184. // 获取活跃的团队成员
  185. $activeMemberIds = UrsUserMapping::getActiveUrsUserIds($allMemberIds);
  186. // 统计各层级的活跃人数
  187. $activeDirectCount = 0;
  188. $activeTotalCount = count($activeMemberIds);
  189. $activeMembers = [];
  190. foreach ($teamMembers as $level => $members) {
  191. foreach ($members as $member) {
  192. if (in_array($member['urs_user_id'], $activeMemberIds)) {
  193. $activeMembers[] = array_merge($member, ['level' => $level]);
  194. if ($level === 1) { // 直推
  195. $activeDirectCount++;
  196. }
  197. }
  198. }
  199. }
  200. return [
  201. 'active_direct_count' => $activeDirectCount,
  202. 'active_total_count' => $activeTotalCount,
  203. 'active_members' => $activeMembers
  204. ];
  205. }
  206. /**
  207. * 获取活跃用户详细统计
  208. *
  209. * @return array
  210. */
  211. public static function getDetailedActiveStats(): array
  212. {
  213. $baseStats = self::getActiveUserStats();
  214. // 获取最近更新统计
  215. $recentUpdates = UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
  216. ->where('last_activity_check', '>=', now()->subDay())
  217. ->count();
  218. // 获取需要检查的用户数量
  219. $needCheckCount = UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
  220. ->where(function($query) {
  221. $query->whereNull('last_activity_check')
  222. ->orWhere('last_activity_check', '<', now()->subDay());
  223. })
  224. ->count();
  225. return array_merge($baseStats, [
  226. 'recent_updates' => $recentUpdates,
  227. 'need_check_count' => $needCheckCount,
  228. 'last_update_time' => UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
  229. ->whereNotNull('last_activity_check')
  230. ->max('last_activity_check'),
  231. ]);
  232. }
  233. /**
  234. * 重置所有用户的活跃状态(用于测试或重新初始化)
  235. *
  236. * @return array
  237. */
  238. public static function resetAllActiveStatus(): array
  239. {
  240. try {
  241. DB::beginTransaction();
  242. // 重置所有用户的活跃状态
  243. $updated = UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
  244. ->update([
  245. 'is_active' => UrsUserMapping::ACTIVE_NO,
  246. 'last_activity_check' => null,
  247. 'active_days_count' => 0,
  248. ]);
  249. DB::commit();
  250. Log::info('重置所有URS用户活跃状态完成', [
  251. 'updated_count' => $updated
  252. ]);
  253. return [
  254. 'success' => true,
  255. 'updated_count' => $updated,
  256. 'message' => '重置完成'
  257. ];
  258. } catch (\Exception $e) {
  259. DB::rollBack();
  260. Log::error('重置URS用户活跃状态失败', [
  261. 'error' => $e->getMessage()
  262. ]);
  263. return [
  264. 'success' => false,
  265. 'updated_count' => 0,
  266. 'message' => '重置失败:' . $e->getMessage()
  267. ];
  268. }
  269. }
  270. }