/// ============================================================ /// 【exam 模块模型】我的考试 —— 对标 Vue3 端 api/exam/type.ts /// /// ExamDto —— 单条考试记录 /// ExamSubjectTab —— 考试科目筛选 Tab /// ExamResponse —— 考试列表分页响应 /// /// 序列化:手动 fromJson,与项目其他模块风格一致,不依赖 build_runner。 /// /// ⚠ 注意:后端返回的 id 字段类型不统一(数字 or 字符串), /// 所有数值字段统一用 _asInt() 做兼容解析,避免类型转换异常。 /// ============================================================ library; int? _optInt(dynamic v) { if (v == null) return null; if (v is int) return v; if (v is double) return v.toInt(); final s = v.toString(); final n = int.tryParse(s); if (n != null) return n; return double.tryParse(s)?.toInt(); } int _asInt(dynamic v, [int fallback = 0]) => _optInt(v) ?? fallback; /// 单条考试记录 class ExamDto { const ExamDto({ this.id = 0, this.taskId = 0, this.taskName = '', this.baseSubjectId = 0, this.baseSubjectName = '', this.startTime = '', this.endTime = '', this.totalScore = 0, this.userScore = 0, }); final int id; final int taskId; final String taskName; final int baseSubjectId; final String baseSubjectName; final String startTime; final String endTime; final int totalScore; final int userScore; factory ExamDto.fromJson(Map json) { return ExamDto( id: _asInt(json['id']), taskId: _asInt(json['taskId']), taskName: (json['taskName'] as String?) ?? '', baseSubjectId: _asInt(json['baseSubjectId']), baseSubjectName: (json['baseSubjectName'] as String?) ?? '', startTime: (json['startTime'] as String?) ?? '', endTime: (json['endTime'] as String?) ?? '', totalScore: _asInt(json['totalScore']), userScore: _asInt(json['userScore']), ); } } /// 考试科目筛选 Tab class ExamSubjectTab { const ExamSubjectTab({this.id, this.name = ''}); /// 为 null 表示"全部" final int? id; final String name; factory ExamSubjectTab.fromJson(Map json) { return ExamSubjectTab( id: _optInt(json['id']), name: (json['name'] as String?) ?? '', ); } } /// 考试列表分页响应 class ExamResponse { const ExamResponse({ this.data = const [], this.total = 0, this.pageIndex = 1, this.pageSize = 10, }); final List data; final int total; final int pageIndex; final int pageSize; factory ExamResponse.fromJson(Map json) { final payload = (json['data'] as Map?) ?? json; final list = (payload['data'] as List? ?? const []) .whereType>() .map(ExamDto.fromJson) .toList(); return ExamResponse( data: list, total: (payload['total'] as num?)?.toInt() ?? list.length, pageIndex: (payload['pageIndex'] as num?)?.toInt() ?? 1, pageSize: (payload['pageSize'] as num?)?.toInt() ?? 10, ); } }