fix(print): 商品标签改为竖向 20mm×38mm 布局

原设计 4in×2in 横向与实际标签纸不符,导致内容旋转 90°。按实测尺寸重设为竖向 20mm×38mm,重新排布:酒行名顶部深色背景→商品名→QR码→规格/批次/生产日期→联系方式底部。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-05-26 21:20:31 +08:00
parent 51863dcbd3
commit ee826eca7f
+58 -98
View File
@@ -30,30 +30,16 @@ Future<void> printProductLabelImpl({
}) async {
final base64Img = base64Encode(qrBytes);
final specVal = (spec ?? '').isNotEmpty ? spec! : '';
final seriesVal = (series ?? '').isNotEmpty ? series! : '';
final batchVal = (batchNo ?? '').isNotEmpty ? batchNo! : '';
final dateVal = (productionDate ?? '').isNotEmpty
final specVal = (spec ?? '').isNotEmpty ? spec! : '';
final batchVal = (batchNo ?? '').isNotEmpty ? batchNo! : '';
final dateVal = (productionDate ?? '').isNotEmpty
? (productionDate!.length > 10 ? productionDate.substring(0, 10) : productionDate)
: '';
final footerContact = [
if (shopAddress.isNotEmpty) shopAddress,
final contactLine = [
if (shopPhone.isNotEmpty) shopPhone,
].join(' · ');
// 标签生成时间
final now = DateTime.now();
final genTime =
'${now.year}-${now.month.toString().padLeft(2,'0')}-${now.day.toString().padLeft(2,'0')}'
' ${now.hour.toString().padLeft(2,'0')}:${now.minute.toString().padLeft(2,'0')}';
final remarkRow = (remark ?? '').isNotEmpty
? '''<div class="spec-row">
<span class="lbl">备 注</span>
<span class="val-full">$remark</span>
</div>'''
: '';
if (shopAddress.isNotEmpty) shopAddress,
].join(' ');
final html = '''<!DOCTYPE html>
<html>
@@ -62,79 +48,71 @@ Future<void> printProductLabelImpl({
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;700&family=Noto+Serif+SC:wght@700&family=IBM+Plex+Mono:wght@400&display=swap" rel="stylesheet">
<style>
@page { size: 4in 2in; margin: 0; }
/* 标签尺寸:20mm × 38mm,竖向 */
@page { size: 20mm 38mm; margin: 0; }
* { box-sizing: border-box; margin: 0; padding: 0;
-webkit-print-color-adjust: exact; print-color-adjust: exact; }
body { width: 4in; height: 2in; overflow: hidden; background: #fff; }
body { width: 20mm; height: 38mm; overflow: hidden; background: #fff; }
.label {
width: 4in; height: 2in;
display: grid; grid-template-rows: 42px 1fr 18px;
width: 20mm; height: 38mm;
display: flex; flex-direction: column;
font-family: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
color: #111;
}
/* ── Header:酒行名称 ── */
/* ── Header:酒行名称 5.5mm ── */
.hdr {
background: #1f2a3a; color: #f4ecd8;
display: flex; align-items: center; justify-content: space-between;
padding: 0 15px; overflow: hidden;
height: 5.5mm; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
padding: 0 1mm; overflow: hidden;
}
.hdr-name {
font-family: "Noto Serif SC", serif;
font-weight: 700; font-size: 17px; letter-spacing: 0.08em;
font-size: 6pt; font-weight: 700; letter-spacing: 0.06em;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hdr-tag {
font-size: 6.5px; letter-spacing: 0.2em; opacity: 0.8;
font-style: italic; white-space: nowrap; flex-shrink: 0; padding-left: 10px;
text-align: center;
}
/* ── Body ── */
.body {
background: #fff; padding: 9px 15px 8px;
display: grid; grid-template-columns: 1fr 76px; gap: 10px;
align-items: center;
}
/* 商品名 */
/* ── 商品名 7mm ── */
.product-name {
font-family: "Noto Serif SC", serif;
font-weight: 700; font-size: 13px; letter-spacing: 0.04em;
margin-bottom: 7px;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
height: 7mm; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
padding: 0 1mm;
font-size: 7pt; font-weight: 700; letter-spacing: 0.03em;
text-align: center; line-height: 1.2;
overflow: hidden;
}
/* 规格行 */
/* ── QR 码区 15mm ── */
.qr-wrap {
height: 15mm; flex-shrink: 0;
display: flex; flex-direction: column;
align-items: center; justify-content: center; gap: 0.5mm;
}
.qr-wrap img { width: 13.5mm; height: 13.5mm; object-fit: contain; }
.qr-cap { font-size: 4pt; color: #888; letter-spacing: 0.12em; }
/* ── 规格/批次 7.5mm ── */
.specs {
flex: 1; padding: 0.5mm 1.5mm;
display: flex; flex-direction: column; justify-content: center; gap: 0.8mm;
}
.spec-row {
display: flex; gap: 6px; align-items: baseline;
font-size: 6.5px; margin-bottom: 3.5px; flex-wrap: nowrap;
display: flex; gap: 1mm; align-items: baseline;
font-size: 5pt; white-space: nowrap; overflow: hidden;
}
.lbl { color: #888; letter-spacing: 0.1em; white-space: nowrap; flex-shrink: 0; }
.lbl { color: #888; flex-shrink: 0; }
.val { font-family: "IBM Plex Mono", monospace;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.val-full { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
color: #444; font-size: 6px; }
overflow: hidden; text-overflow: ellipsis; }
/* 同行双字段 */
.spec-row-2 {
display: grid; grid-template-columns: 28px 1fr 28px 1fr;
gap: 0 7px; font-size: 6.5px; margin-bottom: 3.5px;
align-items: baseline;
}
/* QR */
.qr-col { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.qr-col img { width: 68px; height: 68px; object-fit: contain; display: block; }
.qr-cap { font-size: 5px; letter-spacing: 0.2em; color: #666; text-align: center; }
/* ── Footer:地址 + 生成时间 ── */
/* ── Footer:联系方式 3mm ── */
.ftr {
background: #f4ecd8;
display: flex; align-items: center; justify-content: space-between;
padding: 0 15px;
font-family: "IBM Plex Mono", monospace;
font-size: 5px; color: #5a4e35; letter-spacing: 0.04em; overflow: hidden;
background: #f4ecd8; height: 3mm; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
padding: 0 1mm;
font-size: 4pt; color: #5a4e35; overflow: hidden; white-space: nowrap;
text-overflow: ellipsis;
}
</style>
</head>
@@ -143,41 +121,23 @@ body { width: 4in; height: 2in; overflow: hidden; background: #fff; }
<div class="hdr">
<span class="hdr-name">$shopName</span>
<span class="hdr-tag">Certificate of Authenticity</span>
</div>
<div class="body">
<div>
<div class="product-name">$name</div>
<div class="product-name">$name</div>
<div class="spec-row-2">
<span class="lbl">规 格</span>
<span class="val">$specVal</span>
<span class="lbl">系 列</span>
<span class="val">$seriesVal</span>
</div>
<div class="spec-row-2">
<span class="lbl">批 号</span>
<span class="val">$batchVal</span>
<span class="lbl">生产日期</span>
<span class="val">$dateVal</span>
</div>
$remarkRow
</div>
<div class="qr-col">
<img src="data:image/png;base64,$base64Img" />
<div class="qr-cap">扫码溯源 · TRACE</div>
</div>
<div class="qr-wrap">
<img src="data:image/png;base64,$base64Img" />
<div class="qr-cap">扫码溯源</div>
</div>
<div class="ftr">
<span>${footerContact.isNotEmpty ? footerContact : shopName}</span>
<span>$genTime</span>
<div class="specs">
<div class="spec-row"><span class="lbl">规</span><span class="val">$specVal</span></div>
<div class="spec-row"><span class="lbl">批</span><span class="val">$batchVal</span></div>
<div class="spec-row"><span class="lbl">产</span><span class="val">$dateVal</span></div>
</div>
<div class="ftr">${contactLine.isNotEmpty ? contactLine : shopName}</div>
</div>
<script>
if (document.fonts && document.fonts.ready) {