tcicZipLogsToFileInIsolate function

Map<String, Object?> tcicZipLogsToFileInIsolate(
  1. Map<String, Object?> params
)

在后台 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(),
    };
  }
}