fix(signing-pdf): 修复导出 PDF 丢失 flex 容器内容

This commit is contained in:
yelan
2026-09-18 15:57:29 +08:00
parent 11fe83d807
commit 6034f4f8e2
+43 -1
View File
@@ -7,7 +7,9 @@
* 直接截图既截不全、版面也会跟着变;
* ② 固定页眉在每页重复:页眉是系统按 HIS 数据渲染的,服务端生成 PDF 时同样要按页重复;
* ③ 页码只写 "1 / 2" 这类 ASCII:jsPDF 内置字体不含中文,
* 画中文页码需要内嵌字体(体积会明显变大),这一步留给服务端用真字体实现。
* 画中文页码需要内嵌字体(体积会明显变大),这一步留给服务端用真字体实现;
* ④ 导出前对 flex 容器做一次兼容降级:html2canvas 不实现 flex 布局,
* 填写项胶囊里的文字、输入框取值、签名图会被整块丢掉,见 applyExportFlexFallback。
*
* 输出为位图 PDF:文本不可选中,仅供原型演示;正式文书以服务端生成的 PDF 为准。
*/
@@ -36,6 +38,44 @@ export interface SigningPdfInput {
fileName: string
}
/**
* html2canvas 兼容处理:flex 容器里的文字与控件取值会被整块丢掉。
*
* 实测(签署工作台导出的 PDF,html2canvas 1.4):页面上明明印着「与患者关系:文本框 配偶」、
* 签名图也画出来了,导出的位图里这些却全是空白,只剩胶囊的边框和底色——
* 填写项胶囊 `.sign-field` 与控件容器 `.sign-field__control` 都是 `display: inline-flex`,
* 而 html2canvas 1.4 不实现 flex 布局,容器内文本的落点算不出来,
* 于是连同 `<input>` 的取值、签名 `<img>` 一起被丢掉(连 `<p>` 里的「待签名」提示也不见了)。
*
* 换成 `inline-block` 后内容全部回来,于是这里把这两层降级。**只在导出克隆体上改**:
* 屏幕上的版式一行不动,PDF 也不会丢内容;`.sign-doc-header` 那层 flex 实测不受影响,不动它。
*
* gap 在 inline-block 下失效,所以把原来的 4px 项间距、align-items: center、
* 签名位的 justify-content: center 用等效的 inline 写法补回来,导出结果与屏幕观感一致。
*/
function applyExportFlexFallback(root: HTMLElement) {
root.querySelectorAll<HTMLElement>('.sign-field, .sign-field__control').forEach((element) => {
element.style.display = 'inline-block'
})
// 胶囊原来是 inline-flex + gap: 4px,项名与控件之间的间距要自己补
root.querySelectorAll<HTMLElement>('.sign-field__label').forEach((element) => {
element.style.marginRight = '4px'
})
root.querySelectorAll<HTMLElement>('.sign-field__control').forEach((element) => {
// 原来是 align-items: center
element.style.verticalAlign = 'middle'
})
// 签名位原来是 justify-content: center,inline-block 下改用 text-align 居中
root
.querySelectorAll<HTMLElement>('.sign-field--signature .sign-field__control')
.forEach((element) => {
element.style.textAlign = 'center'
})
}
/** 量固定页眉的高度(含下外边距)——它是每页要重复的那一条 */
function measureHeaderHeight(element: HTMLElement) {
const header = element.querySelector<HTMLElement>('.sign-doc-header')
@@ -68,6 +108,8 @@ export async function createSigningPdf(input: SigningPdfInput): Promise<Blob> {
useCORS: true,
logging: false,
onclone: (clonedDocument, clonedElement) => {
applyExportFlexFallback(clonedElement)
clonedElement.style.width = `${CAPTURE_WIDTH_PX}px`
clonedElement.style.height = 'auto'
clonedElement.style.maxHeight = 'none'