591 lines
15 KiB
Dart
591 lines
15 KiB
Dart
|
|
import 'package:flutter/foundation.dart';
|
|||
|
|
import '../models/test_models.dart';
|
|||
|
|
import '../services/test_api_service.dart';
|
|||
|
|
import '../../../core/models/api_response.dart';
|
|||
|
|
|
|||
|
|
/// 综合测试状态管理类
|
|||
|
|
class TestProvider with ChangeNotifier {
|
|||
|
|
final TestApiService _testService;
|
|||
|
|
|
|||
|
|
TestProvider({TestApiService? testService})
|
|||
|
|
: _testService = testService ?? TestApiService();
|
|||
|
|
|
|||
|
|
// 加载状<E8BDBD>? bool _isLoading = false;
|
|||
|
|
bool get isLoading => _isLoading;
|
|||
|
|
|
|||
|
|
// 错误信息
|
|||
|
|
String? _errorMessage;
|
|||
|
|
String? get errorMessage => _errorMessage;
|
|||
|
|
|
|||
|
|
// 测试模板
|
|||
|
|
List<TestTemplate> _templates = [];
|
|||
|
|
List<TestTemplate> get templates => _templates;
|
|||
|
|
|
|||
|
|
// 当前测试会话
|
|||
|
|
TestSession? _currentSession;
|
|||
|
|
TestSession? get currentSession => _currentSession;
|
|||
|
|
|
|||
|
|
// 当前题目
|
|||
|
|
TestQuestion? get currentQuestion {
|
|||
|
|
if (_currentSession == null ||
|
|||
|
|
_currentSession!.currentQuestionIndex >= _currentSession!.questions.length) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
return _currentSession!.questions[_currentSession!.currentQuestionIndex];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 测试结果
|
|||
|
|
List<TestResult> _testResults = [];
|
|||
|
|
List<TestResult> get testResults => _testResults;
|
|||
|
|
|
|||
|
|
TestResult? _currentResult;
|
|||
|
|
TestResult? get currentResult => _currentResult;
|
|||
|
|
|
|||
|
|
// 用户技能统<E883BD>? Map<SkillType, double> _skillStatistics = {};
|
|||
|
|
Map<SkillType, double> get skillStatistics => _skillStatistics;
|
|||
|
|
|
|||
|
|
// 题目统计
|
|||
|
|
Map<String, dynamic> _questionStatistics = {};
|
|||
|
|
Map<String, dynamic> get questionStatistics => _questionStatistics;
|
|||
|
|
|
|||
|
|
// 计时器相<E599A8>? int _timeRemaining = 0;
|
|||
|
|
int get timeRemaining => _timeRemaining;
|
|||
|
|
|
|||
|
|
bool _isTimerRunning = false;
|
|||
|
|
bool get isTimerRunning => _isTimerRunning;
|
|||
|
|
|
|||
|
|
/// 设置加载状<E8BDBD>? void _setLoading(bool loading) {
|
|||
|
|
_isLoading = loading;
|
|||
|
|
notifyListeners();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 设置错误信息
|
|||
|
|
void _setError(String? error) {
|
|||
|
|
_errorMessage = error;
|
|||
|
|
notifyListeners();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 清除错误信息
|
|||
|
|
void clearError() {
|
|||
|
|
_setError(null);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 加载所有测试模<E8AF95>? Future<void> loadTestTemplates() async {
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.getTestTemplates();
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_templates = response.data!;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('加载测试模板失败: ${e.toString()}');
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 根据类型加载测试模板
|
|||
|
|
Future<void> loadTestTemplatesByType(TestType type) async {
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.getTestTemplatesByType(type);
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_templates = response.data!;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('加载测试模板失败: ${e.toString()}');
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 创建测试会话
|
|||
|
|
Future<bool> createTestSession({
|
|||
|
|
required String templateId,
|
|||
|
|
required String userId,
|
|||
|
|
}) async {
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.createTestSession(
|
|||
|
|
templateId: templateId,
|
|||
|
|
userId: userId,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_currentSession = response.data!;
|
|||
|
|
_timeRemaining = _currentSession!.timeRemaining;
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('创建测试会话失败: ${e.toString()}');
|
|||
|
|
return false;
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 开始测<E5A78B>? Future<bool> startTest() async {
|
|||
|
|
if (_currentSession == null) {
|
|||
|
|
_setError('没有活动的测试会<EFBFBD>?);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.startTest(_currentSession!.id);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_currentSession = response.data!;
|
|||
|
|
_timeRemaining = _currentSession!.timeRemaining;
|
|||
|
|
_startTimer();
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('开始测试失<EFBFBD>? ${e.toString()}');
|
|||
|
|
return false;
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 提交答案
|
|||
|
|
Future<bool> submitAnswer(UserAnswer answer) async {
|
|||
|
|
if (_currentSession == null) {
|
|||
|
|
_setError('没有活动的测试会<EFBFBD>?);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.submitAnswer(
|
|||
|
|
sessionId: _currentSession!.id,
|
|||
|
|
answer: answer,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_currentSession = response.data!;
|
|||
|
|
_timeRemaining = _currentSession!.timeRemaining;
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('提交答案失败: ${e.toString()}');
|
|||
|
|
return false;
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 下一<E4B88B>? void nextQuestion() {
|
|||
|
|
if (_currentSession != null &&
|
|||
|
|
_currentSession!.currentQuestionIndex < _currentSession!.questions.length - 1) {
|
|||
|
|
_currentSession = _currentSession!.copyWith(
|
|||
|
|
currentQuestionIndex: _currentSession!.currentQuestionIndex + 1,
|
|||
|
|
);
|
|||
|
|
notifyListeners();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 上一<E4B88A>? void previousQuestion() {
|
|||
|
|
if (_currentSession != null && _currentSession!.currentQuestionIndex > 0) {
|
|||
|
|
_currentSession = _currentSession!.copyWith(
|
|||
|
|
currentQuestionIndex: _currentSession!.currentQuestionIndex - 1,
|
|||
|
|
);
|
|||
|
|
notifyListeners();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 跳转到指定题<E5AE9A>? void goToQuestion(int index) {
|
|||
|
|
if (_currentSession != null &&
|
|||
|
|
index >= 0 &&
|
|||
|
|
index < _currentSession!.questions.length) {
|
|||
|
|
_currentSession = _currentSession!.copyWith(
|
|||
|
|
currentQuestionIndex: index,
|
|||
|
|
);
|
|||
|
|
notifyListeners();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 暂停测试
|
|||
|
|
Future<bool> pauseTest() async {
|
|||
|
|
if (_currentSession == null) {
|
|||
|
|
_setError('没有活动的测试会<EFBFBD>?);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.pauseTest(_currentSession!.id);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_currentSession = response.data!;
|
|||
|
|
_pauseTimer();
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('暂停测试失败: ${e.toString()}');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 恢复测试
|
|||
|
|
Future<bool> resumeTest() async {
|
|||
|
|
if (_currentSession == null) {
|
|||
|
|
_setError('没有活动的测试会<EFBFBD>?);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.resumeTest(_currentSession!.id);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_currentSession = response.data!;
|
|||
|
|
_startTimer();
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('恢复测试失败: ${e.toString()}');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 完成测试
|
|||
|
|
Future<bool> completeTest() async {
|
|||
|
|
if (_currentSession == null) {
|
|||
|
|
_setError('没有活动的测试会话');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.completeTest(_currentSession!.id);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_currentResult = response.data!;
|
|||
|
|
_stopTimer();
|
|||
|
|
_currentSession = _currentSession!.copyWith(
|
|||
|
|
status: TestStatus.completed,
|
|||
|
|
endTime: DateTime.now(),
|
|||
|
|
);
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('完成测试失败: ${e.toString()}');
|
|||
|
|
return false;
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 加载用户测试历史
|
|||
|
|
Future<void> loadUserTestHistory(String userId, {int page = 1, int limit = 10}) async {
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.getUserTestHistory(
|
|||
|
|
page: page,
|
|||
|
|
limit: limit,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
if (page == 1) {
|
|||
|
|
_testResults = response.data!;
|
|||
|
|
} else {
|
|||
|
|
_testResults.addAll(response.data!);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('加载测试历史失败: ${e.toString()}');
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 加载最近的测试结果
|
|||
|
|
Future<void> loadRecentTestResults(String userId, {int limit = 5}) async {
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.getRecentTestResults(
|
|||
|
|
userId,
|
|||
|
|
limit: limit,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_testResults = response.data!;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('加载最近测试结果失<EFBFBD>? ${e.toString()}');
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 加载测试结果详情
|
|||
|
|
Future<void> loadTestResultById(String resultId) async {
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.getTestResultById(resultId);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_currentResult = response.data!;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('加载测试结果失败: ${e.toString()}');
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 加载用户技能统<E883BD>? Future<void> loadUserSkillStatistics(String userId) async {
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.getUserSkillStatistics(userId);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_skillStatistics = response.data!;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('加载技能统计失<EFBFBD>? ${e.toString()}');
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 加载题目统计
|
|||
|
|
Future<void> loadQuestionStatistics() async {
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.getQuestionStatistics();
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_questionStatistics = response.data!;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('加载题目统计失败: ${e.toString()}');
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 删除测试结果
|
|||
|
|
Future<bool> deleteTestResult(String resultId) async {
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.deleteTestResult(resultId);
|
|||
|
|
|
|||
|
|
if (response.success) {
|
|||
|
|
_testResults.removeWhere((result) => result.id == resultId);
|
|||
|
|
notifyListeners();
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('删除测试结果失败: ${e.toString()}');
|
|||
|
|
return false;
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 重置当前会话
|
|||
|
|
void resetCurrentSession() {
|
|||
|
|
_currentSession = null;
|
|||
|
|
_currentResult = null;
|
|||
|
|
_stopTimer();
|
|||
|
|
notifyListeners();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 开始计时器
|
|||
|
|
void _startTimer() {
|
|||
|
|
_isTimerRunning = true;
|
|||
|
|
_updateTimer();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 暂停计时<E8AEA1>? void _pauseTimer() {
|
|||
|
|
_isTimerRunning = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 停止计时<E8AEA1>? void _stopTimer() {
|
|||
|
|
_isTimerRunning = false;
|
|||
|
|
_timeRemaining = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 更新计时<E8AEA1>? void _updateTimer() {
|
|||
|
|
if (_isTimerRunning && _timeRemaining > 0) {
|
|||
|
|
Future.delayed(const Duration(seconds: 1), () {
|
|||
|
|
if (_isTimerRunning) {
|
|||
|
|
_timeRemaining--;
|
|||
|
|
notifyListeners();
|
|||
|
|
|
|||
|
|
if (_timeRemaining <= 0) {
|
|||
|
|
// 时间到,自动完成测试
|
|||
|
|
completeTest();
|
|||
|
|
} else {
|
|||
|
|
_updateTimer();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 格式化剩余时<E4BD99>? String getFormattedTimeRemaining() {
|
|||
|
|
final hours = _timeRemaining ~/ 3600;
|
|||
|
|
final minutes = (_timeRemaining % 3600) ~/ 60;
|
|||
|
|
final seconds = _timeRemaining % 60;
|
|||
|
|
|
|||
|
|
if (hours > 0) {
|
|||
|
|
return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
|
|||
|
|
} else {
|
|||
|
|
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取测试进度百分<E799BE>? double getTestProgress() {
|
|||
|
|
if (_currentSession == null || _currentSession!.questions.isEmpty) {
|
|||
|
|
return 0.0;
|
|||
|
|
}
|
|||
|
|
return (_currentSession!.currentQuestionIndex + 1) / _currentSession!.questions.length;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取已回答题目数<E79BAE>? int getAnsweredQuestionsCount() {
|
|||
|
|
return _currentSession?.answers.length ?? 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取未回答题目数<E79BAE>? int getUnansweredQuestionsCount() {
|
|||
|
|
if (_currentSession == null) return 0;
|
|||
|
|
return _currentSession!.questions.length - _currentSession!.answers.length;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 检查是否所有题目都已回<E5B7B2>? bool areAllQuestionsAnswered() {
|
|||
|
|
if (_currentSession == null) return false;
|
|||
|
|
return _currentSession!.answers.length == _currentSession!.questions.length;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取技能类型的中文名称
|
|||
|
|
String getSkillTypeName(SkillType skillType) {
|
|||
|
|
switch (skillType) {
|
|||
|
|
case SkillType.vocabulary:
|
|||
|
|
return '词汇';
|
|||
|
|
case SkillType.grammar:
|
|||
|
|
return '语法';
|
|||
|
|
case SkillType.reading:
|
|||
|
|
return '阅读';
|
|||
|
|
case SkillType.listening:
|
|||
|
|
return '听力';
|
|||
|
|
case SkillType.speaking:
|
|||
|
|
return '口语';
|
|||
|
|
case SkillType.writing:
|
|||
|
|
return '写作';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取难度等级的中文名<E69687>? String getDifficultyLevelName(DifficultyLevel level) {
|
|||
|
|
switch (level) {
|
|||
|
|
case DifficultyLevel.beginner:
|
|||
|
|
return '初级';
|
|||
|
|
case DifficultyLevel.elementary:
|
|||
|
|
return '基础';
|
|||
|
|
case DifficultyLevel.intermediate:
|
|||
|
|
return '中级';
|
|||
|
|
case DifficultyLevel.upperIntermediate:
|
|||
|
|
return '中高<EFBFBD>?;
|
|||
|
|
case DifficultyLevel.advanced:
|
|||
|
|
return '高级';
|
|||
|
|
case DifficultyLevel.expert:
|
|||
|
|
return '专家<EFBFBD>?;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取测试类型的中文名<E69687>? String getTestTypeName(TestType type) {
|
|||
|
|
switch (type) {
|
|||
|
|
case TestType.quick:
|
|||
|
|
return '快速测<EFBFBD>?;
|
|||
|
|
case TestType.standard:
|
|||
|
|
return '标准测试';
|
|||
|
|
case TestType.full:
|
|||
|
|
return '完整测试';
|
|||
|
|
case TestType.mock:
|
|||
|
|
return '模拟考试';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 加载最近的测试结果
|
|||
|
|
Future<void> loadRecentResults({String? userId}) async {
|
|||
|
|
_setLoading(true);
|
|||
|
|
_setError(null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _testService.getRecentTestResults(userId);
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
_testResults = response.data!;
|
|||
|
|
} else {
|
|||
|
|
_setError(response.message);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
_setError('加载测试结果失败: ${e.toString()}');
|
|||
|
|
} finally {
|
|||
|
|
_setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
void dispose() {
|
|||
|
|
_stopTimer();
|
|||
|
|
super.dispose();
|
|||
|
|
}
|
|||
|
|
}
|