DirectSurface UIDirectSurface UI
开始使用
组件/可视化和文档组件

可视化和文档组件 / COMPONENT

Printing Components

打印组件提供类似 FASTPRINT 的 JSON 模板设计器、分页预览和完整打印工作区。它使用 ds-ui 自己的 JSON 模型,不读取 FASTPRINT .frx 文件。

文档 READY示例 1
PUBLIC APIRenderPrintWorkspaceRenderPrintDesignerRenderPrintPagesViewpreparePrint

FUNCTION EXPLORER

可运行示例与完整源码。

这里始终保留组件的主运行入口;文档中的示例用于补充具体功能说明。

LIVE EXAMPLE PRINTING
全屏
正在启动 DirectSurface UI 运行时…

Printing 打印组件

通用布局能力RenderPrintWorkspaceRenderPrintDesignerRenderPrintPagesView 继承通用 RenderBox 的尺寸、min/max、margin 和槽位对齐属性。纸张边距和对象坐标属于打印模板设置。详见组件通用布局属性

打印组件提供类似 FAST_PRINT 的 JSON 模板设计器、分页预览和完整打印工作区。它使用 ds-ui 自己的 JSON 模型,不读取 FAST_PRINT .frx 文件。

当前公开能力覆盖模板设计、Canvas 预览和基础 PDF 导出。Electron/本地客户端打印与物理打印校准属于宿主应用和后续输出适配器的职责,它们应继续复用同一份 prepared layout 模型。

LIVE CANVAS可运行组件示例
ON-DEMAND RUNTIME交互式示例将在进入视区时启动避免文档首屏同时初始化多个 Canvas Runtime

API 总览

import {  RenderPrintDesigner,  RenderPrintPagesView,  RenderPrintWorkspace,  createPrintOutputPlan,  preparePrint,  writePrintPdf,  type PreparedPrint,  type PrintTemplate,} from 'ds-ui'
API 类型 用途
RenderPrintWorkspace class 带工具栏、JSON/PDF 导出、保存回调和分页导航的完整设计/预览工作区。
RenderPrintDesigner class 编辑页面、Band、打印对象、数据绑定、对齐、图层、网格、标尺和吸附设置。
RenderPrintPagesView class 只读显示 PreparedPrint 的 Canvas 预览。
preparePrint() function PrintTemplate 和 JSON 数据展开为 prepared pages。
createPrintOutputPlan() function 生成供 Canvas、PDF 或本地打印适配器消费的稳定绘制命令。
writePrintPdf() function PrintOutputPlan 写出基础 PDF。
PrintTemplate type 设计器保存的 JSON 模板格式。
PreparedPrint type 供预览、PDF 和后续打印路径消费的分页模型。

何时使用

适合:

  • 检查、检验等需要重复明细行的打印单;
  • 带排序、过滤、汇总和页脚的费用清单;
  • 包含条码或二维码的标签;
  • 实施人员需要通过设计器调整、而不是手改 JSON 的模板。

不适合:

  • 任意文档编辑,优先使用 RenderMedicalRecordEditor
  • 类似电子表格的单元格编辑,优先使用 RenderDataGrid
  • 服务端 FAST_PRINT .frx 兼容,本组件使用独立 JSON 格式。

最小工作区

const workspace = new RenderPrintWorkspace({  defaultTemplate: {    schemaVersion: 1,    name: '检验报告',    paper: { name: 'A5', widthMm: 148, heightMm: 210 },    margins: { leftMm: 10, topMm: 8, rightMm: 10, bottomMm: 8 },    pages: [{      id: 'page-1',      name: '患者信息',      bands: [        {          id: 'title',          kind: 'printTitle',          heightMm: 18,          objects: [            { id: 'title-text', kind: 'text', xMm: 0, yMm: 2, widthMm: 128, heightMm: 8, text: '检验报告' },          ],        },        {          id: 'items',          kind: 'data',          heightMm: 8,          dataPath: 'items',          objects: [            { id: 'item-name', kind: 'text', xMm: 0, yMm: 1, widthMm: 50, heightMm: 6, text: '{{name}}' },          ],        },        {          id: 'footer',          kind: 'pageFooter',          heightMm: 8,          objects: [            { id: 'page-text', kind: 'text', xMm: 0, yMm: 1, widthMm: 128, heightMm: 6, text: '第 {{page.number}} / {{page.total}} 页' },          ],        },      ],    }],    sampleData: {      items: [{ name: '白细胞' }, { name: '红细胞' }],    },  },  data: {    items: [{ name: '白细胞' }, { name: '红细胞' }],  },  onTemplateChange: template => {    // 更新业务状态中的模板草稿。  },  onSave: template => {    // 响应工作区工具栏的显式保存命令。  },})

模板模型

全部模板坐标和尺寸都使用毫米。当前 schema 版本为 schemaVersion: 1

interface PrintTemplate {
  schemaVersion: 1
  name?: string
  paper: { name?: string; widthMm: number; heightMm: number }
  margins: { leftMm: number; topMm: number; rightMm: number; bottomMm: number }
  pageNumberMode?: 'continuous' | 'perTemplatePage'
  pages: PrintPage[]
  sampleData?: unknown
}

PrintPage 是模板页,不一定对应最终的一张物理纸。当 DataBand 的内容溢出时,一个模板页可以生成多个 prepared pages。

Band 顺序

Band 遵循下列语义顺序:

PrintTitle
PageHeader
GroupHeader
DataHeader
DataBand
ChildBand
DataFooter
GroupFooter
PrintSummary
PageFooter

设计器插入 Band 时保持该顺序。工具栏的移动命令只允许在同一语义区间内调整,例如交换两个 pageHeaderdata 不能移动到 pageHeaderprintTitle 之前。

pageHeaderpageFooter 会在同一模板页生成的每个 prepared page 上重复。数据或分组跨页时,GroupHeader 和 DataHeader 也可以重复。

DataBand

data Band 通过 dataPath 展开数据行:

const itemsBand = {  id: 'items',  kind: 'data',  heightMm: 8,  dataPath: 'items',  filterExpression: '{{enabled}} == true',  sort: [{ field: 'sortNo', direction: 'asc' }],  printIfEmpty: false,  objects: [    { id: 'item-name', kind: 'text', xMm: 0, yMm: 1, widthMm: 50, heightMm: 6, text: '{{name}}' },  ],} as const
  • dataPath 相对当前上下文解析。
  • filterExpression 决定一行是否打印。
  • sort 接收简单排序描述。
  • printIfEmpty 可以在数组为空时打印一次空行上下文。
  • dataHeaderchilddataFooter 可以作为子 Band,分别表达重复表头、附加内容和汇总。
  • 子 DataBand 可以继续使用相对数组路径。

分组 Band

group Band 拥有自己的分组结构。groupHeaderdataHeaderdatachilddataFootergroupFooter 应放入 group.bands,不要通过 id 连接独立的页面级 Band。

const categoryGroupBand = {  id: 'category-group',  kind: 'group',  dataPath: 'items',  groupExpression: '{{category}}',  heightMm: 1,  objects: [],  bands: [    {      id: 'category-header',      kind: 'groupHeader',      heightMm: 8,      objects: [        { id: 'category-text', kind: 'text', xMm: 0, yMm: 1, widthMm: 80, heightMm: 6, text: '类别 {{groupKey}}' },      ],    },    {      id: 'items-row',      kind: 'data',      heightMm: 8,      objects: [        { id: 'item-name', kind: 'text', xMm: 0, yMm: 1, widthMm: 50, heightMm: 6, text: '{{name}}' },      ],    },    { id: 'category-footer', kind: 'groupFooter', heightMm: 8, objects: [] },  ],} as const

GroupFooter 可以通过 groupRows 使用聚合表达式:

const subtotalText = {  id: 'subtotal',  kind: 'text',  xMm: 0,  yMm: 1,  widthMm: 80,  heightMm: 6,  text: "小计 {{format(sum(groupRows.amount), '0.00')}}",} as const

图片对象

图片对象把 source 作为字符串保存在模板中。持久化格式只支持空字符串或 data:image/png;base64,... 这类 base64 data URI;远程图片 URL 不属于打印模板契约。

RenderPrintDesigner 通过 PropertyGrid 的 Image.Source 编辑器打开本地文件选择器,并用 FileReader.readAsDataURL() 写回模板。这样保存后的 JSON 自包含,也能被 PDF writer 直接嵌入。

表达式

打印表达式是受限安全表达式,不是 JavaScript。文本对象通过 {{...}} 渲染:

  • 相对字段,例如 nameamount
  • 根字段,例如 root.patient.name$root.patient.name
  • 比较、布尔和算术运算;
  • formatsumcountavgminmax
  • {{page.number}}{{page.total}} 等页信息。

表达式错误显示为 #ERR,同时写入打印 warnings。

预览导航

RenderPrintWorkspace 提供 prepared page 导航:

workspace.setMode('preview')
workspace.scrollToPreparedPage(1)
workspace.nextPreparedPage()
workspace.previousPreparedPage()

Preview 模式下工具栏提供相同命令。Design 模式编辑模板结构,因此禁用 prepared page 导航。

JSON 导入与导出

const json = workspace.exportJson()
workspace.importJson(json)

导入会执行轻量结构校验。warning 不阻止导入,但会显示在 validationWarnings 和状态栏。

PDF 导出

工作区可以直接导出当前模板和数据:

const result = workspace.exportPdf()

也可以显式构建共享输出计划:

const plan = createPrintOutputPlan(template, { data })
const result = writePrintPdf(plan)

当前 PDF writer 支持文本、线、矩形、data URI 图片、复选框、条码和二维码命令。它是第一种共享输出适配器;本地打印和物理校准应继续消费同一份输出计划。

相关组件