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,168 @@
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/writing_record.dart';
/// 写作记录管理服务
class WritingRecordService {
static const String _recordsKey = 'writing_records';
/// 保存写作记录
static Future<void> saveRecord(WritingRecord record) async {
final prefs = await SharedPreferences.getInstance();
final records = await getRecords();
records.add(record);
final recordsJson = records.map((r) => r.toJson()).toList();
await prefs.setString(_recordsKey, jsonEncode(recordsJson));
}
/// 获取所有写作记录
static Future<List<WritingRecord>> getRecords() async {
final prefs = await SharedPreferences.getInstance();
final recordsString = prefs.getString(_recordsKey);
if (recordsString == null) {
return [];
}
try {
final recordsJson = jsonDecode(recordsString) as List;
return recordsJson.map((json) => WritingRecord.fromJson(json)).toList();
} catch (e) {
return [];
}
}
/// 获取最近的写作记录
static Future<List<WritingRecord>> getRecentRecords({int limit = 5}) async {
final records = await getRecords();
records.sort((a, b) => b.completedAt.compareTo(a.completedAt));
return records.take(limit).toList();
}
/// 根据ID获取写作记录
static Future<WritingRecord?> getRecordById(String id) async {
final records = await getRecords();
try {
return records.firstWhere((record) => record.id == id);
} catch (e) {
return null;
}
}
/// 删除写作记录
static Future<void> deleteRecord(String id) async {
final prefs = await SharedPreferences.getInstance();
final records = await getRecords();
records.removeWhere((record) => record.id == id);
final recordsJson = records.map((r) => r.toJson()).toList();
await prefs.setString(_recordsKey, jsonEncode(recordsJson));
}
/// 获取写作统计数据
static Future<Map<String, dynamic>> getStatistics() async {
final records = await getRecords();
if (records.isEmpty) {
return {
'totalCount': 0,
'averageScore': 0,
'totalTimeUsed': 0,
'averageWordCount': 0,
};
}
final totalScore = records.fold<int>(0, (sum, record) => sum + record.score);
final totalTimeUsed = records.fold<int>(0, (sum, record) => sum + record.timeUsed);
final totalWordCount = records.fold<int>(0, (sum, record) => sum + record.wordCount);
return {
'totalCount': records.length,
'averageScore': (totalScore / records.length).round(),
'totalTimeUsed': totalTimeUsed,
'averageWordCount': (totalWordCount / records.length).round(),
};
}
/// 清空所有记录(用于测试)
static Future<void> clearAllRecords() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_recordsKey);
}
/// 添加一些示例数据(用于演示)
static Future<void> addSampleData() async {
final now = DateTime.now();
final sampleRecords = [
WritingRecord(
id: 'record_1',
taskId: 'essay_1',
taskTitle: '市场调研报告',
taskDescription: '撰写一份关于新产品市场前景的调研报告。',
content: '随着科技的不断发展智能手表市场呈现出强劲的增长势头。根据最新的市场调研数据显示全球智能手表市场规模预计在未来五年内将保持年均15%的增长率。消费者对健康监测、运动追踪等功能的需求日益增长,为智能手表产品提供了广阔的市场空间。建议公司抓住这一机遇,加大研发投入,推出具有竞争力的产品。',
wordCount: 156,
timeUsed: 1800, // 30分钟
score: 90,
completedAt: now.subtract(const Duration(days: 1)),
feedback: {
'content': '内容丰富,主题明确,论述清晰。',
'contentScore': 88,
'grammar': '语法使用准确,句式多样。',
'grammarScore': 92,
'vocabulary': '词汇运用恰当,表达准确。',
'vocabularyScore': 89,
'structure': '文章结构清晰,逻辑性强。',
'structureScore': 91,
},
),
WritingRecord(
id: 'record_2',
taskId: 'letter_1',
taskTitle: '我的理想房屋',
taskDescription: '描述你心目中理想房屋的样子。',
content: '我理想中的房屋坐落在一个安静的社区里,周围绿树成荫,环境优美。房屋采用现代简约风格设计,外观简洁大方。内部布局合理,包括宽敞的客厅、舒适的卧室、功能齐全的厨房和书房。特别是书房,我希望有一面大大的书墙,可以收藏我喜爱的书籍。房屋还应该有一个小花园,种植各种花草,让生活更加贴近自然。',
wordCount: 142,
timeUsed: 1200, // 20分钟
score: 89,
completedAt: now.subtract(const Duration(days: 2)),
feedback: {
'content': '内容充实,描述生动。',
'contentScore': 87,
'grammar': '语法基本正确,表达流畅。',
'grammarScore': 90,
'vocabulary': '词汇使用恰当,描述性强。',
'vocabularyScore': 88,
'structure': '结构清晰,层次分明。',
'structureScore': 92,
},
),
WritingRecord(
id: 'record_3',
taskId: 'review_1',
taskTitle: '电影评论',
taskDescription: '写一篇关于最近观看电影的评论。',
content: '最近观看了《流浪地球2》这部科幻电影给我留下了深刻的印象。影片在视觉效果方面表现出色宏大的场面和精细的特效让人震撼。故事情节紧凑人物刻画也比较丰满。特别是对人类面临危机时的团结精神的展现很有感染力。不过部分情节的发展略显仓促希望能有更多的细节描述。总的来说这是一部值得推荐的优秀科幻电影。',
wordCount: 138,
timeUsed: 1500, // 25分钟
score: 92,
completedAt: now.subtract(const Duration(hours: 12)),
feedback: {
'content': '评论客观全面,观点明确。',
'contentScore': 90,
'grammar': '语法准确,表达自然。',
'grammarScore': 93,
'vocabulary': '词汇丰富,用词精准。',
'vocabularyScore': 91,
'structure': '结构合理,逻辑清晰。',
'structureScore': 94,
},
),
];
for (final record in sampleRecords) {
await saveRecord(record);
}
}
}

View File

@@ -0,0 +1,242 @@
import '../models/writing_task.dart';
import '../models/writing_submission.dart';
import '../models/writing_stats.dart';
import '../../../core/network/api_client.dart';
import '../../../core/network/api_endpoints.dart';
import '../../../core/services/enhanced_api_service.dart';
import '../../../core/models/api_response.dart';
import '../models/writing_task.dart';
import '../models/writing_submission.dart';
import '../models/writing_stats.dart';
/// 写作训练服务
class WritingService {
final EnhancedApiService _enhancedApiService = EnhancedApiService();
// 缓存时长配置
static const Duration _shortCacheDuration = Duration(minutes: 5);
static const Duration _longCacheDuration = Duration(hours: 1);
/// 获取写作任务列表
Future<List<WritingTask>> getWritingTasks({
WritingType? type,
WritingDifficulty? difficulty,
int page = 1,
int limit = 20,
bool forceRefresh = false,
}) async {
try {
final response = await _enhancedApiService.get<List<WritingTask>>(
ApiEndpoints.writingPrompts,
queryParameters: {
'page': page,
'limit': limit,
if (type != null) 'type': type.name,
if (difficulty != null) 'difficulty': difficulty.name,
},
useCache: !forceRefresh,
cacheDuration: _shortCacheDuration,
fromJson: (data) {
final List<dynamic> list = data['data'] ?? [];
return list.map((json) => WritingTask.fromJson(json)).toList();
},
);
if (response.success && response.data != null) {
return response.data!;
} else {
throw Exception(response.message);
}
} catch (e) {
throw Exception('获取写作任务失败: $e');
}
}
/// 获取单个写作任务详情
Future<WritingTask> getWritingTask(String taskId) async {
try {
final response = await _enhancedApiService.get<WritingTask>(
'${ApiEndpoints.writingPrompts}/$taskId',
cacheDuration: _longCacheDuration,
fromJson: (data) => WritingTask.fromJson(data['data']),
);
if (response.success && response.data != null) {
return response.data!;
} else {
throw Exception(response.message);
}
} catch (e) {
throw Exception('获取写作任务详情失败: $e');
}
}
/// 提交写作作业
Future<WritingSubmission> submitWriting({
required String taskId,
required String userId,
required String content,
required int timeSpent,
required int wordCount,
}) async {
try {
final response = await _enhancedApiService.post<WritingSubmission>(
ApiEndpoints.writingSubmissions,
data: {
'prompt_id': taskId,
'user_id': userId,
'content': content,
'time_spent': timeSpent,
'word_count': wordCount,
},
fromJson: (data) => WritingSubmission.fromJson(data['data']),
);
if (response.success && response.data != null) {
return response.data!;
} else {
throw Exception(response.message);
}
} catch (e) {
throw Exception('提交写作作业失败: $e');
}
}
/// 获取用户写作历史
Future<List<WritingSubmission>> getUserWritingHistory({
required String userId,
int page = 1,
int limit = 20,
bool forceRefresh = false,
}) async {
try {
final response = await _enhancedApiService.get<List<WritingSubmission>>(
ApiEndpoints.writingSubmissions,
queryParameters: {
'page': page,
'limit': limit,
},
useCache: !forceRefresh,
cacheDuration: _shortCacheDuration,
fromJson: (data) {
final List<dynamic> list = data['data'] ?? [];
return list.map((json) => WritingSubmission.fromJson(json)).toList();
},
);
if (response.success && response.data != null) {
return response.data!;
} else {
throw Exception(response.message);
}
} catch (e) {
throw Exception('获取写作历史失败: $e');
}
}
/// 获取用户写作统计
Future<WritingStats> getUserWritingStats(String userId, {bool forceRefresh = false}) async {
try {
final response = await _enhancedApiService.get<WritingStats>(
ApiEndpoints.writingStats,
useCache: !forceRefresh,
cacheDuration: _shortCacheDuration,
fromJson: (data) => WritingStats.fromJson(data['data']),
);
if (response.success && response.data != null) {
return response.data!;
} else {
throw Exception(response.message);
}
} catch (e) {
throw Exception('获取写作统计失败: $e');
}
}
/// 获取写作反馈
Future<WritingSubmission> getWritingFeedback(String submissionId) async {
try {
final response = await _enhancedApiService.get<WritingSubmission>(
'${ApiEndpoints.writingSubmissions}/$submissionId',
cacheDuration: _shortCacheDuration,
fromJson: (data) => WritingSubmission.fromJson(data['data']),
);
if (response.success && response.data != null) {
return response.data!;
} else {
throw Exception(response.message);
}
} catch (e) {
throw Exception('获取写作反馈失败: $e');
}
}
/// 搜索写作任务
Future<List<WritingTask>> searchWritingTasks({
required String query,
WritingType? type,
WritingDifficulty? difficulty,
int page = 1,
int limit = 20,
bool forceRefresh = false,
}) async {
try {
final response = await _enhancedApiService.get<List<WritingTask>>(
'${ApiEndpoints.writingPrompts}/search',
queryParameters: {
'q': query,
'page': page,
'limit': limit,
if (type != null) 'type': type.name,
if (difficulty != null) 'difficulty': difficulty.name,
},
useCache: !forceRefresh,
cacheDuration: _shortCacheDuration,
fromJson: (data) {
final List<dynamic> list = data['data'] ?? [];
return list.map((json) => WritingTask.fromJson(json)).toList();
},
);
if (response.success && response.data != null) {
return response.data!;
} else {
throw Exception(response.message);
}
} catch (e) {
throw Exception('搜索写作任务失败: $e');
}
}
/// 获取推荐的写作任务
Future<List<WritingTask>> getRecommendedWritingTasks({
required String userId,
int limit = 10,
bool forceRefresh = false,
}) async {
try {
final response = await _enhancedApiService.get<List<WritingTask>>(
'${ApiEndpoints.writingPrompts}/recommendations',
queryParameters: {
'limit': limit,
},
useCache: !forceRefresh,
cacheDuration: _shortCacheDuration,
fromJson: (data) {
final List<dynamic> list = data['data'] ?? [];
return list.map((json) => WritingTask.fromJson(json)).toList();
},
);
if (response.success && response.data != null) {
return response.data!;
} else {
throw Exception(response.message);
}
} catch (e) {
throw Exception('获取推荐写作任务失败: $e');
}
}
}