更新记录

1.0.0(2026-05-26)

  • 适配安卓、鸿蒙、iOS三端
  • 统一三端API功能,调整功能行为一致性

平台兼容性

uni-app(4.45)

Vue2 Vue2插件版本 Vue3 Vue3插件版本 Chrome Safari app-vue app-vue插件版本 app-nvue app-nvue插件版本 Android Android插件版本 iOS iOS插件版本 鸿蒙 鸿蒙插件版本
1.0.0 1.0.0 × × 1.0.0 1.0.0 5.0 1.0.0 12 1.0.0 1.0.0
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

uni-app x(4.45)

Chrome Safari Android Android插件版本 iOS iOS插件版本 鸿蒙 鸿蒙插件版本 微信小程序
× × 5.0 1.0.0 12 1.0.0 1.0.0 ×

其他

多语言 暗黑模式 宽屏模式

PDF 预览与批注写回 支持安卓 iOS 鸿蒙 UTS插件

介绍

  1. 支持 AndroidiOSHarmonyOS 的 PDF 预览能力封装,可用于打开本地 PDF 文件、翻页、缩放、签名记录、批注记录以及将记录写回到新 PDF,支持手势缩放预览,支持预览加密PDF。
  2. 适用于 uni-appuni-app x App 平台,不支持 Web 和各类小程序平台。
  3. 核心流程为:通过 <cz-pdf-viewer> 组件挂载原生 PDF 视图,调用 open 加载文件,之后调用 prevPagenextPagegoToPagezoomTo 等方法进行交互;签名/批注通过 addSignatureRecordaddAnnotationRecord 等记录 API 管理,最后通过 applyRecordsToPdfAsync 将记录合入新 PDF。
  4. 即使当前平台不支持原生 PDF 预览(如模拟器),签名与批注记录模型仍可独立使用。

插件试用

APK下载体验

平台支持

平台 支持情况
Android 支持
iOS 支持
HarmonyOS 支持
Web 不支持
小程序 不支持

组件属性

属性名称 类型 默认值 说明
src string "" PDF 文件路径
sourceType "filePath" \| "contentUri" \| "asset" "filePath" 文件来源类型;iOS 当前以 filePath/asset 为主;Harmony 以沙箱 filePath 为主
password string PDF 加密密码
defaultPage number 1 打开后默认展示的页码
enableSwipe boolean true 是否允许滑动手势翻页(仅 Android)
swipeHorizontal boolean false 是否横向翻页(仅 Android)
enableDoubleTap boolean true 是否启用双击缩放(仅 Android)
pageSnap boolean false 是否吸附翻页(仅 Android)
pageFling boolean false 是否 fling 翻页(仅 Android)
nightMode boolean false 夜间模式(仅 Android)
autoSpacing boolean false 自动页间距(Android 支持;iOS 近似映射为 page break 显示;Harmony 当前未单独接入)
pageSpacing number 0 页间距,具体效果以平台原生实现为准
fitPolicy "width" \| "height" \| "both" "width" 页面适配策略;iOS 以 sizeToFit 基准缩放近似映射;Harmony 为原生 pageFit 映射,语义非完全一致
minZoom number 1 最小缩放比例
midZoom number 1.75 中间缩放比例
maxZoom number 3 最大缩放比例
enableAnnotationRendering boolean true 是否渲染 PDF 内嵌批注(仅 Android 支持开关)
autoOpen boolean false 组件挂载后是否自动根据 src 调用 open

组件事件

事件名称 说明
load PDF 加载完成,可通过 event.detail.state 获取当前阅读状态
pageChange 页码变化
zoomChange 缩放比例变化
error 发生错误,可通过 event.detail.state.lastErrorCodelastErrorMessage 获取错误信息
viewerTap 点击 PDF 阅读区域(仅 Android)
recordsChange 签名或批注记录发生变化(Android、HarmonyOS 支持;iOS 当前通过组件内部同步)

组件方法(defineExpose)

方法名称 参数 返回 说明
open CzPdfOpenOptions \| null boolean 打开 PDF 文件。为 null 时使用组件属性构建打开参数
reload boolean 重新加载当前 PDF
close void 关闭当前 PDF,释放原生资源
prevPage boolean \| null(animated) boolean 上一页
nextPage boolean \| null(animated) boolean 下一页
goToPage number(page), boolean \| null(animated) boolean 跳转到指定页码
zoomTo number(scale) boolean 设置缩放比例
resetZoom boolean 重置缩放
fitToWidth number \| null(page) boolean 适配页面宽度,不传则适配当前页
getViewState CzPdfViewState 获取当前阅读状态快照
getRecords CzPdfRecordBundle 获取当前签名与批注记录
setRecords CzPdfRecordBundle void 替换全部记录
clearRecords void 清空全部记录
addSignatureRecord CzPdfSignatureRecord void 添加一条签名记录
removeSignatureRecord string(id) boolean 按 ID 移除一条签名记录
addAnnotationRecord CzPdfAnnotationRecord void 添加一条批注记录
removeAnnotationRecord string(id) boolean 按 ID 移除一条批注记录

独立函数

函数名称 参数 返回 说明
applyRecordsToPdf CzPdfApplyRecordsOptions CzPdfApplyRecordsResult 以同步方式将签名/批注记录写入新 PDF
applyRecordsToPdfAsync CzPdfApplyRecordsOptions, CzPdfApplyRecordsCallback void 以异步方式将签名/批注记录写入新 PDF(推荐用于生产环境)
createCzPdfRecordStore CzPdfRecordBundle \| null ICzPdfRecordStore 创建一个独立于预览组件的记录管理实例,适用于无原生 PDF 预览的场景

平台差异说明

不同平台底层 PDF 能力不同,部分功能在三端的支持范围并不完全一致,接入前建议先阅读本节。

API Android iOS HarmonyOS 说明
open 支持 支持 支持 三端都支持打开本地 PDF 文件;iOS/Harmony 的 asset 方案建议业务层先将资源转为绝对路径
reload 支持 支持 支持 关闭后再调用 reload 将返回 false,不会自动恢复
close 支持 支持 支持 关闭后会释放原生资源
prevPage / nextPage 支持 支持 支持 三端都支持翻页
goToPage 支持 支持 支持 三端都支持指定页码跳转
zoomTo 支持 支持 支持 iOS 按 sizeToFit 基准归一化映射;Harmony 使用原生 PDFKit zoom 映射
resetZoom 支持 支持 支持 三端都支持重置缩放至基准倍率
fitToWidth 支持 支持 支持 iOS 缩放基于 PDFView bounds 计算;Harmony 依赖原生布局就绪状态
签名记录模型 支持 支持 支持 三端纯数据模型一致,签名图片路径建议使用绝对路径
批注记录模型 支持 支持 支持 三端纯数据模型一致,支持 highlight、underline、square、text 四种批注类型
applyRecordsToPdf 支持 支持 支持 写回 PDF 为独立能力,不依赖组件实例;写回时会先清除输入 PDF 已有批注再写入新记录
横向翻页 支持 支持 不支持 Harmony 当前未接入横向分页布局
夜间模式 支持 不支持 不支持 仅 Android 支持
pageSnap / pageFling 支持 不支持 不支持 仅 Android 支持
双击缩放开关 支持 不支持 不支持 仅 Android 支持控制开关;iOS/Harmony 由原生组件决定行为
enableAnnotationRendering 支持 不支持 不支持 仅 Android 支持控制是否渲染 PDF 内嵌批注
recordsChange 事件 支持 不支持 支持 iOS 当前通过组件内部 getRecords 同步记录状态

iOS 特别说明

  1. iOS 使用 PDFKit 作为底层渲染引擎,缩放范围基于 sizeToFit 基准归一化映射。
  2. fitToWidth 依赖 PDFView 布局就绪,如果调用时布局未完成可能返回失败。
  3. createCzPdfRecordStore 创建的记录管理实例在所有平台上完全独立于原生 PDF 视图,可用于模拟器或无原生预览的纯数据处理场景。
  4. 写回 PDF 时会在后台 IO 队列加载 PDF 文档、清除已有批注、写入新记录并保存,最终在主线程回调结果。同步版本 applyRecordsToPdf 会阻塞当前线程,生产环境建议使用 applyRecordsToPdfAsync

HarmonyOS 特别说明

  1. HarmonyOS 原生 PDFView 在 close 后会隐藏视图(display:none),避免遮挡后续内容。
  2. open 后会自动恢复视图可见性。
  3. HarmonyOS 写回 PDF 时默认使用 originalInputPath(原始文件路径),而非当前查看的 PDF 路径,以规避重复写回叠加批注的问题。
  4. swipeHorizontal 横向翻页能力鸿蒙侧当前未支持。

Android 特别说明

  1. Android 使用 PDFBox 引擎进行 PDF 写回,打开 PDF 时会在 IO 线程预处理预览文件。
  2. Android 支持 contentUri 方式打开 PDF(如从系统文件选择器获取的 URI)。
  3. viewerTap 事件仅在 Android 平台触发。
  4. enableSwipeenableDoubleTappageSnappageFlingnightMode 等阅读器专属参数仅 Android 平台生效。

数据结构说明

CzPdfViewState

getViewState() 或 load/pageChange/zoomChange 事件的 detail.state 中包含:

字段 类型 说明
isSupported boolean 当前平台是否支持原生 PDF 预览
isReady boolean 原生视图是否就绪
isLoaded boolean PDF 是否已加载
page number 当前页码
pageCount number 总页数
zoom number 当前缩放比例
minZoom number 最小缩放比例
midZoom number 中间缩放比例
maxZoom number 最大缩放比例
source string \| null 当前打开的文件路径
sourceType string \| null 当前文件来源类型
lastErrorCode string \| null 最近一次错误码
lastErrorMessage string \| null 最近一次错误描述

CzPdfSignatureRecord

签名记录结构:

type CzPdfSignatureRecord = {
  id: string           // 唯一标识
  page: number         // 所在页码
  rect: CzPdfRect      // 签名区域
  imagePath: string    // 签名图片路径(建议使用绝对路径)
  createdAt?: number   // 创建时间戳(毫秒)
  extra?: UTSJSONObject // 扩展数据
}

CzPdfAnnotationRecord

批注记录结构:

type CzPdfAnnotationRecord = {
  id: string                    // 唯一标识
  type: "highlight" | "underline" | "square" | "text"  // 批注类型
  page: number                  // 所在页码
  rects: CzPdfRect[]            // 批注区域数组
  color?: string                // 颜色,如 "#FFEB3B"
  opacity?: number              // 透明度 0-1
  contents?: string             // 批注文本内容
  author?: string               // 作者
  iconName?: string             // 图标名称
  createdAt?: number            // 创建时间戳(毫秒)
  extra?: UTSJSONObject         // 扩展数据
}

CzPdfRect

矩形区域结构:

type CzPdfRect = {
  x: number      // 左上角 x
  y: number      // 左上角 y
  width: number  // 宽度
  height: number // 高度
  unit?: "pageRatio" | "pdfPoint"  // 坐标单位,默认使用页面比例(0-1)
}

CzPdfRecordBundle

记录集合:

type CzPdfRecordBundle = {
  signatures: CzPdfSignatureRecord[]
  annotations: CzPdfAnnotationRecord[]
}

CzPdfApplyRecordsResult

写回结果:

字段 类型 说明
success boolean 是否写回成功
outputPath string \| null 输出文件路径
writtenSignatureCount number 成功写入的签名数量
writtenAnnotationCount number 成功写入的批注数量
errorCode string \| null 失败时的错误码
errorMessage string \| null 失败时的错误描述

快速开始

1. 引入组件

在插件市场中导入cz-pdf-viewer到uni_modules,直接在 uvue 模板中使用 <cz-pdf-viewer>

2. 基础 PDF 预览

// 模板中
<cz-pdf-viewer
  ref="viewerRef"
  src="/path/to/document.pdf"
  sourceType="filePath"
  autoOpen
  @load="onLoad"
  @pageChange="onPageChange"
  @error="onError"
/>

// 脚本中
const viewerRef = ref()

function onLoad(event : UniNativeViewEvent) : void {
  const state = event.detail.state
  console.log(`PDF 加载完成,共 ${state.pageCount} 页`)
}

function onPageChange(event : UniNativeViewEvent) : void {
  const state = event.detail.state
  console.log(`当前页:${state.page}/${state.pageCount}`)
}

3. 通过方法控制

const viewer = viewerRef.value
if (viewer != null) {
  // 打开 PDF
  viewer.open({ src: "/path/to/document.pdf" })

  // 翻页
  viewer.nextPage()
  viewer.prevPage()

  // 跳转到第 3 页
  viewer.goToPage(3)

  // 缩放
  viewer.zoomTo(1.5)
  viewer.resetZoom()
  viewer.fitToWidth()
}

4. 添加签名与批注记录

const viewer = viewerRef.value
if (viewer == null) return

// 添加签名记录
viewer.addSignatureRecord({
  id: "sig-001",
  page: 1,
  rect: { x: 0.1, y: 0.1, width: 0.3, height: 0.15 },
  imagePath: "/path/to/signature.png"
} as CzPdfSignatureRecord)

// 添加高亮批注
viewer.addAnnotationRecord({
  id: "ann-001",
  type: "highlight",
  page: 1,
  rects: [{ x: 0.15, y: 0.3, width: 0.7, height: 0.05 }],
  color: "#FFEB3B",
  opacity: 0.5,
  contents: "重点内容"
} as CzPdfAnnotationRecord)

// 添加矩形框批注
viewer.addAnnotationRecord({
  id: "ann-002",
  type: "square",
  page: 1,
  rects: [{ x: 0.2, y: 0.5, width: 0.6, height: 0.2 }],
  color: "#FF5722",
  opacity: 0.8
} as CzPdfAnnotationRecord)

5. 写回到新 PDF

import { applyRecordsToPdfAsync, CzPdfApplyRecordsResult } from "@/uni_modules/cz-pdf-viewer"

const viewer = viewerRef.value
const records = viewer.getRecords()

applyRecordsToPdfAsync({
  inputPath: "/path/to/original.pdf",
  outputPath: "/path/to/output.pdf",
  records: records,
  overwrite: true
}, (result : CzPdfApplyRecordsResult) => {
  if (result.success) {
    console.log(`写回成功:签名 ${result.writtenSignatureCount} 条,批注 ${result.writtenAnnotationCount} 条`)
    console.log(`输出文件:${result.outputPath}`)
  } else {
    console.log(`写回失败:${result.errorMessage}`)
  }
})

6. 脱离预览使用记录模型

import { createCzPdfRecordStore, applyRecordsToPdfAsync } from "@/uni_modules/cz-pdf-viewer"

// 创建独立的记录管理实例(无需原生 PDF 视图)
const store = createCzPdfRecordStore(null)

store.addAnnotationRecord({
  id: "ann-x",
  type: "highlight",
  page: 1,
  rects: [{ x: 0.1, y: 0.2, width: 0.8, height: 0.06 }],
  color: "#FFEB3B"
} as CzPdfAnnotationRecord)

applyRecordsToPdfAsync({
  inputPath: "/path/to/input.pdf",
  outputPath: "/path/to/output.pdf",
  records: store.getRecords(),
  overwrite: true
}, (result) => {
  console.log(`写入 ${result.writtenAnnotationCount} 条批注`)
})

常用方法说明

open

打开一个 PDF 文件。参数为 CzPdfOpenOptions,其中 src 为必填项。

重要参数:

参数 类型 默认值 说明
src string 无(必填) PDF 文件路径
sourceType CzPdfSourceType "filePath" 文件来源类型
password string 加密 PDF 的密码
defaultPage number 1 打开后默认展示的页码
swipeHorizontal boolean false 横向翻页(Android、iOS 支持)
fitPolicy "width" \| "height" \| "both" "width" 页面适配策略
minZoom / midZoom / maxZoom number 1 / 1.75 / 3 缩放范围

prevPage / nextPage / goToPage

翻页相关方法。prevPage 到文件开头停止,nextPage 到末尾停止,均返回 boolean 表示是否成功。goToPage 直接跳转到指定页。

zoomTo / resetZoom / fitToWidth

缩放相关方法。zoomTo 接受缩放比例(相对基准倍率),resetZoom 恢复至 1 倍,fitToWidth 将指定页缩放至与视图等宽。

getRecords / setRecords / clearRecords

记录管理方法。getRecords 返回当前全部记录的深拷贝,setRecords 用于整体替换,clearRecords 清空全部签名与批注。

调用 clearRecords 后立即进行写回不会将旧记录带入输出 PDF。

addSignatureRecord / removeSignatureRecord

签名记录的增删。addSignatureRecord 需要提供 idpagerectimagePath,签名图片建议使用绝对路径以避免路径解析问题。

addAnnotationRecord / removeAnnotationRecord

批注记录的增删。支持四种批注类型:

  • highlight:高亮,可指定多个矩形区域
  • underline:下划线
  • square:矩形框,取第一个矩形区域
  • text:文字批注

applyRecordsToPdf / applyRecordsToPdfAsync

将签名与批注记录写入新的 PDF 文件。执行时会:

  1. 加载输入 PDF
  2. 清除输入 PDF 上已有的批注(避免叠加)
  3. 逐页写入签名图片与批注标记
  4. 保存到输出路径

推荐使用异步版本 applyRecordsToPdfAsync,避免阻塞 UI。

完整示例

import {
  applyRecordsToPdfAsync,
  CzPdfAnnotationRecord,
  CzPdfApplyRecordsResult,
  CzPdfSignatureRecord
} from "@/uni_modules/cz-pdf-viewer"

export default {
  methods: {
    async demoFlow() {
      const viewer = this.$refs.viewerRef

      // 打开 PDF
      viewer.open({
        src: "/var/mobile/Containers/Data/Application/.../doc.pdf",
        sourceType: "filePath"
      })

      // 添加签名
      viewer.addSignatureRecord({
        id: `sig-${Date.now()}`,
        page: 1,
        rect: { x: 0.7, y: 0.8, width: 0.25, height: 0.12 },
        imagePath: "/path/to/signature.png",
        createdAt: Date.now()
      } as CzPdfSignatureRecord)

      // 添加高亮
      viewer.addAnnotationRecord({
        id: `ann-${Date.now()}`,
        type: "highlight",
        page: 1,
        rects: [{ x: 0.1, y: 0.15, width: 0.8, height: 0.04 }],
        color: "#FFEB3B",
        opacity: 0.4,
        createdAt: Date.now()
      } as CzPdfAnnotationRecord)

      // 写回到新 PDF
      const records = viewer.getRecords()
      applyRecordsToPdfAsync({
        inputPath: "/var/mobile/Containers/Data/Application/.../doc.pdf",
        outputPath: "/var/mobile/Containers/Data/Application/.../output.pdf",
        records: records,
        overwrite: true
      }, (result : CzPdfApplyRecordsResult) => {
        if (result.success) {
          uni.showToast({ title: "PDF 已保存" })
        } else {
          uni.showToast({ title: `保存失败:${result.errorMessage}`, icon: "none" })
        }
      })
    }
  }
}

注意事项

  1. 仅支持手机真机调试,不支持模拟器上的原生 PDF 预览(记录模型仍可独立使用)。
  2. 调用 open 前确保 src 指向的文件存在且可读。
  3. 调用 close 后再执行 reload 将返回 false,需要重新调用 open 打开文件。
  4. 签名图片路径建议使用绝对路径,避免写回时因相对路径解析失败导致签名丢失。
  5. 写回 PDF 时会先清除输入 PDF 上已有的批注标记,避免多次写回叠加。
  6. applyRecordsToPdf 是同步方法,大文件或大量批注场景建议使用 applyRecordsToPdfAsync
  7. 不同平台、不同文件格式(加密、损坏等)的支持程度不同,业务接入前建议通过 loaderror 事件进行流程控制。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

本插件不收集任何隐私数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。