diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index c46e3d5..e89d57d 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -161,14 +161,8 @@ class UserController extends Controller 'expires_at' => $signIdentity->expires_at?->toIso8601String(), ] : null, ]; - // 名片展示前先静默补算一次,避免进度已达标但解锁记录尚未落库。 - $this->achievementService->scanUser($targetUser); - $achievementDisplay = $this->achievementService->displayForUser($targetUser); - $data['achievements'] = [ - 'unlocked_count' => $achievementDisplay['unlocked_count'], - 'total_count' => $achievementDisplay['total_count'], - 'recent' => $this->achievementService->recentUnlockedForUser($targetUser, 5)->values()->all(), - ]; + // 名片弹窗只读取已缓存的成就摘要,避免双击用户时同步扫描全量日志造成卡顿。 + $data['achievements'] = $this->achievementService->profileSummaryForUser($targetUser); // 管理员网络信息仅对站长或拥有「封IP」职务权限的操作者展示。 $canViewNetworkInfo = $operator diff --git a/app/Services/AchievementService.php b/app/Services/AchievementService.php index 5465bdc..2cab196 100644 --- a/app/Services/AchievementService.php +++ b/app/Services/AchievementService.php @@ -194,6 +194,23 @@ class AchievementService }); } + /** + * 读取用户资料卡使用的成就摘要。 + * + * @return array{unlocked_count: int, total_count: int, recent: array>} + */ + public function profileSummaryForUser(User $user): array + { + return [ + 'unlocked_count' => (int) UserAchievement::query() + ->where('user_id', $user->id) + ->whereNotNull('achieved_at') + ->count(), + 'total_count' => count(AchievementCatalog::definitions()), + 'recent' => $this->recentUnlockedForUser($user, 5)->values()->all(), + ]; + } + /** * 聚合单个用户所有成就进度。 * diff --git a/tests/Feature/UserControllerTest.php b/tests/Feature/UserControllerTest.php index 15ca701..3815f16 100644 --- a/tests/Feature/UserControllerTest.php +++ b/tests/Feature/UserControllerTest.php @@ -13,6 +13,7 @@ use App\Models\Position; use App\Models\Room; use App\Models\Sysparam; use App\Models\User; +use App\Models\UserAchievement; use App\Models\UserCurrencyLog; use App\Models\UserPosition; use App\Services\ChatUserPresenceService; @@ -65,6 +66,31 @@ class UserControllerTest extends TestCase ->assertJsonPath('data.user_level', 10); } + /** + * 测试用户资料卡只读取已缓存的成就摘要,避免打开名片时触发全量扫描。 + */ + public function test_user_profile_uses_cached_achievement_summary(): void + { + $viewer = User::factory()->create(); + $target = User::factory()->create([ + 'username' => 'achievement-target', + ]); + + UserAchievement::factory()->create([ + 'user_id' => $target->id, + 'achievement_key' => 'chat_first_message', + 'progress_value' => 1, + 'achieved_at' => now(), + ]); + + $response = $this->actingAs($viewer)->getJson("/user/{$target->username}"); + + $response->assertOk() + ->assertJsonPath('data.achievements.unlocked_count', 1) + ->assertJsonPath('data.achievements.recent.0.key', 'chat_first_message') + ->assertJsonMissingPath('data.achievements.achievements'); + } + /** * 测试普通用户查看别人名片时银行存款默认显示星号。 */