@@ -660,7 +660,8 @@ const _orderHeaders = [
' 商品编号 ' , ' 商品名称 ' , ' 系列 ' , ' 规格 ' , ' 批次号 ' ,
' 生产日期 ' , ' 数量 ' , ' 单价 ' , ' 金额 ' , ' 备注 ' ,
] ;
const _orderColFlex = < double > [ 1.5 , 2.0 , 1.1 , 1.3 , 1.6 , 1.3 , 0.7 , 1.1 , 1.2 , 0.9 ] ;
// 针打版式列宽:日期 / 单价 / 金额 加宽,避免大字号下数字、日期断行。
const _orderColFlex = < double > [ 1.4 , 1.8 , 1.0 , 1.2 , 1.6 , 1.45 , 0.7 , 1.45 , 1.45 , 0.7 ] ;
/// 温馨提示文案(入库/出库统一)。
const _kTipsText =
@@ -686,7 +687,7 @@ pw.TextAlign _colAlign(int i) {
/// 构建入库单/出库单 A4 版式(参照「锐浪报表」单据:公司抬头 + 两行三列表头
/// + 明细表 + 单据总计 + 温馨提示 + 签字行)。入库/出库仅称谓不同。
pw . Widget _buildOrderDoc ( {
List < pw . Widget > _buildOrderDoc ( {
required pw . Font font ,
required pw . Font bold ,
required String shopName , // 公司名称(顶部抬头)
@@ -709,30 +710,31 @@ pw.Widget _buildOrderDoc({
required double totalQty ,
required double totalAmt ,
} ) {
// 样式三「紧凑报表」:左侧竖线点缀 + 抬头左对齐内联 + 灰底信息条 + 密集明细表
// + 数字等宽(内置 Courier,ASCII 数字适用)+ 灰底总计条。
final mono = pw . Font . courier ( ) ;
// 针打友好版式:全纯黑、无灰底纹、纯黑实线边框、字号加大。
// 针式打印机打不出灰色(只能抖成稀疏散点→淡而糊),且小号汉字笔画易糊;
// 故正文加粗(重击更黑)、字号上调、所有灰色一律改纯黑。
// 数字等宽(内置 Courier, ASCII 数字适用)。
final mono = pw . Font . courierBold ( ) ;
final monoBold = pw . Font . courierBold ( ) ;
final cellStyle = pw . TextStyle ( font: font , fontSize: 8.5 ) ;
final numStyle = pw . TextStyle ( font: mono , fontSize: 8.5 ) ;
final cellStyle = pw . TextStyle (
font: bold , fontSize: 9 , fontWeight: pw . FontWeight . bold ) ;
final numStyle = pw . TextStyle ( font: mono , fontSize: 9 ) ;
final headStyle =
pw . TextStyle ( font: bold , fontSize: 8.5 , fontWeight: pw . FontWeight . bold ) ;
final metaStyle = pw . TextStyle ( font: font , fontSize: 9 ) ;
pw . TextStyle ( font: bold , fontSize: 9.5 , fontWeight: pw . FontWeight . bold ) ;
final metaStyle = pw . TextStyle (
font: bold , fontSize: 10 , fontWeight: pw . FontWeight . bold ) ;
final metaBold =
pw . TextStyle ( font: bold , fontSize: 9 , fontWeight: pw . FontWeight . bold ) ;
pw . TextStyle ( font: bold , fontSize: 10.5 , fontWeight: pw . FontWeight . bold ) ;
pw . Widget metaText ( String label , String value , pw . TextAlign align ) = >
pw . Text ( ' $ label : $ value ' , style: metaStyle , textAlign: align ) ;
return pw . Container (
// 左侧竖线点缀
decoration: const pw . BoxDecoration (
border: pw . Border ( left: pw . BorderSide ( color: PdfColors . black , width: 3 ) ) ,
) ,
padding: const pw . EdgeInsets . only ( left: 14 ) ,
child: pw . Column (
crossAxisAlignment: pw . CrossAxisAlignment . stretch ,
children: [
// 返回明细块的「子组件列表」而非单个 Container:作为 MultiPage 的顶层
// children,明细表可跨页拆分。左侧竖线点缀改由 pageTheme 背景每页绘制
// (见 _orderPageTheme)——原先用非可拆分的 pw.Container 包裹整块内容,
// 当内容超过一页时 MultiPage 无法拆分,分页算法不前进→无限加页、内存暴涨
// →打印卡死(根因)。
return [
// ── 抬头:公司名 + 单据类型,左对齐内联 ──────────────────────────
pw . Row (
crossAxisAlignment: pw . CrossAxisAlignment . end ,
@@ -745,10 +747,11 @@ pw.Widget _buildOrderDoc({
padding: const pw . EdgeInsets . only ( bottom: 1.5 ) ,
child: pw . Text ( title ,
style: pw . TextStyle (
font: font ,
fontSize: 11 ,
font: bold ,
fontSize: 12 ,
fontWeight: pw . FontWeight . bold ,
letterSpacing: 3 ,
color: PdfColors . grey700 ) ) ,
color: PdfColors . black ) ) ,
) ,
] ,
) ,
@@ -756,8 +759,7 @@ pw.Widget _buildOrderDoc({
// ── 抬头信息:灰底信息条(两行三列)────────────────────────────
pw . Container (
decoration: pw . BoxDecoration (
color: PdfColors . grey100 ,
border: pw . Border . all ( color: PdfColors . grey400 , width: 0.5 ) ,
border: pw . Border . all ( color: PdfColors . black , width: 0.8 ) ,
) ,
padding: const pw . EdgeInsets . symmetric ( horizontal: 8 , vertical: 6 ) ,
child: pw . Column (
@@ -799,14 +801,13 @@ pw.Widget _buildOrderDoc({
pw . SizedBox ( height: 8 ) ,
// ── 明细表(密集、灰底表头、数字等宽)──────────────────────────
pw . Table (
border: pw . TableBorder . all ( color: PdfColors . grey500 , width: 0.5 ) ,
border: pw . TableBorder . all ( color: PdfColors . black , width: 0.8 ) ,
columnWidths: {
for ( var i = 0 ; i < _orderColFlex . length ; i + + )
i: pw . FlexColumnWidth ( _orderColFlex [ i ] )
} ,
children: [
pw . TableRow (
decoration: const pw . BoxDecoration ( color: PdfColors . grey300 ) ,
children: [
for ( final h in _orderHeaders )
pw . Padding (
@@ -837,8 +838,7 @@ pw.Widget _buildOrderDoc({
pw . Container (
width: double . infinity ,
decoration: pw . BoxDecoration (
color: PdfColors . grey100 ,
border: pw . Border . all ( color: PdfColors . grey400 , width: 0.5 ) ,
border: pw . Border . all ( color: PdfColors . black , width: 0.8 ) ,
) ,
padding: const pw . EdgeInsets . symmetric ( horizontal: 10 , vertical: 5 ) ,
child: pw . Row (
@@ -863,13 +863,15 @@ pw.Widget _buildOrderDoc({
pw . Container (
width: double . infinity ,
decoration: pw . BoxDecoration (
border: pw . Border . all ( color: PdfColors . grey400 , width: 0.5 ) ,
color: PdfColors . grey50 ,
border: pw . Border . all ( color: PdfColors . black , width: 0.8 ) ,
) ,
padding: const pw . EdgeInsets . all ( 5 ) ,
child: pw . Text ( _kTipsText ,
style: pw . TextStyle (
font: font , fontSize: 8.5 , color: PdfColors . grey800 ) ) ,
font: bold ,
fontSize: 9 ,
fontWeight: pw . FontWeight . bold ,
color: PdfColors . black ) ) ,
) ,
] ,
pw . SizedBox ( height: 24 ) ,
@@ -887,11 +889,40 @@ pw.Widget _buildOrderDoc({
pw . SizedBox ( height: 10 ) ,
pw . Text ( ' 备注: $ remark ' , style: metaStyle ) ,
] ,
] ,
) ,
) ;
] ;
}
/// 出/入库单 MultiPage 页面主题:内容区左缩进 + 全页高左侧竖线点缀(每页都画)。
/// 用 pageTheme 背景绘制竖线,让明细内容(含表格)可跨页拆分,避免非可拆分
/// Container 在内容超一页时触发 MultiPage 分页死循环。
pw . PageTheme _orderPageTheme ( ) = > pw . PageTheme (
pageFormat: PdfPageFormat . a4 ,
// 左边距 = 原始外边距 15mm + (竖线宽 3 + 内缩 14),与旧版视觉缩进一致。
margin: const pw . EdgeInsets . fromLTRB (
15 * PdfPageFormat . mm + 17 ,
12 * PdfPageFormat . mm ,
15 * PdfPageFormat . mm ,
12 * PdfPageFormat . mm ,
) ,
buildBackground: ( ctx ) = > pw . FullPage (
ignoreMargins: true ,
child: pw . Padding (
padding: const pw . EdgeInsets . fromLTRB (
15 * PdfPageFormat . mm ,
12 * PdfPageFormat . mm ,
0 ,
12 * PdfPageFormat . mm ,
) ,
child: pw . Container (
decoration: const pw . BoxDecoration (
border: pw . Border (
left: pw . BorderSide ( color: PdfColors . black , width: 3 ) ) ,
) ,
) ,
) ,
) ,
) ;
/// 生成入库单 A4 PDF 字节(与实际打印同一套排版,供预览光栅化 + 打印共用)。
Future < Uint8List > buildStockInOrderPdfImpl (
StockInOrder order , OrderPrintMeta meta ) async {
@@ -919,10 +950,8 @@ Future<Uint8List> buildStockInOrderPdfImpl(
final doc = pw . Document ( ) ;
doc . addPage ( pw . MultiPage (
pageFormat: PdfPageFormat . a4 ,
margin: const pw . EdgeInsets . symmetric ( horizontal: 15 * PdfPageFormat . mm , vertical: 12 * PdfPageFormat . mm ) ,
build: ( _ ) = > [
_buildOrderDoc (
pageTheme: _orderPageTheme ( ) ,
build: ( _ ) = > _buildOrderDoc (
font: font , bold: bold ,
shopName: meta . shopName ,
title: ' 入 库 单 ' ,
@@ -944,7 +973,6 @@ Future<Uint8List> buildStockInOrderPdfImpl(
totalQty: totalQty ,
totalAmt: totalAmt ,
) ,
] ,
) ) ;
return doc . save ( ) ;
}
@@ -997,10 +1025,8 @@ Future<Uint8List> buildStockOutOrderPdfImpl(
final doc = pw . Document ( ) ;
doc . addPage ( pw . MultiPage (
pageFormat: PdfPageFormat . a4 ,
margin: const pw . EdgeInsets . symmetric ( horizontal: 15 * PdfPageFormat . mm , vertical: 12 * PdfPageFormat . mm ) ,
build: ( _ ) = > [
_buildOrderDoc (
pageTheme: _orderPageTheme ( ) ,
build: ( _ ) = > _buildOrderDoc (
font: font , bold: bold ,
shopName: meta . shopName ,
title: ' 出 库 单 ' ,
@@ -1022,7 +1048,6 @@ Future<Uint8List> buildStockOutOrderPdfImpl(
totalQty: totalQty ,
totalAmt: totalAmt ,
) ,
] ,
) ) ;
return doc . save ( ) ;
}