本次提交实现了背诵模块的完整基础链路: 1. 新增词书、背单词接口层与对应数据模型 2. 完成背诵首页、章节列表页等核心页面开发 3. 实现音频播放、加载弹窗等通用组件 4. 配置路由跳转链路,替换旧版缓存传参方案 5. 对齐Vue端业务逻辑与UI样式
87 lines
3.0 KiB
Dart
87 lines
3.0 KiB
Dart
import 'package:new_learn/core/api/lexicon/model.dart';
|
||
import 'package:new_learn/core/network/dio_client.dart';
|
||
|
||
/// ============================================================
|
||
/// 【lexicon 模块接口】背单词接口 —— 对标 Vue3 端 api/lexicon/index.ts
|
||
///
|
||
/// getChapters → GET GetChapters/{bookId} 章节列表
|
||
/// getLevels → GET GetLevels/{chapterId} 关卡列表
|
||
/// levelStart → POST LevelStart/{levelId} 开局取题
|
||
/// answerQuestion → POST Answer 提交答案
|
||
/// getLevelIsFinish → GET GetLevelIsFinish/{levelId} 关卡是否完成(轮询)
|
||
/// getLevelOverInfo → GET GetLevelOverInfo/{userLevelId} 闯关小结
|
||
///
|
||
/// 注意:getChapters Vue 端带 hideErrorToast,toast 由页面自行处理;
|
||
/// 异常统一向上抛,页面 catch 后决定提示。
|
||
/// ============================================================
|
||
class LexiconApi {
|
||
LexiconApi._();
|
||
|
||
static final LexiconApi instance = LexiconApi._();
|
||
|
||
/// 后端响应壳 {code, message, data} 统一取 data(用于裸值响应)
|
||
dynamic _unwrap(dynamic data) =>
|
||
data is Map<String, dynamic> && data['data'] != null
|
||
? data['data']
|
||
: data;
|
||
|
||
/// 章节列表(model 内部兼容响应壳)
|
||
Future<ChapterResponse> getChapters(int bookId) async {
|
||
final data = await DioClient.instance.get(
|
||
'/api/v1/Lexicon/GetChapters/$bookId',
|
||
);
|
||
return ChapterResponse.fromJson(data as Map<String, dynamic>);
|
||
}
|
||
|
||
/// 关卡列表
|
||
Future<LevelResponse> getLevels(int chapterId) async {
|
||
final data = await DioClient.instance.get(
|
||
'/api/v1/Lexicon/GetLevels/$chapterId',
|
||
);
|
||
return LevelResponse.fromJson(data as Map<String, dynamic>);
|
||
}
|
||
|
||
/// 开局取题
|
||
Future<LevelStartInfo> levelStart(int levelId) async {
|
||
final data = await DioClient.instance.post(
|
||
'/api/v1/Lexicon/LevelStart/$levelId',
|
||
);
|
||
return LevelStartInfo.fromJson(data as Map<String, dynamic>);
|
||
}
|
||
|
||
/// 提交答案(返回值与开局信息同构,但页面只关心成功与否)
|
||
Future<bool> answerQuestion({
|
||
required int levelId,
|
||
required int userLevelId,
|
||
required int lexiconId,
|
||
required String answer,
|
||
}) async {
|
||
final data = await DioClient.instance.post(
|
||
'/api/v1/Lexicon/Answer',
|
||
data: {
|
||
'levelId': levelId,
|
||
'userLevelId': userLevelId,
|
||
'lexiconId': lexiconId,
|
||
'answer': answer,
|
||
},
|
||
);
|
||
return data != null;
|
||
}
|
||
|
||
/// 关卡是否完成(完关后后端有短暂处理延迟,需轮询)
|
||
Future<bool> getLevelIsFinish(int levelId) async {
|
||
final data = _unwrap(
|
||
await DioClient.instance.get('/api/v1/Lexicon/GetLevelIsFinish/$levelId'),
|
||
);
|
||
return data == true;
|
||
}
|
||
|
||
/// 闯关小结
|
||
Future<LevelOverInfo> getLevelOverInfo(int userLevelId) async {
|
||
final data = await DioClient.instance.get(
|
||
'/api/v1/Lexicon/GetLevelOverInfo/$userLevelId',
|
||
);
|
||
return LevelOverInfo.fromJson(data as Map<String, dynamic>);
|
||
}
|
||
}
|