99 lines
3.2 KiB
PHP
99 lines
3.2 KiB
PHP
<?php
|
|
|
|
/**
|
|
* 文件功能:扫描并补算用户成就的 Artisan 命令。
|
|
*
|
|
* 支持单用户、全量与最近活跃用户三种扫描方式,便于定时任务和后台补算复用。
|
|
*/
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\User;
|
|
use App\Services\AchievementService;
|
|
use Illuminate\Console\Command;
|
|
|
|
/**
|
|
* 类功能:通过命令行批量检查用户成就进度并写入解锁记录。
|
|
*/
|
|
class ScanAchievementsCommand extends Command
|
|
{
|
|
/**
|
|
* 命令签名。
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $signature = 'achievements:scan
|
|
{--user= : 指定用户 ID 或用户名}
|
|
{--all : 扫描全部用户}
|
|
{--notify : 解锁时向用户推送本人可见通知}
|
|
{--dry-run : 仅预览,不写入成就记录}';
|
|
|
|
/**
|
|
* 命令描述。
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $description = '扫描聊天室用户成就进度并补齐解锁记录';
|
|
|
|
/**
|
|
* 创建命令依赖。
|
|
*/
|
|
public function __construct(
|
|
private readonly AchievementService $achievementService,
|
|
) {
|
|
parent::__construct();
|
|
}
|
|
|
|
/**
|
|
* 执行成就扫描命令。
|
|
*/
|
|
public function handle(): int
|
|
{
|
|
$notify = (bool) $this->option('notify');
|
|
$dryRun = (bool) $this->option('dry-run');
|
|
|
|
if ($this->option('user')) {
|
|
$user = $this->resolveUser((string) $this->option('user'));
|
|
if (! $user) {
|
|
$this->error('未找到指定用户。');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$result = $this->achievementService->scanUser($user, $notify, $dryRun);
|
|
$this->info("已扫描用户 {$user->username}:检查 {$result['checked']} 项,解锁 {$result['unlocked']} 项,更新 {$result['updated']} 项。");
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
$query = User::query()->orderBy('id');
|
|
if (! $this->option('all')) {
|
|
// 默认只扫最近活跃用户,避免定时任务每次全表扫描。
|
|
$query->where('updated_at', '>=', now()->subDay())->limit(200);
|
|
}
|
|
|
|
$summary = ['users' => 0, 'checked' => 0, 'unlocked' => 0, 'updated' => 0, 'dry_run' => $dryRun];
|
|
$query->chunkById(100, function ($users) use (&$summary, $notify, $dryRun): void {
|
|
$chunkSummary = $this->achievementService->scanUsers($users, $notify, $dryRun);
|
|
$summary['users'] += $chunkSummary['users'];
|
|
$summary['checked'] += $chunkSummary['checked'];
|
|
$summary['unlocked'] += $chunkSummary['unlocked'];
|
|
$summary['updated'] += $chunkSummary['updated'];
|
|
});
|
|
|
|
$this->info("成就扫描完成:用户 {$summary['users']} 人,检查 {$summary['checked']} 项,解锁 {$summary['unlocked']} 项,更新 {$summary['updated']} 项。");
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* 根据 ID 或用户名解析用户。
|
|
*/
|
|
private function resolveUser(string $value): ?User
|
|
{
|
|
return User::query()
|
|
->when(is_numeric($value), fn ($query) => $query->where('id', (int) $value), fn ($query) => $query->where('username', $value))
|
|
->first();
|
|
}
|
|
}
|