fix(client): 标签打印布局与字号优化
Deploy / build-linux-web (push) Successful in 49s
Deploy / build-windows (push) Successful in 1m43s
Deploy / build-macos (push) Successful in 1m24s
Deploy / build-android (push) Successful in 1m9s
Deploy / build-ios (push) Successful in 7s
Deploy / release-deploy (push) Successful in 1m55s
Deploy / build-linux-web (push) Successful in 49s
Deploy / build-windows (push) Successful in 1m43s
Deploy / build-macos (push) Successful in 1m24s
Deploy / build-android (push) Successful in 1m9s
Deploy / build-ios (push) Successful in 7s
Deploy / release-deploy (push) Successful in 1m55s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,12 @@ 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/),
|
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).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.0.41] - 2026-06-15
|
||||||
|
|
||||||
|
### 改进
|
||||||
|
- 标签打印布局优化:编号字体与度数/日期统一大小,内容整体下移并填满标签底部,店名适当放大
|
||||||
|
- 标签度数与规格之间加宽间距,两个字段更易区分
|
||||||
|
|
||||||
## [1.0.40] - 2026-06-15
|
## [1.0.40] - 2026-06-15
|
||||||
|
|
||||||
### 新功能
|
### 新功能
|
||||||
|
|||||||
@@ -224,26 +224,38 @@ Future<ui.Image> _renderLabelBitmap({
|
|||||||
// 扫码溯源:居中于二维码正下方
|
// 扫码溯源:居中于二维码正下方
|
||||||
_drawText(canvas, '扫码溯源', qrLeft, qrTop + qrS + 2, 14, qrS, center: true);
|
_drawText(canvas, '扫码溯源', qrLeft, qrTop + qrS + 2, 14, qrS, center: true);
|
||||||
|
|
||||||
// 左侧文字(无字段名标签):按行等比分配高度铺满,字号自适应填充
|
// 左侧文字:固定字号 + 自适应行间距(与二维码上下对齐,行距均匀分配剩余空间)
|
||||||
const lx = 22.0;
|
const lx = 22.0;
|
||||||
const textMaxW = qrLeft - lx - 6; // 164
|
const textMaxW = qrLeft - lx - 6; // 164
|
||||||
|
|
||||||
|
// 字号固定:只有商品名按宽度自适应,其余行均固定,杜绝自动放大
|
||||||
|
const double kShopSize = 17.0; // 酒行名,粗体
|
||||||
|
const double kSmallSize = 13.0; // 编号 / 度数 / 日期,统一小字
|
||||||
|
// 商品名:仅按宽度适配,上限 26px,下限 14px
|
||||||
|
final double nameSize = _fitFont(name, textMaxW, 1000, true, 26.0).clamp(14.0, 26.0);
|
||||||
|
|
||||||
final codeText = code.isNotEmpty ? '编号:$code' : '';
|
final codeText = code.isNotEmpty ? '编号:$code' : '';
|
||||||
final rows = <(String, double, bool)>[
|
final rows = <(String, double, bool)>[
|
||||||
(shop, 0.9, true),
|
if (shop.isNotEmpty) (shop, kShopSize, true),
|
||||||
(name, 1.5, true),
|
if (name.isNotEmpty) (name, nameSize, true),
|
||||||
if (codeText.isNotEmpty) (codeText, 1.0, false),
|
if (codeText.isNotEmpty) (codeText, kSmallSize, false),
|
||||||
if (degSpec.isNotEmpty) (degSpec, 1.05, false),
|
if (degSpec.isNotEmpty) (degSpec, kSmallSize, false),
|
||||||
if (date.isNotEmpty) (date, 1.0, false),
|
if (date.isNotEmpty) (date, kSmallSize, false),
|
||||||
];
|
];
|
||||||
const topY = 4.0, botY = 156.0;
|
|
||||||
final totalWeight = rows.fold<double>(0, (a, r) => a + r.$2);
|
// 文字区域:整体略低于二维码顶部,底部延伸至扫码溯源文字下方
|
||||||
double yy = topY;
|
const double kTextTop = 16.0; // 比二维码顶部(8)低一些,整体下移
|
||||||
|
const double kTextBot = 150.0; // 延伸至底部,减少留白
|
||||||
|
const double kLineH = 1.35; // 行高倍数(字号 × 行高 = 该行占用高度)
|
||||||
|
final double totalTextH = rows.fold(0.0, (s, r) => s + r.$2 * kLineH);
|
||||||
|
final int n = rows.length;
|
||||||
|
final double rawGap = n > 0 ? (kTextBot - kTextTop - totalTextH) / (n + 1) : 4.0;
|
||||||
|
final double gap = rawGap < 1.5 ? 1.5 : rawGap;
|
||||||
|
|
||||||
|
double yy = kTextTop + gap;
|
||||||
for (final r in rows) {
|
for (final r in rows) {
|
||||||
final rowH = (botY - topY) * r.$2 / totalWeight;
|
_drawText(canvas, r.$1, lx, yy, r.$2, textMaxW, bold: r.$3);
|
||||||
final fs = _fitFont(r.$1, textMaxW, rowH * 0.84, r.$3, 30);
|
yy += r.$2 * kLineH + gap;
|
||||||
final ty = yy + (rowH - fs * 1.25) / 2;
|
|
||||||
_drawText(canvas, r.$1, lx, ty < yy ? yy : ty, fs, textMaxW, bold: r.$3);
|
|
||||||
yy += rowH;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return recorder.endRecording().toImage(w, h);
|
return recorder.endRecording().toImage(w, h);
|
||||||
@@ -327,7 +339,7 @@ Future<void> printProductLabelImpl({
|
|||||||
final specVal = (spec ?? '').isNotEmpty ? spec! : '';
|
final specVal = (spec ?? '').isNotEmpty ? spec! : '';
|
||||||
final seriesVal = (series ?? '').isNotEmpty ? series! : '';
|
final seriesVal = (series ?? '').isNotEmpty ? series! : '';
|
||||||
// 度数(系列) + 规格 同一行
|
// 度数(系列) + 规格 同一行
|
||||||
final degSpecVal = [seriesVal, specVal].where((s) => s.isNotEmpty).join(' ');
|
final degSpecVal = [seriesVal, specVal].where((s) => s.isNotEmpty).join(' ');
|
||||||
final dateVal = (productionDate ?? '').isNotEmpty
|
final dateVal = (productionDate ?? '').isNotEmpty
|
||||||
? (productionDate!.length > 10 ? productionDate.substring(0, 10) : productionDate)
|
? (productionDate!.length > 10 ? productionDate.substring(0, 10) : productionDate)
|
||||||
: '—';
|
: '—';
|
||||||
@@ -484,7 +496,7 @@ Future<void> printProductLabelImpl({
|
|||||||
Future<Uint8List> renderLabelPreviewImpl(LabelData label) async {
|
Future<Uint8List> renderLabelPreviewImpl(LabelData label) async {
|
||||||
final specVal = (label.spec ?? '').isNotEmpty ? label.spec! : '';
|
final specVal = (label.spec ?? '').isNotEmpty ? label.spec! : '';
|
||||||
final seriesVal = (label.series ?? '').isNotEmpty ? label.series! : '';
|
final seriesVal = (label.series ?? '').isNotEmpty ? label.series! : '';
|
||||||
final degSpecVal = [seriesVal, specVal].where((s) => s.isNotEmpty).join(' ');
|
final degSpecVal = [seriesVal, specVal].where((s) => s.isNotEmpty).join(' ');
|
||||||
final dateVal = (label.productionDate ?? '').isNotEmpty
|
final dateVal = (label.productionDate ?? '').isNotEmpty
|
||||||
? (label.productionDate!.length > 10
|
? (label.productionDate!.length > 10
|
||||||
? label.productionDate!.substring(0, 10)
|
? label.productionDate!.substring(0, 10)
|
||||||
|
|||||||
Reference in New Issue
Block a user