达人等级逻辑.md 34 KB

URS推广模块 - 达人等级逻辑详解

1. 概述

URS推广模块的达人等级系统是整个推广体系的核心组件,通过评估用户的团队规模和推广能力,将用户划分为不同的达人等级,并根据等级提供相应的收益分成权益。该系统采用6级达人体系,从非达人到顶级达人,每个等级都有明确的升级条件和收益权益。

1.1 设计理念

  • 激励导向:通过等级差异化收益,激励用户积极发展团队
  • 公平透明:升级条件明确,收益分成规则透明
  • 可持续发展:等级设计考虑长期运营和用户成长路径
  • 业务适配:专门为URS业务场景定制,与农场系统深度集成

1.2 核心特性

  • 6级达人体系:从0级非达人到5级顶级达人
  • 双重升级条件:同时考虑直推人数和团队总人数
  • 三代收益分成:支持直推、间推、三推三代收益分成
  • 双重收益类型:推广收益和种植收益两种分成机制
  • 动态等级更新:团队变化时自动重新计算等级
  • 配置化管理:等级要求和收益比例支持后台配置

2. 达人等级体系

2.1 等级结构

等级 名称 直推要求 团队要求(20代) 活跃直推要求 活跃团队要求(20代) 三代人数要求 三代活跃要求 描述
0 非达人 0人 0人 0人 0人 0人 0人 普通用户,无达人等级
1 URS初级达人 3人 10人 2人 3人 10人 3人 初级达人,享有基础推广收益
2 URS中级达人 8人 30人 5人 8人 30人 8人 中级达人,享有更高推广收益
3 URS高级达人 15人 80人 8人 15人 80人 15人 高级达人,享有优质推广收益
4 URS资深达人 30人 200人 15人 30人 200人 30人 资深达人,享有专业推广收益
5 URS顶级达人 50人 500人 25人 50人 500人 50人 顶级达人,享有最高推广收益

2.2 等级枚举定义

enum UrsTalentLevel: int
{
    case NONE = 0;          // 非达人
    case JUNIOR = 1;        // 初级达人
    case INTERMEDIATE = 2;  // 中级达人
    case SENIOR = 3;        // 高级达人
    case EXPERT = 4;        // 资深达人
    case MASTER = 5;        // 顶级达人
}

3. 升级条件和规则

3.1 升级条件

达人等级的升级需要同时满足六个条件:

  1. 直推人数:用户直接推荐的下级用户数量
  2. 团队总人数:包括直推、间推、三推的所有下级用户总数(20代统计)
  3. 活跃直推人数:直推用户中活跃用户的数量
  4. 活跃团队总人数:团队中所有活跃用户的数量(20代统计)
  5. 三代人数:包括直推、间推、三推的用户总数(3代统计)
  6. 三代活跃人数:三代用户中活跃用户的数量(3代统计)

3.1.1 统计指标说明

团队统计维度

  • 20代团队统计:团队总人数和活跃团队总人数使用20代深度统计,包含所有下级用户
  • 3代团队统计:三代人数和三代活跃人数仅统计直推、间推、三推三个层级

活跃用户判定标准

  • 时间范围:最近15天内有活动记录
  • 判定依据:基于用户的 last_activity_time 字段
  • 更新机制:每日定时任务自动更新活跃状态
  • 存储位置:用户映射表(urs_promotion_user_mappings)的 is_active 字段

活跃状态字段

  • is_active:是否活跃(1=活跃,0=不活跃)
  • last_activity_check:最后活跃检查时间
  • active_days_count:活跃天数统计

指标设计说明

  • 三代人数/三代活跃人数:当前阶段数值等于团队人数/团队活跃人数,为后续业务扩展预留
  • 20代统计:提供更全面的团队规模评估,支持深度推广激励
  • 3代统计:保持传统推广模式的兼容性,便于业务对比分析

活跃用户的业务价值

  • 提升推广体系的质量和真实性
  • 避免僵尸用户影响达人等级评估
  • 激励推广者关注用户活跃度而非单纯数量

3.2 升级算法

private static function calculateTalentLevel(
    int $directCount,
    int $totalCount,
    int $activeDirectCount = 0,
    int $activeTotalCount = 0,
    int $threeGenCount = 0,
    int $threeGenActiveCount = 0
): int {
    // 获取等级配置(按等级倒序排列)
    $configs = UrsTalentConfig::where('status', 1)
        ->orderBy('level', 'desc')
        ->get();

    foreach ($configs as $config) {
        // 检查基础条件
        $directCountMet = $directCount >= $config->direct_count_required;
        $totalCountMet = $totalCount >= $config->promotion_count_required;

        // 检查活跃用户条件
        $activeDirectMet = $activeDirectCount >= $config->active_direct_required;
        $activeTotalMet = $activeTotalCount >= $config->active_count_required;

        // 检查三代条件
        $threeGenCountMet = $threeGenCount >= $config->three_gen_count_required;
        $threeGenActiveMet = $threeGenActiveCount >= $config->three_gen_active_required;

        if ($directCountMet && $totalCountMet && $activeDirectMet && $activeTotalMet
            && $threeGenCountMet && $threeGenActiveMet) {
            return $config->level;
        }
    }

    return 0; // 默认等级
}

3.3 升级触发机制

  • 团队成员变化时:新增推荐关系时自动检查升级
  • 活跃状态变化时:用户活跃状态更新时重新计算等级
  • 定期批量更新:系统定期批量重新计算所有用户等级
  • 手动触发更新:管理员可手动触发特定用户的等级更新

3.4 活跃用户管理

3.4.1 活跃状态更新机制

定时任务UrsUpdateActiveStatusCommand

  • 执行频率:每日凌晨2点自动执行
  • 处理方式:批量更新用户活跃状态
  • 性能优化:支持分批处理,避免内存溢出

手动命令

# 正常更新所有用户活跃状态
php artisan urs:update-active-status

# 限制处理500个用户
php artisan urs:update-active-status --limit=500

# 试运行模式(不实际更新)
php artisan urs:update-active-status --dry-run

# 重置所有用户活跃状态
php artisan urs:update-active-status --reset

3.4.2 活跃用户统计服务

UrsActiveUserService 提供以下功能:

  • updateUserActiveStatus():更新单个用户活跃状态
  • batchUpdateActiveStatus():批量更新活跃状态
  • checkUserActivity():检查用户活跃状态
  • getActiveTeamMembers():获取活跃团队成员
  • getActiveUserStats():获取活跃用户统计

4. 收益分成机制

4.1 收益类型

推广收益 (promotion_reward)

  • 触发时机:下级用户进入农场时
  • 分成方式:固定奖励组发放
  • 分成对象:直推、间推、三推上级

种植收益 (planting_reward)

  • 触发时机:下级用户收获作物时
  • 分成方式:按比例分成
  • 分成对象:直推、间推、三推上级

4.2 默认分成比例配置

推广收益分成比例

等级 直推分成 间推分成 三推分成
0级 0% 0% 0%
1级 5% 2% 1%
2级 8% 3% 1.5%
3级 12% 5% 2%
4级 15% 8% 3%
5级 20% 10% 5%

种植收益分成比例

等级 直推分成 间推分成 三推分成
0级 0% 0% 0%
1级 3% 1% 0.5%
2级 5% 2% 1%
3级 8% 3% 1.5%
4级 10% 5% 2%
5级 15% 8% 3%

5. 有效人数(活跃人数)系统

5.1 活跃用户概念

5.1.1 定义和标准

活跃用户定义:在最近15天内有活动记录的用户

判定标准

  • 数据源:基于农场用户表的 last_activity_time 字段
  • 时间阈值:15天(可配置)
  • 更新频率:每日自动更新
  • 存储位置:用户映射表的 is_active 字段

5.1.2 活跃状态字段说明

字段名 类型 说明
is_active TINYINT(1) 是否活跃:1=活跃,0=不活跃
last_activity_check TIMESTAMP 最后活跃检查时间
active_days_count INT 活跃天数统计

5.1.3 业务价值

  1. 质量保证:确保达人等级基于真实活跃用户
  2. 防刷机制:避免僵尸用户影响等级评估
  3. 激励导向:引导推广者关注用户质量而非数量
  4. 数据真实性:提升推广体系的可信度

5.2 活跃用户服务

5.2.1 UrsActiveUserService

核心常量

const ACTIVE_DAYS_THRESHOLD = 15; // 活跃天数阈值

主要方法

// 更新单个用户活跃状态
public static function updateUserActiveStatus(int $ursUserId): bool

// 批量更新活跃状态
public static function batchUpdateActiveStatus(array $ursUserIds): array

// 检查用户活跃状态
public static function checkUserActivity(User $user): bool

// 获取活跃团队成员
public static function getActiveTeamMembers(int $ursUserId): array

// 获取活跃用户统计
public static function getActiveUserStats(): array

5.2.2 活跃状态判定逻辑

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;
}

5.2.3 活跃团队统计

public static function getActiveTeamMembers(int $ursUserId): array
{
    // 获取团队成员
    $teamMembers = UrsReferralService::getTeamMembers($ursUserId);

    // 统计活跃成员
    $activeDirectCount = 0;
    $activeTotalCount = 0;

    // 返回活跃统计
    return [
        'active_direct_count' => $activeDirectCount,
        'active_total_count' => $activeTotalCount,
        'active_members' => $activeMembers
    ];
}

5.3 定时任务管理

5.3.1 UrsUpdateActiveStatusCommand

命令签名urs:update-active-status

支持参数

  • --limit=N:限制处理用户数量
  • --dry-run:试运行模式,不实际更新
  • --reset:重置所有用户活跃状态

执行示例

# 正常更新所有用户
php artisan urs:update-active-status

# 限制处理500个用户
php artisan urs:update-active-status --limit=500

# 试运行模式
php artisan urs:update-active-status --dry-run

# 重置所有状态
php artisan urs:update-active-status --reset

5.3.2 定时任务配置

Crontab配置

# 每日凌晨2点执行
0 2 * * * cd /path/to/project && php artisan urs:update-active-status

Laravel调度配置

// 在 UCore/Providers/CommandServiceProvider.php 中注册
$schedule->command('urs:update-active-status')->dailyAt('02:00');

5.4 活跃用户在达人等级中的应用

5.4.1 等级计算集成

在达人等级计算中,活跃用户条件与基础条件并列:

private static function calculateTalentLevel(
    int $directCount,
    int $totalCount,
    int $activeDirectCount,
    int $activeTotalCount
): int {
    foreach ($configs as $config) {
        $basicConditionsMet = $directCount >= $config->direct_count_required
            && $totalCount >= $config->promotion_count_required;

        $activeConditionsMet = $activeDirectCount >= $config->active_direct_required
            && $activeTotalCount >= $config->active_count_required;

        if ($basicConditionsMet && $activeConditionsMet) {
            return $config->level;
        }
    }
    return 0;
}

5.4.2 升级条件检查

public static function checkUpgradeEligibility(int $userId): array
{
    // 获取活跃团队统计
    $activeStats = UrsActiveUserService::getActiveTeamMembers($ursUserId);

    // 检查各项条件
    $activeDirectMet = $activeStats['active_direct_count'] >= $nextConfig->active_direct_required;
    $activeTotalMet = $activeStats['active_total_count'] >= $nextConfig->active_count_required;

    return [
        'eligible' => $basicConditionsMet && $activeConditionsMet,
        'requirements' => [
            'active_direct_count' => [
                'required' => $nextConfig->active_direct_required,
                'current' => $activeStats['active_direct_count'],
                'met' => $activeDirectMet,
            ],
            'active_total_count' => [
                'required' => $nextConfig->active_count_required,
                'current' => $activeStats['active_total_count'],
                'met' => $activeTotalMet,
            ],
        ]
    ];
}

6. 核心服务和逻辑

6.1 UrsTalentService(服务层)

主要提供对外的静态服务方法:

class UrsTalentService
{
    // 更新用户达人等级
    public static function updateTalentLevel(int $ursUserId): UrsUserTalentDto
    
    // 获取用户达人信息
    public static function getUserTalent(int $ursUserId): ?UrsUserTalentDto
    
    // 批量更新达人等级
    public static function batchUpdateTalentLevels(array $ursUserIds): array
    
    // 获取所有达人等级配置
    public static function getAllTalentConfigs(): array
}

6.2 UrsTalentLogic(逻辑层)

处理具体的业务逻辑:

class UrsTalentLogic
{
    // 更新用户团队统计和达人等级
    public function updateUserTalent(int $userId): ?UrsUserTalent
    
    // 计算团队统计数据
    private function calculateTeamStats(int $userId): array
    
    // 根据团队数据计算达人等级
    private function calculateTalentLevel(int $directCount, int $promotionCount): int
}

7. 数据模型设计

7.1 UrsUserTalent(用户达人等级模型)

class UrsUserTalent extends ModelCore
{
    protected $table = 'urs_promotion_user_talents';
    
    // 主要字段
    // urs_user_id: URS用户ID
    // talent_level: 达人等级
    // direct_count: 直推人数
    // indirect_count: 间推人数
    // third_count: 三推人数
    // promotion_count: 团队总人数
    // last_level_update_time: 最后等级更新时间
}

7.2 UrsTalentConfig(达人等级配置模型)

class UrsTalentConfig extends ModelCore
{
    protected $table = 'urs_promotion_talent_configs';

    // 主要字段
    // level: 等级
    // name: 等级名称
    // direct_count_required: 所需直推人数
    // promotion_count_required: 所需团队总人数
    // active_direct_required: 所需活跃直推人数
    // active_count_required: 所需活跃团队总人数
    // three_gen_count_required: 所需三代人数
    // three_gen_active_required: 所需三代活跃人数
    // promotion_direct_group: 直推奖励组ID
    // promotion_indirect_group: 间推奖励组ID
    // promotion_third_group: 三推奖励组ID
    // planting_direct_rate: 直推分成比例
    // planting_indirect_rate: 间推分成比例
    // planting_third_rate: 三推分成比例
}

7.3 UrsUserMapping(用户映射关系模型)

class UrsUserMapping extends ModelCore
{
    protected $table = 'urs_promotion_user_mappings';

    // 活跃状态相关字段
    // is_active: 是否活跃(1=活跃,0=不活跃)
    // last_activity_check: 最后活跃检查时间
    // active_days_count: 活跃天数统计

    // 活跃状态常量
    const ACTIVE_NO = 0;  // 不活跃
    const ACTIVE_YES = 1; // 活跃

    // 活跃用户相关方法
    public function isActive(): bool;
    public static function getActiveUrsUserIds(array $ursUserIds): array;
    public static function getActiveUserStats(): array;
    public static function batchUpdateActiveStatus(array $activeData): int;
}

8. 业务流程图

8.1 达人等级升级流程

graph TD
    A[团队成员变化] --> B[获取用户团队统计]
    B --> C[计算直推人数]
    B --> D[计算间推人数]
    B --> E[计算三推人数]
    C --> F[计算团队总人数]
    D --> F
    E --> F
    F --> G[获取等级配置]
    G --> H[按等级倒序遍历]
    H --> I{满足升级条件?}
    I -->|是| J[更新达人等级]
    I -->|否| K[检查下一等级]
    K --> I
    J --> L[记录升级时间]
    L --> M[触发升级事件]
    M --> N[返回达人信息]

8.2 收益分成流程

graph TD
    A[收益产生事件] --> B[获取产生收益的用户]
    B --> C[查询用户的推荐关系链]
    C --> D[遍历上级用户]
    D --> E[检查用户映射关系]
    E --> F{用户已进入农场?}
    F -->|否| G[跳过该用户]
    F -->|是| H[获取用户达人等级]
    G --> I[继续处理上级]
    H --> J[根据等级和层级计算分成]
    J --> K[发放收益奖励]
    K --> L[记录收益明细]
    L --> I
    I --> M{还有上级?}
    M -->|是| D
    M -->|否| N[分成完成]

9. 配置管理

9.1 等级配置表结构

CREATE TABLE `kku_urs_promotion_talent_configs` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `level` tinyint NOT NULL COMMENT '等级:0无,1初级,2中级,3高级,4资深,5顶级',
  `name` varchar(50) NOT NULL COMMENT '等级名称',
  `direct_count_required` int NOT NULL DEFAULT '0' COMMENT '所需直推人数',
  `promotion_count_required` int NOT NULL DEFAULT '0' COMMENT '所需团队总人数',
  `active_direct_required` int NOT NULL DEFAULT '0' COMMENT '所需活跃直推人数',
  `active_count_required` int NOT NULL DEFAULT '0' COMMENT '所需活跃团队总人数',
  `three_gen_count_required` int NOT NULL DEFAULT '0' COMMENT '所需三代人数',
  `three_gen_active_required` int NOT NULL DEFAULT '0' COMMENT '所需三代活跃人数',
  `icon` varchar(255) DEFAULT NULL COMMENT '等级图标',
  `description` text COMMENT '等级描述',
  `sort_order` int NOT NULL DEFAULT '0' COMMENT '排序权重',
  `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:1启用,0禁用',
  `promotion_direct_group` int NOT NULL DEFAULT '0' COMMENT '直推奖励组ID',
  `promotion_indirect_group` int NOT NULL DEFAULT '0' COMMENT '间推奖励组ID',
  `promotion_third_group` int NOT NULL DEFAULT '0' COMMENT '三推奖励组ID',
  `planting_direct_rate` decimal(8,6) NOT NULL DEFAULT '0.000000' COMMENT '直推分成比例',
  `planting_indirect_rate` decimal(8,6) NOT NULL DEFAULT '0.000000' COMMENT '间推分成比例',
  `planting_third_rate` decimal(8,6) NOT NULL DEFAULT '0.000000' COMMENT '三推分成比例',
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_level` (`level`),
  KEY `idx_status` (`status`),
  KEY `idx_sort_order` (`sort_order`)
);

9.2 用户映射表活跃字段结构

-- 为用户映射表添加活跃状态字段
ALTER TABLE `kku_urs_promotion_user_mappings`
ADD COLUMN `is_active` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '是否活跃:1活跃,0不活跃' AFTER `status`,
ADD COLUMN `last_activity_check` TIMESTAMP NULL COMMENT '最后活跃检查时间' AFTER `is_active`,
ADD COLUMN `active_days_count` INT NOT NULL DEFAULT '0' COMMENT '活跃天数统计' AFTER `last_activity_check`,
ADD INDEX `idx_is_active` (`is_active`),
ADD INDEX `idx_last_activity_check` (`last_activity_check`);

9.3 配置管理方法

// 获取推广收益奖励组ID
public function getPromotionRewardGroupId(int $relationLevel): ?int
{
    return match($relationLevel) {
        1 => $this->promotion_direct_group ?: null,
        2 => $this->promotion_indirect_group ?: null,
        3 => $this->promotion_third_group ?: null,
        default => null,
    };
}

// 获取种植收益分成比例
public function getPlantingRewardRate(int $relationLevel): float
{
    return match($relationLevel) {
        1 => (float)$this->planting_direct_rate,
        2 => (float)$this->planting_indirect_rate,
        3 => (float)$this->planting_third_rate,
        default => 0.0,
    };
}

// 检查是否满足升级条件
public function meetsRequirements(
    int $directCount,
    int $promotionCount,
    int $activeDirectCount = 0,
    int $activeTotalCount = 0,
    int $threeGenCount = 0,
    int $threeGenActiveCount = 0
): bool {
    return $directCount >= $this->direct_count_required
        && $promotionCount >= $this->promotion_count_required
        && $activeDirectCount >= $this->active_direct_required
        && $activeTotalCount >= $this->active_count_required
        && $threeGenCount >= $this->three_gen_count_required
        && $threeGenActiveCount >= $this->three_gen_active_required;
}

10. 使用示例

10.1 更新用户达人等级

use App\Module\UrsPromotion\Services\UrsTalentService;

// 更新单个用户的达人等级
$ursUserId = 12345;
$talentDto = UrsTalentService::updateTalentLevel($ursUserId);

echo "用户 {$ursUserId} 的达人等级:{$talentDto->talentName}";
echo "直推人数:{$talentDto->directCount}";
echo "团队总人数:{$talentDto->promotionCount}";

10.2 批量更新达人等级

// 批量更新多个用户的达人等级
$ursUserIds = [12345, 12346, 12347];
$results = UrsTalentService::batchUpdateTalentLevels($ursUserIds);

foreach ($results as $ursUserId => $result) {
    if ($result['success']) {
        echo "用户 {$ursUserId} 更新成功,等级:{$result['talent_level']}";
    } else {
        echo "用户 {$ursUserId} 更新失败:{$result['error']}";
    }
}

10.3 获取用户达人信息

// 获取用户的达人信息
$ursUserId = 12345;
$talentDto = UrsTalentService::getUserTalent($ursUserId);

if ($talentDto) {
    echo "达人等级:{$talentDto->talentName}";
    echo "当前配置:" . json_encode($talentDto->currentConfig);
    echo "下一等级:" . json_encode($talentDto->nextConfig);
}

10.4 获取等级配置

// 获取所有达人等级配置
$configs = UrsTalentService::getAllTalentConfigs();

foreach ($configs as $config) {
    echo "等级 {$config['level']}:{$config['name']}";
    echo "直推要求:{$config['direct_count_required']}人";
    echo "团队要求:{$config['promotion_count_required']}人";
}

11. 事件系统

11.1 达人等级升级事件

use App\Module\UrsPromotion\Events\UrsTalentLevelUpEvent;

// 事件定义
class UrsTalentLevelUpEvent
{
    public int $ursUserId;
    public int $oldLevel;
    public int $newLevel;
    public array $teamStats;

    public function __construct(int $ursUserId, int $oldLevel, int $newLevel, array $teamStats)
    {
        $this->ursUserId = $ursUserId;
        $this->oldLevel = $oldLevel;
        $this->newLevel = $newLevel;
        $this->teamStats = $teamStats;
    }
}

// 事件触发
if ($newLevel > $talent->talent_level) {
    event(new UrsTalentLevelUpEvent(
        $ursUserId,
        $talent->talent_level,
        $newLevel,
        $stats
    ));
}

11.2 事件监听器

use App\Module\UrsPromotion\Listeners\UrsTalentLevelUpListener;

class UrsTalentLevelUpListener
{
    public function handle(UrsTalentLevelUpEvent $event): void
    {
        // 记录升级日志
        Log::info('URS达人等级升级', [
            'urs_user_id' => $event->ursUserId,
            'old_level' => $event->oldLevel,
            'new_level' => $event->newLevel,
            'team_stats' => $event->teamStats
        ]);

        // 发送升级通知
        // 触发相关任务完成
        // 更新用户权益
    }
}

12. 数据统计和分析

12.1 达人等级分布统计

use App\Module\UrsPromotion\Models\UrsUserTalent;

// 获取达人等级分布
$levelDistribution = UrsUserTalent::selectRaw('talent_level, COUNT(*) as count')
    ->groupBy('talent_level')
    ->orderBy('talent_level')
    ->get()
    ->pluck('count', 'talent_level')
    ->toArray();

// 输出结果
foreach ($levelDistribution as $level => $count) {
    $levelName = UrsTalentLevel::getLevelName($level);
    echo "{$levelName}:{$count}人";
}

12.2 团队规模统计

// 获取团队规模统计
$teamStats = UrsUserTalent::selectRaw('
    AVG(direct_count) as avg_direct,
    AVG(indirect_count) as avg_indirect,
    AVG(third_count) as avg_third,
    AVG(promotion_count) as avg_total,
    MAX(promotion_count) as max_team_size
')->first();

echo "平均直推人数:{$teamStats->avg_direct}";
echo "平均间推人数:{$teamStats->avg_indirect}";
echo "平均三推人数:{$teamStats->avg_third}";
echo "平均团队总人数:{$teamStats->avg_total}";
echo "最大团队规模:{$teamStats->max_team_size}";

12.3 达人排行榜

// 获取达人排行榜(按团队总人数排序)
$topTalents = UrsUserTalent::where('talent_level', '>', 0)
    ->orderBy('promotion_count', 'desc')
    ->orderBy('talent_level', 'desc')
    ->limit(50)
    ->get();

foreach ($topTalents as $index => $talent) {
    $rank = $index + 1;
    $levelName = $talent->getTalentLevelName();
    echo "第{$rank}名:用户{$talent->urs_user_id} - {$levelName} - 团队{$talent->promotion_count}人";
}

13. 性能优化

13.1 缓存策略

use Illuminate\Support\Facades\Cache;

class UrsTalentService
{
    // 缓存用户达人信息
    public static function getUserTalentCached(int $ursUserId): ?UrsUserTalentDto
    {
        $cacheKey = "urs_talent:{$ursUserId}";

        return Cache::remember($cacheKey, 3600, function () use ($ursUserId) {
            return self::getUserTalent($ursUserId);
        });
    }

    // 清除用户达人缓存
    public static function clearUserTalentCache(int $ursUserId): void
    {
        $cacheKey = "urs_talent:{$ursUserId}";
        Cache::forget($cacheKey);
    }

    // 缓存等级配置
    public static function getAllTalentConfigsCached(): array
    {
        return Cache::remember('urs_talent_configs', 7200, function () {
            return self::getAllTalentConfigs();
        });
    }
}

13.2 批量处理优化

// 批量更新优化
public static function batchUpdateTalentLevelsOptimized(array $ursUserIds): array
{
    $results = [];

    // 分批处理,避免内存溢出
    $chunks = array_chunk($ursUserIds, 100);

    foreach ($chunks as $chunk) {
        DB::transaction(function () use ($chunk, &$results) {
            foreach ($chunk as $ursUserId) {
                try {
                    $talent = self::updateTalentLevel($ursUserId);
                    $results[$ursUserId] = [
                        'success' => true,
                        'talent_level' => $talent->talentLevel,
                    ];
                } catch (\Exception $e) {
                    $results[$ursUserId] = [
                        'success' => false,
                        'error' => $e->getMessage(),
                    ];
                }
            }
        });
    }

    return $results;
}

14. 测试和调试

14.1 单元测试示例

use Tests\TestCase;
use App\Module\UrsPromotion\Services\UrsTalentService;

class UrsTalentServiceTest extends TestCase
{
    public function testUpdateTalentLevel()
    {
        // 准备测试数据
        $userId = 12345;

        // 执行测试
        $result = UrsTalentService::updateTalentLevel($userId);

        // 断言结果
        $this->assertInstanceOf(UrsUserTalentDto::class, $result);
        $this->assertEquals($userId, $result->user_id);
        $this->assertGreaterThanOrEqual(0, $result->talentLevel);
    }

    public function testCalculateTalentLevel()
    {
        // 测试等级计算逻辑
        $directCount = 5;
        $totalCount = 15;

        // 应该达到中级达人等级
        $expectedLevel = 2;

        // 这里需要通过反射或其他方式测试私有方法
        // 或者创建公共的测试方法
    }
}

14.2 调试命令

use Illuminate\Console\Command;

class TestUrsTalentCommand extends Command
{
    protected $signature = 'urs:test-talent {urs_user_id}';
    protected $description = '测试URS达人等级功能';

    public function handle()
    {
        $ursUserId = $this->argument('urs_user_id');

        $this->info("测试用户 {$ursUserId} 的达人等级功能");

        // 获取团队统计
        $stats = UrsReferralService::getReferralStats($ursUserId);
        $this->table(['项目', '数值'], [
            ['直推人数', $stats['direct_count']],
            ['间推人数', $stats['indirect_count']],
            ['三推人数', $stats['third_count']],
            ['团队总人数', $stats['total_team_count']],
        ]);

        // 更新达人等级
        $talent = UrsTalentService::updateTalentLevel($ursUserId);
        $this->info("达人等级:{$talent->talentName}");

        // 显示配置信息
        if ($talent->currentConfig) {
            $this->info("当前等级配置:" . json_encode($talent->currentConfig, JSON_UNESCAPED_UNICODE));
        }

        if ($talent->nextConfig) {
            $this->info("下一等级配置:" . json_encode($talent->nextConfig, JSON_UNESCAPED_UNICODE));
        }
    }
}

15. 注意事项和最佳实践

15.1 开发注意事项

  1. 数据一致性

    • 所有涉及等级更新的操作必须使用数据库事务
    • 团队统计数据与推荐关系数据保持一致
    • 等级更新时同步更新相关缓存
  2. 性能考虑

    • 大批量用户的等级更新应分批处理
    • 频繁查询的数据使用缓存机制
    • 复杂的团队统计查询考虑使用索引优化
  3. 业务逻辑

    • 等级只能升级不能降级(除非特殊业务需求)
    • 升级条件必须同时满足直推和团队总人数要求
    • 分成比例配置变更不影响历史收益记录
  4. 安全验证

    • 所有用户ID参数必须验证有效性
    • 等级配置修改需要管理员权限
    • 防止恶意刷等级行为

15.2 维护建议

  1. 定期检查

    • 定期检查团队统计数据的准确性
    • 监控异常的等级升级情况
    • 检查配置数据的合理性
  2. 日志记录

    • 记录所有等级变更操作
    • 记录批量更新的执行情况
    • 记录异常和错误信息
  3. 监控告警

    • 监控等级更新的执行时间
    • 监控异常升级的用户
    • 监控系统性能指标

15.3 扩展考虑

  1. 等级体系扩展

    • 预留更高等级的扩展空间
    • 支持特殊等级或荣誉等级
    • 考虑等级有效期机制
  2. 收益类型扩展

    • 支持更多收益来源类型
    • 支持动态分成比例
    • 支持等级专属奖励
  3. 统计维度扩展

    • 支持更多团队统计维度
    • 支持时间段内的活跃度统计
    • 支持团队质量评估

16. 常见问题解答

16.1 等级计算相关

Q: 为什么我的团队人数够了但等级没有升级? A: 达人等级升级需要同时满足直推人数和团队总人数两个条件,请检查直推人数是否达标。

Q: 等级更新的频率是多少? A: 系统会在团队成员变化时自动触发等级更新,同时也支持定期批量更新和手动触发更新。

Q: 等级会降级吗? A: 默认情况下等级只升不降,除非有特殊的业务需求或管理员手动调整。

16.2 收益分成相关

Q: 收益分成是如何计算的? A: 根据用户的达人等级和推荐关系层级,按照配置的分成比例进行计算。推广收益使用固定奖励组,种植收益使用比例分成。

Q: 如果上级用户没有进入农场怎么办? A: 系统会跳过未进入农场的用户,继续向上级分发收益,确保有效用户能够获得应得的收益。

Q: 分成比例可以修改吗? A: 分成比例支持后台配置修改,但修改只影响新产生的收益,不会影响历史收益记录。

16.3 技术实现相关

Q: 如何处理大量用户的等级更新? A: 使用批量处理机制,分批更新用户等级,避免内存溢出和数据库压力过大。

Q: 缓存策略是什么? A: 用户达人信息缓存1小时,等级配置缓存2小时,在数据更新时及时清除相关缓存。

Q: 如何保证数据一致性? A: 所有涉及多表操作的功能都使用数据库事务,确保数据的一致性和完整性。

16.4 活跃用户相关

Q: 什么是活跃用户?如何判定? A: 活跃用户是指最近15天内有活动记录的用户,基于农场用户的 last_activity_time 字段判定。系统每日自动更新活跃状态。

Q: 活跃用户条件是否会影响已有的达人等级? A: 活跃用户条件是新增的升级要求,与原有条件并列。如果用户的活跃团队成员不足,可能会影响等级升级,但不会导致等级降级。

Q: 如何提高团队的活跃度? A: 推广者应该关注推荐用户的质量,引导用户积极参与农场活动,而不是单纯追求推荐数量。

Q: 活跃状态更新失败怎么办? A: 可以使用命令 php artisan urs:update-active-status --limit=100 进行小批量重试,或联系技术人员检查系统状态。

17. 总结

URS推广模块的达人等级系统是一个完整的用户激励体系,通过6级达人等级、四重升级条件(直推人数、团队总人数、活跃直推人数、活跃团队总人数)、三代收益分成等机制,有效激励用户发展高质量团队,提升用户活跃度和粘性。

17.1 核心优势

  1. 体系完整:从等级定义到收益分成,形成完整的激励闭环
  2. 质量导向:引入活跃用户概念,确保推广体系的真实性和有效性
  3. 配置灵活:支持后台配置管理,适应业务发展需要
  4. 性能优化:采用缓存、批量处理等优化策略,保证系统性能
  5. 扩展性强:预留扩展接口,支持未来业务发展需求

17.2 应用价值

  1. 用户激励:通过等级差异化收益,激励用户积极发展高质量团队
  2. 质量保证:活跃用户机制确保推广体系的真实性和可持续性
  3. 社交裂变:推荐关系形成社交网络,促进用户增长
  4. 收益分配:公平透明的收益分成机制,提升用户满意度
  5. 数据驱动:完整的统计分析功能,支持运营决策

17.3 持续优化

达人等级系统作为核心业务功能,需要持续关注用户反馈,优化升级条件和收益配置,确保系统的公平性和激励效果。同时要关注系统性能,及时优化查询和计算逻辑,保证用户体验。


文档版本:v1.0.0 创建时间:2025年06月16日 最后更新:2025年06月16日 维护人员:URS推广模块开发团队

注意:本文档详细描述了URS推广模块的达人等级逻辑,请在开发和维护过程中严格遵循相关规范和最佳实践。

```