| | |
| | | import QRCode from "qrcode"; |
| | | |
| | | const PRINT_TITLE = "生产流程卡(成品)"; |
| | | |
| | | const formatDisplayDate = (value) => { |
| | |
| | | return columns || '<td class="route-col"></td>'; |
| | | }; |
| | | |
| | | const renderItems = (items, startIndex, routeNodes, totalCols) => { |
| | | const renderItems = ( |
| | | items, |
| | | startIndex, |
| | | routeNodes, |
| | | totalCols, |
| | | previousProductName, |
| | | fallbackProductName |
| | | ) => { |
| | | const list = Array.isArray(items) ? items : []; |
| | | if (list.length === 0) { |
| | | return `<tr><td colspan="${totalCols}" style="text-align:center;">暂无明细</td></tr>`; |
| | | } |
| | | const routeEmptyCells = renderRouteEmptyCells(routeNodes); |
| | | let lastProductName = String(previousProductName ?? "").trim(); |
| | | return list |
| | | .map( |
| | | (item, index) => ` |
| | | .map((item, index) => { |
| | | const currentProductName = |
| | | String(item?.productDescription ?? "").trim() || fallbackProductName; |
| | | const shouldRenderProductRow = currentProductName !== lastProductName; |
| | | lastProductName = currentProductName; |
| | | return ` |
| | | ${shouldRenderProductRow ? `<tr><td colspan="${totalCols}" class="section-title">产品名称:${escapeHtml(currentProductName)}</td></tr>` : ""} |
| | | <tr> |
| | | <td>${startIndex + index + 1}</td> |
| | | <td class="no-wrap">${escapeHtml(item?.floorCode)}</td> |
| | |
| | | <td class="no-wrap">${escapeHtml(item?.processRequirement)}</td> |
| | | ${routeEmptyCells} |
| | | </tr> |
| | | ` |
| | | ) |
| | | `; |
| | | }) |
| | | .join(""); |
| | | }; |
| | | |
| | |
| | | return pages; |
| | | }; |
| | | |
| | | export const printFinishedProcessCard = (cardData) => { |
| | | export const printFinishedProcessCard = async (cardData) => { |
| | | const data = cardData ?? {}; |
| | | const routeNodes = Array.isArray(data.routeNodes) ? data.routeNodes : []; |
| | | const items = Array.isArray(data.items) ? data.items : []; |
| | | const firstItem = items[0] ?? {}; |
| | | const productName = firstItem.productDescription || ""; |
| | | const fallbackProductName = String(data?.productName ?? "").trim(); |
| | | const totalCols = 6 + Math.max(routeNodes.length, 1); |
| | | const signLabelCols = 2; |
| | | const signBlankCols = Math.max(totalCols - 5 - signLabelCols, 1); |
| | | const pageSize = 10; |
| | | const itemPages = splitItemsByPage(items, pageSize); |
| | | const totalPages = itemPages.length; |
| | | |
| | | const ledgerId = |
| | | data?.salesLedgerId ?? data?.ledgerId ?? data?.id ?? data?.salesLedgerID; |
| | | const salesContractNo = String(data?.salesContractNo ?? "").trim(); |
| | | const qrPayload = JSON.stringify({ |
| | | id: ledgerId ?? "", |
| | | salesContractNo, |
| | | type: "XS", |
| | | }); |
| | | let qrDataUrl = ""; |
| | | try { |
| | | qrDataUrl = await QRCode.toDataURL(qrPayload, { width: 180, margin: 2 }); |
| | | } catch { |
| | | qrDataUrl = ""; |
| | | } |
| | | |
| | | const printWindow = window.open("", "_blank", "width=1200,height=900"); |
| | | if (!printWindow) { |
| | |
| | | <title>${PRINT_TITLE}</title> |
| | | <style> |
| | | body { margin: 0; padding: 0; font-family: "SimSun", serif; color: #222; } |
| | | .page { width: 198mm; margin: 0 auto; padding: 6mm 3mm 5mm; box-sizing: border-box; page-break-after: always; } |
| | | .page { position: relative; width: 198mm; margin: 0 auto; padding: 6mm 3mm 5mm; box-sizing: border-box; page-break-after: always; } |
| | | .page:last-child { page-break-after: auto; } |
| | | .table-wrap { position: relative; } |
| | | .table-wrap { position: relative; margin-top: 22mm; } |
| | | .header { position: relative; padding-top: 0; } |
| | | .qr-block { |
| | | position: absolute; |
| | | right: 2mm; |
| | | top: -1mm; |
| | | width: 32mm; |
| | | text-align: center; |
| | | z-index: 3; |
| | | } |
| | | .qr-block img { width: 32mm; height: 32mm; display: block; margin: 0 auto; } |
| | | .page-mark { |
| | | position: absolute; |
| | | left: 0; |
| | |
| | | .map((pageItems, pageIndex) => { |
| | | const isLastPage = pageIndex === totalPages - 1; |
| | | const startIndex = pageIndex * pageSize; |
| | | const previousProductName = |
| | | startIndex > 0 |
| | | ? String(items[startIndex - 1]?.productDescription ?? "").trim() || |
| | | fallbackProductName |
| | | : ""; |
| | | return ` |
| | | <div class="page"> |
| | | <div class="title">鹤壁天沐钢化玻璃厂<br /><span class="sub-title">生产流程卡(成品)</span></div> |
| | | <div class="header"> |
| | | ${ |
| | | qrDataUrl |
| | | ? `<div class="qr-block"> |
| | | <img src="${qrDataUrl}" alt="二维码" /> |
| | | </div>` |
| | | : "" |
| | | } |
| | | <div class="title">鹤壁天沐钢化玻璃厂<br /><span class="sub-title">生产流程卡(成品)</span></div> |
| | | </div> |
| | | <div class="table-wrap"> |
| | | <div class="page-mark">第${pageIndex + 1}页,共${totalPages}页</div> |
| | | <table> |
| | |
| | | <tr>${renderRouteRow(routeNodes)}</tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td colspan="${totalCols}" class="section-title">产品名称:${escapeHtml(productName)}</td> |
| | | </tr> |
| | | ${renderItems(pageItems, startIndex, routeNodes, totalCols)} |
| | | ${renderItems( |
| | | pageItems, |
| | | startIndex, |
| | | routeNodes, |
| | | totalCols, |
| | | previousProductName, |
| | | fallbackProductName |
| | | )} |
| | | ${ |
| | | isLastPage |
| | | ? `<tr> |