Skip to content
全新发布

PDF SDK 与 AI 文档处理

在 GitHub 获取完整的私有化部署SDK 包及 AI 智能文档处理能力,一键部署,快速构建您的文档处理工作流。

Guides

注释回复

ComPDF Flutter SDK 提供注释回复接口,用于为 PDF 注释添加、读取、更新和删除回复。你也可以为注释或注释回复设置标记状态和审阅状态。这些接口适用于文档审阅、协作批注、反馈跟踪和审批流程等场景。

API 概览

注释回复接口位于 CPDFDocument

dart
Future<CPDFReplyAnnotation?> addAnnotationReply(
  CPDFAnnotation annotation, {
  required String content,
  String title = '',
});

Future<List<CPDFReplyAnnotation>> getAnnotationReplies(
  CPDFAnnotation annotation,
);

Future<bool> updateAnnotationReply(
  CPDFReplyAnnotation reply, {
  required String content,
  String? title,
});

Future<bool> removeAnnotationReply(CPDFReplyAnnotation reply);

Future<bool> removeAllAnnotationReplies(CPDFAnnotation annotation);

Future<bool> setAnnotationMarkState(
  CPDFAnnotation annotation,
  CPDFAnnotationMarkState state,
);

Future<CPDFAnnotationMarkState> getAnnotationMarkState(
  CPDFAnnotation annotation,
);

Future<bool> setAnnotationReviewState(
  CPDFAnnotation annotation,
  CPDFAnnotationReviewState state,
);

Future<CPDFAnnotationReviewState> getAnnotationReviewState(
  CPDFAnnotation annotation,
);

接口说明:

API说明
addAnnotationReply为注释添加一条普通回复
getAnnotationReplies获取注释下的全部普通回复
updateAnnotationReply更新普通回复的内容和可选标题
removeAnnotationReply删除单条普通回复
removeAllAnnotationReplies删除某个注释下的全部普通回复
setAnnotationMarkState设置注释或回复的标记状态
getAnnotationMarkState获取注释或回复的标记状态
setAnnotationReviewState设置注释或回复的审阅状态
getAnnotationReviewState获取注释或回复的审阅状态

回复模型

注释回复使用 CPDFReplyAnnotation 表示。

dart
class CPDFReplyAnnotation extends CPDFAnnotation {
  final DateTime? modifyDate;
}

由于 CPDFReplyAnnotation 继承自 CPDFAnnotation,它也包含审阅流程中常用的注释字段:

属性说明
page页面索引,从 0 开始
title回复作者或标题
content回复内容
createDate回复创建时间,如果原生 SDK 提供
modifyDate回复修改时间,如果原生 SDK 提供
markState当前标记状态
reviewState当前审阅状态

调用更新、删除或状态接口时,请使用 addAnnotationReplygetAnnotationReplies 返回的回复对象。不要手动构造 CPDFReplyAnnotation 对象后传入这些接口。

标记状态和审阅状态

标记状态:

dart
enum CPDFAnnotationMarkState {
  marked,
  unmarked,
}

审阅状态:

dart
enum CPDFAnnotationReviewState {
  accepted,
  rejected,
  cancelled,
  completed,
  none,
  error,
}

标记状态和审阅状态既可以设置到父注释,也可以设置到回复注释:

dart
await document.setAnnotationMarkState(
  annotation,
  CPDFAnnotationMarkState.marked,
);

await document.setAnnotationReviewState(
  annotation,
  CPDFAnnotationReviewState.accepted,
);

获取注释对象

大多数回复操作都从一个已有注释开始。下面示例获取第 1 页的第一条注释。

dart
final CPDFPage page = document.pageAtIndex(0);
final List<CPDFAnnotation> annotations = await page.getAnnotations();

if (annotations.isEmpty) {
  return;
}

final CPDFAnnotation annotation = annotations.first;

页面索引从 0 开始。

添加回复

使用 addAnnotationReply 为注释添加一条普通回复。

dart
final CPDFReplyAnnotation? reply = await document.addAnnotationReply(
  annotation,
  content: 'Please review this highlight.',
  title: 'Alex',
);

if (reply == null) {
  throw Exception('Add annotation reply failed.');
}

print('Reply content: ${reply.content}');

content 为必填参数。title 为可选参数,通常用于表示回复作者名称。

读取回复列表

使用 getAnnotationReplies 获取注释下的全部普通回复。

dart
final List<CPDFReplyAnnotation> replies =
    await document.getAnnotationReplies(annotation);

for (final reply in replies) {
  print('Author: ${reply.title}');
  print('Content: ${reply.content}');
  print('Mark state: ${reply.markState.name}');
  print('Review state: ${reply.reviewState.name}');
}

返回列表只包含普通回复。内部用于保存标记状态和审阅状态的状态回复不会作为单独回复项暴露。

更新回复

使用 updateAnnotationReply 更新已有回复的内容和可选标题。

dart
final List<CPDFReplyAnnotation> replies =
    await document.getAnnotationReplies(annotation);

if (replies.isNotEmpty) {
  final bool success = await document.updateAnnotationReply(
    replies.first,
    content: 'Updated reply content.',
    title: 'Alex',
  );

  if (!success) {
    throw Exception('Update annotation reply failed.');
  }
}

reply 参数应来自 getAnnotationRepliesaddAnnotationReply 的返回值。

删除单条回复

使用 removeAnnotationReply 删除一条普通回复。

dart
final List<CPDFReplyAnnotation> replies =
    await document.getAnnotationReplies(annotation);

if (replies.isNotEmpty) {
  final bool success = await document.removeAnnotationReply(replies.first);

  if (!success) {
    throw Exception('Remove annotation reply failed.');
  }
}

删除全部回复

使用 removeAllAnnotationReplies 删除某个注释下的全部普通回复。

dart
final bool success = await document.removeAllAnnotationReplies(annotation);

if (!success) {
  throw Exception('Remove all annotation replies failed.');
}

该接口只删除普通回复。标记状态和审阅状态信息会被保留。

设置回复的标记状态和审阅状态

你可以为某条回复设置标记状态或审阅状态。

dart
final List<CPDFReplyAnnotation> replies =
    await document.getAnnotationReplies(annotation);

if (replies.isNotEmpty) {
  final CPDFReplyAnnotation reply = replies.first;

  await document.setAnnotationMarkState(
    reply,
    CPDFAnnotationMarkState.marked,
  );

  await document.setAnnotationReviewState(
    reply,
    CPDFAnnotationReviewState.completed,
  );
}

设置回复状态后,如果界面需要展示最新数据,请再次调用 getAnnotationReplies 读取回复列表。

设置父注释状态

你也可以直接设置父注释本身的标记状态和审阅状态。

dart
await document.setAnnotationMarkState(
  annotation,
  CPDFAnnotationMarkState.marked,
);

await document.setAnnotationReviewState(
  annotation,
  CPDFAnnotationReviewState.accepted,
);

final CPDFAnnotationMarkState markState =
    await document.getAnnotationMarkState(annotation);

final CPDFAnnotationReviewState reviewState =
    await document.getAnnotationReviewState(annotation);

print('Mark: ${markState.name}');
print('Review: ${reviewState.name}');

在 CPDFReaderWidget 中使用

在阅读器页面中,可以通过 controller.document 调用相同接口。

dart
Future<void> addReplyToFirstAnnotation(
  CPDFReaderWidgetController controller,
) async {
  final int pageIndex = await controller.getCurrentPageIndex();
  final CPDFPage page = controller.document.pageAtIndex(pageIndex);
  final List<CPDFAnnotation> annotations = await page.getAnnotations();

  if (annotations.isEmpty) {
    return;
  }

  await controller.document.addAnnotationReply(
    annotations.first,
    content: 'Reviewed in the reader.',
    title: 'Reviewer',
  );
}

这个方式适用于自定义审阅面板、注释列表和协作工具栏等场景。

完整示例

下面示例演示如何打开文档,为第 1 页第一条注释添加回复,设置该回复的审阅状态,并重新读取回复列表。

dart
import 'package:compdfkit_flutter/annotation/cpdf_annotation.dart';
import 'package:compdfkit_flutter/annotation/cpdf_annotation_reply.dart';
import 'package:compdfkit_flutter/annotation/cpdf_annotation_state.dart';
import 'package:compdfkit_flutter/document/cpdf_document.dart';
import 'package:compdfkit_flutter/page/cpdf_page.dart';

Future<void> reviewFirstAnnotation(String filePath) async {
  final CPDFDocument document = await CPDFDocument.createInstance();
  await document.open(filePath);

  final CPDFPage page = document.pageAtIndex(0);
  final List<CPDFAnnotation> annotations = await page.getAnnotations();

  if (annotations.isEmpty) {
    return;
  }

  final CPDFAnnotation annotation = annotations.first;

  final CPDFReplyAnnotation? reply = await document.addAnnotationReply(
    annotation,
    content: 'Please verify this annotation.',
    title: 'Reviewer',
  );

  if (reply == null) {
    throw Exception('Add annotation reply failed.');
  }

  await document.setAnnotationReviewState(
    reply,
    CPDFAnnotationReviewState.completed,
  );

  final List<CPDFReplyAnnotation> replies =
      await document.getAnnotationReplies(annotation);

  print('Reply count: ${replies.length}');
}

注意事项

  • 更新或删除回复时,请使用 SDK 返回的 CPDFReplyAnnotation 对象。
  • 不建议在业务逻辑中依赖内部注释标识。需要操作注释或回复时,请直接传入 SDK 返回的注释对象或回复对象。
  • getAnnotationReplies 只返回普通回复。状态回复由 SDK 内部处理。
  • removeAllAnnotationReplies 会删除普通回复,并保留标记状态和审阅状态信息。
  • 设置标记状态或审阅状态后,如果界面需要最新模型数据,请重新读取注释或回复。
  • 注释和回复接口使用从 0 开始的页面索引。
  • 如果需要将修改持久化到文件,请在操作完成后保存文档。