合并代买

This commit is contained in:
chenshuainan
2026-09-09 16:12:59 +08:00
parent 44fb5f86e2
commit 592e576319
7 changed files with 1227 additions and 332 deletions
@@ -0,0 +1,33 @@
import 'package:new_learn/core/api/conquerPackage/captureList/model.dart';
import 'package:new_learn/core/network/dio_client.dart';
/// ============================================================
/// 【captureList 模块接口】攻克学习包 —— 对标 Vue3 端 api/task/index.ts
///
/// getCoursePack —— 获取课程下的攻克学习包列表
/// GET /api/v1/StudyPack/GetCoursePacks/{courseId}
///
/// startOvercome —— 开始 / 继续攻克学习包
/// POST /api/v1/StudyPack/StartOvercome/{packId}
/// ============================================================
class CaptureListApi {
CaptureListApi._();
static final CaptureListApi instance = CaptureListApi._();
/// 获取课程下的攻克学习包列表
Future<CoursePackResponse> getCoursePack(String courseId) async {
final data = await DioClient.instance.get(
'/api/v1/StudyPack/GetCoursePacks/$courseId',
);
return CoursePackResponse.fromJson(data as Map<String, dynamic>);
}
/// 开始 / 继续攻克学习包
Future<TaskDetail> startOvercome(String packId) async {
final data = await DioClient.instance.post(
'/api/v1/StudyPack/StartOvercome/$packId',
);
return TaskDetail.fromJson(data as Map<String, dynamic>);
}
}
@@ -0,0 +1,156 @@
/// ============================================================
/// 【captureList 模块模型】攻克学习包 —— 对标 Vue3 端 api/task/type.ts
///
/// CoursePackResponse / CourseInfo / CourseRecord
/// TaskDetail(开始/继续攻克返回)
///
/// 序列化:手动 fromJson(兼容 {code, message, data: {...}} 响应壳)
/// ============================================================
library;
/// 攻克记录(单次攻克的结果)
class CourseRecord {
const CourseRecord({
this.id = 0,
this.createTime = '',
this.accuracyRate = 0,
this.status = 0,
this.statusName = '',
});
final int id; // 记录 id
final String createTime; // 创建时间
final int accuracyRate; // 正确率(0-100)
final int status; // 状态:0 未开始 / 1 进行中 / 2 成功 / 3 失败 等(按后端枚举)
final String statusName; // 状态名称
factory CourseRecord.fromJson(Map<String, dynamic> json) {
return CourseRecord(
id: _parseInt(json['id']),
createTime: json['createTime'] as String? ?? '',
accuracyRate: _parseInt(json['accuracyRate']),
status: _parseInt(json['status']),
statusName: json['statusName'] as String? ?? '',
);
}
}
/// 单个学习包(攻克包)信息
class CourseInfo {
const CourseInfo({
this.id = 0,
this.name = '',
this.baseSubjectName = '',
this.overcomeStandard = 0,
this.estimatedTime = 0,
this.maxOvercomeCount = 0,
this.recordCount = 0,
this.records = const [],
this.status = 0,
this.statusName = '',
});
final int id; // 学习包 id
final String name; // 名称
final String baseSubjectName; // 学科名称
final int overcomeStandard; // 攻克标准(百分比)
final int estimatedTime; // 预计用时(分钟)
final int maxOvercomeCount; // 最大可攻克次数
final int recordCount; // 已攻克次数
final List<CourseRecord> records; // 历次攻克记录
final int status; // 状态:0 未开始 / 1 进行中 / 2 已攻克 / 3 失败 / 4 后续学习 / 5 判题中(按后端枚举)
final String statusName; // 状态名称
factory CourseInfo.fromJson(Map<String, dynamic> json) {
return CourseInfo(
id: _parseInt(json['id']),
name: json['name'] as String? ?? '',
baseSubjectName: json['baseSubjectName'] as String? ?? '',
overcomeStandard: _parseInt(json['overcomeStandard']),
estimatedTime: _parseInt(json['estimatedTime']),
maxOvercomeCount: _parseInt(json['maxOvercomeCount']),
recordCount: _parseInt(json['recordCount']),
records: (json['records'] as List<dynamic>? ?? const [])
.whereType<Map<String, dynamic>>()
.map(CourseRecord.fromJson)
.toList(),
status: _parseInt(json['status']),
statusName: json['statusName'] as String? ?? '',
);
}
}
/// 学习包列表响应(接口返回 {packs: [...], remark: '...'})
class CoursePackResponse {
const CoursePackResponse({
this.packs = const [],
this.remark = '',
});
final List<CourseInfo> packs; // 学习包列表
final String remark; // 规则说明文字
/// 兼容业务响应壳 {code, message, data: {...}}:data 存在就取 data
factory CoursePackResponse.fromJson(Map<String, dynamic> json) {
final payload = (json['data'] as Map<String, dynamic>?) ?? json;
return CoursePackResponse(
packs: (payload['packs'] as List<dynamic>? ??
payload['courses'] as List<dynamic>? ??
const [])
.whereType<Map<String, dynamic>>()
.map(CourseInfo.fromJson)
.toList(),
remark: payload['remark'] as String? ?? '',
);
}
}
/// 开始 / 继续攻克 接口返回(精简版,包含进入下一步所需字段)
class TaskDetail {
const TaskDetail({
this.id = 0,
this.name = '',
this.overcomeStandard = 0,
this.planTimeMinute = 0,
this.recordId = 0,
this.nowStudyObjectType = 0,
this.nowStudyObjectId = 0,
this.hasHandout = false,
this.hasQuestion = false,
});
final int id; // 学习包 id
final String name; // 名称
final int overcomeStandard; // 攻克标准
final int planTimeMinute; // 计划用时(分钟)
final int recordId; // 学习记录 id(跳转到习题/讲义页用)
final int nowStudyObjectType; // 当前学习对象类型:0 讲义 / 11 习题 等
final int nowStudyObjectId; // 当前学习对象 id
final bool hasHandout; // 是否有讲义
final bool hasQuestion; // 是否有题目
factory TaskDetail.fromJson(Map<String, dynamic> json) {
final payload = (json['data'] as Map<String, dynamic>?) ?? json;
return TaskDetail(
id: _parseInt(payload['id']),
name: payload['name'] as String? ?? '',
overcomeStandard: _parseInt(payload['overcomeStandard']),
planTimeMinute: _parseInt(payload['planTimeMinute']),
recordId: _parseInt(payload['recordId']),
nowStudyObjectType: _parseInt(payload['nowStudyObjectType']),
nowStudyObjectId: _parseInt(payload['nowStudyObjectId']),
hasHandout: payload['hasHandout'] as bool? ?? false,
hasQuestion: payload['hasQuestion'] as bool? ?? false,
);
}
}
/// 安全解析 int:兼容数字和字符串数字,解析失败返回 0
int _parseInt(dynamic value) {
if (value == null) return 0;
if (value is int) return value;
if (value is double) return value.toInt();
if (value is num) return value.toInt();
if (value is String) return int.tryParse(value) ?? 0;
return 0;
}