UrsActiveUserService.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  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. // 获取用户信息中的活动时间
  133. $userInfo = $user->info;
  134. if (!$userInfo || !$userInfo->last_activity_time) {
  135. return false;
  136. }
  137. $threshold = Carbon::now()->subDays(self::ACTIVE_DAYS_THRESHOLD);
  138. return $userInfo->last_activity_time >= $threshold;
  139. }
  140. /**
  141. * 计算用户活跃天数
  142. *
  143. * @param User $user 农场用户对象
  144. * @return int
  145. */
  146. public static function calculateActiveDaysCount(User $user): int
  147. {
  148. // 获取用户信息中的活动时间
  149. $userInfo = $user->info;
  150. if (!$userInfo || !$userInfo->last_activity_time) {
  151. return 0;
  152. }
  153. $daysSinceLastActivity = Carbon::now()->diffInDays($userInfo->last_activity_time);
  154. // 如果在活跃期内,返回1,否则返回0
  155. return $daysSinceLastActivity <= self::ACTIVE_DAYS_THRESHOLD ? 1 : 0;
  156. }
  157. /**
  158. * 获取活跃用户统计信息
  159. *
  160. * @return array
  161. */
  162. public static function getActiveUserStats(): array
  163. {
  164. return UrsUserMapping::getActiveUserStats();
  165. }
  166. /**
  167. * 获取指定URS用户的活跃团队成员
  168. *
  169. * @param int $ursUserId URS用户ID
  170. * @return array
  171. */
  172. public static function getActiveTeamMembers(int $ursUserId): array
  173. {
  174. // 获取用户的推荐关系(使用配置的团队统计深度,支持达人等级统计)
  175. $teamMembers = UrsReferralService::getTeamMembers($ursUserId);
  176. if (empty($teamMembers)) {
  177. return [
  178. 'active_direct_count' => 0,
  179. 'active_total_count' => 0,
  180. 'active_members' => []
  181. ];
  182. }
  183. // 提取所有团队成员的URS用户ID
  184. $allMemberIds = [];
  185. foreach ($teamMembers as $level => $members) {
  186. // $members 是一个简单的用户ID数组,不是对象数组
  187. $allMemberIds = array_merge($allMemberIds, $members);
  188. }
  189. // 获取活跃的团队成员
  190. $activeMemberIds = UrsUserMapping::getActiveUrsUserIds($allMemberIds);
  191. // 统计各层级的活跃人数
  192. $activeDirectCount = 0;
  193. $activeTotalCount = count($activeMemberIds);
  194. $activeMembers = [];
  195. foreach ($teamMembers as $level => $members) {
  196. foreach ($members as $memberId) {
  197. if (in_array($memberId, $activeMemberIds)) {
  198. $activeMembers[] = [
  199. 'urs_user_id' => $memberId,
  200. 'level' => $level
  201. ];
  202. if ($level === 1) { // 直推
  203. $activeDirectCount++;
  204. }
  205. }
  206. }
  207. }
  208. return [
  209. 'active_direct_count' => $activeDirectCount,
  210. 'active_total_count' => $activeTotalCount,
  211. 'active_members' => $activeMembers
  212. ];
  213. }
  214. /**
  215. * 获取指定URS用户的活跃直推成员(仅直推层级)
  216. *
  217. * 针对达人等级升级条件优化,只统计直推活跃用户
  218. * 相比getActiveTeamMembers方法,此方法只关注直推层级,性能更优
  219. *
  220. * @param int $ursUserId URS用户ID
  221. * @return array 返回活跃直推统计信息
  222. */
  223. public static function getActiveDirectMembers(int $ursUserId): array
  224. {
  225. // 只获取直推成员(第1层级)
  226. $directMembers = UrsReferralService::getDirectReferrals($ursUserId);
  227. if (empty($directMembers)) {
  228. return [
  229. 'active_direct_count' => 0,
  230. 'active_direct_members' => []
  231. ];
  232. }
  233. // 获取活跃的直推成员
  234. $activeDirectIds = UrsUserMapping::getActiveUrsUserIds($directMembers);
  235. // 构建活跃直推成员详情
  236. $activeDirectMembers = [];
  237. foreach ($activeDirectIds as $memberId) {
  238. $activeDirectMembers[] = [
  239. 'urs_user_id' => $memberId,
  240. 'level' => 1 // 直推层级
  241. ];
  242. }
  243. return [
  244. 'active_direct_count' => count($activeDirectIds),
  245. 'active_direct_members' => $activeDirectMembers
  246. ];
  247. }
  248. /**
  249. * 获取活跃用户详细统计
  250. *
  251. * @return array
  252. */
  253. public static function getDetailedActiveStats(): array
  254. {
  255. $baseStats = self::getActiveUserStats();
  256. // 获取最近更新统计
  257. $recentUpdates = UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
  258. ->where('last_activity_check', '>=', now()->subDay())
  259. ->count();
  260. // 获取需要检查的用户数量
  261. $needCheckCount = UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
  262. ->where(function($query) {
  263. $query->whereNull('last_activity_check')
  264. ->orWhere('last_activity_check', '<', now()->subDay());
  265. })
  266. ->count();
  267. return array_merge($baseStats, [
  268. 'recent_updates' => $recentUpdates,
  269. 'need_check_count' => $needCheckCount,
  270. 'last_update_time' => UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
  271. ->whereNotNull('last_activity_check')
  272. ->max('last_activity_check'),
  273. ]);
  274. }
  275. /**
  276. * 重置所有用户的活跃状态(用于测试或重新初始化)
  277. *
  278. * @return array
  279. */
  280. public static function resetAllActiveStatus(): array
  281. {
  282. try {
  283. DB::beginTransaction();
  284. // 重置所有用户的活跃状态
  285. $updated = UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
  286. ->update([
  287. 'is_active' => UrsUserMapping::ACTIVE_NO,
  288. 'last_activity_check' => null,
  289. 'active_days_count' => 0,
  290. ]);
  291. DB::commit();
  292. Log::info('重置所有URS用户活跃状态完成', [
  293. 'updated_count' => $updated
  294. ]);
  295. return [
  296. 'success' => true,
  297. 'updated_count' => $updated,
  298. 'message' => '重置完成'
  299. ];
  300. } catch (\Exception $e) {
  301. DB::rollBack();
  302. Log::error('重置URS用户活跃状态失败', [
  303. 'error' => $e->getMessage()
  304. ]);
  305. return [
  306. 'success' => false,
  307. 'updated_count' => 0,
  308. 'message' => '重置失败:' . $e->getMessage()
  309. ];
  310. }
  311. }
  312. }