使用Flutter的pdf与sunmi_printer_plus插件在Sunmi设备打印发票遇问题求助
问题描述
我使用 pdf: ^3.10.4 生成了发票PDF,希望通过 sunmi_printer_plus: ^2.1.01 在Sunmi设备上打印该发票。尝试将PDF转为图片打印时,发票输出效果异常。
PDF生成代码
class PdfInvoiceApi { static Future<Document> generate( Pump_Transactions pump) async { final pdf = Document(); final font= await rootBundle.load("lib/fonts/HacenTunisia.ttf"); final ttf= Font.ttf(font); double fontSize10=12; double fontSize12=14; pdf.addPage(Page( theme: ThemeData.withFont( base: ttf, ), pageFormat: PdfPageFormat.roll80, build: (Context context) { return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.end, children: [ Divider(), if(pump.name != null && pump.name!.length>0) Directionality( textDirection: TextDirection.rtl, child: Center( child: Text( 'فاتورة ضريبية ', style: TextStyle( fontSize: fontSize12, )) ) ), if(pump.name == null || pump.name!.isEmpty) Directionality( textDirection: TextDirection.rtl, child: Center( child: Text( 'فاتورة ضريبية مبسطة ', style: TextStyle( fontSize: fontSize12, )) ) ), Directionality( textDirection: TextDirection.rtl, child: Center( child: Text( CompanyData.companyData!.name!, style: TextStyle( fontSize: fontSize12, )) ) ), Directionality( textDirection: TextDirection.rtl, child: Center( child: Text( 'رقم ضريبى : '+CompanyData.companyData!.taxNumber!, style: TextStyle( fontSize: fontSize12, )) ) ), Divider(), Directionality( textDirection: TextDirection.rtl, child: Text( 'رقم الفاتورة :'+ pump.bill!.transaction!.toString(), style: TextStyle( fontSize: fontSize10, ) ) ), Directionality( textDirection: TextDirection.rtl, child: Text( 'التاريخ :'+ pump.bill!.dateTime!, style: TextStyle( fontSize: fontSize10, ) ) ), Directionality( textDirection: TextDirection.rtl, child: Text( 'العنوان :'+CompanyData.companyData!.address!, style: TextStyle( fontSize: fontSize10, ) ) ), Directionality( textDirection: TextDirection.rtl, child: Text( 'الفرع :'+CompanyData.companyData!.branch!, style: TextStyle( fontSize: fontSize10, ) ) ), Divider(), if(pump.name != null && pump.name!.length>0) Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment:CrossAxisAlignment.end , children: [ Directionality( textDirection: TextDirection.rtl, child: Text( 'اسم العميل :'+ pump.name!.toString(), style: TextStyle( fontSize: fontSize10, ) ) ), Directionality( textDirection: TextDirection.rtl, child: Text( 'العنوان :'+ pump.address!, style: TextStyle( fontSize: fontSize10, ) ) ), Directionality( textDirection: TextDirection.rtl, child: Text( 'الرقم الضريبي :'+pump.tax_number!, style: TextStyle( fontSize: fontSize10, ) ) ), Divider(), ] ), Container( // margin: EdgeInsets.fromLTRB(22, 5, 22, 5), child: Directionality( textDirection: TextDirection.rtl, child: Table.fromTextArray( headerStyle: TextStyle( fontSize: 12 ), headers: <dynamic>['الإجمالي', 'السعر' ,'الكمية باللتر ', 'الصنف'], cellAlignment: Alignment.center, cellStyle: TextStyle( fontSize: 12 ), data: <List<dynamic>>[ <dynamic>[pump.bill!.amount!.toStringAsFixed(2), pump.bill!.price!.toStringAsFixed(2) ,pump.bill!.volume, pump.bill!.productName ], ], ), ), ), Divider(), Directionality( textDirection: TextDirection.rtl, child: Text('الإجمالي : '+pump.bill!.amount!.toStringAsFixed(2)+" ريال ", style: TextStyle( fontSize: fontSize10, ) ) ), Divider(), Directionality( textDirection: TextDirection.rtl, child: Text('الضريبة : '+(CompanyData.companyData!.tax!*100).toStringAsFixed(0)+"% "+ ( pump.bill!.amount!- (pump.bill!.amount! / (1 + CompanyData.companyData!.tax!))).toStringAsFixed(2)+" ريال ", style: TextStyle( fontSize: fontSize10, ) ), ), Divider(), Center( child: BarcodeWidget( data: pump.qr!, barcode: Barcode.qrCode(), // width: 200, height: 150 ), ), SizedBox(height: 15.0) ] ) ; } )); return pdf; } }
尝试的打印代码
方案1(输出效果异常)
final pdfFile = await PdfInvoiceApi.generate(pump); Uint8List bytes=await pdfFile.save(); await SunmiPrinter.bindingPrinter(); await SunmiPrinter.initPrinter(); await SunmiPrinter.startTransactionPrint(true); await SunmiPrinter.setAlignment(SunmiPrintAlign.CENTER); await SunmiPrinter.printImage(bytes!); await SunmiPrinter.lineWrap(10); await SunmiPrinter.submitTransactionPrint(); await SunmiPrinter.exitTransactionPrint(true);
方案2(无输出)
final pdfFile = await PdfInvoiceApi.generate(pump); await for (var page in Printing.raster(await pdfFile.save(), pages: [0, 1], dpi: 72)) { final image = await page.toPng(); bytes=image; await SunmiPrinter.bindingPrinter(); await SunmiPrinter.initPrinter(); await SunmiPrinter.startTransactionPrint(true); await SunmiPrinter.setAlignment(SunmiPrintAlign.CENTER); await SunmiPrinter.printImage(bytes!); await SunmiPrinter.lineWrap(10); await SunmiPrinter.submitTransactionPrint(); await SunmiPrinter.exitTransactionPrint(true); }
解决方案
1. 优化PDF转图片参数,适配Sunmi打印机分辨率
Sunmi小票打印机默认分辨率为203DPI,80mm纸宽对应像素宽度约为576。转图时需匹配该参数,避免变形:
final pdfBytes = await pdfFile.save(); // 仅打印第一页,适配打印机分辨率和纸宽 await for (var page in Printing.raster(pdfBytes, pages: [0], dpi: 203, width: 576)) { final imageBytes = await page.toPng(); // 简化打印流程 await SunmiPrinter.bindingPrinter(); await SunmiPrinter.initPrinter(); await SunmiPrinter.setAlignment(SunmiPrintAlign.CENTER); await SunmiPrinter.printImage(imageBytes); await SunmiPrinter.lineWrap(2); }
2. 跳过PDF生成,直接用Sunmi API构建打印内容(推荐)
转图片打印易出现模糊、排版问题,直接调用打印机API拼接内容更可靠:
await SunmiPrinter.bindingPrinter(); await SunmiPrinter.initPrinter(); // 打印标题 await SunmiPrinter.setAlignment(SunmiPrintAlign.CENTER); await SunmiPrinter.setFontSize(16); if(pump.name != null && pump.name!.length>0) { await SunmiPrinter.printText('فاتورة ضريبية'); } else { await SunmiPrinter.printText('فاتورة ضريبية مبسطة'); } await SunmiPrinter.printText(CompanyData.companyData!.name!); await SunmiPrinter.printText('رقم ضريبى : ${CompanyData.companyData!.taxNumber!}'); await SunmiPrinter.printLine(); // 打印发票基础信息 await SunmiPrinter.setFontSize(12); await SunmiPrinter.setAlignment(SunmiPrintAlign.RIGHT); await SunmiPrinter.printText('رقم الفاتورة : ${pump.bill!.transaction!}'); await SunmiPrinter.printText('التاريخ : ${pump.bill!.dateTime!}'); await SunmiPrinter.printText('العنوان : ${CompanyData.companyData!.address!}'); await SunmiPrinter.printText('الفرع : ${CompanyData.companyData!.branch!}'); await SunmiPrinter.printLine(); // 打印客户信息(如有) if(pump.name != null && pump.name!.length>0) { await SunmiPrinter.printText('اسم العميل : ${pump.name!}'); await SunmiPrinter.printText('العنوان : ${pump.address!}'); await SunmiPrinter.printText('الرقم الضريبي : ${pump.tax_number!}'); await SunmiPrinter.printLine(); } // 打印商品表格 await SunmiPrinter.setAlignment(SunmiPrintAlign.CENTER); await SunmiPrinter.printColumnsText( texts: ['الصنف', 'الكمية باللتر', 'السعر', 'الإجمالي'], columnWidths: [3, 2, 2, 2], columnAlignments: [SunmiPrintAlign.CENTER, SunmiPrintAlign.CENTER, SunmiPrintAlign.CENTER, SunmiPrintAlign.CENTER], ); await SunmiPrinter.printLine(); await SunmiPrinter.printColumnsText( texts: [ pump.bill!.productName!, pump.bill!.volume.toString(), pump.bill!.price!.toStringAsFixed(2), pump.bill!.amount!.toStringAsFixed(2) ], columnWidths: [3, 2, 2, 2], columnAlignments: [SunmiPrintAlign.CENTER, SunmiPrintAlign.CENTER, SunmiPrintAlign.CENTER, SunmiPrintAlign.CENTER], ); await SunmiPrinter.printLine(); // 打印总计与税费 await SunmiPrinter.setAlignment(SunmiPrintAlign.RIGHT); await SunmiPrinter.printText('الإجمالي : ${pump.bill!.amount!.toStringAsFixed(2)} ريال'); await SunmiPrinter.printLine(); final taxRate = (CompanyData.companyData!.tax! * 100).toStringAsFixed(0); final taxAmount = (pump.bill!.amount! - (pump.bill!.amount! / (1 + CompanyData.companyData!.tax!))).toStringAsFixed(2); await SunmiPrinter.printText('الضريبة : $taxRate% $taxAmount ريال'); await SunmiPrinter.printLine(); // 打印二维码 await SunmiPrinter.setAlignment(SunmiPrintAlign.CENTER); await SunmiPrinter.printQRCode(pump.qr!, size: 150); await SunmiPrinter.lineWrap(2);
3. 检查字体兼容性
确保HacenTunisia.ttf字体能被打印机正确识别,若转图后字体模糊,可在PDF生成时增大字号,或更换为Sunmi设备内置的阿拉伯字体。
内容的提问来源于stack exchange,提问作者raito tec
相关产品推荐
相关产品推荐

