167 lines
7.1 KiB
TypeScript
167 lines
7.1 KiB
TypeScript
|
|
import { useEffect, useRef } from 'react';
|
|||
|
|
import { Head } from '@inertiajs/react';
|
|||
|
|
import JsBarcode from 'jsbarcode';
|
|||
|
|
|
|||
|
|
interface PrintProps {
|
|||
|
|
doc: {
|
|||
|
|
doc_no: string;
|
|||
|
|
warehouse_name: string;
|
|||
|
|
snapshot_date: string;
|
|||
|
|
created_at: string;
|
|||
|
|
print_date: string;
|
|||
|
|
created_by: string;
|
|||
|
|
items: Array<{
|
|||
|
|
id: string;
|
|||
|
|
product_name: string;
|
|||
|
|
product_code: string;
|
|||
|
|
specification: string;
|
|||
|
|
unit: string;
|
|||
|
|
quantity: number;
|
|||
|
|
counted_qty: number | null;
|
|||
|
|
notes: string;
|
|||
|
|
}>;
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default function Print({ doc }: PrintProps) {
|
|||
|
|
const barcodeRef = useRef<SVGSVGElement>(null);
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (barcodeRef.current) {
|
|||
|
|
try {
|
|||
|
|
JsBarcode(barcodeRef.current, doc.doc_no, {
|
|||
|
|
format: "CODE128",
|
|||
|
|
width: 2, // Thicker bars for better scanning
|
|||
|
|
height: 50, // Taller
|
|||
|
|
displayValue: false,
|
|||
|
|
margin: 10, // Mandatory quiet zone for scanners
|
|||
|
|
marginBottom: 5
|
|||
|
|
});
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error("Barcode generation failed", e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Delay print slightly to ensure render
|
|||
|
|
const timer = setTimeout(() => {
|
|||
|
|
window.print();
|
|||
|
|
}, 500);
|
|||
|
|
|
|||
|
|
return () => clearTimeout(timer);
|
|||
|
|
}, [doc.doc_no]);
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="bg-white text-black font-sans text-sm min-h-screen">
|
|||
|
|
<Head title={`列印盤點單 ${doc.doc_no}`} />
|
|||
|
|
|
|||
|
|
<style>{`
|
|||
|
|
@media print {
|
|||
|
|
@page {
|
|||
|
|
size: A4 landscape;
|
|||
|
|
margin: 10mm;
|
|||
|
|
}
|
|||
|
|
body {
|
|||
|
|
-webkit-print-color-adjust: exact;
|
|||
|
|
print-color-adjust: exact;
|
|||
|
|
}
|
|||
|
|
/* Hide browser default header/footer if possible (browser dependent) */
|
|||
|
|
}
|
|||
|
|
`}</style>
|
|||
|
|
|
|||
|
|
{/* Header Section */}
|
|||
|
|
<div className="relative mb-6">
|
|||
|
|
{/* Barcode - Top Right */}
|
|||
|
|
<div className="absolute top-0 right-0 flex flex-col items-end">
|
|||
|
|
<svg ref={barcodeRef}></svg>
|
|||
|
|
{/* <span className="text-xs font-mono mt-1">{doc.doc_no}</span> */}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Company & Title - Center */}
|
|||
|
|
<div className="text-center pt-4">
|
|||
|
|
<h1 className="text-2xl font-bold tracking-widest mb-2">台灣心零售股份有限公司</h1>
|
|||
|
|
<h2 className="text-xl font-bold tracking-widest">盤點單</h2>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Info Section */}
|
|||
|
|
<div className="flex justify-between items-end mb-2 border-b-2 border-black pb-2">
|
|||
|
|
<div className="space-y-1">
|
|||
|
|
<div className="flex gap-4">
|
|||
|
|
<span className="font-bold">單號:</span>
|
|||
|
|
<span className="font-mono font-bold">{doc.doc_no}</span>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex gap-4">
|
|||
|
|
<span className="font-bold">日期:</span>
|
|||
|
|
<span>{doc.created_at}</span>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex gap-4">
|
|||
|
|
<span className="font-bold">倉庫:</span>
|
|||
|
|
<span>{doc.warehouse_name}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="text-right">
|
|||
|
|
<div className="flex gap-4">
|
|||
|
|
<span className="font-bold">印單日期:</span>
|
|||
|
|
<span>{doc.print_date}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Table Section */}
|
|||
|
|
<table className="w-full border-collapse border border-black mb-8">
|
|||
|
|
<thead>
|
|||
|
|
<tr className="bg-gray-100">
|
|||
|
|
<th className="border border-black px-2 py-1 w-12 text-center">序號</th>
|
|||
|
|
<th className="border border-black px-2 py-1 w-32 text-left">品號</th>
|
|||
|
|
<th className="border border-black px-2 py-1 text-left">品名</th>
|
|||
|
|
<th className="border border-black px-2 py-1 w-32 text-left">規格</th>
|
|||
|
|
<th className="border border-black px-2 py-1 w-20 text-right">數量</th>
|
|||
|
|
<th className="border border-black px-2 py-1 w-16 text-center">單位</th>
|
|||
|
|
<th className="border border-black px-2 py-1 w-32 text-left">備註</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
{doc.items.map((item, index) => (
|
|||
|
|
<tr key={item.id}>
|
|||
|
|
<td className="border border-black px-2 py-2 text-center">{index + 1}</td>
|
|||
|
|
<td className="border border-black px-2 py-2 font-mono">{item.product_code}</td>
|
|||
|
|
<td className="border border-black px-2 py-2">{item.product_name}</td>
|
|||
|
|
<td className="border border-black px-2 py-2">{item.specification || '-'}</td>
|
|||
|
|
<td className="border border-black px-2 py-2 text-right">
|
|||
|
|
{item.counted_qty !== null ? Number(item.counted_qty).toFixed(2) : ''}
|
|||
|
|
</td>
|
|||
|
|
<td className="border border-black px-2 py-2 text-center">{item.unit || '-'}</td>
|
|||
|
|
<td className="border border-black px-2 py-2">{item.notes}</td>
|
|||
|
|
</tr>
|
|||
|
|
))}
|
|||
|
|
{/* Empty rows filler if needed, but usually not required unless strictly paging */}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
|
|||
|
|
{/* Footer Section */}
|
|||
|
|
<div className="fixed bottom-0 w-full mb-4">
|
|||
|
|
<div className="flex justify-between items-end px-4">
|
|||
|
|
<div className="w-1/3 border-b border-black pb-1 mb-1">
|
|||
|
|
<span className="font-bold">製單人員:</span>
|
|||
|
|
<span className="ml-2">{doc.created_by}</span>
|
|||
|
|
</div>
|
|||
|
|
<div className="w-1/3 border-b border-black pb-1 mb-1 mx-4">
|
|||
|
|
<span className="font-bold">盤點人員:</span>
|
|||
|
|
</div>
|
|||
|
|
<div className="w-1/3 border-b border-black pb-1 mb-1">
|
|||
|
|
<span className="font-bold">核對人員:</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex justify-between items-center text-xs mt-4 px-4">
|
|||
|
|
<div>
|
|||
|
|
製單人員:系統管理員 印單人員:{doc.created_by}
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
第 1 頁 / 共 1 頁
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|