tcicZipLogsToFileInIsolate function
在后台 isolate 中:筛选最近 N 天更新的日志并压缩写入 zip 文件(并改名为 .pdf)。
isolate 里不要依赖 UI isolate 的日志/插件能力,只返回摘要信息。
Implementation
@pragma('vm:entry-point')
Map<String, Object?> tcicZipLogsToFileInIsolate(
Map<String, Object?> params,
) {
final logDirPath = (params['logDirPath'] as String?) ?? '';
final zipFilePath = (params['zipFilePath'] as String?) ?? '';
final keepDays = ((params['keepDays'] as num?)?.toInt() ?? 2).clamp(1, 30);
if (logDirPath.isEmpty || zipFilePath.isEmpty) {
return <String, Object?>{'ok': false, 'reason': 'invalid_params'};
}
try {
final dir = Directory(logDirPath);
if (!dir.existsSync()) {
return <String, Object?>{'ok': false, 'reason': 'log_dir_not_found'};
}
final cutoff = DateTime.now().subtract(Duration(days: keepDays));
// listSync + statSync/IO 都在后台 isolate 执行,避免 UI 卡顿
final files = <File>[];
for (final entity in dir.listSync(recursive: true)) {
if (entity is! File) continue;
try {
final stat = entity.statSync();
final updatedAt =
stat.modified.isAfter(stat.changed) ? stat.modified : stat.changed;
if (updatedAt.isAfter(cutoff)) {
// 仅打包日志文件
if (entity.path.endsWith('.mx') ||
entity.path.endsWith('.clog') ||
entity.path.endsWith('.log') || entity.path.endsWith('.xlog')) {
files.add(entity);
}
}
} catch (_) {
// ignore
}
}
if (files.isEmpty) {
return <String, Object?>{
'ok': false,
'reason': 'no_recent_files',
'cutoff': cutoff.toIso8601String(),
};
}
final archive = Archive();
for (final file in files) {
try {
final fileBytes = file.readAsBytesSync();
final relativePath = file.path.substring(dir.path.length + 1);
archive.addFile(ArchiveFile(relativePath, fileBytes.length, fileBytes));
} catch (_) {
// ignore single file failure
}
}
final zipBytes = ZipEncoder().encode(archive);
final zipFile = File(zipFilePath);
zipFile.parent.createSync(recursive: true);
zipFile.writeAsBytesSync(zipBytes, flush: true);
// 将 zip 文件重命名为 .pdf(业务侧/后台限制)
final pdfFilePath = zipFile.path.replaceAll('.zip', '.pdf');
final newFile = File(pdfFilePath);
newFile.parent.createSync(recursive: true);
newFile.writeAsBytesSync(zipBytes, flush: true);
zipFile.deleteSync();
return <String, Object?>{
'ok': true,
'files': files.length,
'zipFilePath': pdfFilePath,
'cutoff': cutoff.toIso8601String(),
};
} catch (e) {
return <String, Object?>{
'ok': false,
'reason': 'exception',
'error': e.toString(),
};
}
}