# 打印设计器

# 概述

打印设计器为打印需求提供了一个统一的解决方案。让开发人员无需编写代码,或编写少量代码即可实现打印功能,满足各种打印需求。

# 部署指引

若需要使用打印设计器,后端部署需要以下几个步骤:

1、引入打印设计器模块 maven 依赖

    <dependency>
        <groupId>com.mediway.hos</groupId>
        <artifactId>hos-app-print</artifactId>
    </dependency>

2、下载 pageOffice 插件相关的依赖文件。将此文件解压缩到某个路径

3、将第二步文件的路径配置到配置文件中

4、完成以上三步后启动后端服务,后端服务成功后再启动前端服务。

# 环境要求

  • Office 在线编辑插件:PageOffice5.4

若未安装 PageOffice,首次进入打印设计功能时,系统会提示需要安装此插件,按照提示完成插件安装后,再次进入系统即可。

  • Excel 环境: 至少需要安装下述软件中的其中一种
    • Microsoft Office Excel (版本>=2007)
    • Wps Office Excel

# 打印功能配置流程

# 模板管理

# 概述

模板管理用于配置应用中的打印功能,每一个打印模板就对应着模板管理中的一条记录。

【模板管理路径:】开发集成 -> 打印设计器 -> 模板管理

# 查询模板

可根据模板编码、模板名称模糊查询。数据列表的显示支持自定义,点击表格右上角的小齿轮,即可选择需要显示的列。查询结果按照模板的创建时间倒序显示。

# 新增模板

点击新增按钮,弹出新增页面,编辑模板信息后点击保存或保存并设计按钮即可。若点击的是保存并设计按钮,则将自动跳转到模板设计页面。

# 示例

# 属性说明

字段名     字段说明
编码 必填、长度最大为 75 字符、只允许输入数字字母下划线、有唯一性校验
名称 必填、长度最大为 37 字符
类型 必填、指打印使用的插件类型
描述 长度最大为 250 字符

# 编辑模板

点击需要修改的数据右侧编辑按钮,弹出编辑页面。修改表单内容,点击保存即可。若点击的是保存并设计按钮,则将自动跳转到模板设计页面。


提示
编码不可编辑。

# 删除模板

模板删除包含两种操作场景:单独删除和批量删除。

  • 单独删除:点击数据表格行操作列删除按钮,即可对单条数据进行删除。

  • 批量删除:勾选需要删除的数据后,点击表头上方删除按钮,即可对模板数据进行批量删除。

# 复制模板

用户若想要复用旧模板的设计和配置,可使用复制模板功能。点击旧模板数据右侧复制按钮,修改模板编码、名称等内容,点击保存,即可保存一个新模板数据。其模板文件和配置都是从旧模板复制而来。

# 模板设计

# 概述

点击模板数据右侧设计按钮,将会弹出一个打印模板设计页面。

打印设计页面分为两个部分,左侧是Excel 设计页面,右侧是模板相关的数据配置页面。数据配置有三个部分,分别为数据集管理属性配置打印配置


提示
使用模板设计功能时,本地Excel不能处于编辑状态(即光标不能定位到单元格内),否则将会弹出以下错误提示

# Excel 设计

Excel 设计页面和 Microsoft Office Excel 使用方法一致,在此页面中我们可以画出需要打印的模板。同时,Excel 设计页面提供了多个功能按钮, 包括打印设置保存关闭最大化窗口打开另存为

# 打印设置

点击打印设置按钮,将弹出打印设置弹窗,可在弹窗中设置系统页码、纸张大小等选项,点击保存按钮后,这些配置都将被保存,并将在打印时生效。

# 保存

模板设计页面中 excel 模板,以及右侧所有配置数据都通过此按钮进行保存。右侧配置页面中的其他的保存按钮不会将数据保存到数据库中。

# 关闭

点击关闭按钮,模板设计窗口将被关闭,修改的数据不会保存。

# 最大化窗口

点击模板右上角图标,excel 模板将最大化,方便用户进行模板设计。

再次点击右上角图标,excel 模板大小将还原。

# 打开

点击模板设计窗口左上角文件按钮,将显示多个下拉选项,点击打开选项,即可打开本地文件到模板设计窗口中。

# 另存为

点击模板设计窗口左上角文件按钮,将显示多个下拉选项,点击另存为选项,即可将当前设计的模板文件保存到本地。

# 数据集管理

数据集管理用于配置打印时的数据来源,目前只支持反射调用数据集这一种方式。

字段名     字段说明
数据集来源 反射调用数据集:从 spring 容器获取配置的 bean,再通过反射调用指定方法获取数据
类名 长度最大为 200 字符,数据集来源配置为反射调用数据集 时必填,填写 spring 容器中的 beanName
方法名 长度最大为 200 字符,数据集来源配置为反射调用数据集 时必填,方法请求参数及返回参数结构见接口文档-打印数据接口

# 属性配置

属性配置包含数据对象配置和数据属性配置。主要功能有数据对象的增删改、属性对象的增删改、以及函数导入。

  • 数据对象:将同一种类型的属性维护为一个数据对象,通常可以将同一个数据表的字段配到同一个数据对象中。
  • 属性对象:对于模板中每一个需要填充数据的单元格,都需要配置一个对应的属性。

# 数据对象

点击新增数据对象按钮,弹出新增页面,输入数据对象相关信息,点击保存按钮,即可完成数据对象的创建。

字段名     字段说明
编码 必填、长度最大为 75 字符、只允许输入数字字母下划线、同一个模板内不能重复
名称 必填、长度最大为 37 字符
类型 表单数据:在模板中的固定数据,只出现一次。例如表头表尾中的数据。
列表数据:模板中的明细数据,数据条数是多条的,不固定。
明细开始行 数据对象为列表数据时才有此属性,必填
明细结束行 数据对象为列表数据时才有此属性,非必填,是否配置明细结束行影响到打印效果,详见批量凭证打印示例批量表格打印示例

点击表格右上方编辑按钮,可对数据对象进行编辑。

点击表格右上方删除按钮,可删除对应的数据对象,注意:数据对象中的数据属性也将会被删除

# 属性对象

点击数据对象右上角新增按钮,可以给此数据对象新增数据属性。

字段名     字段说明
编码 必填、长度最大为 75 字符、只允许输入数字字母下划线、同一个模板内不能重复
名称 必填、长度最大为 75 字符
数据类型 必填、 数据:文本、日期、数字等一般数据。
图片:图片数据,需要配置额外的参数。详见图片配置
是否分组 必填、详见分组打印示例
坐标 指属性需要填充的单元格的坐标,格式为:列坐标,行坐标

提示
鼠标定位到需要填充的单元格,点击坐标输入框右侧的取值按钮,输入框内将自动填入此单元格的坐标。

# 图片配置

若数据属性类型为图片,则还需添加以下配置

字段名     字段说明
图片类型 必填、目前只支持 PNG、JPEG 两种类型
左上角坐标 必填、确定图片左上角的位置
右下角坐标 必填、确定图片右下角的位置
上边距 非必填,默认为 0
下边距 非必填,默认为 0
左边距 非必填,默认为 0
右边距 非必填,默认为 0

其中左上角坐标和右小角坐标确定了图片的位置和初步大小,如下图所示:

上下左右四个边距分别是与四条单元格边线的距离。通过设置这四个参数,可以放大或缩小图片。

  • 四个参数分别设置为:上边距=5、下边距=-5、左边距=5、右边距=-5。打印效果如下:

  • 四个参数分别设置为:上边距=-5、下边距=5、左边距=-5、右边距=5。打印效果如下:


提示
通过上面的示例可以发现:左上边距为正数时,图片缩小,为负数时,图片扩大。相反的,右下边距为负数时,图片缩小,为正数时,图片扩大

# 函数导入

除手动添加外,本功能页支持通过函数调用,解析函数返回的数据结果,直接导入所有的数据对象和数据属性配置。

点击表格上方函数导入按钮,弹出函数导入窗口,输入相关信息后,点击确定按钮,系统将自动调用配置的方法,并对返回结果进行解析,展示返回的数据对象和数据属性。接口详情见接口文档-函数导入

接口实现以及入参等参考函数导入配置接口

字段名     字段说明
类名 必填,填写 spring 容器中的 beanName
方法名 必填,填写 beanName 中的方法名
参数配置 自定义配置函数需要的参数名和值

# 打印配置

打印配置是配置打印时的一些扩展功能。主要功能有是否套打、是否清除空行、是否取打印机默认纸张、总页数坐标、当前页数坐标。

字段名     字段说明
是否套打 是-打印数据生成时,清空打印模板的所有线框。 否-不做特殊处理。详情见套打打印示例
是否清除空行 是-删除最后一页多余的空行,只有凭证类型起作用。 否-不做特殊处理
是否取打印机默认纸张 是-打印时取打印机的默认纸张。 否-打印时取模板配置的纸张。
总页数 配置需显示总页数的坐标。只有凭证类型起作用。 详情见批量凭证打印示例
当前页数 配置需显示当前页数的坐标。只有凭证类型起作用。 详情见批量凭证打印示例

# 打印示例

# 概述

打印示例展示了本设计器支持的四个核心打印功能,包括批量凭证打印示例批量表格打印示例分组打印示例套打打印示例

【打印示例路径:】开发集成 -> 打印设计器 -> 打印示例

  • 点击示例卡片右上角设计按钮,即可打开该示例的模板设计页面,查看示例是如何配置的。

  • 点击示例卡片右上角打印按钮,即可进入打印预览页面,查看给模板填充数据后的效果。

  • 点击打印预览页面中的打印按钮,选择打印到 pdf,即可生成 pdf 文件,预览打印的最终效果。

# 批量凭证打印示例

凭证打印通常用于收据、记账等财务场景。在数据过多,需要分页打印时,凭据每页打印的明细条数固定,且每一页都打印表头和表尾。即每页除明细数据内容不同外,其他内容都相同。

以下图模板为例。凭证类型的打印模板需要注意以下几点:

  • 类型为列表的数据的数据对象有且只能有一个。
  • 必须配置明细开始行和明细结束行。
  • 模板设计中的明细行数必须和配置保持一致。例如示例中的模板设计表示该模板每页只打印三行数据。

示例的打印效果如下图,数据来源即数据集管理中配置的方法。其逻辑可见对应的源码。入参出参结果即接口文档-打印数据接口中的示例所示。


提示
另外,本示例配置了当前页数和总页数。从打印效果上可以看出,页数的计算是以单批数据为单位的。 本示例批量打印了两批数据。第一批数据为2页。因此第一批数据的总页数为2,而不是3。这和我们平常使用的excel配置自动页码有所不同。

# 批量表格打印示例

表格打印通常适用于普通列表数据打印、申请单、记录表等大部分打印场景。在数据过多,需要分页打印时,表格根据打印纸张大小进行自动分页,每页数据条数不固定。只有第一页打印表头,最后一页打印表尾。

以下图模板为例。表格类型的打印模板需要注意以下几点:

  • 不能配置明细结束行。
  • 模板设计中的数据列表只需要空出一行,若多画了空行,打印结果将始终保留多余的空行,不会填充数据。

打印效果如下图所示:

# 分组打印示例

在某些业务场景下,需要生成如下图所示的打印效果。即将同一列内数据内容相同的单元格合并。

要实现上图的的效果,需要做两步操作:

  • 将对应属性的是否分组设置为
  • 返回的数据集需要按对应属性有序排序

# 套打打印示例

在某些业务场景下,例如发票打印,打印纸张中已经有了模板内容,只需要将抬头、金额的打印上去。 此时就需要将模板中的固定内容和网格线去除,这种打印场景即为套打。

  • 在打印配置中将是否套打选择为
  • 若想保留部分固定内容。例如在本示例中,需要保留模板标题,只需在标题上加上备注标记即可。

打印效果如下:

# 后端接口

若数据集来源选择反射调用数据集,则使用者需要提供对应的接口,返回需要打印的数据集。接口规范详见接口文档-打印数据

# 前端组件

用户可根据业务需求,自行给需要打印功能的页面添加打印按钮。只需要在页面内添加以下代码:

该函数用于打开 PageOffice 应用,当使用 openPageOffice 组件时,需要传递一个包含函数所需参数的对象。该函数无返回值,入参说明如下:

  • data [Object]: 包含函数所需的参数对象
    • isPreview [Boolean]:区分打印功能是否需要预览,true:需要预览;false:无需预览。具体效果见无预览打印
    • params [Object]:用于接口请求的入参对象
      • templateCode [String]:模版 templateCode,即模板管理中填写的模板编码,也用于 PageOffice 标题展示
      • id [String]:模版 id
      • fileId [String]:模版 fileId
    • sourceType [String]:业务场景来源,默认值 printPreview(printPreview-打印,printExample-打印示例)
    • templateName [String]:模版名称,用于 PageOffice 标题展示
  • style [String, 可选]:附加的样式信息,用于自定义页面展示样式,默认值为 'width=1800px;height=900px'
// 引入openPageOffice
import { openPageOffice } from '@base/utils/print'

// 使用示例
openPageOffice({
  params: {
    templateCode: 'dengxing-test-org',
    id: id,
    fileId: fileId
  },
  isPreview: true, // 需要预览
  templateName: '打印',
  sourceType: 'printPreview'
})

# 无预览打印

打印功能支持两种展示效果,分别是有预览打印无预览打印。由前端组件传入的参数值决定。

# 有预览打印

若选择有预览打印,点击打印按钮后,会弹出 pageOffice 打印预览窗口,显示模板中填充具体数据后的效果。如下图所示:

点击右上角打印按钮,才会弹出打印配置,打印文件。

# 无预览打印

若选择有预览打印,点击打印按钮后,不会弹出 pageOffice 打印预览窗口和打印配置窗口,而是直接使用保存好的打印配置打印文件,只会弹出打印进程窗口。

# 打印日志

# 概述

打印日志功能用于记录业务数据每一次打印的相关信息。用户可根据业务需求,自行给需要记录打印日志的业务添加打印日志功能。打印日志功能包括查询日志审核日志

# 添加打印日志功能

# 前端

前端只需要在页面代码内添加数据打印日志的按钮和入口方法。如下:

// template
<hos-button icon="hos-icom-Detail_print" @click="openPrintLog()">数据打印日志</hos-button>

// 打开数据打印日志的方法
openPrintLog() {
  this.$router.push({
    path: '/base-monitor-print-log',
    query: {
      id: this.ids[0] // 选中的数据id
    }
  })
}

添加效果如下图所示:

# 后端

若需要记录打印日志,打印数据接口必须固定返回 id 参数,即业务数据的主键,这样才能给该条数据绑定打印日志。详见打印数据接口出参示例。

# 查询打印日志

勾选一条数据,点击数据打印日志按钮,即可跳转到打印日志页面。该页面分页显示当前数据所有的打印日志信息,支持根据模板编码、模板名称、类型、操作人、操作时间查询。

点击日志右侧查看按钮,可查看该日志的详细信息。

# 审核打印日志

点击需要审核的日志右侧审核按钮,将弹窗审核窗口,输入审核类型和审核意见后,点击保存按钮,即可完成审核

# 接口文档

# 函数导入接口

# 接口说明

# 接口入参

  • 参数名和参数值即函数导入页面中用户填写的参数名和参数值
  • 入参 demo 示例
入参对象:
List<HosPrintFuncImportSubDto>(com.mediway.hos.app.print.template.model.dto.HosPrintFuncImportSubDto)
入参格式:
[
  {
    "paramCode": "paramCode1",
    "paramValue": "paramValue1"
  },
  {
    "paramCode": "paramCode2",
    "paramValue": "paramValue2"
  }
]

# 接口出参

  • 出参 demo 示例,
+ 实体对象HosPrintAttrEntity(com.mediway.hos.app.print.template.model.entity.HosPrintAttrEntity)
{
	"mainData":[{
			"dataCode": "t_table_main",
			"dataName": "用户",
			"dataType": "1",	//主数据
			"dataAttribute": [
				{
					"fieldCode": "name",
					"fieldName": "用户名"
				},
				{
					"fieldCode": "qcode",
					"fieldName": "二维码"
				}
			]
	}],

	"listData":[
		{
			"dataCode": "t_table_sub1",
			"dataName": "学历",
			"dataType": "2",   //子数据
			"dataAttribute": [
				{
					"fieldCode": "type",
					"fieldName": "类别"
				},
				{
					"fieldCode": "fromdate",
					"fieldName": "获取时间"
			]
		},
		{
			"dataCode": "t_table_sub2",
			"dataName": "教育经历",
			"dataType": "2",   //子数据
			"dataAttribute": [
				{
					"fieldCode": "startDate",
					"fieldName": "开始时间"
				},
				{
					"fieldCode": "endDate",
					"fieldName": "结束时间"
				},
				{
					"fieldCode": "school",
					"fieldName": "学校"
				}
			]
		}
	]
}

# 参考 demo 示例

  • 包名:com.mediway.hos.app.print.template.demo.bean
  • 类名:ImportFuncDemo

# 打印数据接口

# 接口说明

# 接口入参

  • 入参固定为类com.mediway.hos.app.print.template.model.dto.HosPrintReflectParamDto,其由 3 个变量组成
    • templateCode:模板编码
    • fieldParams:属性配置。即模板设计-属性配置中,所有数据对象和属性对象的编码及名称
    • businessParams:业务自定义参数。点击打印按钮时,前端页面传入的请求体参数,都将原封不动的封装在此对象中
  • 入参结构示例

此示例即批量凭证打印示例的数据接口入参

{
  "templateCode": "batch_voucher_demo",
  "fieldParams": {
    "mainData": [
      //表单数据集合
      {
        "dataCode": "mainObj", //数据对象编码
        "dataName": "附加数据", //数据对象名称
        "dataType": "1", //数据对象类型。1-表单数据,2-列表数据
        "dataAttribute": [
          //属性集合
          {
            "fieldCode": "printDate", //属性编码
            "fieldName": "打印日期", //属性名称
            "fieldType": "1" //属性类型。1-数据;2-图片
          },
          {
            "fieldCode": "bookKeeper",
            "fieldName": "记账人",
            "fieldType": "2"
          }
        ]
      }
    ],
    "listData": [
      //列表数据集合
      {
        "dataCode": "detailObj",
        "dataName": "列表数据",
        "dataType": "2",
        "dataAttribute": [
          {
            "fieldCode": "code",
            "fieldName": "预算编码",
            "fieldType": "1"
          },
          {
            "fieldCode": "name",
            "fieldName": "预算名称",
            "fieldType": "1"
          },
          {
            "fieldCode": "type",
            "fieldName": "预算类别",
            "fieldType": "1"
          },
          {
            "fieldCode": "person",
            "fieldName": "预算经办人",
            "fieldType": "1"
          },
          {
            "fieldCode": "usedAmount",
            "fieldName": "预算已使用额度",
            "fieldType": "1"
          },
          {
            "fieldCode": "totalAmount",
            "fieldName": "预算总额度",
            "fieldType": "1"
          }
        ]
      }
    ]
  },
  "businessParams": {
    "templateCode": "batch_voucher_demo",
    "ids": [],
    "...": "..."
  }
}

# 接口出参

  • 接口出参结构为List<Map<String, JSONArray>>
    • 最外层为一个 List,他表示本功能支持批量打印。此 List 的元素个数就是批量打印个数
    • List 内是一个 Map 对象,key 为模板设计-属性配置中,配置的数据对象的编码。value 则是数据对象中的属性
    • Map 的 value 也是一个集合。对于表单数据对象,该集合固定只有一条数据。对于列表数据,该集合的元素个数就是明细数据的条数。 集合内是一个 Object,他的 Key 为模板设计-属性配置中,配置的属性编码。value 即为该属性需要填充的值
  • 出参结构示例

此示例即批量凭证打印示例的数据接口出参

[
  {
    //表单数据对象,mainObj即模板设计中配置的数据对象编码。
    //该集合固定只有一个数据,为了方便解析,才设计为一个集合
    "mainObj": [
      {
        "printDate": "2023-08-21", //属性编码和对应的值。编码即模板设计中配置的属性编码
        "bookKeeper": "张三签名图片的base64",
        "id": "1d657c4ff4ee60c00f48228376f6627c" //数据主键,需要记录打印日志时必传
      }
    ],
    //列表数据对象,detailObj即模板设计中配置的数据对象编码
    "detailObj": [
      {
        "code": "budget_1", //属性编码和对应的值。编码即模板设计中配置的属性编码
        "usedAmount": 400000,
        "remark": "年度先进科室,每科室奖励预算20000元",
        "type": "奖励",
        "totalAmount": 200000,
        "person": "张三",
        "name": "年度先进科室预算奖励",
        "id": "3102889cd08f84f183935f79293848f6" //数据主键,需要记录打印日志时必传
      },
      {
        "code": "budget_2",
        "usedAmount": 6000,
        "remark": "督导检查优秀科室,每科室奖励预算3000元",
        "type": "奖励",
        "totalAmount": 30000,
        "person": "李四",
        "name": "督导检查优秀科室预算奖励"
      }
    ]
  },
  {
    "detailObj": [
      {
        "code": "budget_21",
        "usedAmount": -10000,
        "remark": "控烟工作不合格,每科室罚款5000元",
        "type": "罚款",
        "totalAmount": -200000,
        "person": "张三",
        "name": "控烟工作不合格"
      },
      {
        "code": "budget_22",
        "usedAmount": -20000,
        "remark": "发生安全事故,每科室罚款20000元",
        "type": "罚款",
        "totalAmount": -5000000,
        "person": "李四",
        "name": "发生安全事故"
      }
    ],
    "mainObj": [
      {
        "printDate": "2023-08-21",
        "bookKeeper": "张三签名图片的base64"
      }
    ]
  }
]