diff --git a/backend/services/planting-service/src/infrastructure/pdf/pdf-generator.service.ts b/backend/services/planting-service/src/infrastructure/pdf/pdf-generator.service.ts index e67c2895..54b6bb1c 100644 --- a/backend/services/planting-service/src/infrastructure/pdf/pdf-generator.service.ts +++ b/backend/services/planting-service/src/infrastructure/pdf/pdf-generator.service.ts @@ -383,41 +383,48 @@ export class PdfGeneratorService { const form = pdfDoc.getForm(); const signatureButton = form.getButton(FORM_FIELDS.SIGNATURE); - // 获取按钮的 widget 和位置 + // 获取按钮的 widget 和尺寸 const widgets = signatureButton.acroField.getWidgets(); if (widgets.length > 0) { const widget = widgets[0]; const rect = widget.getRectangle(); + const { width: fieldWidth, height: fieldHeight } = rect; - // 获取签名图片原始尺寸 + // 计算图片缩放尺寸(保持宽高比,适应字段大小) const imgDims = signatureImage.scale(1); - - // 按字段尺寸等比例缩放签名图片 - // 计算宽度和高度的缩放比例,取较小值以确保签名完全在字段内 - const scaleX = rect.width / imgDims.width; - const scaleY = rect.height / imgDims.height; - const scale = Math.min(scaleX, scaleY); - + const scale = Math.min(fieldWidth / imgDims.width, fieldHeight / imgDims.height); const scaledWidth = imgDims.width * scale; const scaledHeight = imgDims.height * scale; - // 在字段内居中放置签名 - const offsetX = (rect.width - scaledWidth) / 2; - const offsetY = (rect.height - scaledHeight) / 2; + // 计算居中位置 + const x = (fieldWidth - scaledWidth) / 2; + const y = (fieldHeight - scaledHeight) / 2; - // 获取按钮所在的页面 - const pages = pdfDoc.getPages(); - const page = pages[5]; // 第6页(签名区域) + // 创建外观流内容 + const appearanceStream = `q ${scaledWidth} 0 0 ${scaledHeight} ${x} ${y} cm /Img Do Q`; - // 在按钮位置绘制缩放后的签名图片(居中) - page.drawImage(signatureImage, { - x: rect.x + offsetX, - y: rect.y + offsetY, - width: scaledWidth, - height: scaledHeight, + // 创建 XObject Form 作为外观 + const context = pdfDoc.context; + const imageXObjectName = 'Img'; + + const Resources = context.obj({ + XObject: { [imageXObjectName]: signatureImage.ref }, }); - this.logger.log(`Signature embedded at (${rect.x + offsetX}, ${rect.y + offsetY}) with size ${scaledWidth}x${scaledHeight}, field size: ${rect.width}x${rect.height}`); + const appearanceStreamRef = context.register( + context.stream(appearanceStream, { + Type: 'XObject', + Subtype: 'Form', + FormType: 1, + BBox: [0, 0, fieldWidth, fieldHeight], + Resources, + }), + ); + + // 设置外观到 widget + widget.setNormalAppearance(appearanceStreamRef); + + this.logger.log(`Signature embedded using custom appearance stream, field size: ${fieldWidth}x${fieldHeight}`); } else { throw new Error('No widgets found for signature button'); }