init
This commit is contained in:
168
client/lib/features/writing/services/writing_record_service.dart
Normal file
168
client/lib/features/writing/services/writing_record_service.dart
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
242
client/lib/features/writing/services/writing_service.dart
Normal file
242
client/lib/features/writing/services/writing_service.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user