Vue 组件

inklayer-vue 提供 PdfAnnotatorPdfViewer 两个顶层组件,基于 Vue 3 Composition API 构建,使用 Pinia 管理状态,集成 shadcn-vue UI 组件库。

安装

npm install inklayer-vue

基础导入

// 组件
import { PdfAnnotator, PdfViewer } from 'inklayer-vue'
import 'inklayer-vue/style'

// 类型
import type { PdfAnnotatorProps, PdfViewerProps, User, Annotation } from 'inklayer-vue'

PdfAnnotator

完整的 PDF 批注组件,内置工具栏、批注编辑、侧边栏。

Props

Prop类型默认值说明
urlstring | URLPDF 文件的 URL 地址
datastring | number[] | ArrayBuffer | Uint8Array | Uint16Array | Uint32ArrayPDF 的二进制数据
theme见下方主题色表格'violet'UI 主题色
titlestring'PDF ANNOTATOR'批注器标题
locale'zh-CN' | 'en-US''zh-CN'界面语言
initialScale'auto' | 'page-actual' | 'page-fit' | 'page-width' | number'auto'初始缩放比例
layoutStyleCSSProperties{ width: '100vw', height: '100vh' }容器样式(Vue 版有默认值)
user{ id: string, name: string }{ id: 'null', name: 'unknown' }当前用户信息
enableNativeAnnotationsbooleanfalse是否启用 PDF.js 原生批注
enableRangeboolean | 'auto''auto'PDF 范围加载模式
defaultOptionsPartial<PdfAnnotatorOptions>默认批注配置
initialAnnotationsAnnotation[][]初始批注数据
defaultShowAnnotationsSidebarbooleanfalse批注侧边栏默认是否展开

主题色选项

颜色值说明
gray灰色
gold金色
bronze青铜色
brown棕色
yellow黄色
amber琥珀色
orange橙色
tomato番茄色
red红色
ruby红宝石色
crimson深红色
pink粉色
plum梅子色
purple紫色
violet紫罗兰色(默认)
iris鸢尾花色
indigo靛蓝色
blue蓝色
cyan青色
teal蓝绿色
jade翡翠色
green绿色
grass草绿色
lime青柠色
mint薄荷色
sky天空色

Events

React → Vue 事件名对照:React 的 onXxx Prop 对应 Vue 的 @xxx 事件(首字母小写)。例如:onSave@saveonLoad@loadonAnnotationAdded@annotation-added

事件参数触发时机
save(annotations: Annotation[])用户点击保存
load()PDF 加载完成
annotation-added(annotation: Annotation)新批注创建
annotation-deleted(id: string)批注删除
annotation-selected(annotation: Annotation | null, isClick: boolean)批注选中/取消
annotation-updated(annotation: Annotation)批注更新

Slots (PdfAnnotator)

插槽名称Slot Props说明
actions{ onSave, getAnnotations, exportToExcel, exportToPdf }自定义操作区域,渲染在工具栏右侧

Slots (PdfViewer)

插槽名称Slot Props说明
actionscontext: PdfViewerContextValue自定义操作区域
toolbarcontext: PdfViewerContextValue完全替换工具栏
sidebar-search-sidebarcontext: PdfViewerContextValue自定义搜索侧边栏面板
sidebar-${key}context: PdfViewerContextValue动态插槽,key 来自 sidebar prop 配置

Expose 方法

通过 ref 调用组件暴露的方法:

方法说明
save()触发保存操作
getAnnotations()获取当前所有批注数据

完整示例:带持久化和插槽的批注器

<script setup lang="ts">
import { ref } from 'vue'
import { PdfAnnotator } from 'inklayer-vue'
import 'inklayer-vue/style'
import type { Annotation } from 'inklayer-vue'

const annotatorRef = ref<InstanceType<typeof PdfAnnotator>>()
const annotations = ref<Annotation[]>([])

function handleSave(data: Annotation[]) {
  annotations.value = data
  // 发送到后端
  fetch('/api/annotations', {
    method: 'POST',
    body: JSON.stringify(data),
  })
}
</script>

<template>
  <PdfAnnotator
    ref="annotatorRef"
    url="/document.pdf"
    locale="zh-CN"
    :layout-style="{ height: '96vh' }"
    :enable-range="true"
    :default-show-annotations-sidebar="true"
    :user="{ id: '9527', name: 'Lao Mai' }"
    :enable-native-annotations="true"
    :initial-annotations="[]"
    :default-options="defaultOptions"
    @save="handleSave"
    @load="() => console.log('PDF Loaded')"
    @annotation-added="(a) => console.log('Added:', a.id)"
    @annotation-deleted="(id) => console.log('Deleted:', id)"
    @annotation-updated="(a) => console.log('Updated:', a.id)"
    @annotation-selected="(a, isClick) => console.log('Selected:', a?.id, isClick)"
  >
    <template #actions="{ onSave, getAnnotations, exportToExcel, exportToPdf }">
      <button @click="onSave()">保存</button>
      <button @click="console.log(getAnnotations())">获取批注</button>
      <button @click="exportToExcel('my-export')">导出 Excel</button>
      <button @click="exportToPdf('my-export')">导出 PDF</button>
    </template>
  </PdfAnnotator>
</template>

PdfViewer

轻量级 PDF 查看器,不包含批注功能。

Props(继承 PdfAnnotator 基础属性,新增以下)

Prop类型默认值说明
showTextLayerbooleantrue是否显示文本选区层
showAnnotationsbooleanfalse是否显示已有批注
defaultActiveSidebarKeystring | nullnull默认展开侧边栏面板
toolbarComponent | ((context: PdfViewerContextValue) => VueNode)自定义工具栏
sidebarSidebarPanel[]自定义侧边栏面板
actionsComponent | ((context: PdfViewerContextValue) => VueNode)自定义操作区域
onDocumentLoaded(pdfViewer: PDFViewer | null) => voidPDF 加载完成回调
onEventBusReady(eventBus: EventBus | null) => voidPDF.js EventBus 就绪回调

查看器完整示例

<script setup lang="ts">
import { ref } from 'vue'
import { PdfViewer } from 'inklayer-vue'
import 'inklayer-vue/style'

function onEventBusReady(eventBus: any) {
  eventBus?.on('page-rendered', (e: any) => console.log('Page:', e.pageNumber))
}

function onDocumentLoaded(pdfViewer: any) {
  console.log('Document loaded:', pdfViewer)
}
</script>

<template>
  <PdfViewer
    :enable-range="false"
    title="PDF VIEWER CUSTOM"
    :url="pdfUrl"
    :layout-style="{ width: '100vw', height: '96vh' }"
    :show-text-layer="false"
    :show-annotations="true"
    :default-active-sidebar-key="null"
    :sidebar="customSidebar"
    @event-bus-ready="onEventBusReady"
    @document-loaded="onDocumentLoaded"
  >
    <template #actions="{ context }">
      <button @click="context.print()">打印</button>
      <button @click="context.download('test')">下载</button>
    </template>
    <template #toolbar="{ context }">
      <button @click="context.toggleSidebar()">切换侧边栏</button>
    </template>
  </PdfViewer>
</template>

SidebarPanel 类型

sidebar prop 接受 SidebarPanel[],定义自定义侧边栏面板:

interface SidebarPanel {
  key: string                    // 面板唯一 key
  title: string                  // 面板标题
  icon: Vue.VNode                // 面板图标
  render: (context: PdfViewerContextValue) => Vue.VNode  // 面板内容渲染函数
}

PdfViewerContextValue 类型

actionstoolbarsidebar 的 slot 或函数形式接收 PdfViewerContextValue 对象:

interface PdfViewerContextValue {
  pdfViewer: PDFViewer | null    // PDFViewer 实例
  currentPage: number           // 当前页码(0-based)
  totalPages: number            // 总页数
  scale: number                 // 当前缩放比例
  print: () => void           // 打印
  download: (filename?: string) => void  // 下载
  toggleSidebar: () => void   // 切换侧边栏
  scrollPageIntoView: (opts: { pageNumber: number }) => void  // 滚动到指定页
}

PdfAnnotatorOptions 配置

通过 defaultOptions prop 自定义批注的默认行为:

interface PdfAnnotatorOptions {
  colors?: string[]  // 可用颜色列表

  signature?: {
    colors?: string[]                    // 签名可选颜色列表
    type?: 'Draw' | 'Enter' | 'Upload'   // 签名类型(首字母大写)
    maxSize?: number                     // 签名图片最大文件大小(字节)
    accept?: string                      // 接受的图片格式
    defaultSignature?: string[]          // 默认签名列表
    defaultFont?: {                      // 默认字体列表
      label: string
      value: string
      external?: boolean
      url?: string                     // 外部字体 URL
    }[]
  }

  stamp?: {
    maxSize?: number                     // 印章图片最大文件大小
    accept?: string                      // 接受的图片格式
    defaultStamp?: string[]              // 默认印章列表
    editor?: {                           // 印章编辑器配置
      defaultBackgroundColor?: string
      defaultBorderColor?: string
      defaultBorderStyle?: 'none' | 'solid' | 'dashed'
      defaultTextColor?: string
      defaultFont?: {
        label: string
        value: string
      }[]
    }
  }
}

注意signature.type 的值是 'Draw' | 'Enter' | 'Upload'(首字母大写),不是 'draw' | 'text' | 'image'