vg-print
v1.0.422
Published
vg-print Vue3.x 支持拖拽(分页(不分页)、表头表脚、样式设置、复制粘贴、缩放、撤销重做)生成打印模板、导出json模板数据、静默打印/获取MAC地址(借助客户端)
Readme
vg-print
[开源免费]一个开箱即用的打印设计器组件库(Vue 3)。现在聚焦于单一组件 FullDesigner,同时暴露底层 hiprint 能力与客户端直连(hiwebSocket)配置,便于快速集成模板设计、预览、浏览器打印、导出 PDF/图片、直接打印等功能。
- 您可以直接安装引入体验功能.功能在不断完善中,请及时更新使用,欢迎反馈与建议,共同成长
- 没有域名限制,无网可用. 随时提供帮助和解决问题.
- npm搜索vg-print.
- 联系我加 QQ: 984239686 或使用首页有微信加入群聊解决问题.
授权密钥(authKey)与默认水印
行为说明:
- 设计态(FullDesigner 设计界面):不自动注入默认水印;是否显示水印由面板中的“水印功能”设置项决定,与
authKey无关。 - 运行态(预览、浏览器打印、导出 PDF/图片、直连打印):
- 无授权(未注册
authKey):- 面板未填写内容 → 显示默认水印
{ content: 'vg-print', timestamp: true } - 面板填写了内容 → 显示面板内容 + "试用版" 后缀
- 面板未填写内容 → 显示默认水印
- 有授权(已注册有效
authKey):- 面板未填写内容 → 不显示水印(默认水印被移除)
- 面板填写了内容 → 显示面板内容(无后缀)
- 无授权(未注册
- 设计态(FullDesigner 设计界面):不自动注入默认水印;是否显示水印由面板中的“水印功能”设置项决定,与
注册授权密钥(密钥添加除水印): 在项目入口(如
main.js或App.vue)尽早注册:import { hiprint } from 'vg-print'; // 填入生成的 Key hiprint.register({ authKey: 'eyJrIjoiZ21jNTc2MDMzNyJ9' });注册后,以下所有使用方式均会自动生效(移除默认水印):
- 完整设计器组件
FullDesigner - 核心类
new hiprint.PrintTemplate(...) - 轻量运行时 helper
createTemplate(...)
- 完整设计器组件
示例:轻量运行时使用授权
import { hiprint, createTemplate, printBrowser } from 'vg-print'
hiprint.register({ authKey: 'eyJrIjoiZ21jNTc2MDMzNyJ9' })
const tpl = createTemplate(tmplJson) // 不再自动注入默认水印
printBrowser(tpl, data)- 自定义或显式控制水印:
// 无授权时,库会注入默认水印;如需自定义水印样式/内容
const tpl = new hiprint.PrintTemplate({
template: {},
watermarkOptions: { content: 'your-brand', timestamp: true, rotate: 20 }
})
// 有授权时,运行态不会注入默认水印;若仍需水印,请显式传入
const tpl2 = createTemplate(tmplJson, {
watermarkOptions: { content: 'your-brand', timestamp: true }
})
// 设计态由面板设置项决定水印,不受 authKey 控制。
// 运行态的默认水印由授权控制,不建议通过传入空对象取消;如需取消,请注册有效 authKey。
const tpl3 = new hiprint.PrintTemplate({ template: {}, watermarkOptions: { content: 'your-brand', timestamp: true } })- 插件注册(可选):
import { hiprint } from 'vg-print'
// 两种形式的插件均支持
function pluginFn(h) { /* 扩展逻辑 */ }
const pluginObj = { install(h) { /* 扩展逻辑 */ } }
hiprint.register({
authKey: 'eyJrIjoiZ21jNTc2MDMzNyJ9',
plugins: [pluginFn, pluginObj]
})默认水印参数参考:
{ content: 'vg-print', timestamp: true }静默打印客户端工具安装包

客户端工具下载:
https://download.csdn.net/download/github_38400706/92538739特性
- 全功能页面组件
FullDesigner,直接使用,无需拼装子组件 - 支持预览、浏览器打印、导出 PDF/图片、直接打印(需客户端)
- 通过属性配置
hiwebSocket的host、token与自动连接 - 暴露实例方法:预览、打印、导出、连接控制等,外部可直接调用
- 集成并导出
hiprint,可进行模板对象级的高级定制
安装
npm i vg-printHeader 顶部工具栏组件
- 用于页面一级头部区域,内置常用操作按钮与打印机设置;支持通过
props与slots定制。 - 默认嵌入在
FullDesigner中;也可单独使用。
属性(Props)
logoHtml: string左侧 Logo 区自定义 HTML 片段title: string左侧标题文本printCount: number打印份数,默认1(支持v-model:printCount)printerName: string当前选择的打印机名称(支持v-model:printerName)printerList: Array<{ name: string; label: string }>打印机列表waitShowPrinter: boolean显示“浏览器打印”按钮的加载状态languages: Array<{ label: string; value: string }>语言切换下拉选项
事件(Emits)
preview打开预览print-view浏览器打印to-pdf导出 PDFto-image导出图片print直接打印(需客户端)clear-paper清空(带二次确认)save保存(拆分按钮的主键)edit-template打开“编辑模板数据”对话框edit-data打开“编辑打印数据”对话框lang-change语言切换(值为语言码:cn、en、de、es、fr、it、ja、ru、cn_tw)feedback反馈/帮助
插槽(Slots)
headerLeft左侧区域(默认:logo + 标题)headerCenter中间自定义区域(默认空)headerRight右侧操作区(默认:打印机与一组按钮)
如果发现外部调用安装过程页面样式有丢失情况, 可以引入打印样式重要提醒需要复制
【node_modules/@vg-print/hiprint/dist/css/print-lock.css】到开发资源目录。
例如: Vue 项目的 public 目录。
假如你部署的网站是: https://www.abcd.com/index.html
那么确保 https://www.abcd.com/print-lock.css
能够正常访问在你项目的 index.html 入口 添加 print-lock.css 打印样式【名称 print-lock.css】注意: media="print"
可以调整成相对链接/自有链接,但【重要】名称需要一致(print-lock.css):
<link rel="stylesheet" type="text/css" media="print" href="/print-lock.css" />使用示例:与 FullDesigner 配合
<template>
<FullDesigner
ref="designer"
:initial-template="tpl"
:initial-print-data="rows"
default-lang="cn"
:hi-host="host"
:hi-token="token"
:hi-auto-connect="true"
@save="onSave"
>
<!-- 顶部区域(Header 默认内置;也可通过 slot 定制) -->
<template #headerLeft>
<div style="display:flex;align-items:center;color:#fff;">
<img src="/logo.svg" style="height:24px;margin-right:8px;" />
<span>自定义标题</span>
</div>
</template>
<template #headerCenter>
<el-tag type="success">中间自定义区域</el-tag>
</template>
<!-- 保留默认按钮时无需提供 headerRight;若完全替换按钮则提供该插槽 -->
<template #headerRight>
<el-button size="small" @click="designer.value.preView()">预览</el-button>
<el-button size="small" @click="designer.value.printView()">浏览器打印</el-button>
<el-button type="primary" size="small" @click="designer.value.toPdf()">导出 PDF</el-button>
<el-button size="small" @click="designer.value.toImage()">导出图片</el-button>
<el-button size="small" @click="designer.value.print()">直接打印</el-button>
<el-button type="warning" size="small" @click="onClear()">清空</el-button>
<el-button type="success" size="small" @click="onSaveDirect()">保存</el-button>
</template>
</FullDesigner>
</template>
<script setup>
import { ref } from 'vue'
const designer = ref(null)
const host = ref('http://127.0.0.1:17521')
const token = ref('')
const tpl = { panels: [ /* ... */ ] }
const rows = [{ title: '病理图文报告', name: '东东' }]
const onSave = ({ template, data }) => { /* 保存到后端 */ }
const onClear = () => { /* 清空数据/元素 */ }
const onSaveDirect = () => designer.value?.save()
</script>使用示例:单独使用 Header
<template>
<Header
v-model:printCount="count"
v-model:printerName="printer"
:printerList="printers"
:waitShowPrinter="loading"
:languages="langs"
title="打印设计器"
@preview="onPreview"
@print-view="onPrintView"
@to-pdf="onToPdf"
@to-image="onToImage"
@print="onPrint"
@clear-paper="onClear"
@save="onSave"
@lang-change="onLangChange"
@feedback="onFeedback"
/>
</template>响应式策略(已内置)
- 窗口缩小时自动隐藏中间区域与次要按钮,保留右侧“保存”和“反馈”等关键操作;左侧 logo/标题不受影响。
- 断点规则:
≤1600px隐藏中间区域≤1400px隐藏打印份数、打印机选择、预览、浏览器打印、导出 PDF、导出图片≤1200px隐藏直接打印、语言切换≤992px隐藏清空≤768px隐藏标题文本(保留 Logo)
提示:如需完全自定义按钮,请提供
headerRight插槽实现自己的按钮布局。
Preview 预览组件
- 独立的预览弹窗组件,支持渲染模板 HTML、选择打印机、导出 PDF/图片、直接打印等。
- 可单独使用或与
FullDesigner搭配。
属性(Props)
printTemplate: object模板对象(hiprint.PrintTemplate或createTemplate返回值)printData: object | array打印数据printerList: Array<{ name: string; label: string }>打印机列表selectedPrinter: string选中的打印机名称showPdf: boolean是否显示“导出 PDF”按钮,默认trueshowImg: boolean是否显示“导出图片”按钮,默认trueshowPrint2: boolean是否显示“直接打印”按钮,默认truemodalShow: boolean弹窗显隐(支持v-model:modalShow)width: string | number弹窗宽度(默认'80%')defaultLang: string组件内 i18n 语言(Standalone 时使用);支持cn、en、de、es、fr、it、ja、ru、cn_tw;默认cn
事件(Emits)
update:modalShow双向绑定弹窗显隐update:selectedPrinter选中打印机变更close关闭弹窗
暴露方法(defineExpose)
show(template, data, width?)显示并渲染预览内容;可传入模板/数据与弹窗宽度hideModal()关闭弹窗init()初始化(内部使用)getTarget()获取预览容器 DOM
使用示例(单独使用)
<template>
<el-button @click="openPreview">显示预览</el-button>
<Preview
ref="previewRef"
v-model:modalShow="visible"
default-lang="cn"
:printerList="printers"
:selectedPrinter="printer"
@update:selectedPrinter="printer = $event"
/>
</template>
<script setup>
import { ref } from 'vue'
import { Preview, createTemplate } from 'vg-print'
import 'vg-print/style.css'
const previewRef = ref(null)
const visible = ref(false)
const printers = ref([{ name: 'HP_001', label: 'HP 打印机' }])
const printer = ref('')
const tmplJson = { panels: [ /* ... */ ] }
const data = { title: '病理图文报告', name: '东东' }
const openPreview = () => {
const tpl = createTemplate(tmplJson) // 也可传入 hiprint.PrintTemplate
previewRef.value.show(tpl, data, '80%')
}
</script>使用示例(与 FullDesigner 搭配)
<template>
<FullDesigner ref="designer" default-lang="cn" />
<Preview ref="previewRef" v-model:modalShow="visible" />
<el-button @click="designer.value.preView()">直接使用 FullDesigner 的预览</el-button>
<el-button @click="showCustomPreview">用 Preview 展示当前模板</el-button>
</template>
<script setup>
import { ref } from 'vue'
const designer = ref(null)
const previewRef = ref(null)
const visible = ref(false)
const showCustomPreview = () => {
const tpl = designer.value.getTemplate() // 假设暴露了获取模板的方法
const data = designer.value.getPrintData() // 假设暴露了获取数据的方法
previewRef.value.show(tpl, data, '80%')
}
</script>注意
- 使用组件库时请引入
vg-print/style.css,其中包含自定义图标字体与预览/设计样式。 Preview内部会根据printTemplate与printData自动渲染内容;也支持通过show(...)主动传入。- 若在外部项目未安装插件(未执行
app.use(vgPrint))而单独使用Preview,请通过default-lang显式设置语言;安装插件时无需设置,语言默认随全局 i18n。
样式引入(确保设计与打印样式生效):
// 全局样式(组件库样式)
import 'vg-print/style.css'<!-- 打印锁样式(推荐;保证打印时样式稳定) -->
<link rel="stylesheet" type="text/css" media="print" href="/css/print-lock.css" />环境要求:Vue 3、Node >= 18.18。无需单独安装 vue-plugin-hiprint,本库已内置并导出 hiprint 能力。
快速开始
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import vgPrint from 'vg-print'
import 'vg-print/style.css'
createApp(App).use(vgPrint).mount('#app')<template>
<FullDesigner
ref="designer"
:hi-host="'http://127.0.0.1:17521'"
:hi-token="'your-token'"
:hi-auto-connect="true"
/>
<el-button @click="preview">预览</el-button>
<el-button @click="printBrowser">浏览器打印</el-button>
<el-button @click="exportPdf">导出 PDF</el-button>
<el-button @click="exportImage">导出图片</el-button>
<el-button @click="directPrint">直接打印(需客户端)</el-button>
</template>
<script setup>
import { ref } from 'vue'
const designer = ref(null)
// 预览
const preview = () => designer.value.preView()
// 浏览器打印
const printBrowser = () => designer.value.printView()
// 导出 PDF
const exportPdf = () => designer.value.toPdf()
// 导出图片
const exportImage = () => designer.value.toImage()
// 直接打印(需客户端已连接)
const directPrint = () => designer.value.print()
// 连接控制与参数设置
const setHostToken = () => designer.value.setHiwebSocket('http://127.0.0.1:17521', 'token')
// 主动连接客户端
const connect = () => designer.value.connect()
// 断开客户端
const disconnect = () => designer.value.disconnect()
// 关闭自动连接策略
const disableAutoConnect = () => designer.value.disAutoConnect()
</script>API(FullDesigner)
属性(Props,含描述)
hi-host: string客户端服务地址;示例http://127.0.0.1:17521,用于直连打印hi-token: string客户端鉴权令牌;与客户端配置一致时方可直连打印hi-auto-connect: boolean是否自动连接客户端;默认true,为false时需手动调用connect()initial-template: object初始化模板 JSON;为空时使用内置示例模板initial-print-data: object | array初始化打印数据;支持对象或数组,运行时变更会即时生效default-lang: string默认语言;支持cn、en、de、es、fr、it、ja、ru、cn_tw;默认cnconfig: object设计器引擎配置;会在初始化前注入到hiprint.setConfig(config)(同时写入window.HIPRINT_CONFIG)。常用字段:showAdsorbLine: boolean是否显示吸附参考线(拖动/缩放时的对齐辅助线)showPosition: boolean是否显示元素坐标提示(移动元素时显示位置)showSizeBox: boolean是否显示元素尺寸提示框(缩放时显示宽高)adsorbMin: number吸附阈值(距离小于等于该值时触发吸附,单位:pt)adsorbLineMin: number吸附线阈值(参考线判定阈值,单位:pt)
design-options: object设计器 UI/行为配置(初始化时生效):grid: boolean是否显示网格线,默认trueactivePanel: boolean是否默认显示右侧属性面板,默认trueadaptToSize: boolean是否初始化时自动缩放以适配设计区可视范围,默认false
theme: string | object主题;支持内置主题名或传入自定义主题对象theme-list: Array<string | object>主题列表(用于顶部主题切换菜单),默认:light/dark/emerald/corporate/bumblebee/retro/cyberpunk/valentineshow-option: object区域显示控制(默认全部显示):showHeader: boolean是否显示顶部 Header,默认trueshowToolbar: boolean是否显示二级工具栏 Toolbar,默认trueshowFooter: boolean是否显示底部 Footer,默认true
footer-text: string底部默认文案(仅在未提供#footer插槽时展示)
以上属性支持运行时动态修改;组件内部已监听并应用。
示例(FullDesigner 直接传入 config / designOptions):
<template>
<FullDesigner
:config="{ showAdsorbLine: true, showPosition: true, showSizeBox: true }"
:design-options="{ grid: true, activePanel: true, adaptToSize: true }"
theme="light"
:show-option="{ showHeader: true, showToolbar: true, showFooter: true }"
footer-text="联系我:xxxx(这里可写联系信息)"
/>
</template>示例(主题切换:限制可选主题 + 自定义主题):
<template>
<FullDesigner
:theme-list="[
'light',
'dark',
{ name: '自定义1', colors: { accent: '#16a34a', headerBg: '#16a34a', toolbarBg: '#f0fdf4' } }
]"
:theme="{ name: '自定义1', colors: { accent: '#16a34a', headerBg: '#16a34a', toolbarBg: '#f0fdf4' } }"
/>
</template>自定义主题颜色字段说明(theme.colors):
accent: string主题强调色(影响:滚动条、选中态边框/高亮、部分 hover)accentSoft: string强调色浅背景(可选,建议rgba;用于选中态/hover 底色,默认由accent自动生成)headerBg: stringHeader/面板标题栏背景色(属性/结构/历史面板的标题栏也会使用)headerText: stringHeader/面板标题栏文字颜色toolbarBg: string二级工具栏背景色panelBg: string左侧模板面板背景色(不传则默认跟随toolbarBg)surfaceBg: string面板/弹窗主体背景色(属性/结构/历史面板、右键菜单等)text: string主文字颜色mutedText: string次级文字颜色(列表辅助信息、提示文字等)border: string边框/分割线颜色menuBg: string右键菜单背景色(可选,默认跟随surfaceBg)menuHoverBg: string菜单 hover 背景色(可选)footerBg: stringFooter 背景色(可选,默认跟随surfaceBg)footerText: stringFooter 文字颜色(可选,默认跟随mutedText)
示例(自定义 Footer 内容):
<template>
<FullDesigner :show-option="{ showFooter: true }">
<template #footer>
<div style="width:100%;display:flex;justify-content:space-between;">
<span>联系信息:xxx</span>
<span>QQ群:xxx</span>
</div>
</template>
</FullDesigner>
</template>方法(通过组件 ref 调用,含描述)
preView()打开预览弹窗;将当前模板与数据渲染为预览 HTMLprintView()浏览器打印;不依赖客户端,调起系统打印对话框print()直接打印;需客户端已连接,按当前选定打印机输出toPdf()导出 PDF;使用内置 A4 排版示例参数导出toPdf2()导出 PDF;支持自定义参数,如缩放比例、页边距等(通过@zumer/snapdom库插件)toImage()导出图片;使用内置 A4 排版示例参数导出toImage2()导出图片;支持自定义参数,如缩放比例、页边距等(通过@zumer/snapdom库插件)setHiwebSocket(host: string, token?: string, cb?: Function)设置客户端地址与令牌并尝试重连;cb(status, msg)为连接回调connect(cb?: Function)主动连接客户端;cb(status, msg)为连接回调disconnect()断开客户端连接disAutoConnect()关闭自动连接策略;阻止自动重连
事件(Emits,含描述)
save保存模板与数据;回调参数结构:
{
template, // 模板 JSON
data, // 当前打印数据(对象或数组)
templateId // 模板标识(若存在)
}示例:
<template>
<FullDesigner
:initial-template="tpl"
:initial-print-data="rows"
default-lang="cn"
@save="onSave"
/>
</template>
<script setup>
const onSave = ({ template, data, templateId }) => {
// 调用接口持久化到数据库
// await api.saveTemplate({ template, data, templateId })
}
</script>语言与国际化
- 通过
default-lang设置初始语言(cn默认为中文);内部会同步vue-i18n与hiprint的语言。 - 运行时可在页面右上角语言切换菜单切换(无需刷新)。
高级用法(hiprint)
本库导出 hiprint,可直接创建与操作模板对象(hiprint.PrintTemplate):
import { hiprint, defaultElementTypeProvider } from 'vg-print'
// 全局配置
hiprint.setConfig({ showAdsorbLine: true, showPosition: true, showSizeBox: true })
// 注册插件
hiprint.register({ authKey: '', plugins: [] })
// 初始化元素提供器 (默认元素提供器)
hiprint.init({
// providers: [new defaultElementTypeProvider()],
host: 'http://localhost:17521',
token: '',
lang: 'en'
})
// 创建模板对象
const tpl = new hiprint.PrintTemplate({ template: {} })
// 设计模板
tpl.design('#hiprint-printTemplate', { grid: true })
// 浏览器打印
tpl.print({ name: '示例' }, {}, {
callback: () => {
this.waitShowPrinter = false
},
})
// 直接打印(需客户端已连接)
tpl.print2({ name: '示例' }, {
printer: '', // 打印机名称
title: '打印预览pdf'
});
// 导出 PDF(内置示例参数)
//模式1: 小模版需要在一页中排列的话,增加增加页面宽高参数(想把多订单放在一页中排列)----小模板拼到大纸张(例如 A4)
tpl.toPdf(this.printDataVar, '打印预览pdf', {
paperWidth: 210,
paperHeight: 297,
scale: 2,
perPage: 6, // 每页模板数
leftOffset: -1, // 对齐偏移
topOffset: -1, // 对齐偏移
onProgress: (cur, total) => {
// 导出进度100%的时候关闭等待
if (cur === total) {
this.loading = false
}
console.log('toPdf 进度', Math.floor((cur/total)*100))
}
})
// 模式2:普通模板,导出预览全部页:
tpl.toPdf(this.printDataVar, '打印预览pdf', {
onProgress: (cur, total) => {
// 导出进度100%的时候关闭等待
if (cur === total) {
this.loading = false
}
}
});
// 这是使用@zumer/snapdom库插件导出PDF的示例,使用方式和toPdf一样
tpl.toPdf2(this.printDataVar, '打印预览pdf', {
onProgress: (cur, total) => {
// 导出进度100%的时候关闭等待
if (cur === total) {
this.loading = false
}
}
});
// 导出图片(内置示例参数)
// 导出为多张图片,每张合成 6 页,自动下载 JPEG
tpl.toImage(this.printDataVar, {
isDownload: true,
name: '图片名称',
limit: 0,
type: 'image/jpeg',
pixelRatio: 2,
quality: 0.8,
toType: 'url',
onProgress: (cur, total) => {
// 导出进度100%的时候关闭等待
if (cur === total) {
this.loading = false;
}
}
})
//按 A4 纸张排版导出(把小模板排到 A4):
tpl.toImage(this.printDataVar, {
paperWidth: 210,
paperHeight: 297,
limit: 6,
isDownload: true,
name: 'A4排版',
type: 'image/jpeg',
pixelRatio: 2,
onProgress: (cur, total) => {
console.log('toImage 进度', Math.floor((cur/total)*100))
// 导出进度100%的时候关闭等待
if (cur === total) {
this.loading = false
}
}
})
// 这是使用@zumer/snapdom库插件导出图片的示例,使用方式和oImage一样
tpl.toImage2(this.printDataVar, {
paperWidth: 210,
paperHeight: 297,
limit: 6,
isDownload: true,
name: 'A4排版',
type: 'image/jpeg',
pixelRatio: 2,
onProgress: (cur, total) => {
console.log('toImage 进度', Math.floor((cur/total)*100))
// 导出进度100%的时候关闭等待
if (cur === total) {
this.loading = false
}
}
})水印与授权行为说明:设计态与运行态分离。设计态不自动显示默认水印(由面板设置项决定);运行态按授权和面板内容合并控制。
轻量运行时 API(无需设计器 UI)
当你只想“拿模板 + 数据”直接做预览、浏览器打印、导出 PDF/图片或进行客户端直连打印,而不引入页面设计器时,使用以下 API:
import {
createTemplate,
getHtml,
printBrowser,
exportPdf,
exportPdf2,
exportImage,
exportImage2,
getPrinterList,
refreshPrinterList,
getAddress,
getClientInfo,
getClients,
ippPrint,
ippRequest,
setHiwebSocket,
connect,
disconnect,
isClientConnected,
clientGenerate
} from 'vg-print'
// 连接客户端(需要先启动客户端)
connect()
// 检查客户端是否已连接
console.log(isClientConnected())
// 1) 创建模板实例(可复用)
const tpl = createTemplate(tmplJson)
// 2) 生成预览 HTML,自行渲染到容器
const preview = async () => {
visible.value = true // 弹出框容器显示
await nextTick() // 等容器渲染出来
const tpl = createTemplate(tmplJson)
const html = getHtml(tpl, printData) // 始终为字符串
const container = document.getElementById('preview_content_custom') // 显示内容的div的id
if (!container) {
console.warn('预览容器不存在')
return
}
container.innerHTML = html
}
// 3) 浏览器打印(不需要客户端)
printBrowser(tpl, printData)
// 4) 导出 PDF
// 原生方法
exportPdf(tpl, printData, '打印预览pdf', {
paperWidth: 210,
paperHeight: 297,
scale: 2,
perPage: 6,
leftOffset:-1,
topOffset:-1,
onProgress: (cur: number, total: number) => {
console.log('toPdf 进度', Math.floor((cur/total)*100))
}
})
// 插件方法
exportPdf2(tpl, printData, '打印预览pdf', {
paperWidth: 210,
paperHeight: 297,
scale: 2,
perPage: 6,
leftOffset:-1,
topOffset:-1,
onProgress: (cur: number, total: number) => {
console.log('toPdf 进度', Math.floor((cur/total)*100))
}
})
// 原生方法
await exportImage(tpl, printData, {
isDownload: true,
name: '图片名称',
limit: 1,
type: 'image/jpeg',
pixelRatio: 2,
quality: 0.8,
toType: 'url',
useCORS: true, // 开启跨域支持
onProgress: (cur: number, total: number) => {
console.log('toImage 进度', Math.floor((cur/total)*100))
}
})
// 插件方法
exportImage2(tpl, printData, {
paperWidth: 210,
paperHeight: 297,
limit: 6,
isDownload: true,
name: 'A4排版',
type: 'image/jpeg',
pixelRatio: 2,
onProgress: (cur: number, total: number) => {
console.log('toImage 进度', Math.floor((cur/total)*100))
}
})
// 6) 客户端直连打印(需要本地客户端)
setHiwebSocket('http://127.0.0.1:17521', 'your-token') // 遵循 autoConnect 状态
// 或者使用标准 API(设置即连接)
// setHost('http://127.0.0.1:17521', 'your-token')
connect() // setHiwebSocket 且 autoConnect: false 时需要手动 connect
// 6.1) 获取打印机列表
// 方式 A: 异步获取 (推荐) - 会触发刷新并等待返回
const printers = await refreshPrinterList();
console.log('打印机列表 (Async):', printers);
// 方式 B: 回调获取
getPrinterList((list) => {
console.log('打印机列表 (Callback):', list)
})
// 方式 C: 同步获取 (需确保已连接且已缓存) 这种方式可用于在连接成功后,点击按钮获取打印机列表
const cachedList = getPrinterList()
// 6.2) 其他客户端信息获取
// 获取 MAC/IP
const address = await getAddress();
// 获取客户端信息
const clientInfo = await getClientInfo();
// 获取连接的客户端 socket 信息
const clients = await getClients();
// 6.3) IPP 打印与请求
// ippPrint({ ...options });
ippPrint(options, callback, connectedCallback);
// ippRequest({ ...options });
ippRequest(options, callback);
// 使用模板对象直接发起直连打印
tpl.print2(printData, { printer: printers?.[0]?.name || '' })
// 7) 客户端生成(返回客户端保存路径,便于上传到服务器)
const { pdfPath, imgPath } = await clientGenerate(tpl, printData, {
pdfName: 'reportPdf', // 不带后缀,内部自动生成 .pdf
imgName: 'reportJpg', // 不带后缀,内部自动生成 .jpg
timeout: 60000
})
// 例如:上传到后端
// await api.upload({ pdfPath, imgPath })
// 7) 断开连接
disconnect()导出 PDF(toPdf / exportPdf)
exportPdf(tpl, data, filename, options)本质调用的是模板实例的tpl.toPdf(data, filename, options);两者参数一致。
模式 A:普通导出(按模板自身纸张与分页)
- 特点:不传纸张宽高,导出结果与预览分页一致(每个
.hiprint-printPaper一页)。 - 适用:报告类、A4/A5 正常分页模板。
// 不传 paperWidth/paperHeight,使用模板的面板尺寸与分页配置
exportPdf(tpl, printData, '打印预览pdf', {
onProgress: (cur, total) => console.log('toPdf 进度', Math.floor((cur / total) * 100))
})
exportPdf2(tpl, printData, '打印预览pdf', {
onProgress: (cur, total) => console.log('toPdf 进度', Math.floor((cur / total) * 100))
})模式 B:排版导出(把小模板拼到大纸张,例如 A4)
- 特点:传入
paperWidth/paperHeight(mm)后,会进入“平铺排版导出”。 - 适用:小标签、小票、多订单合并到一张纸导出。
// 传入纸张尺寸与排版参数,将多个“标签模板”平铺到一张 A4
exportPdf(tpl, printData, '打印预览pdf', {
paperWidth: 210, // mm
paperHeight: 297, // mm
perPage: 6, // 每页放 6 个(不够的到下一页)
leftOffset: -1, // -1 表示水平居中;>=0 表示左边距 mm
topOffset: -1, // -1 表示垂直居中;>=0 表示上边距 mm
scale: 2, // 清晰度/性能权衡(也可用 pixelRatio)
onProgress: (cur, total) => console.log('toPdf 进度', Math.floor((cur / total) * 100))
})
exportPdf2(tpl, printData, '打印预览pdf', {
paperWidth: 210, // mm
paperHeight: 297, // mm
perPage: 6, // 每页放 6 个(不够的到下一页)
leftOffset: -1, // -1 表示水平居中;>=0 表示左边距 mm
topOffset: -1, // -1 表示垂直居中;>=0 表示上边距 mm
scale: 2, // 清晰度/性能权衡(也可用 pixelRatio)
onProgress: (cur, total) => console.log('toPdf 进度', Math.floor((cur / total) * 100))
})排版规则(重点:perPage=0/不传的行为)
- 传入了纸张宽高(
paperWidth/paperHeight或usePaperType: true)时:perPage > 0:强制“每页 N 个”,例如perPage: 6就会 6 个一页。perPage = 0或不传perPage:自动计算“一页能放几个放几个”(由纸张尺寸 + 标签尺寸 + 行列间距决定)。
- 没有传纸张宽高时:
- 默认导出与预览一致(通常“一个模板一页”)。
perPage在该模式下不生效(因为不做平铺排版)。
导出图片(toImage / exportImage)
exportImage(tpl, data, options)本质调用的是模板实例的tpl.toImage(data, options);两者参数一致。
模式 A:普通导出(按模板分页导出图片)
// 不传 paperWidth/paperHeight:按模板分页导出
// splitPages: true 表示“每页一张图片”(推荐:避免长图占用太大内存)
await exportImage(tpl, printData, {
isDownload: true,
name: '图片',
splitPages: true,
type: 'image/png', // 含二维码/条码建议 png;纯文字/照片可 jpeg
pixelRatio: 2,
quality: 0.8, // 仅 JPEG 有效(0-1)
toType: 'blob', // 推荐 blob(避免大 dataURL 阻塞)
onProgress: (cur, total) => console.log('toImage 进度', Math.floor((cur / total) * 100))
})合成长图(可选)
// limit: N 表示每 N 页合成一张“长图”;limit<=0 表示全部页合成一张(可能很大,不推荐)
await exportImage(tpl, printData, {
isDownload: true,
name: '长图',
limit: 6,
type: 'image/jpeg',
pixelRatio: 2,
quality: 0.85
})模式 B:排版导出(把小模板拼到大纸张,例如 A4)
// 传入纸张尺寸后,图片导出也会进入“平铺排版导出”
// 注意:在排版模式下 limit 的语义等同于 perPage(每张纸放几个标签)
await exportImage(tpl, printData, {
paperWidth: 210, // mm
paperHeight: 297, // mm
limit: 6, // 每张“纸”放 6 个(不够的到下一张)
isDownload: true,
name: 'A4排版',
splitPages: true, // 每张纸输出一张图片(文件名自动追加 -1/-2/...)
type: 'image/png',
pixelRatio: 2
})排版规则(重点:limit=0/不传的行为)
- 传入了纸张宽高(
paperWidth/paperHeight)时:limit > 0:强制“每张纸 N 个”(等同于 PDF 的perPage)。limit = 0或不传limit:自动计算“一张纸能放几个放几个”。
- 没有传纸张宽高时:
splitPages: true:每页一张图(推荐)。splitPages: false且limit > 0:每 N 页合成长图。splitPages: false且limit <= 0:所有页合成一张超长图(不推荐)。
参数说明(PDF/图片通用,含描述)
paperWidth、paperHeight:纸张尺寸(mm);传入后启用“排版导出”(小模板拼到大纸张)。usePaperType:PDF/图片可用;为true时按模板的paperType(如 A4)设置页面尺寸。scale/pixelRatio:渲染缩放;pixelRatio优先级高于scale。值越大越清晰,但越耗时/耗内存。perPage:PDF 排版模式每页模板数量;0/不传表示自动填充。limit:图片普通模式下用于“每 N 页合成长图”;图片排版模式下等同于“每张纸 N 个”;0/不传表示自动填充(排版模式)或全量合成(普通模式,谨慎)。splitPages:图片每页/每张纸输出一张(推荐)。type:图片格式;'image/jpeg'或'image/png'(二维码/条码建议 png)。quality:图片质量(0-1,仅 JPEG 有效)。toType:返回类型(不下载时);'url'或'blob'。isDownload:是否自动触发下载。name:文件名(图片会自动追加页码后缀)。leftOffset、topOffset:排版对齐偏移(mm);-1表示居中,>=0表示边距。onProgress(cur, total):导出进度回调;以cur/total计算百分比。forcePng(PDF):强制使用 PNG 写入 PDF(条码/二维码建议开启)。maxCanvasPixels:单页最大画布像素上限;导出卡顿/崩溃时可调小(例如2e7)。debugPerf:输出每页渲染耗时到控制台,便于定位慢点。
导入说明(含描述)
- 所有运行时 API 由库入口直接导出;无需另装
vue-plugin-hiprint - 如需自定义元素提供器,在调用前执行
hiprint.init({ providers: [...] });默认已初始化内置提供器
适用场景(含描述)
- 后台页面、弹窗、任务流:仅需“模板 + 数据”的预览/打印/导出能力
- 脚本或批量任务:结合
exportPdf/exportImage实现批量导出
注意事项
- 建议在
index.html注入print-lock.css,保证打印样式稳定 - 直接打印需配套客户端(Electron 或服务端),跨域部署需启用 HTTPS
- 若使用自定义
host/token,确保客户端配置一致且网络可达 - SSR 兼容:插件安装仅在浏览器环境执行(
typeof window !== 'undefined'),在 SSR 框架中引入不会因window未定义报错。
完整示例
<template>
<FullDesigner
:initial-template="tpl"
:initial-print-data="rows"
default-lang="cn"
:hi-host="host"
:hi-token="token"
:hi-auto-connect="true"
@save="onSave"
/>
<div style="margin-top: 12px;">
<el-input v-model="host" placeholder="客户端地址,如 http://127.0.0.1:17521" style="width: 360px; margin-right: 8px;" />
<el-input v-model="token" placeholder="鉴权令牌" style="width: 200px; margin-right: 8px;" />
<el-button type="primary" @click="applyHostToken">应用连接参数</el-button>
<el-button style="margin-left:8px;" @click="preview">预览</el-button>
<el-button style="margin-left:8px;" @click="printBrowser">浏览器打印</el-button>
</div>
</template>
<script setup>
import { ref } from 'vue'
// 模板(示例)
const tpl = {
panels: [
{
index: 0,
paperType: 'A4',
width: 210,
height: 297,
printElements: [
{
options: { left: 20, top: 20, title: '标题', field: 'title', fontSize: 18 },
printElementType: { type: 'text' }
},
{
options: { left: 20, top: 50, title: '姓名', field: 'name' },
printElementType: { type: 'text' }
}
]
}
]
}
// 数据(对象或数组均可)
const rows = [{ title: '病理图文报告', name: '东东' }]
// 连接参数
const host = ref('http://127.0.0.1:17521')
const token = ref('')
// 组件引用
const designer = ref(null)
const applyHostToken = () => {
// 设置客户端地址与令牌,并尝试重连
designer.value?.setHiwebSocket(host.value, token.value)
}
// 预览与浏览器打印
const preview = () => designer.value?.preView()
const printBrowser = () => designer.value?.printView()
// 保存事件:拿到模板与数据入库
const onSave = ({ template, data, templateId }) => {
// 持久化示例
// await api.save({ template, data, templateId })
console.log('save payload:', { template, data, templateId })
}
</script>