合并代买
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -148,7 +148,8 @@ final GoRouter appRouter = GoRouter(
|
||||
// ---------- 攻克包 - 截图名单 ----------
|
||||
GoRoute(
|
||||
path: '/conquerPackage/captureList',
|
||||
builder: (_, _) => const CaptureListPage(),
|
||||
builder: (_, state) =>
|
||||
CaptureListPage(courseId: state.extra as String),
|
||||
),
|
||||
// app_router.dart 的 routes 里加,不用管跳转逻辑
|
||||
// GoRoute(path: '/task/:id', builder: (_, _) => const TaskDetailPage()),
|
||||
|
||||
Reference in New Issue
Block a user