【EMR 编辑器 · PDF 导出详解】
为什么必须给字体 · 导出与上传 · 特殊字符 · HTML / 图片 / 长图导出
本篇只讲「输出文件」:PDF(重点)、HTML、图片与长图,以及最省事的上传方式。打印走《打印与续打详解》。
【一、必须先懂的一件事:字体】
90% 的导出问题都出在字体上,先讲透。屏幕上看到字,用的是操作系统里的字体(宋体、微软雅黑谁都有);但 PDF 文件要「自带字体」才能在任何机器上打开都一样——所以导出时必须提供字体文件本身(TTF / OTF),编辑器负责把它嵌入 PDF。
字体从哪来:用系统自带的(Windows 的 C:\Windows\Fonts\simsun.ttc 需转 ttf)或下载开源中文字体(思源宋体 / Noto Sans SC 等);
放在哪:放到自己网站的静态目录(如 /fonts/SimSun.ttf),导出时传 URL;或程序读成 ArrayBuffer 传入;
用完整版字体:精简 / 子集化的字体缺字形——℃、≥、±、× 这些符号在屏显正常(浏览器自动兜底),PDF 里就会缺字或乱码;
性能建议:字体文件几 MB 到二十几 MB,建议预加载并用 IndexedDB 缓存字节,避免每次导出重复下载;URL 字体注意 CORS。
【二、导出 PDF:完整示例】
三端调用方式一致(React / Vue 用 ref,HTML 用实例)。导出的是矢量 PDF:文字可选中、可搜索、可复制;样式 = 预览模式(数据域标记色不会出现);水印、背景图、页眉页脚都会包含:
const bytes: Uint8Array = await api.exportPDF({
fonts: {
regular: '/fonts/SimSun.ttf', // 必填:常规体
bold: '/fonts/SimHei.ttf', // 可选:粗体(缺省复用regular)
italic: ..., boldItalic: ..., // 可选:斜体/粗斜体
byFamily: { '楷体': '/fonts/KaiTi.ttf' }, // 可选:按字体族嵌入
fallback: '/fonts/NotoSansSC.ttf', // 可选:兜底符号字体
},
metadata: { title: '入院记录', author: '张医生(1001)',
subject: '...', keywords: ['病历'] }, // 文档属性
});
// bytes 是文件字节:触发浏览器下载
const url = URL.createObjectURL(new Blob([bytes], { type: 'application/pdf' }));
byFamily:正文某段文字设了「楷体」时,导出才会用对应字体文件渲染该段;
fallback:✓ ✔ ⚠ ❤ 等符号常不在中文字体内,屏显靠系统兜底、PDF 不会——配置符号覆盖广的字体可救;
metadata.author 未指定时默认写当前登录用户「姓名(工号)」(user prop);
内置工具栏「文件 → 导出 PDF」按钮需要在 toolbar.pdfFonts 配置字体(同结构),否则按钮禁用;
导出前内部自动同步布局——不需要等渲染完成,改完文档立刻导也是新内容。
【三、最省事的上传:直接拿 File】
「导出再上传」是高频组合,编辑器提供四个一步到位的方法,返回值直接是 File,塞进 FormData 就能发:
方法
返回
getJSONFile('入院记录.json')
文档 JSON 文件(同步)
getPDFFile({ fonts }, '入院记录.pdf')
PDF 文件(options 同 exportPDF,fonts 必填)
getImageFiles({ scale: 2 }, '病历')
每页一张图片 File[](多页自动 _第N页 后缀)
getLongImageFiles()
长图 File[](多页垂直拼接;超 canvas 上限自动分段)
const form = new FormData();
form.append('pdf', await api.getPDFFile({ fonts }, '入院记录.pdf'));
form.append('json', api.getJSONFile('入院记录.json'));
await fetch('/api/emr/upload', { method: 'POST', body: form });
文件名可选:缺省自动命名(文档_日期.json / 电子病历_日期.pdf / 电子病历_日期_第N页.png 等)。
【四、HTML 导出】
const html = api.exportHTML({ title: '入院记录' }); // 完整独立 HTML 字符串
导出语义化标签 + 内嵌样式的单文件 HTML(含水印与背景图,可选项关闭);页码 {total} 占位符自动按当前页数填充。适合在线预览页、邮件正文等场景——不依赖编辑器即可打开。
【五、图片与长图导出】
const blobs = await api.exportImages({
pages: [0, 2], // 页号(0-based),缺省全部
scale: 2, // 清晰度倍率,打印建议 2-3
format: 'png', // 或 'jpeg'(更小、无透明)
quality: 0.92, // jpeg 质量
merge: false, // true = 拼接成长图
onPage: (b, i) => {...}, // 每页就绪回调(渐进上传)
}); // Blob[],与页序一致
长图注意:浏览器对 canvas 物理高度有上限(Firefox 32767px / Chrome 65535px),页数过多时 merge 会自动分段为多张,保证图片能正常打开。
【六、免费版导出限制】
未激活授权:2 页以内文档导出完全免费;超过 2 页时 exportPDF / getPDFFile 抛出中文错误提示、打印同理;
激活(license prop 或 setLicense)后解除全部限制;授权说明见《下载与授权说明》。