// 成就 BLoC — 通过 API 加载成就列表 import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:nuanji_app/data/remote/api_client.dart'; // ===== 模型 ===== /// 成就数据 class Achievement { final String id; final String code; final String name; final String? description; final String? icon; final String category; final bool isUnlocked; final DateTime? unlockedAt; const Achievement({ required this.id, required this.code, required this.name, this.description, this.icon, required this.category, this.isUnlocked = false, this.unlockedAt, }); } // ===== State ===== /// 成就页面状态 class AchievementState { final List achievements; final bool isLoading; final String? errorMessage; const AchievementState({ this.achievements = const [], this.isLoading = false, this.errorMessage, }); int get unlockedCount => achievements.where((a) => a.isUnlocked).length; AchievementState copyWith({ List? achievements, bool? isLoading, String? errorMessage, }) => AchievementState( achievements: achievements ?? this.achievements, isLoading: isLoading ?? this.isLoading, errorMessage: errorMessage, ); } // ===== BLoC ===== /// 成就 BLoC — ChangeNotifier 模式 class AchievementBloc extends ChangeNotifier { final ApiClient _api; AchievementState _state = const AchievementState(); AchievementState get state => _state; AchievementBloc({required ApiClient api}) : _api = api; /// 加载成就列表 void load() { _state = _state.copyWith(isLoading: true); notifyListeners(); _fetchAchievements(); } Future _fetchAchievements() async { try { final response = await _api.get('/diary/achievements'); final body = response.data as Map; final list = body['data'] as List? ?? []; final achievements = list.map((item) { final m = item as Map; return Achievement( id: m['id'] as String, code: m['code'] as String, name: m['name'] as String, description: m['description'] as String?, icon: m['icon'] as String?, category: m['category'] as String, isUnlocked: m['is_unlocked'] as bool? ?? false, unlockedAt: m['unlocked_at'] != null ? DateTime.tryParse(m['unlocked_at'] as String) : null, ); }).toList(); _state = _state.copyWith(isLoading: false, achievements: achievements); } catch (e) { debugPrint('AchievementBloc._fetchAchievements 失败: $e'); _state = _state.copyWith( isLoading: false, errorMessage: '加载成就列表失败', ); } notifyListeners(); } }