Files
AutoTime-Tracker/lib/services/export_service.dart
2025-11-13 15:45:28 +08:00

157 lines
5.3 KiB
Dart

import '../database/app_usage_dao.dart';
import '../database/daily_stats_dao.dart';
import '../theme/app_theme.dart';
class ExportService {
final AppUsageDao _appUsageDao = AppUsageDao();
final DailyStatsDao _dailyStatsDao = DailyStatsDao();
/// 导出 CSV 格式数据
Future<String> exportToCSV({
required DateTime startDate,
required DateTime endDate,
}) async {
final appUsages = await _appUsageDao.getAppUsages(
startTime: startDate,
endTime: endDate,
);
final buffer = StringBuffer();
// CSV 头部
buffer.writeln('应用名称,包名,开始时间,结束时间,使用时长(秒),使用时长(格式化),分类');
// 数据行
for (final usage in appUsages) {
buffer.writeln([
_escapeCsvField(usage.appName),
_escapeCsvField(usage.packageName),
usage.startTime.toIso8601String(),
usage.endTime.toIso8601String(),
usage.duration.toString(),
usage.formattedDuration,
AppTheme.getCategoryName(usage.category),
].join(','));
}
return buffer.toString();
}
/// 导出统计报告(文本格式)
Future<String> exportStatsReport({
required DateTime startDate,
required DateTime endDate,
}) async {
final stats = await _dailyStatsDao.getStatsRange(
startDate: startDate,
endDate: endDate,
);
final buffer = StringBuffer();
buffer.writeln('=== AutoTime Tracker 统计报告 ===');
buffer.writeln('报告时间: ${startDate.toString().split(' ')[0]}${endDate.toString().split(' ')[0]}');
buffer.writeln('');
buffer.writeln('日期统计:');
buffer.writeln('');
int totalWorkTime = 0;
int totalStudyTime = 0;
int totalEntertainmentTime = 0;
int totalSocialTime = 0;
int totalToolTime = 0;
int totalTime = 0;
for (final stat in stats) {
buffer.writeln('${stat.date.toString().split(' ')[0]}:');
buffer.writeln(' 总时长: ${stat.formattedTotalTime}');
buffer.writeln(' 工作: ${_formatTime(stat.workTime)}');
buffer.writeln(' 学习: ${_formatTime(stat.studyTime)}');
buffer.writeln(' 娱乐: ${_formatTime(stat.entertainmentTime)}');
buffer.writeln(' 社交: ${_formatTime(stat.socialTime)}');
buffer.writeln(' 工具: ${_formatTime(stat.toolTime)}');
if (stat.efficiencyScore != null) {
buffer.writeln(' 效率评分: ${stat.efficiencyScore}%');
}
buffer.writeln('');
totalWorkTime += stat.workTime;
totalStudyTime += stat.studyTime;
totalEntertainmentTime += stat.entertainmentTime;
totalSocialTime += stat.socialTime;
totalToolTime += stat.toolTime;
totalTime += stat.totalTime;
}
buffer.writeln('总计:');
buffer.writeln(' 总时长: ${_formatTime(totalTime)}');
buffer.writeln(' 工作: ${_formatTime(totalWorkTime)} (${(totalWorkTime / totalTime * 100).toStringAsFixed(1)}%)');
buffer.writeln(' 学习: ${_formatTime(totalStudyTime)} (${(totalStudyTime / totalTime * 100).toStringAsFixed(1)}%)');
buffer.writeln(' 娱乐: ${_formatTime(totalEntertainmentTime)} (${(totalEntertainmentTime / totalTime * 100).toStringAsFixed(1)}%)');
buffer.writeln(' 社交: ${_formatTime(totalSocialTime)} (${(totalSocialTime / totalTime * 100).toStringAsFixed(1)}%)');
buffer.writeln(' 工具: ${_formatTime(totalToolTime)} (${(totalToolTime / totalTime * 100).toStringAsFixed(1)}%)');
return buffer.toString();
}
/// 导出今日报告
Future<String> exportTodayReport() async {
final today = DateTime.now();
final startOfDay = DateTime(today.year, today.month, today.day);
final endOfDay = startOfDay.add(const Duration(days: 1));
final stats = await _dailyStatsDao.getTodayStats();
final topApps = await _appUsageDao.getTopApps(
startTime: startOfDay,
endTime: endOfDay,
limit: 10,
);
final buffer = StringBuffer();
buffer.writeln('=== AutoTime Tracker 今日报告 ===');
buffer.writeln('日期: ${today.toString().split(' ')[0]}');
buffer.writeln('');
if (stats != null) {
buffer.writeln('总时长: ${stats.formattedTotalTime}');
buffer.writeln('工作: ${_formatTime(stats.workTime)}');
buffer.writeln('学习: ${_formatTime(stats.studyTime)}');
buffer.writeln('娱乐: ${_formatTime(stats.entertainmentTime)}');
buffer.writeln('社交: ${_formatTime(stats.socialTime)}');
buffer.writeln('工具: ${_formatTime(stats.toolTime)}');
if (stats.efficiencyScore != null) {
buffer.writeln('效率评分: ${stats.efficiencyScore}%');
}
buffer.writeln('');
}
if (topApps.isNotEmpty) {
buffer.writeln('Top 应用:');
for (int i = 0; i < topApps.length; i++) {
final app = topApps[i];
buffer.writeln('${i + 1}. ${app.appName}: ${app.formattedDuration} (${AppTheme.getCategoryName(app.category)})');
}
}
return buffer.toString();
}
String _escapeCsvField(String field) {
if (field.contains(',') || field.contains('"') || field.contains('\n')) {
return '"${field.replaceAll('"', '""')}"';
}
return field;
}
String _formatTime(int seconds) {
final hours = seconds ~/ 3600;
final minutes = (seconds % 3600) ~/ 60;
if (hours > 0) {
return '${hours}h ${minutes}m';
}
return '${minutes}m';
}
}