This commit is contained in:
sjk
2025-11-17 13:39:05 +08:00
commit d4cfe2b9de
479 changed files with 109324 additions and 0 deletions

View File

@@ -0,0 +1,416 @@
import '../../../core/models/api_response.dart';
import '../../../core/services/enhanced_api_service.dart';
import '../models/test_models.dart';
/// 综合测试API服务类
/// 使用后端API替代静态数据
class TestApiService {
static final TestApiService _instance = TestApiService._internal();
factory TestApiService() => _instance;
TestApiService._internal();
final EnhancedApiService _enhancedApiService = EnhancedApiService();
// 缓存时长配置
static const Duration _shortCacheDuration = Duration(minutes: 5);
static const Duration _longCacheDuration = Duration(hours: 1);
/// 获取所有测试模板
Future<ApiResponse<List<TestTemplate>>> getTestTemplates() async {
try {
final response = await _enhancedApiService.get<List<TestTemplate>>(
'/tests/templates',
cacheDuration: _longCacheDuration,
fromJson: (data) {
final templates = data['templates'] as List?;
if (templates == null) return [];
return templates.map((json) => TestTemplate.fromJson(json)).toList();
},
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '获取测试模板成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '获取测试模板失败: $e');
}
}
/// 根据类型获取测试模板
Future<ApiResponse<List<TestTemplate>>> getTestTemplatesByType(
TestType type,
) async {
try {
final response = await _enhancedApiService.get<List<TestTemplate>>(
'/tests/templates',
queryParameters: {
'type': type.toString().split('.').last,
},
cacheDuration: _longCacheDuration,
fromJson: (data) {
final templates = data['templates'] as List?;
if (templates == null) return [];
return templates.map((json) => TestTemplate.fromJson(json)).toList();
},
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '获取测试模板成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '获取测试模板失败: $e');
}
}
/// 根据ID获取测试模板
Future<ApiResponse<TestTemplate>> getTestTemplateById(String id) async {
try {
final response = await _enhancedApiService.get<TestTemplate>(
'/tests/templates/$id',
cacheDuration: _longCacheDuration,
fromJson: (data) => TestTemplate.fromJson(data['data'] ?? data),
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '获取测试模板成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '获取测试模板失败: $e');
}
}
/// 创建测试会话
Future<ApiResponse<TestSession>> createTestSession({
required String templateId,
required String userId,
}) async {
try {
final response = await _enhancedApiService.post<TestSession>(
'/tests/sessions',
data: {
'template_id': templateId,
'user_id': userId,
},
fromJson: (data) => TestSession.fromJson(data['data'] ?? data),
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '创建测试会话成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '创建测试会话失败: $e');
}
}
/// 开始测试
Future<ApiResponse<TestSession>> startTest(String sessionId) async {
try {
final response = await _enhancedApiService.put<TestSession>(
'/tests/sessions/$sessionId/start',
fromJson: (data) => TestSession.fromJson(data['data'] ?? data),
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '开始测试成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '开始测试失败: $e');
}
}
/// 提交答案
Future<ApiResponse<TestSession>> submitAnswer({
required String sessionId,
required UserAnswer answer,
}) async {
try {
final response = await _enhancedApiService.post<TestSession>(
'/tests/sessions/$sessionId/answers',
data: {
'question_id': answer.questionId,
'answer': answer.answer,
},
fromJson: (data) => TestSession.fromJson(data['data'] ?? data),
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '提交答案成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '提交答案失败: $e');
}
}
/// 暂停测试
Future<ApiResponse<TestSession>> pauseTest(String sessionId) async {
try {
final response = await _enhancedApiService.put<TestSession>(
'/tests/sessions/$sessionId/pause',
fromJson: (data) => TestSession.fromJson(data['data'] ?? data),
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '测试已暂停');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '暂停测试失败: $e');
}
}
/// 恢复测试
Future<ApiResponse<TestSession>> resumeTest(String sessionId) async {
try {
final response = await _enhancedApiService.put<TestSession>(
'/tests/sessions/$sessionId/resume',
fromJson: (data) => TestSession.fromJson(data['data'] ?? data),
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '测试已恢复');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '恢复测试失败: $e');
}
}
/// 完成测试
Future<ApiResponse<TestResult>> completeTest(String sessionId) async {
try {
final response = await _enhancedApiService.put<TestResult>(
'/tests/sessions/$sessionId/complete',
fromJson: (data) => TestResult.fromJson(data['data'] ?? data),
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '完成测试成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '完成测试失败: $e');
}
}
/// 获取测试结果
Future<ApiResponse<TestResult>> getTestResult(String sessionId) async {
try {
final response = await _enhancedApiService.get<TestResult>(
'/tests/sessions/$sessionId/result',
cacheDuration: _shortCacheDuration,
fromJson: (data) => TestResult.fromJson(data['data'] ?? data),
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '获取测试结果成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '获取测试结果失败: $e');
}
}
/// 获取用户测试历史
Future<ApiResponse<List<TestSession>>> getUserTestHistory({
int page = 1,
int limit = 20,
}) async {
try {
final response = await _enhancedApiService.get<List<TestSession>>(
'/tests/sessions',
queryParameters: {
'page': page,
'limit': limit,
},
cacheDuration: _shortCacheDuration,
fromJson: (data) {
final sessions = data['sessions'] as List?;
if (sessions == null) return [];
return sessions.map((json) => TestSession.fromJson(json)).toList();
},
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '获取测试历史成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '获取测试历史失败: $e');
}
}
/// 获取用户测试统计
Future<ApiResponse<Map<String, dynamic>>> getUserTestStats() async {
try {
final response = await _enhancedApiService.get<Map<String, dynamic>>(
'/tests/stats',
cacheDuration: _shortCacheDuration,
fromJson: (data) => data,
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '获取测试统计成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '获取测试统计失败: $e');
}
}
/// 获取最近的测试结果
Future<ApiResponse<List<TestResult>>> getRecentTestResults(
String? userId, {
int limit = 5,
}) async {
try {
final response = await _enhancedApiService.get<List<TestResult>>(
'/tests/sessions/recent',
queryParameters: {
if (userId != null) 'user_id': userId,
'limit': limit,
},
cacheDuration: _shortCacheDuration,
fromJson: (data) {
final sessions = data['sessions'] as List?;
if (sessions == null) return [];
return sessions.map((json) => TestResult.fromJson(json)).toList();
},
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '获取最近测试结果成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '获取最近测试结果失败: $e');
}
}
/// 获取测试结果详情
Future<ApiResponse<TestResult>> getTestResultById(String resultId) async {
try {
final response = await _enhancedApiService.get<TestResult>(
'/tests/results/$resultId',
cacheDuration: _shortCacheDuration,
fromJson: (data) => TestResult.fromJson(data['data'] ?? data),
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '获取测试结果成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '获取测试结果失败: $e');
}
}
/// 获取用户技能统计
Future<ApiResponse<Map<SkillType, double>>> getUserSkillStatistics(
String userId,
) async {
try {
final response = await _enhancedApiService.get<Map<SkillType, double>>(
'/tests/users/$userId/skills',
cacheDuration: _shortCacheDuration,
fromJson: (data) {
final skillsData = data['skills'] as Map<String, dynamic>?;
if (skillsData == null) return {};
final result = <SkillType, double>{};
skillsData.forEach((key, value) {
final skillType = _parseSkillType(key);
if (skillType != null) {
result[skillType] = (value as num).toDouble();
}
});
return result;
},
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '获取技能统计成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '获取技能统计失败: $e');
}
}
/// 获取题目统计
Future<ApiResponse<Map<String, dynamic>>> getQuestionStatistics() async {
try {
final response = await _enhancedApiService.get<Map<String, dynamic>>(
'/tests/questions/statistics',
cacheDuration: _longCacheDuration,
fromJson: (data) => data,
);
if (response.success && response.data != null) {
return ApiResponse.success(data: response.data!, message: '获取题目统计成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '获取题目统计失败: $e');
}
}
/// 删除测试结果
Future<ApiResponse<void>> deleteTestResult(String resultId) async {
try {
final response = await _enhancedApiService.delete<void>(
'/tests/results/$resultId',
fromJson: (data) => null,
);
if (response.success) {
return ApiResponse.success(message: '删除测试结果成功');
} else {
return ApiResponse.error(message: response.message);
}
} catch (e) {
return ApiResponse.error(message: '删除测试结果失败: $e');
}
}
/// 解析技能类型
SkillType? _parseSkillType(String key) {
switch (key.toLowerCase()) {
case 'vocabulary':
return SkillType.vocabulary;
case 'grammar':
return SkillType.grammar;
case 'reading':
return SkillType.reading;
case 'listening':
return SkillType.listening;
case 'speaking':
return SkillType.speaking;
case 'writing':
return SkillType.writing;
default:
return null;
}
}
}

View File

@@ -0,0 +1,468 @@
import '../models/test_models.dart';
import '../data/test_static_data.dart';
import '../../../core/models/api_response.dart';
/// 综合测试服务类
class TestService {
// 单例模式
static final TestService _instance = TestService._internal();
factory TestService() => _instance;
TestService._internal();
/// 获取所有测试模板
Future<ApiResponse<List<TestTemplate>>> getTestTemplates() async {
try {
// 模拟网络延迟
await Future.delayed(const Duration(milliseconds: 500));
final templates = TestStaticData.getAllTemplates();
return ApiResponse.success(
data: templates,
message: '获取测试模板成功',
);
} catch (e) {
return ApiResponse.error(
message: '获取测试模板失败: ${e.toString()}',
);
}
}
/// 根据类型获取测试模板
Future<ApiResponse<List<TestTemplate>>> getTestTemplatesByType(
TestType type,
) async {
try {
await Future.delayed(const Duration(milliseconds: 300));
final templates = TestStaticData.getTemplatesByType(type);
return ApiResponse.success(
data: templates,
message: '获取${_getTestTypeName(type)}模板成功',
);
} catch (e) {
return ApiResponse.error(
message: '获取测试模板失败: ${e.toString()}',
);
}
}
/// 根据ID获取测试模板
Future<ApiResponse<TestTemplate>> getTestTemplateById(String id) async {
try {
await Future.delayed(const Duration(milliseconds: 200));
final template = TestStaticData.getTemplateById(id);
if (template == null) {
return ApiResponse.error(message: '测试模板不存在');
}
return ApiResponse.success(
data: template,
message: '获取测试模板成功',
);
} catch (e) {
return ApiResponse.error(
message: '获取测试模板失败: ${e.toString()}',
);
}
}
/// 创建测试会话
Future<ApiResponse<TestSession>> createTestSession({
required String templateId,
required String userId,
}) async {
try {
await Future.delayed(const Duration(milliseconds: 800));
final session = TestStaticData.createTestSession(
templateId: templateId,
userId: userId,
);
return ApiResponse.success(
data: session,
message: '创建测试会话成功',
);
} catch (e) {
return ApiResponse.error(
message: '创建测试会话失败: ${e.toString()}',
);
}
}
/// 开始测试
Future<ApiResponse<TestSession>> startTest(String sessionId) async {
try {
await Future.delayed(const Duration(milliseconds: 300));
// 模拟开始测试,实际应用中会更新数据库中的会话状态
// 这里返回一个模拟的已开始的会话
return ApiResponse.success(
data: TestSession(
id: sessionId,
templateId: 'template_quick',
userId: 'user_001',
status: TestStatus.inProgress,
questions: TestStaticData.getQuestionsByIds(['vocab_001', 'grammar_001']),
answers: [],
currentQuestionIndex: 0,
startTime: DateTime.now(),
timeRemaining: 900, // 15分钟
),
message: '测试已开始',
);
} catch (e) {
return ApiResponse.error(
message: '开始测试失败: ${e.toString()}',
);
}
}
/// 提交答案
Future<ApiResponse<TestSession>> submitAnswer({
required String sessionId,
required UserAnswer answer,
}) async {
try {
await Future.delayed(const Duration(milliseconds: 400));
// 模拟提交答案并返回更新后的会话
return ApiResponse.success(
data: TestSession(
id: sessionId,
templateId: 'template_quick',
userId: 'user_001',
status: TestStatus.inProgress,
questions: TestStaticData.getQuestionsByIds(['vocab_001', 'grammar_001']),
answers: [answer],
currentQuestionIndex: 1,
startTime: DateTime.now().subtract(const Duration(minutes: 5)),
timeRemaining: 600, // 剩余10分钟
),
message: '答案提交成功',
);
} catch (e) {
return ApiResponse.error(
message: '提交答案失败: ${e.toString()}',
);
}
}
/// 暂停测试
Future<ApiResponse<TestSession>> pauseTest(String sessionId) async {
try {
await Future.delayed(const Duration(milliseconds: 200));
return ApiResponse.success(
data: TestSession(
id: sessionId,
templateId: 'template_quick',
userId: 'user_001',
status: TestStatus.paused,
questions: TestStaticData.getQuestionsByIds(['vocab_001', 'grammar_001']),
answers: [],
currentQuestionIndex: 0,
startTime: DateTime.now().subtract(const Duration(minutes: 5)),
timeRemaining: 600,
),
message: '测试已暂停',
);
} catch (e) {
return ApiResponse.error(
message: '暂停测试失败: ${e.toString()}',
);
}
}
/// 恢复测试
Future<ApiResponse<TestSession>> resumeTest(String sessionId) async {
try {
await Future.delayed(const Duration(milliseconds: 200));
return ApiResponse.success(
data: TestSession(
id: sessionId,
templateId: 'template_quick',
userId: 'user_001',
status: TestStatus.inProgress,
questions: TestStaticData.getQuestionsByIds(['vocab_001', 'grammar_001']),
answers: [],
currentQuestionIndex: 0,
startTime: DateTime.now().subtract(const Duration(minutes: 5)),
timeRemaining: 600,
),
message: '测试已恢复',
);
} catch (e) {
return ApiResponse.error(
message: '恢复测试失败: ${e.toString()}',
);
}
}
/// 完成测试
Future<ApiResponse<TestResult>> completeTest({
required String sessionId,
required List<UserAnswer> answers,
}) async {
try {
await Future.delayed(const Duration(milliseconds: 1000));
// 模拟计算测试结果
final result = _calculateTestResult(sessionId, answers);
// 保存结果到静态数据
TestStaticData.addTestResult(result);
return ApiResponse.success(
data: result,
message: '测试完成,结果已保存',
);
} catch (e) {
return ApiResponse.error(
message: '完成测试失败: ${e.toString()}',
);
}
}
/// 获取用户测试历史
Future<ApiResponse<List<TestResult>>> getUserTestHistory(
String userId, {
int page = 1,
int limit = 10,
}) async {
try {
await Future.delayed(const Duration(milliseconds: 600));
final allResults = TestStaticData.getUserResults(userId);
final startIndex = (page - 1) * limit;
final endIndex = startIndex + limit;
final results = allResults.length > startIndex
? allResults.sublist(
startIndex,
endIndex > allResults.length ? allResults.length : endIndex,
)
: <TestResult>[];
return ApiResponse.success(
data: results,
message: '获取测试历史成功',
);
} catch (e) {
return ApiResponse.error(
message: '获取测试历史失败: ${e.toString()}',
);
}
}
/// 获取最近的测试结果
Future<ApiResponse<List<TestResult>>> getRecentTestResults(
String userId, {
int limit = 5,
}) async {
try {
await Future.delayed(const Duration(milliseconds: 400));
final results = TestStaticData.getRecentResults(userId, limit: limit);
return ApiResponse.success(
data: results,
message: '获取最近测试结果成功',
);
} catch (e) {
return ApiResponse.error(
message: '获取最近测试结果失败: ${e.toString()}',
);
}
}
/// 获取测试结果详情
Future<ApiResponse<TestResult>> getTestResultById(String resultId) async {
try {
await Future.delayed(const Duration(milliseconds: 300));
final result = TestStaticData.getResultById(resultId);
if (result == null) {
return ApiResponse.error(message: '测试结果不存在');
}
return ApiResponse.success(
data: result,
message: '获取测试结果成功',
);
} catch (e) {
return ApiResponse.error(
message: '获取测试结果失败: ${e.toString()}',
);
}
}
/// 获取用户技能统计
Future<ApiResponse<Map<SkillType, double>>> getUserSkillStatistics(
String userId,
) async {
try {
await Future.delayed(const Duration(milliseconds: 500));
final statistics = TestStaticData.getSkillStatistics(userId);
return ApiResponse.success(
data: statistics,
message: '获取技能统计成功',
);
} catch (e) {
return ApiResponse.error(
message: '获取技能统计失败: ${e.toString()}',
);
}
}
/// 获取题目统计
Future<ApiResponse<Map<String, dynamic>>> getQuestionStatistics() async {
try {
await Future.delayed(const Duration(milliseconds: 300));
final difficultyStats = TestStaticData.getDifficultyStatistics();
final skillStats = TestStaticData.getSkillDistributionStatistics();
return ApiResponse.success(
data: {
'difficultyDistribution': difficultyStats,
'skillDistribution': skillStats,
'totalQuestions': TestStaticData.getAllQuestions().length,
},
message: '获取题目统计成功',
);
} catch (e) {
return ApiResponse.error(
message: '获取题目统计失败: ${e.toString()}',
);
}
}
/// 删除测试结果
Future<ApiResponse<bool>> deleteTestResult(String resultId) async {
try {
await Future.delayed(const Duration(milliseconds: 300));
final success = TestStaticData.deleteTestResult(resultId);
if (success) {
return ApiResponse.success(
data: true,
message: '删除测试结果成功',
);
} else {
return ApiResponse.error(message: '测试结果不存在');
}
} catch (e) {
return ApiResponse.error(
message: '删除测试结果失败: ${e.toString()}',
);
}
}
/// 获取测试类型名称
String _getTestTypeName(TestType type) {
switch (type) {
case TestType.quick:
return '快速测试';
case TestType.standard:
return '标准测试';
case TestType.full:
return '完整测试';
case TestType.mock:
return '模拟考试';
case TestType.vocabulary:
return '词汇专项';
case TestType.grammar:
return '语法专项';
case TestType.reading:
return '阅读专项';
case TestType.listening:
return '听力专项';
case TestType.speaking:
return '口语专项';
case TestType.writing:
return '写作专项';
}
}
/// 计算测试结果(模拟)
TestResult _calculateTestResult(String sessionId, List<UserAnswer> answers) {
// 这里是一个简化的计算逻辑,实际应用中会更复杂
final totalQuestions = answers.length;
final correctAnswers = (totalQuestions * 0.8).round(); // 模拟80%正确率
final totalScore = correctAnswers;
final maxScore = totalQuestions;
final percentage = (totalScore / maxScore) * 100;
return TestResult(
id: 'result_${DateTime.now().millisecondsSinceEpoch}',
testId: 'template_quick',
userId: 'user_001',
testType: TestType.quick,
totalScore: totalScore,
maxScore: maxScore,
percentage: percentage,
overallLevel: _calculateOverallLevel(percentage),
skillScores: _calculateSkillScores(answers),
answers: answers,
startTime: DateTime.now().subtract(const Duration(minutes: 15)),
endTime: DateTime.now(),
duration: 900,
feedback: _generateFeedback(percentage),
recommendations: {
'nextLevel': 'intermediate',
'focusAreas': ['grammar', 'vocabulary'],
'suggestedStudyTime': 45,
},
);
}
/// 计算整体水平
DifficultyLevel _calculateOverallLevel(double percentage) {
if (percentage >= 90) return DifficultyLevel.advanced;
if (percentage >= 80) return DifficultyLevel.upperIntermediate;
if (percentage >= 70) return DifficultyLevel.intermediate;
if (percentage >= 60) return DifficultyLevel.elementary;
return DifficultyLevel.beginner;
}
/// 计算技能得分
List<SkillScore> _calculateSkillScores(List<UserAnswer> answers) {
// 简化的技能得分计算
return [
SkillScore(
skillType: SkillType.vocabulary,
score: 4,
maxScore: 5,
percentage: 80.0,
level: DifficultyLevel.elementary,
feedback: '词汇掌握良好',
),
SkillScore(
skillType: SkillType.grammar,
score: 3,
maxScore: 4,
percentage: 75.0,
level: DifficultyLevel.elementary,
feedback: '语法基础扎实',
),
];
}
/// 生成反馈
String _generateFeedback(double percentage) {
if (percentage >= 90) {
return '优秀!您的英语水平很高,继续保持。';
} else if (percentage >= 80) {
return '良好!您的英语基础扎实,可以尝试更高难度的内容。';
} else if (percentage >= 70) {
return '不错!您的英语水平中等,建议加强薄弱环节的练习。';
} else if (percentage >= 60) {
return '及格!您的英语基础还需要加强,建议多练习基础知识。';
} else {
return '需要努力!建议从基础开始,系统性地学习英语。';
}
}
}

View File

@@ -0,0 +1,329 @@
import '../models/test_models.dart';
import 'test_service.dart';
import '../../../core/models/api_response.dart';
import '../../../core/network/api_client.dart';
import '../../../core/network/api_endpoints.dart';
/// 测试服务实现类HTTP使用后端真实API
class TestServiceImpl implements TestService {
final ApiClient _apiClient = ApiClient.instance;
@override
Future<ApiResponse<List<TestTemplate>>> getTestTemplates() async {
try {
final response = await _apiClient.get('${ApiEndpoints.baseUrl}/tests/templates');
if (response.statusCode == 200) {
final root = response.data['data'];
List<dynamic> list = const [];
if (root is List) {
list = root;
} else if (root is Map<String, dynamic>) {
final v = root['templates'];
if (v is List) list = v;
}
final templates = list.map((e) => TestTemplate.fromJson(e)).toList();
return ApiResponse.success(message: '获取测试模板成功', data: templates);
}
return ApiResponse.error(message: '加载测试模板失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '获取测试模板失败: $e');
}
}
@override
Future<ApiResponse<List<TestTemplate>>> getTestTemplatesByType(
TestType type, {
bool? isActive,
}) async {
try {
final response = await _apiClient.get(
'${ApiEndpoints.baseUrl}/tests/templates',
queryParameters: {
'type': type.name,
if (isActive != null) 'active': isActive,
},
);
if (response.statusCode == 200) {
final root = response.data['data'];
List<dynamic> list = const [];
if (root is List) {
list = root;
} else if (root is Map<String, dynamic>) {
final v = root['templates'];
if (v is List) list = v;
}
final templates = list.map((e) => TestTemplate.fromJson(e)).toList();
return ApiResponse.success(message: '获取测试模板成功', data: templates);
}
return ApiResponse.error(message: '加载测试模板失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '获取测试模板失败: $e');
}
}
@override
Future<ApiResponse<TestTemplate>> getTestTemplateById(String id) async {
try {
final response = await _apiClient.get('${ApiEndpoints.baseUrl}/tests/templates/$id');
if (response.statusCode == 200) {
return ApiResponse.success(
message: '获取测试模板成功',
data: TestTemplate.fromJson(response.data['data']),
);
}
return ApiResponse.error(message: '模板不存在', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '获取测试模板失败: $e');
}
}
@override
Future<ApiResponse<TestSession>> createTestSession({
required String templateId,
required String userId,
Map<String, dynamic>? metadata,
}) async {
try {
final response = await _apiClient.post(
'${ApiEndpoints.baseUrl}/tests/sessions',
data: {
'template_id': templateId,
'user_id': userId,
'metadata': metadata ?? {},
},
);
if (response.statusCode == 200) {
return ApiResponse.success(
message: '创建测试会话成功',
data: TestSession.fromJson(response.data['data']),
);
}
return ApiResponse.error(message: '创建测试会话失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '创建测试会话失败: $e');
}
}
@override
Future<ApiResponse<TestSession>> startTest(String sessionId) async {
try {
final response = await _apiClient.put('${ApiEndpoints.baseUrl}/tests/sessions/$sessionId/start');
if (response.statusCode == 200) {
return ApiResponse.success(
message: '测试已开始',
data: TestSession.fromJson(response.data['data']),
);
}
return ApiResponse.error(message: '开始测试失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '开始测试失败: $e');
}
}
@override
Future<ApiResponse<TestSession>> submitAnswer({
required String sessionId,
required UserAnswer answer,
}) async {
try {
final response = await _apiClient.post(
'${ApiEndpoints.baseUrl}/tests/sessions/$sessionId/answers',
data: answer.toJson(),
);
if (response.statusCode == 200) {
return ApiResponse.success(
message: '答案提交成功',
data: TestSession.fromJson(response.data['data']),
);
}
return ApiResponse.error(message: '提交答案失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '提交答案失败: $e');
}
}
@override
Future<ApiResponse<TestSession>> pauseTest(String sessionId) async {
try {
final response = await _apiClient.put('${ApiEndpoints.baseUrl}/tests/sessions/$sessionId/pause');
if (response.statusCode == 200) {
return ApiResponse.success(
message: '测试已暂停',
data: TestSession.fromJson(response.data['data']),
);
}
return ApiResponse.error(message: '暂停测试失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '暂停测试失败: $e');
}
}
@override
Future<ApiResponse<TestSession>> resumeTest(String sessionId) async {
try {
final response = await _apiClient.put('${ApiEndpoints.baseUrl}/tests/sessions/$sessionId/resume');
if (response.statusCode == 200) {
return ApiResponse.success(
message: '测试已恢复',
data: TestSession.fromJson(response.data['data']),
);
}
return ApiResponse.error(message: '恢复测试失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '恢复测试失败: $e');
}
}
@override
Future<ApiResponse<TestResult>> completeTest({
required String sessionId,
required List<UserAnswer> answers,
}) async {
try {
final response = await _apiClient.put(
'${ApiEndpoints.baseUrl}/tests/sessions/$sessionId/complete',
data: {
'answers': answers.map((a) => a.toJson()).toList(),
},
);
if (response.statusCode == 200) {
return ApiResponse.success(
message: '提交测试成功',
data: TestResult.fromJson(response.data['data']),
);
}
return ApiResponse.error(message: '完成测试失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '完成测试失败: $e');
}
}
@override
Future<ApiResponse<List<TestResult>>> getUserTestHistory(
String userId, {
int page = 1,
int limit = 10,
}) async {
try {
final response = await _apiClient.get(
'${ApiEndpoints.baseUrl}/tests/sessions',
queryParameters: {
'page': page,
'limit': limit,
},
);
if (response.statusCode == 200) {
final root = response.data['data'];
List<dynamic> list = const [];
if (root is List) {
list = root;
} else if (root is Map<String, dynamic>) {
final v = root['sessions'];
if (v is List) list = v;
}
final results = list.map((e) => TestResult.fromJson(e)).toList();
return ApiResponse.success(message: '获取测试历史成功', data: results);
}
return ApiResponse.error(message: '获取测试历史失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '获取测试历史失败: $e');
}
}
@override
Future<ApiResponse<List<TestResult>>> getRecentTestResults(
String userId, {
int limit = 10,
}) async {
try {
final response = await _apiClient.get(
'${ApiEndpoints.baseUrl}/tests/sessions',
queryParameters: {
'limit': limit,
},
);
if (response.statusCode == 200) {
final root = response.data['data'];
List<dynamic> list = const [];
if (root is List) {
list = root;
} else if (root is Map<String, dynamic>) {
final v = root['sessions'];
if (v is List) list = v;
}
final results = list.map((e) => TestResult.fromJson(e)).toList();
return ApiResponse.success(message: '获取最近测试结果成功', data: results);
}
return ApiResponse.error(message: '获取最近测试结果失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '获取最近测试结果失败: $e');
}
}
@override
Future<ApiResponse<TestResult>> getTestResultById(String resultId) async {
try {
final response = await _apiClient.get('${ApiEndpoints.baseUrl}/tests/results/$resultId');
if (response.statusCode == 200) {
return ApiResponse.success(
message: '获取测试结果成功',
data: TestResult.fromJson(response.data['data']),
);
}
return ApiResponse.error(message: '测试结果不存在', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '获取测试结果失败: $e');
}
}
@override
Future<ApiResponse<Map<SkillType, double>>> getUserSkillStatistics(
String userId, {
int? daysPeriod,
}) async {
try {
final response = await _apiClient.get('${ApiEndpoints.baseUrl}/tests/stats');
if (response.statusCode == 200) {
final Map<String, dynamic> data = response.data['data'] ?? {};
final Map<SkillType, double> stats = {};
data.forEach((k, v) {
final skill = SkillType.values.firstWhere((s) => s.name == k, orElse: () => SkillType.reading);
stats[skill] = (v as num).toDouble();
});
return ApiResponse.success(message: '获取技能统计成功', data: stats);
}
return ApiResponse.error(message: '获取技能统计失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '获取技能统计失败: $e');
}
}
@override
Future<ApiResponse<Map<String, dynamic>>> getQuestionStatistics() async {
try {
final response = await _apiClient.get('${ApiEndpoints.baseUrl}/tests/stats');
if (response.statusCode == 200) {
return ApiResponse.success(
message: '获取题目统计成功',
data: response.data['data'] ?? {},
);
}
return ApiResponse.error(message: '获取题目统计失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '获取题目统计失败: $e');
}
}
@override
Future<ApiResponse<bool>> deleteTestResult(String resultId) async {
try {
final response = await _apiClient.delete('${ApiEndpoints.baseUrl}/tests/results/$resultId');
if (response.statusCode == 200) {
return ApiResponse.success(message: '删除测试结果成功', data: true);
}
return ApiResponse.error(message: '删除测试结果失败', code: response.statusCode);
} catch (e) {
return ApiResponse.error(message: '删除测试结果失败: $e');
}
}
}