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 { }) async {
final base64Img = base64Encode(qrBytes); final base64Img = base64Encode(qrBytes);
final specVal = (spec ?? '').isNotEmpty ? spec! : ''; final specVal = (spec ?? '').isNotEmpty ? spec! : '';
final seriesVal = (series ?? '').isNotEmpty ? series! : ''; final batchVal = (batchNo ?? '').isNotEmpty ? batchNo! : '';
final batchVal = (batchNo ?? '').isNotEmpty ? batchNo! : ''; final dateVal = (productionDate ?? '').isNotEmpty
final dateVal = (productionDate ?? '').isNotEmpty
? (productionDate!.length > 10 ? productionDate.substring(0, 10) : productionDate) ? (productionDate!.length > 10 ? productionDate.substring(0, 10) : productionDate)
: ''; : '';
final footerContact = [ final contactLine = [
if (shopAddress.isNotEmpty) shopAddress,
if (shopPhone.isNotEmpty) shopPhone, if (shopPhone.isNotEmpty) shopPhone,
].join(' · '); if (shopAddress.isNotEmpty) shopAddress,
].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>'''
: '';
final html = '''<!DOCTYPE html> final html = '''<!DOCTYPE html>
<html> <html>
@@ -62,79 +48,71 @@ Future<void> printProductLabelImpl({
<link rel="preconnect" href="https://fonts.googleapis.com"> <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"> <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> <style>
@page { size: 4in 2in; margin: 0; } /* 标签尺寸:20mm × 38mm,竖向 */
@page { size: 20mm 38mm; margin: 0; }
* { box-sizing: border-box; margin: 0; padding: 0; * { box-sizing: border-box; margin: 0; padding: 0;
-webkit-print-color-adjust: exact; print-color-adjust: exact; } -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 { .label {
width: 4in; height: 2in; width: 20mm; height: 38mm;
display: grid; grid-template-rows: 42px 1fr 18px; display: flex; flex-direction: column;
font-family: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif; font-family: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
color: #111; color: #111;
} }
/* ── Header:酒行名称 ── */ /* ── Header:酒行名称 5.5mm ── */
.hdr { .hdr {
background: #1f2a3a; color: #f4ecd8; background: #1f2a3a; color: #f4ecd8;
display: flex; align-items: center; justify-content: space-between; height: 5.5mm; flex-shrink: 0;
padding: 0 15px; overflow: hidden; display: flex; align-items: center; justify-content: center;
padding: 0 1mm; overflow: hidden;
} }
.hdr-name { .hdr-name {
font-family: "Noto Serif SC", serif; font-size: 6pt; font-weight: 700; letter-spacing: 0.06em;
font-weight: 700; font-size: 17px; letter-spacing: 0.08em;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
} text-align: center;
.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;
} }
/* ── Body ── */ /* ── 商品名 7mm ── */
.body {
background: #fff; padding: 9px 15px 8px;
display: grid; grid-template-columns: 1fr 76px; gap: 10px;
align-items: center;
}
/* 商品名 */
.product-name { .product-name {
font-family: "Noto Serif SC", serif; height: 7mm; flex-shrink: 0;
font-weight: 700; font-size: 13px; letter-spacing: 0.04em; display: flex; align-items: center; justify-content: center;
margin-bottom: 7px; padding: 0 1mm;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; 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 { .spec-row {
display: flex; gap: 6px; align-items: baseline; display: flex; gap: 1mm; align-items: baseline;
font-size: 6.5px; margin-bottom: 3.5px; flex-wrap: nowrap; 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; .val { font-family: "IBM Plex Mono", monospace;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } overflow: hidden; text-overflow: ellipsis; }
.val-full { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
color: #444; font-size: 6px; }
/* 同行双字段 */ /* ── Footer:联系方式 3mm ── */
.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:地址 + 生成时间 ── */
.ftr { .ftr {
background: #f4ecd8; background: #f4ecd8; height: 3mm; flex-shrink: 0;
display: flex; align-items: center; justify-content: space-between; display: flex; align-items: center; justify-content: center;
padding: 0 15px; padding: 0 1mm;
font-family: "IBM Plex Mono", monospace; font-size: 4pt; color: #5a4e35; overflow: hidden; white-space: nowrap;
font-size: 5px; color: #5a4e35; letter-spacing: 0.04em; overflow: hidden; text-overflow: ellipsis;
} }
</style> </style>
</head> </head>
@@ -143,41 +121,23 @@ body { width: 4in; height: 2in; overflow: hidden; background: #fff; }
<div class="hdr"> <div class="hdr">
<span class="hdr-name">$shopName</span> <span class="hdr-name">$shopName</span>
<span class="hdr-tag">Certificate of Authenticity</span>
</div> </div>
<div class="body"> <div class="product-name">$name</div>
<div>
<div class="product-name">$name</div>
<div class="spec-row-2"> <div class="qr-wrap">
<span class="lbl">规 格</span> <img src="data:image/png;base64,$base64Img" />
<span class="val">$specVal</span> <div class="qr-cap">扫码溯源</div>
<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> </div>
<div class="ftr"> <div class="specs">
<span>${footerContact.isNotEmpty ? footerContact : shopName}</span> <div class="spec-row"><span class="lbl">规</span><span class="val">$specVal</span></div>
<span>$genTime</span> <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>
<div class="ftr">${contactLine.isNotEmpty ? contactLine : shopName}</div>
</div> </div>
<script> <script>
if (document.fonts && document.fonts.ready) { if (document.fonts && document.fonts.ready) {