- 清理大量废弃的 barrel 导出文件,移除冗余的中间导出层 - 修复所有相对路径导入错误,统一调整为扁平化模块引用 - 更新多平台 pubspec 版本号与依赖库版本 - 补充后端功能问题管理后台与脚本工具 - 调整部分页面的快捷方式文案适配新功能 - 更新部分翻译覆盖率与API文档
125 lines
3.6 KiB
Dart
125 lines
3.6 KiB
Dart
/// ============================================================
|
|
/// 闲言APP — 学习进度状态管理
|
|
/// 创建时间: 2026-05-10
|
|
/// 更新时间: 2026-05-10
|
|
/// 作用: 学习进度数据加载、目标设置、进度更新
|
|
/// 上次更新: 初始创建
|
|
/// ============================================================
|
|
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../../../core/utils/logger.dart';
|
|
import '../services/user_center_service.dart';
|
|
|
|
class LearningProgressState {
|
|
const LearningProgressState({
|
|
this.isLoading = false,
|
|
this.error,
|
|
this.overviewData,
|
|
this.categoryData,
|
|
this.trendData,
|
|
this.dailyGoal = 10,
|
|
this.todayProgress = 0,
|
|
});
|
|
|
|
final bool isLoading;
|
|
final String? error;
|
|
final Map<String, dynamic>? overviewData;
|
|
final Map<String, dynamic>? categoryData;
|
|
final Map<String, dynamic>? trendData;
|
|
final int dailyGoal;
|
|
final int todayProgress;
|
|
|
|
double get goalCompletionRate =>
|
|
dailyGoal > 0 ? todayProgress / dailyGoal : 0.0;
|
|
|
|
LearningProgressState copyWith({
|
|
bool? isLoading,
|
|
String? error,
|
|
bool clearError = false,
|
|
Map<String, dynamic>? overviewData,
|
|
Map<String, dynamic>? categoryData,
|
|
Map<String, dynamic>? trendData,
|
|
int? dailyGoal,
|
|
int? todayProgress,
|
|
}) {
|
|
return LearningProgressState(
|
|
isLoading: isLoading ?? this.isLoading,
|
|
error: clearError ? null : (error ?? this.error),
|
|
overviewData: overviewData ?? this.overviewData,
|
|
categoryData: categoryData ?? this.categoryData,
|
|
trendData: trendData ?? this.trendData,
|
|
dailyGoal: dailyGoal ?? this.dailyGoal,
|
|
todayProgress: todayProgress ?? this.todayProgress,
|
|
);
|
|
}
|
|
}
|
|
|
|
class LearningProgressNotifier extends Notifier<LearningProgressState> {
|
|
@override
|
|
LearningProgressState build() => const LearningProgressState();
|
|
LearningProgressNotifier();
|
|
|
|
Future<void> loadAll() async {
|
|
state = state.copyWith(isLoading: true, clearError: true);
|
|
try {
|
|
final results = await Future.wait([
|
|
UserCenterService.getStats(),
|
|
UserCenterService.getStats(type: StatsType.category),
|
|
UserCenterService.getStats(
|
|
type: StatsType.trend,
|
|
period: StatsPeriod.week,
|
|
),
|
|
]);
|
|
final overview = results[0];
|
|
final todayViewCount = (overview['today_view_count'] as num?)?.toInt() ?? 0;
|
|
state = state.copyWith(
|
|
isLoading: false,
|
|
overviewData: overview,
|
|
categoryData: results[1],
|
|
trendData: results[2],
|
|
todayProgress: todayViewCount,
|
|
);
|
|
} catch (e) {
|
|
Log.e('加载学习进度失败', e);
|
|
state = state.copyWith(isLoading: false, error: '加载失败');
|
|
}
|
|
}
|
|
|
|
Future<void> setDailyGoal(int goal) async {
|
|
state = state.copyWith(dailyGoal: goal);
|
|
try {
|
|
await UserCenterService.interaction(
|
|
action: InteractionAction.preference,
|
|
extra: 'daily_goal:$goal',
|
|
);
|
|
Log.i('每日目标已设置: $goal');
|
|
} catch (e) {
|
|
Log.w('保存每日目标失败', e);
|
|
}
|
|
}
|
|
|
|
Future<void> updateProgress({
|
|
required int targetId,
|
|
required String targetType,
|
|
required int value,
|
|
}) async {
|
|
try {
|
|
await UserCenterService.interaction(
|
|
action: InteractionAction.progress,
|
|
targetId: targetId,
|
|
targetType: targetType,
|
|
extra: value.clamp(0, 100).toString(),
|
|
);
|
|
Log.i('进度已更新: $targetType:$targetId → $value%');
|
|
} catch (e) {
|
|
Log.e('更新进度失败', e);
|
|
}
|
|
}
|
|
}
|
|
|
|
final learningProgressProvider =
|
|
NotifierProvider<LearningProgressNotifier, LearningProgressState>(
|
|
LearningProgressNotifier.new,
|
|
);
|