157 lines
5.3 KiB
Dart
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';
|
|
}
|
|
}
|
|
|