190 lines
5.7 KiB
Dart
190 lines
5.7 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import '../models/reading_exercise_model.dart';
|
|
import '../services/reading_service.dart';
|
|
|
|
/// 阅读材料列表状态
|
|
class ReadingMaterialsState {
|
|
final List<ReadingExercise> materials;
|
|
final bool isLoading;
|
|
final String? error;
|
|
|
|
ReadingMaterialsState({
|
|
this.materials = const [],
|
|
this.isLoading = false,
|
|
this.error,
|
|
});
|
|
|
|
ReadingMaterialsState copyWith({
|
|
List<ReadingExercise>? materials,
|
|
bool? isLoading,
|
|
String? error,
|
|
}) {
|
|
return ReadingMaterialsState(
|
|
materials: materials ?? this.materials,
|
|
isLoading: isLoading ?? this.isLoading,
|
|
error: error,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 阅读材料列表 Notifier
|
|
class ReadingMaterialsNotifier extends StateNotifier<ReadingMaterialsState> {
|
|
final ReadingService _readingService;
|
|
|
|
ReadingMaterialsNotifier(this._readingService) : super(ReadingMaterialsState());
|
|
|
|
/// 加载阅读材料列表
|
|
Future<void> loadMaterials({
|
|
String? category,
|
|
String? difficulty,
|
|
int page = 1,
|
|
}) async {
|
|
state = state.copyWith(isLoading: true, error: null);
|
|
|
|
try {
|
|
final materials = await _readingService.getArticles(
|
|
category: category,
|
|
difficulty: difficulty,
|
|
page: page,
|
|
);
|
|
|
|
// 将后端数据转换为前端模型
|
|
final exercises = materials.map<ReadingExercise>((article) {
|
|
return ReadingExercise(
|
|
id: article.id,
|
|
title: article.title,
|
|
content: article.content,
|
|
summary: '', // 后端ReadingArticle没有summary字段
|
|
type: _mapCategoryToType(article.category),
|
|
difficulty: _mapDifficultyLevel(article.difficulty),
|
|
wordCount: article.wordCount,
|
|
estimatedTime: article.estimatedReadingTime,
|
|
questions: [], // 题目需要单独获取
|
|
tags: article.tags, // 已经是List<String>
|
|
source: article.source,
|
|
publishDate: article.publishDate,
|
|
imageUrl: '', // 后端暂无图片字段
|
|
);
|
|
}).toList();
|
|
|
|
state = state.copyWith(materials: exercises, isLoading: false);
|
|
} catch (e) {
|
|
state = state.copyWith(
|
|
isLoading: false,
|
|
error: e.toString(),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 获取推荐材料
|
|
Future<void> loadRecommendedMaterials() async {
|
|
state = state.copyWith(isLoading: true, error: null);
|
|
|
|
try {
|
|
final materials = await _readingService.getRecommendedArticles(limit: 3);
|
|
|
|
final exercises = materials.map<ReadingExercise>((article) {
|
|
return ReadingExercise(
|
|
id: article.id,
|
|
title: article.title,
|
|
content: article.content,
|
|
summary: '', // 后端ReadingArticle没有summary字段
|
|
type: _mapCategoryToType(article.category),
|
|
difficulty: _mapDifficultyLevel(article.difficulty),
|
|
wordCount: article.wordCount,
|
|
estimatedTime: article.estimatedReadingTime,
|
|
questions: [],
|
|
tags: article.tags, // 已经是List<String>
|
|
source: article.source,
|
|
publishDate: article.publishDate,
|
|
imageUrl: '', // 后端暂无图片字段
|
|
);
|
|
}).toList();
|
|
|
|
state = state.copyWith(materials: exercises, isLoading: false);
|
|
} catch (e) {
|
|
state = state.copyWith(
|
|
isLoading: false,
|
|
error: e.toString(),
|
|
);
|
|
}
|
|
}
|
|
|
|
ReadingExerciseType _mapCategoryToType(String category) {
|
|
switch (category.toLowerCase()) {
|
|
case 'news':
|
|
return ReadingExerciseType.news;
|
|
case 'story':
|
|
return ReadingExerciseType.story;
|
|
case 'science':
|
|
return ReadingExerciseType.science;
|
|
case 'business':
|
|
return ReadingExerciseType.business;
|
|
case 'technology':
|
|
return ReadingExerciseType.technology;
|
|
default:
|
|
return ReadingExerciseType.news;
|
|
}
|
|
}
|
|
|
|
ReadingDifficulty _mapDifficultyLevel(String difficulty) {
|
|
switch (difficulty.toLowerCase()) {
|
|
case 'beginner':
|
|
case 'elementary':
|
|
return ReadingDifficulty.elementary;
|
|
case 'intermediate':
|
|
return ReadingDifficulty.intermediate;
|
|
case 'upper-intermediate':
|
|
case 'upperintermediate':
|
|
return ReadingDifficulty.upperIntermediate;
|
|
case 'advanced':
|
|
return ReadingDifficulty.advanced;
|
|
case 'proficient':
|
|
return ReadingDifficulty.proficient;
|
|
default:
|
|
return ReadingDifficulty.intermediate;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 阅读服务 Provider
|
|
final readingServiceProvider = Provider<ReadingService>((ref) {
|
|
return ReadingService();
|
|
});
|
|
|
|
/// 阅读材料列表 Provider
|
|
final readingMaterialsProvider = StateNotifierProvider<ReadingMaterialsNotifier, ReadingMaterialsState>((ref) {
|
|
final service = ref.watch(readingServiceProvider);
|
|
return ReadingMaterialsNotifier(service);
|
|
});
|
|
|
|
/// 推荐阅读材料 Provider
|
|
final recommendedReadingProvider = FutureProvider<List<ReadingExercise>>((ref) async {
|
|
final service = ref.watch(readingServiceProvider);
|
|
|
|
try {
|
|
final materials = await service.getRecommendedArticles(limit: 3);
|
|
|
|
return materials.map<ReadingExercise>((article) {
|
|
return ReadingExercise(
|
|
id: article.id,
|
|
title: article.title,
|
|
content: article.content,
|
|
summary: '', // 后端ReadingArticle没有summary字段
|
|
type: ReadingExerciseType.news,
|
|
difficulty: ReadingDifficulty.intermediate,
|
|
wordCount: article.wordCount,
|
|
estimatedTime: article.estimatedReadingTime,
|
|
questions: [],
|
|
tags: article.tags, // 已经是List<String>
|
|
source: article.source,
|
|
publishDate: article.publishDate,
|
|
imageUrl: '', // 后端暂无图片字段
|
|
);
|
|
}).toList();
|
|
} catch (e) {
|
|
// 发生错误时返回空列表
|
|
return [];
|
|
}
|
|
});
|