Frappe(ERPNext)框架下销售发票二维码显示与打印问题咨询
解决方案
问题1:ERPNext预存渲染后的二维码方案(优先推荐)
该方案完全规避前端渲染的兼容性问题,表单、打印场景都可直接调用,无需重复生成二维码。
操作步骤:
- 进入自定义DocType编辑页,给「销售发票(Sales Invoice)」新增一个类型为
Image的自定义字段,字段API名可设为custom_qr_image,权限设为只读,可隐藏在非必要视图中。 - 服务端安装Python二维码生成依赖:
pip install qrcode[pil] - 在自定义APP的Sales Invoice控制器钩子中加入生成逻辑,示例代码如下:
import qrcode import io import frappe from frappe.model.document import Document class SalesInvoice(Document): def before_save(self): # 替换为你需要编码进二维码的业务字符串 qr_encode_value = f"INVOICE|{self.name}|{self.grand_total}|{self.posting_date}" # 生成二维码对象 qr_img = qrcode.make(qr_encode_value) # 转PNG字节流 img_byte_io = io.BytesIO() qr_img.save(img_byte_io, format="PNG") img_content = img_byte_io.getvalue() qr_file_name = f"qr_sales_invoice_{self.name}.png" # 删除历史旧二维码文件 frappe.db.delete("File", { "attached_to_doctype": "Sales Invoice", "attached_to_name": self.name, "file_name": qr_file_name }) # 写入新二维码到File文档 qr_file = frappe.get_doc({ "doctype": "File", "file_name": qr_file_name, "attached_to_doctype": "Sales Invoice", "attached_to_name": self.name, "content": img_content, "is_private": 0 # 设为公开可避免打印时权限校验问题 }) qr_file.save(ignore_permissions=True) # 关联到自定义图片字段 self.custom_qr_image = qr_file.file_url
- 打印格式中直接拖入
custom_qr_image字段即可正常显示二维码,无需额外逻辑。
问题2:不预存图片,打印页渲染二维码方案
如果不需要持久化存储二维码,可通过自定义打印格式实现渲染:
操作步骤:
- 提前将QRious库的JS文件上传到ERPNext站点的
public/js目录下。 - 进入「打印格式(Print Format)」新建页面,选择销售发票DocType,类型选「HTML」。
- 在打印格式模板中写入如下代码:
<!-- 二维码渲染容器 --> <canvas id="qr_code_container" width="200" height="200"></canvas> <!-- 引入本地QRious库 --> <script src="/js/qrious.min.js"></script> <script> // 页面加载完成后渲染二维码 document.addEventListener("DOMContentLoaded", () => { new QRious({ element: document.getElementById("qr_code_container"), size: 200, // 替换为你存储编码字符串的自定义字段API名,Jinja会直接渲染当前发票的对应值 value: "{{ doc.custom_qr_encode_str }}", foreground: "black" }) }) </script>
如果使用系统标准打印格式,也可以在销售发票的客户端脚本中监听before_print钩子,提前生成二维码base64写入自定义HTML字段后再触发打印。
内容的提问来源于stack exchange,提问作者Taimur
相关产品推荐
相关产品推荐

