# 打印模板技术方案 ## 1. 方案概述 ### 1.1 目标 - **设计态**:提供控件区、工具栏、画布(类 Excel 网格)、属性区四块区域的可视化模板编辑;支持主表/子表/流程等字段拖放、单元格样式与表格绘制、多 Sheet、多页、页眉页脚与背景图、全局水印等。 - **运行态**:将模板 `content` + `settings` 与业务数据 `RuntimeFormData` 合并,完成预览与浏览器打印(iframe 输出,可降级为新窗口)。 - **工程目标**:与平台「打印管理」融合;模板以 JSON 持久化;内核与 UI 分层,便于维护与扩展。 ### 1.2 技术栈(与代码一致) | 层级 | 技术 | | --- | --- | | 设计器 UI | Vue 3(`H3PrintDesigner` 等) | | 画布与渲染内核 | `excellit`:Lit HTML 模板 + 数据仓库(DataStore)+ 工厂(factory) | | 打印运行时 | `runtime`:`H3PrintRuntime`,封装预览/打印与数据过滤 | | 条码/二维码 | `jsbarcode`、`qrcode` | | 样式 | SCSS,独立 `style` 出口 | SDK 通过 `package.json` 的 `exports` 暴露 `./designer`、`./runtime`、`./excellit` 与统一样式 `./style`。 --- ## 2. 整体架构 ### 2.1 分层 ```text 平台宿主(打印管理 / 表单) ↓ 元数据 metaData + 模板 templateData print-webapp / designer(H3PrintDesigner) ↓ 产出 PageData:content[] + settings 持久化 API(如 /api/v1/print/tpl/detail/:id) ↓ print-webapp / runtime(H3PrintRuntime) ↓ PageData + RuntimeFormData[] excellit(ExcelLitApi / ExcelLitCore) ↓ Lit 渲染 + parse-cell 数据绑定 浏览器预览 / window.print(runtime/print) ``` ### 2.2 包职责 | 包 | 职责 | | --- | --- | | **designer** | 设计器壳层:`metaData`(字段树)、`templateData`(content/settings 字符串需 JSON 解析)、`ExcelLit` 单例驱动画布;提供控件区、设置区、在线 Excel 工具条等。 | | **excellit** | 表格画布:行列、合并单元格、浮动层、子表/流程日志区域、水印与背景层、单元格内容解析(含富文本、条码、图片等)。 | | **runtime** | 无设计器 UI:加载模板与表单数据,创建 `ExcelLitApi` 实例执行 `printPreview`,处理默认模板、加载态、生命周期回调与字段占用分析等。 | ### 2.3 设计器与内核连接要点 - 设计器 `provide`:`$excelLit`(`ExcelLit` 实例)、`fileUploader`。 - 模板变更时销毁并重建 `excelLitInstance`,避免状态污染。 - `PageData` 中 `content` 为 **Sheet 数组**,支持多 Sheet;`settings` 为全局页面设置(纸张、边距、打印类型等)。 --- ## 3. 数据模型 ### 3.1 顶层:`PageData` 与 `packages/excellit/src/types/page-data/index.d.ts` 一致: ```ts interface PageData { id?: string templateName: string content: SheetContent[] // 多 Sheet,每页一块 sheet 数据 settings: PageSetting metaData?: any[] language?: string } ``` ### 3.2 单 Sheet:`SheetContent` 包含列宽 `cols`、行高 `rows`、单元格矩阵 `cells`、浮动块 `floatLayer`、子表范围 `subTableRanges`、流程日志范围 `workflowLogRanges` 等,支撑需求中的子表循环体、流程日志多行打印等。 ### 3.3 页面设置:`PageSetting` 与 `page-setting.d.ts` 及 `DefaultPageSetting`(`const/page-setting.ts`)对齐,核心字段包括: | 概念 | 代码字段 | 说明 | | --- | --- | --- | | 文档类 / 套打类 | `printType`:`PrintType.Document` / `PrintType.TemplatePrint` | 控制行高自适应 vs 固定区域截断、子表分页策略等(业务规则在解析与布局层实现) | | 分页 / 连续 | `pageMode`:`'break'` / `'continuity'` | 对应需求「分页打印」「连续打印」 | | 纸张 | `sizeType`、`size`(宽×高,单位与 UI 一致) | A4/A5/B3/B4/B5/自定义 | | 方向 | `orientation`:`portrait` / `landscape` | | | 边距 | `margin`:left/right/top/bottom(mm) | 画布可打印区 = 纸张 − 边距 | | 页眉页脚 | `pageHeader`、`pageFooter` | 左/中/右三块配置 | | 背景 | `background`、`backgroundArr`、`checkPrintBgArr` | 支持多背景与是否打印 | | 水印 | `watermarkEnabled`、`watermarkSetting` | 内容、字号、颜色、透明度、角度、密度、排列方式 | | 多页索引 | `pageNumberArr`、`sheetIndex` | 与多 Sheet、多页删除图标等联动 | ### 3.4 运行时数据:`RuntimeFormData` ```ts type RuntimeFormData = { [fieldCode: string]: any } ``` 为单条或批量记录字段值的扁平字典;子表、流程日志等多行数据由内核在 `compositionCellsDataBySubTableForm` 等工具中展开到网格。 --- ## 4. 设计态实现要点 ### 4.1 四块区域 | 区域 | 实现落点 | | --- | --- | | 控件区 | `controls-section.vue` 等,按 `metaData.fields` 分类展示业务字段、流程字段、系统字段、其他字段(图片、富文本、二维码、条形码等) | | 工具栏 | `online-excel/excel-toolbar`:字体、对齐、边框、合并单元格;含「富文本」入口(`setRichText` 写入 `fieldType: 'RichText'`) | | 画布 | `OnlineExcel` + excellit `DesignerLayout`:白底可印区、灰底非印区、行列标题拖拽 | | 属性区 | `settings-section`:全局页面属性 + 选中单元格/控件属性(子表列、流程日志节点等) | ### 4.2 画布内核(excellit) - **入口**:`ExcelLitCore.initExcelData` 依次提交 `setPageSetting`、`initSheetData`,注册 Lit 模板与工厂,订阅 action/mutation。 - **布局**:`template/layout/designer.ts` 组合表体、边框层、浮动层、背景层、水印层、子表层、流程层、分页删除图标等。 - **交互**:selection、shortcuts、context menu、拖拽虚拟展示(`dragger-virtual-dom`)等由 factory 注入。 ### 4.3 子表 / 流程日志 - 子表、流程日志在数据结构中占用 `subTableRanges` / `workflowLogRanges`,渲染由 `subTableRender`、`workflowLogRender` 等承担。 - **文档类**:子表循环体下方内容随数据下移。 - **套打类**:需配置每页子表(或流程日志)行数并预留空白行,避免叠字;主表在每页重复——与 `printType` 及分页算法一致。 --- ## 5. 富文本在打印模板中的技术衔接 表单侧富文本编辑器能力(KindEditor、HTML 存储、上传、DOMPurify 等)同模型内富文本组件。在**打印模板**中: ### 5.1 设计态 - 工具栏可将单元格设为 **打印富文本**(`FieldType.RichText`),打开表格弹窗编辑(`tableDialog` 等对 `RichText` 分支)。 - 设计态拖拽预览使用 `TextVirtualDom` 等轻量展示。 ### 5.2 数据形态 - 单元格 `content` 携带 `fieldType: 'RichText'` 与 `text`(HTML 字符串)。 - HTML 内可嵌入带 `fieldCode` 的占位 `span`,运行时用 `runtimeFormData[fieldCode]` 替换为实际值(可能仍是 HTML)。 ### 5.3 运行态渲染 - `parse-cell.ts` 中 `parseRichText`:运行态下构建 `.xlt__runtime-richtext` 容器,解析占位节点并注入数据;可对高度相关样式过滤以配合分页高度预计算(`prefetch-cell-height.ts` 等对 `RichText` 的特殊处理)。 - 企微等特殊环境可走 `EngineEntryType.WECOMESTANDARD` 分支。 --- ## 6. 运行态与打印链路 ### 6.1 `H3PrintRuntime` 主流程 1. `renderData(templateData, runtimeFormData)` 合并模板与数据。 2. `printPreview` 中创建 `ExcelLitApi`(`isParse` 等参数控制是否解析为打印视图)。 3. 内核在存在 `formData` 时 `setFormData` 并走打印渲染路径。 ### 6.2 物理打印 - `excellit/src/runtime/print.ts`:`runtimePrint` 收集 DOM `outerHTML`,写入隐藏 iframe,复制当前页 `style/link/meta`,再触发打印;失败时降级 `printContentInNewWindow`。 - 打印样式含对粗体等类的补偿,保证与屏幕一致。 ### 6.3 前台调用 - **列表批量打印**、**表单打印**:由宿主传入多条或单条 `RuntimeFormData` 与模板 `PageData`;连续模式依赖 `pageMode: 'continuity'` 与排版结果。 --- ## 7. 与平台融合 ### 7.1 API 约定(designer/services) 待确定... ### 7.2 设计器入参校验(`designer-index.vue`) - `metaData` 需包含 `fields`、`workflowField`(或 workflow 配置)等。 - `templateData` 需包含 `content`、`settings`、`templateName`。 ### 7.3 与旧模板 新模板入口与旧模板入口相同,通过增加配置项区分。 技术方案待确定。 --- ## 8. 非功能需求 ### 8.1 性能 - 大表分页与行高预计算:`prefetch-cell-height` 等避免一次性撑破布局。 - 富文本避免频繁整段 `innerHTML` 回灌导致光标问题属表单编辑器范畴;打印侧关注分页前高度预估一致性。 ### 8.2 国际化 - `ExcelLit.I18n` 与设计器 `$prt_Lng`:`language` 变更时重置语言与表格。 ### 8.3 可测试性 - 单元测试:`parse-cell` 中各 `fieldType`、水印与页边距计算、toolbar 映射。 - 集成测试:设计器保存 → runtime 预览 → 打印 DOM 结构。 --- ## 9. 交付拆分与里程碑建议 | 阶段 | 内容 | | --- | --- | | M1 | `PageData` 协议与宿主联调;列表/表单打开设计器、保存接口 | | M2 | 文档类/套打类、分页/连续、纸张边距、页眉页脚、背景图 | | M3 | 子表与流程日志循环、套打行数与换页、主表每页重复 | | M4 | 全局水印、二维码/条形码/图片等控件闭环 | | M5 | 富文本占位与运行态替换、高度与分页联调;与《富文本方案》安全策略对齐 | | M6 | 批量打印、性能与浏览器打印回归 | --- ## 10. 附录:关键文件索引 | 模块 | 路径(相对于 `packages/print-webapp`) | | --- | --- | | 设计器入口 | `packages/designer/src/views/designer-index.vue` | | 设计器导出 | `packages/designer/src/index.js` | | Runtime | `packages/runtime/src/index.ts` | | 画布核心 | `packages/excellit/src/core/main.ts` | | 表格 API | `packages/excellit/src/api/table.ts` | | 页面默认设置 | `packages/excellit/src/const/page-setting.ts` | | 类型定义 | `packages/excellit/src/types/page-data/*.d.ts`、`sheet-content/*.d.ts` | | 单元格解析 | `packages/excellit/src/utils/parse-cell.ts` | | 打印执行 | `packages/excellit/src/runtime/print.ts` | | SDK 聚合导出 | `src/index.ts` | --- *文档版本与代码库同步维护;若实现与本文不一致,以 `packages/print-webapp` 源码为准。*