// 自然写互动课堂平板端应用软件 V1.0 // bloc/homework_bloc.dart - 作业状态管理(Bloc模式) import 'dart:async'; /// 作业状态枚举 enum HomeworkStatus { /// 待完成 pending, /// 进行中(已开始作答) inProgress, /// 已提交 submitted, /// 已批改 graded, /// 已过期 expired, } /// 作业数据模型 class HomeworkItem { final String id; final String title; final String subject; final String teacherName; final HomeworkStatus status; final DateTime? assignedAt; final DateTime? deadline; final DateTime? submittedAt; final int? score; final int totalQuestions; final int answeredQuestions; final String? coverImageUrl; HomeworkItem({ required this.id, required this.title, required this.subject, required this.teacherName, this.status = HomeworkStatus.pending, this.assignedAt, this.deadline, this.submittedAt, this.score, this.totalQuestions = 0, this.answeredQuestions = 0, this.coverImageUrl, }); /// 是否已过截止时间 bool get isOverdue => deadline != null && DateTime.now().isAfter(deadline!); /// 作答进度百分比 double get progress => totalQuestions > 0 ? answeredQuestions / totalQuestions : 0.0; /// 从JSON解析 factory HomeworkItem.fromJson(Map json) { return HomeworkItem( id: json['id'] ?? '', title: json['title'] ?? '', subject: json['subject'] ?? '', teacherName: json['teacher_name'] ?? '', status: _parseStatus(json['status']), assignedAt: json['assigned_at'] != null ? DateTime.tryParse(json['assigned_at']) : null, deadline: json['deadline'] != null ? DateTime.tryParse(json['deadline']) : null, submittedAt: json['submitted_at'] != null ? DateTime.tryParse(json['submitted_at']) : null, score: json['score'], totalQuestions: json['total_questions'] ?? 0, answeredQuestions: json['answered_questions'] ?? 0, coverImageUrl: json['cover_image_url'], ); } /// 解析状态字符串 static HomeworkStatus _parseStatus(String? status) { switch (status) { case 'pending': return HomeworkStatus.pending; case 'in_progress': return HomeworkStatus.inProgress; case 'submitted': return HomeworkStatus.submitted; case 'graded': return HomeworkStatus.graded; case 'expired': return HomeworkStatus.expired; default: return HomeworkStatus.pending; } } } /// 作业详情中的题目数据 class HomeworkQuestion { final String id; final int index; final String type; final String content; final String? imageUrl; final List? options; final String? correctAnswer; final String? studentAnswer; final List>? studentStrokes; final int? questionScore; final int? earnedScore; final String? teacherComment; HomeworkQuestion({ required this.id, required this.index, required this.type, required this.content, this.imageUrl, this.options, this.correctAnswer, this.studentAnswer, this.studentStrokes, this.questionScore, this.earnedScore, this.teacherComment, }); /// 从JSON解析 factory HomeworkQuestion.fromJson(Map json) { return HomeworkQuestion( id: json['id'] ?? '', index: json['index'] ?? 0, type: json['type'] ?? 'write', content: json['content'] ?? '', imageUrl: json['image_url'], options: json['options'] != null ? List.from(json['options']) : null, correctAnswer: json['correct_answer'], studentAnswer: json['student_answer'], studentStrokes: json['student_strokes'] != null ? List>.from(json['student_strokes']) : null, questionScore: json['question_score'], earnedScore: json['earned_score'], teacherComment: json['teacher_comment'], ); } } // ============================================================ // Bloc Events(作业相关事件定义) // ============================================================ /// 作业事件基类 abstract class HomeworkEvent {} /// 加载作业列表事件 class LoadHomeworkListEvent extends HomeworkEvent { final HomeworkStatus? filterStatus; final int page; final bool refresh; LoadHomeworkListEvent({ this.filterStatus, this.page = 1, this.refresh = false, }); } /// 下载作业详情事件(用于离线作答) class DownloadHomeworkEvent extends HomeworkEvent { final String homeworkId; DownloadHomeworkEvent(this.homeworkId); } /// 保存作答进度事件(本地暂存) class SaveAnswerProgressEvent extends HomeworkEvent { final String homeworkId; final String questionId; final String? textAnswer; final List>? strokeData; SaveAnswerProgressEvent({ required this.homeworkId, required this.questionId, this.textAnswer, this.strokeData, }); } /// 提交作业事件 class SubmitHomeworkEvent extends HomeworkEvent { final String homeworkId; SubmitHomeworkEvent(this.homeworkId); } /// 查看批改结果事件 class ViewGradeResultEvent extends HomeworkEvent { final String homeworkId; ViewGradeResultEvent(this.homeworkId); } // ============================================================ // Bloc States(作业相关状态定义) // ============================================================ /// 作业状态基类 abstract class HomeworkState {} /// 初始状态 class HomeworkInitialState extends HomeworkState {} /// 加载中状态 class HomeworkLoadingState extends HomeworkState { final String? message; HomeworkLoadingState({this.message}); } /// 作业列表加载成功状态 class HomeworkListLoadedState extends HomeworkState { final List homeworks; final bool hasMore; final int currentPage; final HomeworkStatus? currentFilter; /// 各状态的作业计数统计 final Map statusCounts; HomeworkListLoadedState({ required this.homeworks, this.hasMore = false, this.currentPage = 1, this.currentFilter, this.statusCounts = const {}, }); } /// 作业详情加载成功状态 class HomeworkDetailLoadedState extends HomeworkState { final HomeworkItem homework; final List questions; final bool isOfflineAvailable; HomeworkDetailLoadedState({ required this.homework, required this.questions, this.isOfflineAvailable = false, }); } /// 作答进度保存成功状态 class AnswerSavedState extends HomeworkState { final String homeworkId; final String questionId; final int answeredCount; final int totalCount; AnswerSavedState({ required this.homeworkId, required this.questionId, required this.answeredCount, required this.totalCount, }); } /// 作业提交成功状态 class HomeworkSubmittedState extends HomeworkState { final String homeworkId; final DateTime submittedAt; HomeworkSubmittedState({ required this.homeworkId, required this.submittedAt, }); } /// 批改结果状态 class GradeResultState extends HomeworkState { final HomeworkItem homework; final List questions; final int totalScore; final int earnedScore; final String? overallComment; GradeResultState({ required this.homework, required this.questions, required this.totalScore, required this.earnedScore, this.overallComment, }); } /// 错误状态 class HomeworkErrorState extends HomeworkState { final String message; final String? actionType; HomeworkErrorState({ required this.message, this.actionType, }); } // ============================================================ // HomeworkBloc 实现 // ============================================================ /// 作业状态管理Bloc /// 管理作业列表加载、下载、作答、提交、查看批改结果等完整流程 class HomeworkBloc { /// 当前状态 HomeworkState _state = HomeworkInitialState(); /// 状态流控制器 final StreamController _stateController = StreamController.broadcast(); /// 本地缓存的作业列表 List _cachedHomeworks = []; /// 本地缓存的作答进度 {homeworkId: {questionId: answerData}} final Map> _answerCache = {}; /// 获取当前状态 HomeworkState get state => _state; /// 状态流 Stream get stateStream => _stateController.stream; /// 发射新状态 void _emit(HomeworkState newState) { _state = newState; _stateController.add(newState); } /// 处理事件分发 void add(HomeworkEvent event) { if (event is LoadHomeworkListEvent) { _handleLoadList(event); } else if (event is DownloadHomeworkEvent) { _handleDownload(event); } else if (event is SaveAnswerProgressEvent) { _handleSaveAnswer(event); } else if (event is SubmitHomeworkEvent) { _handleSubmit(event); } else if (event is ViewGradeResultEvent) { _handleViewGrade(event); } } /// 处理加载作业列表 Future _handleLoadList(LoadHomeworkListEvent event) async { try { _emit(HomeworkLoadingState(message: '正在加载作业列表...')); // 调用API获取作业列表 // final response = await PadApiService.instance.getHomeworkList( // page: event.page, // status: event.filterStatus?.name, // ); // 模拟数据处理逻辑 if (event.refresh) { _cachedHomeworks.clear(); } // 统计各状态作业数量 final statusCounts = {}; for (final hw in _cachedHomeworks) { statusCounts[hw.status] = (statusCounts[hw.status] ?? 0) + 1; } // 根据筛选条件过滤 List filtered = _cachedHomeworks; if (event.filterStatus != null) { filtered = _cachedHomeworks .where((hw) => hw.status == event.filterStatus) .toList(); } _emit(HomeworkListLoadedState( homeworks: filtered, hasMore: false, currentPage: event.page, currentFilter: event.filterStatus, statusCounts: statusCounts, )); } catch (e) { _emit(HomeworkErrorState( message: '加载作业列表失败: $e', actionType: 'load_list', )); } } /// 处理下载作业详情(支持离线作答) Future _handleDownload(DownloadHomeworkEvent event) async { try { _emit(HomeworkLoadingState(message: '正在下载作业内容...')); // 调用API下载作业详情 // final response = await PadApiService.instance.downloadHomework( // event.homeworkId, // ); // 将作业内容缓存到本地SQLite(支持离线作答) // await LocalRepository.instance.cacheHomework(...) // _emit(HomeworkDetailLoadedState(...)); } catch (e) { _emit(HomeworkErrorState( message: '下载作业失败: $e', actionType: 'download', )); } } /// 处理保存作答进度(本地暂存,支持断点续答) Future _handleSaveAnswer(SaveAnswerProgressEvent event) async { try { // 更新内存缓存 _answerCache.putIfAbsent(event.homeworkId, () => {}); _answerCache[event.homeworkId]![event.questionId] = { 'text_answer': event.textAnswer, 'stroke_data': event.strokeData, 'saved_at': DateTime.now().toIso8601String(), }; // 持久化到本地数据库 // await LocalRepository.instance.saveAnswerProgress(...) // 计算已作答题目数 final answeredCount = _answerCache[event.homeworkId]?.length ?? 0; _emit(AnswerSavedState( homeworkId: event.homeworkId, questionId: event.questionId, answeredCount: answeredCount, totalCount: 0, // 从缓存的作业详情中获取 )); } catch (e) { _emit(HomeworkErrorState( message: '保存作答进度失败: $e', actionType: 'save_answer', )); } } /// 处理提交作业 Future _handleSubmit(SubmitHomeworkEvent event) async { try { _emit(HomeworkLoadingState(message: '正在提交作业...')); // 收集所有作答数据 final answers = _answerCache[event.homeworkId] ?? {}; // 构建提交数据(含笔迹页面数据) final strokePages = answers.entries.map((entry) { return { 'question_id': entry.key, 'answer': entry.value, }; }).toList(); // 调用API提交 // final response = await PadApiService.instance.submitHomework( // homeworkId: event.homeworkId, // strokePages: strokePages, // ); // 提交成功后清除本地缓存 _answerCache.remove(event.homeworkId); _emit(HomeworkSubmittedState( homeworkId: event.homeworkId, submittedAt: DateTime.now(), )); } catch (e) { _emit(HomeworkErrorState( message: '提交作业失败: $e', actionType: 'submit', )); } } /// 处理查看批改结果 Future _handleViewGrade(ViewGradeResultEvent event) async { try { _emit(HomeworkLoadingState(message: '正在加载批改结果...')); // 调用API获取批改结果 // final response = await PadApiService.instance.getHomeworkResult( // event.homeworkId, // ); // _emit(GradeResultState(...)); } catch (e) { _emit(HomeworkErrorState( message: '加载批改结果失败: $e', actionType: 'view_grade', )); } } /// 释放资源 void dispose() { _stateController.close(); _cachedHomeworks.clear(); _answerCache.clear(); } }