注释回复
ComPDF Flutter SDK 提供注释回复接口,用于为 PDF 注释添加、读取、更新和删除回复。你也可以为注释或注释回复设置标记状态和审阅状态。这些接口适用于文档审阅、协作批注、反馈跟踪和审批流程等场景。
API 概览
注释回复接口位于 CPDFDocument:
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 表示。
class CPDFReplyAnnotation extends CPDFAnnotation {
final DateTime? modifyDate;
}由于 CPDFReplyAnnotation 继承自 CPDFAnnotation,它也包含审阅流程中常用的注释字段:
| 属性 | 说明 |
|---|---|
page | 页面索引,从 0 开始 |
title | 回复作者或标题 |
content | 回复内容 |
createDate | 回复创建时间,如果原生 SDK 提供 |
modifyDate | 回复修改时间,如果原生 SDK 提供 |
markState | 当前标记状态 |
reviewState | 当前审阅状态 |
调用更新、删除或状态接口时,请使用 addAnnotationReply 或 getAnnotationReplies 返回的回复对象。不要手动构造 CPDFReplyAnnotation 对象后传入这些接口。
标记状态和审阅状态
标记状态:
enum CPDFAnnotationMarkState {
marked,
unmarked,
}审阅状态:
enum CPDFAnnotationReviewState {
accepted,
rejected,
cancelled,
completed,
none,
error,
}标记状态和审阅状态既可以设置到父注释,也可以设置到回复注释:
await document.setAnnotationMarkState(
annotation,
CPDFAnnotationMarkState.marked,
);
await document.setAnnotationReviewState(
annotation,
CPDFAnnotationReviewState.accepted,
);获取注释对象
大多数回复操作都从一个已有注释开始。下面示例获取第 1 页的第一条注释。
final CPDFPage page = document.pageAtIndex(0);
final List<CPDFAnnotation> annotations = await page.getAnnotations();
if (annotations.isEmpty) {
return;
}
final CPDFAnnotation annotation = annotations.first;页面索引从 0 开始。
添加回复
使用 addAnnotationReply 为注释添加一条普通回复。
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 获取注释下的全部普通回复。
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 更新已有回复的内容和可选标题。
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 参数应来自 getAnnotationReplies 或 addAnnotationReply 的返回值。
删除单条回复
使用 removeAnnotationReply 删除一条普通回复。
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 删除某个注释下的全部普通回复。
final bool success = await document.removeAllAnnotationReplies(annotation);
if (!success) {
throw Exception('Remove all annotation replies failed.');
}该接口只删除普通回复。标记状态和审阅状态信息会被保留。
设置回复的标记状态和审阅状态
你可以为某条回复设置标记状态或审阅状态。
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 读取回复列表。
设置父注释状态
你也可以直接设置父注释本身的标记状态和审阅状态。
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 调用相同接口。
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 页第一条注释添加回复,设置该回复的审阅状态,并重新读取回复列表。
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 开始的页面索引。
- 如果需要将修改持久化到文件,请在操作完成后保存文档。