|
|
@@ -0,0 +1,315 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Module\UrsPromotion\Services;
|
|
|
+
|
|
|
+use App\Module\UrsPromotion\Models\UrsUserMapping;
|
|
|
+use App\Module\User\Models\User;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+use Illuminate\Support\Facades\Log;
|
|
|
+use Carbon\Carbon;
|
|
|
+
|
|
|
+/**
|
|
|
+ * URS活跃用户服务
|
|
|
+ *
|
|
|
+ * 负责管理URS用户的活跃状态,包括活跃状态检查、更新和统计
|
|
|
+ */
|
|
|
+class UrsActiveUserService
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * 活跃用户定义:最近15天有活动的用户
|
|
|
+ */
|
|
|
+ const ACTIVE_DAYS_THRESHOLD = 15;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新单个用户的活跃状态
|
|
|
+ *
|
|
|
+ * @param int $ursUserId URS用户ID
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public static function updateUserActiveStatus(int $ursUserId): bool
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ // 获取用户映射关系
|
|
|
+ $mapping = UrsUserMapping::where('urs_user_id', $ursUserId)
|
|
|
+ ->where('status', UrsUserMapping::STATUS_VALID)
|
|
|
+ ->with('user')
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if (!$mapping || !$mapping->user) {
|
|
|
+ Log::warning('URS用户映射关系不存在或农场用户不存在', [
|
|
|
+ 'urs_user_id' => $ursUserId
|
|
|
+ ]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查用户活跃状态
|
|
|
+ $isActive = self::checkUserActivity($mapping->user);
|
|
|
+ $activeDaysCount = self::calculateActiveDaysCount($mapping->user);
|
|
|
+
|
|
|
+ // 更新活跃状态
|
|
|
+ $mapping->update([
|
|
|
+ 'is_active' => $isActive ? UrsUserMapping::ACTIVE_YES : UrsUserMapping::ACTIVE_NO,
|
|
|
+ 'last_activity_check' => now(),
|
|
|
+ 'active_days_count' => $activeDaysCount,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ Log::info('URS用户活跃状态更新成功', [
|
|
|
+ 'urs_user_id' => $ursUserId,
|
|
|
+ 'farm_user_id' => $mapping->user_id,
|
|
|
+ 'is_active' => $isActive,
|
|
|
+ 'active_days_count' => $activeDaysCount
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return true;
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Log::error('URS用户活跃状态更新失败', [
|
|
|
+ 'urs_user_id' => $ursUserId,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量更新用户活跃状态
|
|
|
+ *
|
|
|
+ * @param int $limit 每次处理的用户数量限制
|
|
|
+ * @return array 更新结果统计
|
|
|
+ */
|
|
|
+ public static function batchUpdateActiveStatus(int $limit = 1000): array
|
|
|
+ {
|
|
|
+ $stats = [
|
|
|
+ 'total_processed' => 0,
|
|
|
+ 'successful_updates' => 0,
|
|
|
+ 'failed_updates' => 0,
|
|
|
+ 'active_users' => 0,
|
|
|
+ 'inactive_users' => 0,
|
|
|
+ ];
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 获取需要检查的用户
|
|
|
+ $mappings = UrsUserMapping::getUsersNeedActivityCheck($limit);
|
|
|
+ $stats['total_processed'] = $mappings->count();
|
|
|
+
|
|
|
+ Log::info('开始批量更新URS用户活跃状态', [
|
|
|
+ 'total_users' => $stats['total_processed'],
|
|
|
+ 'limit' => $limit
|
|
|
+ ]);
|
|
|
+
|
|
|
+ foreach ($mappings as $mapping) {
|
|
|
+ try {
|
|
|
+ if (!$mapping->user) {
|
|
|
+ $stats['failed_updates']++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查用户活跃状态
|
|
|
+ $isActive = self::checkUserActivity($mapping->user);
|
|
|
+ $activeDaysCount = self::calculateActiveDaysCount($mapping->user);
|
|
|
+
|
|
|
+ // 更新活跃状态
|
|
|
+ $mapping->update([
|
|
|
+ 'is_active' => $isActive ? UrsUserMapping::ACTIVE_YES : UrsUserMapping::ACTIVE_NO,
|
|
|
+ 'last_activity_check' => now(),
|
|
|
+ 'active_days_count' => $activeDaysCount,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $stats['successful_updates']++;
|
|
|
+ if ($isActive) {
|
|
|
+ $stats['active_users']++;
|
|
|
+ } else {
|
|
|
+ $stats['inactive_users']++;
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $stats['failed_updates']++;
|
|
|
+ Log::error('单个用户活跃状态更新失败', [
|
|
|
+ 'urs_user_id' => $mapping->urs_user_id,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Log::info('批量更新URS用户活跃状态完成', $stats);
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Log::error('批量更新URS用户活跃状态失败', [
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
+ 'stats' => $stats
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $stats;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查用户活跃状态
|
|
|
+ *
|
|
|
+ * @param User $user 农场用户对象
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public static function checkUserActivity(User $user): bool
|
|
|
+ {
|
|
|
+ if (!$user->last_activity_time) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ $threshold = Carbon::now()->subDays(self::ACTIVE_DAYS_THRESHOLD);
|
|
|
+ return $user->last_activity_time >= $threshold;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算用户活跃天数
|
|
|
+ *
|
|
|
+ * @param User $user 农场用户对象
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ public static function calculateActiveDaysCount(User $user): int
|
|
|
+ {
|
|
|
+ if (!$user->last_activity_time) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ $daysSinceLastActivity = Carbon::now()->diffInDays($user->last_activity_time);
|
|
|
+
|
|
|
+ // 如果在活跃期内,返回1,否则返回0
|
|
|
+ return $daysSinceLastActivity <= self::ACTIVE_DAYS_THRESHOLD ? 1 : 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取活跃用户统计信息
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public static function getActiveUserStats(): array
|
|
|
+ {
|
|
|
+ return UrsUserMapping::getActiveUserStats();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取指定URS用户的活跃团队成员
|
|
|
+ *
|
|
|
+ * @param int $ursUserId URS用户ID
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public static function getActiveTeamMembers(int $ursUserId): array
|
|
|
+ {
|
|
|
+ // 获取用户的推荐关系
|
|
|
+ $teamMembers = UrsReferralService::getTeamMembers($ursUserId, 3); // 获取三代团队
|
|
|
+
|
|
|
+ if (empty($teamMembers)) {
|
|
|
+ return [
|
|
|
+ 'active_direct_count' => 0,
|
|
|
+ 'active_total_count' => 0,
|
|
|
+ 'active_members' => []
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取所有团队成员的URS用户ID
|
|
|
+ $allMemberIds = [];
|
|
|
+ foreach ($teamMembers as $level => $members) {
|
|
|
+ $allMemberIds = array_merge($allMemberIds, array_column($members, 'urs_user_id'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取活跃的团队成员
|
|
|
+ $activeMemberIds = UrsUserMapping::getActiveUrsUserIds($allMemberIds);
|
|
|
+
|
|
|
+ // 统计各层级的活跃人数
|
|
|
+ $activeDirectCount = 0;
|
|
|
+ $activeTotalCount = count($activeMemberIds);
|
|
|
+ $activeMembers = [];
|
|
|
+
|
|
|
+ foreach ($teamMembers as $level => $members) {
|
|
|
+ foreach ($members as $member) {
|
|
|
+ if (in_array($member['urs_user_id'], $activeMemberIds)) {
|
|
|
+ $activeMembers[] = array_merge($member, ['level' => $level]);
|
|
|
+ if ($level === 1) { // 直推
|
|
|
+ $activeDirectCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'active_direct_count' => $activeDirectCount,
|
|
|
+ 'active_total_count' => $activeTotalCount,
|
|
|
+ 'active_members' => $activeMembers
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取活跃用户详细统计
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public static function getDetailedActiveStats(): array
|
|
|
+ {
|
|
|
+ $baseStats = self::getActiveUserStats();
|
|
|
+
|
|
|
+ // 获取最近更新统计
|
|
|
+ $recentUpdates = UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
|
|
|
+ ->where('last_activity_check', '>=', now()->subDay())
|
|
|
+ ->count();
|
|
|
+
|
|
|
+ // 获取需要检查的用户数量
|
|
|
+ $needCheckCount = UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
|
|
|
+ ->where(function($query) {
|
|
|
+ $query->whereNull('last_activity_check')
|
|
|
+ ->orWhere('last_activity_check', '<', now()->subDay());
|
|
|
+ })
|
|
|
+ ->count();
|
|
|
+
|
|
|
+ return array_merge($baseStats, [
|
|
|
+ 'recent_updates' => $recentUpdates,
|
|
|
+ 'need_check_count' => $needCheckCount,
|
|
|
+ 'last_update_time' => UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
|
|
|
+ ->whereNotNull('last_activity_check')
|
|
|
+ ->max('last_activity_check'),
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重置所有用户的活跃状态(用于测试或重新初始化)
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public static function resetAllActiveStatus(): array
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+
|
|
|
+ // 重置所有用户的活跃状态
|
|
|
+ $updated = UrsUserMapping::where('status', UrsUserMapping::STATUS_VALID)
|
|
|
+ ->update([
|
|
|
+ 'is_active' => UrsUserMapping::ACTIVE_NO,
|
|
|
+ 'last_activity_check' => null,
|
|
|
+ 'active_days_count' => 0,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ DB::commit();
|
|
|
+
|
|
|
+ Log::info('重置所有URS用户活跃状态完成', [
|
|
|
+ 'updated_count' => $updated
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'success' => true,
|
|
|
+ 'updated_count' => $updated,
|
|
|
+ 'message' => '重置完成'
|
|
|
+ ];
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ DB::rollBack();
|
|
|
+ Log::error('重置URS用户活跃状态失败', [
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'success' => false,
|
|
|
+ 'updated_count' => 0,
|
|
|
+ 'message' => '重置失败:' . $e->getMessage()
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|