标签打印防御性布局: Flex分栏+line-clamp截断+分割线+预览同款
This commit is contained in:
@ -291,7 +291,10 @@ export default function CreateProductDialog({ open, onClose, onCreated }: Props)
|
|||||||
function printCurrentQRCode() {
|
function printCurrentQRCode() {
|
||||||
if (!createdSn) return;
|
if (!createdSn) return;
|
||||||
const qrUrl = `/api/v1/products/qrcode/${createdSn}`;
|
const qrUrl = `/api/v1/products/qrcode/${createdSn}`;
|
||||||
const printWindow = window.open("", "_blank", "width=600,height=600");
|
const productName = selected?.material_name ?? "";
|
||||||
|
const spec = selected?.spec_model ?? "";
|
||||||
|
const orderNo2 = orderNo || "—";
|
||||||
|
const printWindow = window.open("", "_blank", "width=420,height=480");
|
||||||
if (!printWindow) return;
|
if (!printWindow) return;
|
||||||
printWindow.document.write(`
|
printWindow.document.write(`
|
||||||
<html>
|
<html>
|
||||||
@ -299,17 +302,40 @@ export default function CreateProductDialog({ open, onClose, onCreated }: Props)
|
|||||||
<title>打印标签 - ${createdSn}</title>
|
<title>打印标签 - ${createdSn}</title>
|
||||||
<style>
|
<style>
|
||||||
@page { size: auto; margin: 0mm; }
|
@page { size: auto; margin: 0mm; }
|
||||||
body {
|
.print-label-container {
|
||||||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
display: flex; flex-direction: column; width: 100%; height: 100%;
|
||||||
margin: 0; padding: 20px; text-align: center; font-family: monospace;
|
box-sizing: border-box; padding: 10px; background: #fff;
|
||||||
|
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; color: #000; overflow: hidden;
|
||||||
|
}
|
||||||
|
.label-top {
|
||||||
|
display: flex; flex-direction: row; align-items: flex-start; gap: 12px;
|
||||||
|
flex: 1; min-height: 0;
|
||||||
|
}
|
||||||
|
.qr-box { flex-shrink: 0; width: 50%; }
|
||||||
|
.qr-box img { width: 100%; height: auto; display: block; }
|
||||||
|
.info-box { flex: 1; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
||||||
|
.info-item { font-size: 14px; font-weight: 900; line-height: 1.15; word-break: break-all; }
|
||||||
|
.item-name { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
|
||||||
|
.label-bottom {
|
||||||
|
flex-shrink: 0; margin-top: 10px; font-size: 18px; font-weight: 900;
|
||||||
|
text-align: center; border-top: 2px solid #000; padding-top: 6px; letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
img { width: 200px; height: 200px; object-fit: contain; }
|
|
||||||
.sn { font-size: 24px; font-weight: bold; margin-top: 10px; letter-spacing: 1px; }
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="margin:0;">
|
||||||
<img src="${qrUrl}" onload="window.print(); window.close();" />
|
<div class="print-label-container">
|
||||||
<div class="sn">${createdSn}</div>
|
<div class="label-top">
|
||||||
|
<div class="qr-box">
|
||||||
|
<img src="${qrUrl}" onload="window.print(); window.close();" />
|
||||||
|
</div>
|
||||||
|
<div class="info-box">
|
||||||
|
<div class="info-item item-name">名:${productName}</div>
|
||||||
|
<div class="info-item">规:${spec}</div>
|
||||||
|
<div class="info-item">单:${orderNo2}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="label-bottom">码:${createdSn}</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`);
|
`);
|
||||||
@ -331,23 +357,35 @@ export default function CreateProductDialog({ open, onClose, onCreated }: Props)
|
|||||||
>
|
>
|
||||||
{createdSn ? (
|
{createdSn ? (
|
||||||
/* ---- 成功页 ---- */
|
/* ---- 成功页 ---- */
|
||||||
<div className="flex flex-col items-center py-6">
|
<div className="py-4">
|
||||||
<img
|
<div style={{
|
||||||
src={`/api/v1/products/qrcode/${createdSn}`}
|
display: "flex", gap: 12, alignItems: "flex-start",
|
||||||
alt={`QR-${createdSn}`}
|
border: "1px solid #e5e7eb", borderRadius: 10, padding: 14, background: "#fff"
|
||||||
className="h-48 w-48 rounded-lg border"
|
}}>
|
||||||
/>
|
<img
|
||||||
<p className="mt-3 font-mono text-lg font-bold tracking-widest text-gray-800">
|
src={`/api/v1/products/qrcode/${createdSn}`}
|
||||||
{createdSn}
|
alt={`QR-${createdSn}`}
|
||||||
</p>
|
style={{ width: "50%", flexShrink: 0, borderRadius: 6 }}
|
||||||
<p className="mt-1 text-sm text-green-600">产品创建成功!</p>
|
/>
|
||||||
<Space className="mt-5">
|
<div style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 6 }}>
|
||||||
<Button type="primary" icon={<span>🖨️</span>} onClick={printCurrentQRCode}>
|
<div style={{ fontSize: 14, fontWeight: 900, lineHeight: 1.15, wordBreak: "break-all",
|
||||||
直接打印标签
|
display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: 3, overflow: "hidden" }}>
|
||||||
</Button>
|
名:{selected?.material_name ?? ""}
|
||||||
<Button onClick={() => setCreatedSn(null)}>
|
</div>
|
||||||
继续创建
|
<div style={{ fontSize: 14, fontWeight: 900 }}>规:{selected?.spec_model ?? ""}</div>
|
||||||
</Button>
|
<div style={{ fontSize: 14, fontWeight: 900 }}>单:{orderNo || "—"}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style={{
|
||||||
|
marginTop: 10, fontSize: 18, fontWeight: 900, textAlign: "center",
|
||||||
|
borderTop: "2px solid #000", paddingTop: 6, letterSpacing: 1, fontFamily: "monospace"
|
||||||
|
}}>
|
||||||
|
码:{createdSn}
|
||||||
|
</div>
|
||||||
|
<p className="mt-2 text-center text-sm text-green-600">产品创建成功!</p>
|
||||||
|
<Space className="mt-3 flex justify-center">
|
||||||
|
<Button type="primary" onClick={printCurrentQRCode}>🖨️ 直接打印标签</Button>
|
||||||
|
<Button onClick={() => setCreatedSn(null)}>继续创建</Button>
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
Reference in New Issue
Block a user