feat(recite): 完成背诵模块基础框架与核心页面开发
本次提交实现了背诵模块的完整基础链路: 1. 新增词书、背单词接口层与对应数据模型 2. 完成背诵首页、章节列表页等核心页面开发 3. 实现音频播放、加载弹窗等通用组件 4. 配置路由跳转链路,替换旧版缓存传参方案 5. 对齐Vue端业务逻辑与UI样式
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
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>);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user