Compare commits

..

2 Commits

Author SHA1 Message Date
wangjia ed7a37cc05 chore: release client-v1.0.85
Deploy Client / build-client-web (push) Successful in 50s
Deploy Client / build-macos (push) Successful in 2m16s
Deploy Client / build-android (push) Successful in 1m31s
Deploy Client / build-ios (push) Successful in 2m31s
Deploy Client / build-windows (push) Successful in 1m53s
Deploy Client / release-deploy-client (push) Successful in 1m55s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 16:49:00 +08:00
wangjia 47cf0ae547 chore: release client-v1.0.84
Deploy Client / build-client-web (push) Successful in 45s
Deploy Client / build-windows (push) Successful in 2m43s
Deploy Client / build-macos (push) Successful in 2m15s
Deploy Client / build-android (push) Successful in 1m20s
Deploy Client / build-ios (push) Successful in 2m52s
Deploy Client / release-deploy-client (push) Successful in 1m51s
修复出库单/入库单打印时单据明细超过一页导致 MultiPage 分页死循环卡死的回归
(_buildOrderDoc 改返回可拆分子组件列表,左侧竖线点缀改由 pageTheme 背景每页绘制)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 22:28:00 +08:00
2 changed files with 79 additions and 44 deletions
+10
View File
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.85] - 2026-06-27
### 改进
- 出库单 / 入库单打印改为针式打印机友好版式:全部纯黑、去除灰色底纹、表格改纯黑实线边框、字体加粗加大,针打输出更清晰、不再发淡发糊;同时优化列宽,避免单价 / 金额 / 日期等数字被换行截断。
## [1.0.84] - 2026-06-26
### 修复
- 修复出库单 / 入库单打印时,单据明细超过一页会导致程序卡死无响应的问题(新版打印版式引入的回归)。
## [1.0.83] - 2026-06-26
### 改进
+69 -44
View File
@@ -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();
// 针打友好版式:全纯黑、无灰底纹、纯黑实线边框、字号加大。
// 针式打印机打不出灰色(只能抖成稀疏散点→淡而糊),且小号汉字笔画易糊;
// 故正文加粗(重击更黑)、字号上调、所有灰色一律改纯黑。
// 数字等宽(内置 CourierASCII 数字适用)。
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();
}