Skip to content

PDF 生成模板编辑器

开源可视化 PDF 生成引擎,支持自定义模板,并提供面向开发者的 API,灵活构建文档生成流程。

查看 GitHub

状态管理 ​

UI 状态由 Pinia 管理,拆分为两个 store。本指南描述 store 架构、各 store 持有的关键状态,以及 apis/ 层如何与之交互。

Store 设置 ​

packages/webview/src/stores/index.js 创建单个 Pinia 实例并导出 setupStore(app) 安装。store 遵循严格的双 store 分离(记录于 stores/AGENTS.md):

  • Viewer store —— "如何看待文档"(UI/视图状态)。
  • Document store —— "文档里有什么 & 如何在其上绘制"(数据 + 工具样式)。

两个 store 被 components/ 和 apis/ 中约 102 个文件引用。

Viewer store — modules/viewer.js(useViewerStore,约 1770 行) ​

持有 UI/视图状态。要点:

类别字段
视图/导航currentPage、scale、oldScale、newScale、zoomLevel(预设数组)、scrollMode、pageMode、pageLabels。
主题/显示theme('light'/'dark')、fullScreen、language、languages[]。
工具模式toolMode(默认 'view')、activeHand、activeStickNote、activeActiveMeasure。
元素开关activeElements{}(按 DataElements.* 键的布尔映射)、activeElementsTab{}、panelSpace{left,right}、openedPanelsNum{left,right}。
禁用元素disabledElements{} —— 每元素 { disabled, style }。
工具栏定义headers{}(按分组)、rightHeaders[]、toolItems{}、documentEditorHeaders、toolbarGroup、activeHeaderGroup。
签名配置signatureDialogTabs、signatureDialogProperties{}、enableSignatureTemplates、digitalSignature{}、selectedSignatureField、disableSignatureTool、electronicSignaturesList[]、digitalSignaturesList[]。
印章customStamps[]、stampPanelTabs[]、importStamps[]。
对比compareStatus、compareMode、showCompareTip。
弹出菜单textPopup[]、cropPagePopup[]、contentEditorPopup[]、annotationPopup[]、showAnnotationPopup、popoverChanged。
表单面板formBoardFold、formBoardPosition{}、enableFillForm、skipNoRequired、consecutiveType。
杂项标志license、verified、readOnly、userAdmin、isDisabledHeader、downloading、upload、uploadLoading、customLoading、documentEditorSaveStatus、documentEditorSaveAsStatus、webviewerMode。
字体customFonts[]、fontSizes[]。
面板配置genericPanels[]、customModals[]。
批注标志annotation{isAnnotationExport, isAnnotationImport}。

关键 action ​

  • openElement(dataElement, capability?) —— 设置 activeElements[de]=true;关闭同侧兄弟面板;在 LEFT_PANEL 时切换 core.toggleSidebar();在 SEARCH_PANEL 时还打开 LEFT_PANEL 并切换其标签。
  • closeElement / openElements / closeElements / toggleElement / resetPanels —— 变体。关闭 LEFT_PANEL 还会调用 core.webViewerPageMode('none') 并关闭 SEARCH_PANEL。
  • setActiveElementTab(dataElement, tab) —— 将 ThumbnailsButton 映射为 core.webViewerPageMode('thumbs'),OutlinesButton 为 'outline'。
  • setActiveToolMode(mode) —— 守卫 readOnly 和移动端(阻止 separation/measurement);关闭上下文面板;调用 core.setToolMode(mode)。
  • setToolbarGroup(value) —— 移动端对分色/测量的守卫。
  • disableElement / enableElement / disableElements / enableElements(de, key?) —— 切换禁用标志。
  • 印章/签名列表修改器持久化到 localStorage。
  • dispatch(action) / getState(key) —— 明确的 API 访问通道;向 apis/ 暴露 store action/state。

Document store — modules/document.js(useDocumentStore,约 600 行) ​

持有文档数据 + 工具配置。要点:

类别字段
文档元数据totalPages、loadingProgress、annotationsCount、info、currentPdfData{}、fileHasPwd、pwd。
批注annotations(shallowReactive)、selected{}、selectedAnnotation、outlines[]、activeOutlineId、searchResults[]、activeSearchResult、layers[]、selectedLayer。
当前工具activeTool、markupTool(默认 HIGHLIGHT)、shapeTool(默认 SQUARE)。
工具样式预设按工具的 { color, opacity?, stroke? }(高亮、下划线、波浪线、删除线、矩形、弧、多边形、折线、圆、箭头、线、墨迹、自由文本、文本、表单字段、密文、移除)。
属性面板propertyPanel{} —— 表单字段/编辑器属性模型。
对比compareFiles{}、compareSettings{}、compareResult。
签名signatures[]、selectedSignature、trustedCertificateLists[]、pkcs12、author、annotator、highlightLink、highlightForm、autoJumpNextSign、disableDigitalSignature、disableElectronicSignature。
测量measure{scale, precision}。
文档编辑documentEditor{operationList[], pageList[], selectedPageList[]}。
撤销/重做canUndo{content, annotation}、canRedo{content, annotation}。

关键 action ​

  • setActiveToolColor(color) —— 写入 this[activeTool].color 并调用 core.setTool(activeTool)。
  • setToolState(tool) —— 相同则切换关闭;否则查找 map[tool],调用 core.setTool(mapTool.tool, mapTool.toolName),设置 activeTool,表单工具还会调用 core.setInitProperty()。
  • setActiveToolColor / setPropertyPanel / setCurrentUser / setHighlightLink / setHighlightForm / setAutoJumpNextSign —— 存储的同时推送到 core。
  • initAnnotations / setAnnotations(annotation, type) —— 按页索引管理批注数组。
  • dispatch(action) / getState(key) —— API 访问。

apis/ 如何与 store 交互 ​

每个 apis/*.js 模块是工厂 (stores...) => (...args) => result。两种访问模式:

  • 通过 getter 读取:getActiveTool.js → store.getActiveTool。
  • 通过 dispatch 调用 action:closeElement.js → store.dispatch('closeElement')(dataElement)。

部分 API(openElement、closeElements、enableElements、disableElements、addPanel、getPanels、isElementOpen、getPassword)使用 dispatch/getState;其他直接调用 getter。api_helpers/createEncapsulatedStore.js 构建封装的 viewerStore / documentStore 包装器(仅暴露 dispatch/getState),供弹出菜单 API、getPassword 和 getPanels 使用。

持久化 ​

  • localStorage['language'] —— 所选语言。
  • localStorage['customStamps']、['electronicSignatures']、['digitalSignatures'] —— 印章/签名列表。

相关 ​