| | |
| | | toNumber(item?.area || item?.settleTotalArea || item?.actualTotalArea); |
| | | |
| | | const getDeliveryAddress = (data) => |
| | | data?.deliveryAddress || data?.shippingAddress || data?.address || data?.shipAddress || ""; |
| | | data?.companyAddress || data?.deliveryAddress || data?.shippingAddress || data?.address || data?.shipAddress || ""; |
| | | |
| | | const normalizeRequirementText = (value) => { |
| | | const text = String(value ?? "").trim(); |
| | |
| | | |
| | | const extractOtherFees = (data, items) => { |
| | | const source = []; |
| | | if (Array.isArray(data?.otherFees)) source.push(...data.otherFees); |
| | | if (Array.isArray(data?.otherAmounts)) source.push(...data.otherAmounts); |
| | | if (Array.isArray(data?.otherAmountList)) source.push(...data.otherAmountList); |
| | | if (Array.isArray(data?.otherAmountProjects)) source.push(...data.otherAmountProjects); |
| | |
| | | |
| | | const map = new Map(); |
| | | source.forEach((fee) => { |
| | | const name = String(fee?.processName || fee?.name || fee?.itemName || "").trim(); |
| | | const name = String(fee?.feeName || fee?.processName || fee?.name || fee?.itemName || "").trim(); |
| | | if (!name) return; |
| | | const quantity = toNumber(fee?.quantity || fee?.num); |
| | | const unitPrice = toNumber(fee?.unitPrice || fee?.price); |
| | |
| | | return Array.from(map.values()); |
| | | }; |
| | | |
| | | const renderOtherFeeNames = (rows) => |
| | | (Array.isArray(rows) ? rows : []) |
| | | .map((row) => escapeHtml(row.name)) |
| | | .filter(Boolean) |
| | | .join("<br/>"); |
| | | |
| | | const renderOtherFeeUnitPrices = (rows) => |
| | | (Array.isArray(rows) ? rows : []) |
| | | .map((row) => (row.unitPrice ? formatMoney(row.unitPrice) : "")) |
| | | .filter(Boolean) |
| | | .join("<br/>"); |
| | | |
| | | const renderOtherFeeQuantities = (rows) => |
| | | (Array.isArray(rows) ? rows : []) |
| | | .map((row) => (row.quantity ? String(row.quantity) : "")) |
| | | .filter(Boolean) |
| | | .join("<br/>"); |
| | | |
| | | const renderOtherFeeAmounts = (rows) => |
| | | (Array.isArray(rows) ? rows : []) |
| | | .map((row) => (row.amount ? formatMoney(row.amount) : "")) |
| | | .filter(Boolean) |
| | | .join("<br/>"); |
| | | const renderOtherFeeRows = (rows) => { |
| | | const list = Array.isArray(rows) ? rows : []; |
| | | if (list.length === 0) { |
| | | return `<tr><td></td><td></td><td></td><td></td></tr>`; |
| | | } |
| | | return list |
| | | .map((row) => { |
| | | const name = escapeHtml(row.name); |
| | | const unitPrice = row.unitPrice ? formatMoney(row.unitPrice) : ""; |
| | | const quantity = row.quantity ? String(row.quantity) : ""; |
| | | const amount = row.amount ? formatMoney(row.amount) : ""; |
| | | return `<tr><td class="other-fee-shift-left">${name}</td><td class="other-fee-shift-left">${unitPrice}</td><td class="other-fee-shift-left">${quantity}</td><td>${amount}</td></tr>`; |
| | | }) |
| | | .join(""); |
| | | }; |
| | | |
| | | const splitItemsByPage = (items, pageSize) => { |
| | | const list = Array.isArray(items) ? items : []; |
| | |
| | | const pages = splitItemsByPage(items, pageSize); |
| | | const totalPages = pages.length; |
| | | |
| | | const subtotalQuantity = toNumber(data.subtotalQuantity); |
| | | const subtotalArea = toNumber(data.subtotalArea); |
| | | const subtotalAmount = toNumber(data.subtotalAmount); |
| | | const totalQuantity = toNumber(data.totalQuantity) || items.reduce((sum, item) => sum + toNumber(item?.quantity), 0); |
| | | const totalArea = toNumber(data.totalArea) || items.reduce((sum, item) => sum + getItemArea(item), 0); |
| | | const totalAmount = items.reduce((sum, item) => sum + getItemAmount(item), 0); |
| | | const totalAmount = toNumber(data.totalAmount) || items.reduce((sum, item) => sum + getItemAmount(item), 0); |
| | | const otherFees = extractOtherFees(data, items); |
| | | |
| | | const printWindow = window.open("", "_blank", "width=1200,height=900"); |
| | |
| | | table { width: 100%; border-collapse: collapse; table-layout: fixed; border: 1px solid #222; } |
| | | .detail-table { |
| | | border-right: 1px solid #222 !important; |
| | | box-shadow: inset -1px 0 0 #222; |
| | | } |
| | | .detail-table-wrap { |
| | | position: relative; |
| | | margin-top: -1px; |
| | | } |
| | | .detail-table-wrap::after { |
| | | content: ""; |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | width: 1px; |
| | | height: 100%; |
| | | background: #222; |
| | | pointer-events: none; |
| | | content: none; |
| | | } |
| | | .sheet-wrap { |
| | | position: relative; |
| | | overflow: visible; |
| | | } |
| | | .sheet-wrap::after { |
| | | content: ""; |
| | | position: absolute; |
| | | top: 0; |
| | | right: -0.4px; |
| | | width: 1.2px; |
| | | height: 100%; |
| | | background: #222; |
| | | pointer-events: none; |
| | | z-index: 20; |
| | | content: none; |
| | | } |
| | | td, th { border: 1px solid #222; padding: 2px 4px; font-size: 13px; text-align: center; vertical-align: middle; } |
| | | tr > td:first-child, tr > th:first-child { border-left: 1px solid #222 !important; } |
| | |
| | | .product-row td { font-size: 13px; font-weight: 700; } |
| | | .empty { height: 140px; color: #777; } |
| | | .large-row td { height: 46px; vertical-align: top; } |
| | | .other-fee-content-row td { height: auto !important; } |
| | | .total-row td { font-weight: 700; font-size: 13px; line-height: 1.2; } |
| | | .footer { margin-top: 5px; display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; font-size: 13px; line-height: 1.7; } |
| | | .footer b { display: inline-block; min-width: 74px; } |
| | |
| | | justify-content: space-between; |
| | | gap: 8px; |
| | | } |
| | | .other-fee-cell { white-space: normal; word-break: break-all; line-height: 1.5; vertical-align: top; } |
| | | .other-fee-cell { white-space: normal; word-break: break-all; line-height: 1.35; vertical-align: top; } |
| | | .other-fee-header { font-weight: 700; } |
| | | .other-fee-header-grid { |
| | | display: grid; |
| | |
| | | } |
| | | .other-fee-header-row td { border-bottom: none !important; } |
| | | .other-fee-content-row td { border-top: none !important; } |
| | | .other-fee-inner { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | table-layout: fixed; |
| | | border: none !important; |
| | | } |
| | | .other-fee-inner td { |
| | | border: none !important; |
| | | padding: 0 1px; |
| | | text-align: center; |
| | | vertical-align: middle; |
| | | white-space: normal; |
| | | word-break: break-all; |
| | | line-height: 1.1; |
| | | } |
| | | .other-fee-inner tr > td:first-child, |
| | | .other-fee-inner tr > td:last-child { |
| | | border-left: none !important; |
| | | border-right: none !important; |
| | | } |
| | | .other-fee-shift-left { |
| | | position: relative; |
| | | left: -30px; |
| | | } |
| | | @media print { |
| | | @page { size: A4 landscape; margin: 6mm; } |
| | | .page { width: 100%; margin: 0; padding: 0 0 14mm; min-height: 0; } |
| | |
| | | const startIndex = pageIndex * pageSize; |
| | | return ` |
| | | <div class="page"> |
| | | <div class="title-main">鹤壁天沐钢化玻璃厂</div> |
| | | <div class="title-main">${escapeHtml(data.companyName || "鹤壁天沐钢化玻璃厂")}</div> |
| | | <div class="title-sub">销售订单</div> |
| | | |
| | | <div class="sheet-wrap"> |
| | |
| | | </tr> |
| | | <tr> |
| | | <td class="cell-title">制单日期:</td> |
| | | <td class="left">${escapeHtml(formatDisplayDate(data.registerDate || data.entryDate))}</td> |
| | | <td class="left">${escapeHtml(formatDisplayDate(data.executionDate || data.orderMakerDate || data.registerDate || data.entryDate))}</td> |
| | | <td class="cell-title">交货日期:</td> |
| | | <td class="left">${escapeHtml(formatDisplayDate(data.deliveryDate))}</td> |
| | | <td class="left"></td> |
| | |
| | | <th>加工要求</th> |
| | | </tr> |
| | | <tr class="product-row"> |
| | | <td colspan="6" class="left">产品名称: ${escapeHtml(items[0]?.productDescription)}</td> |
| | | <td colspan="6" class="left">产品名称: ${escapeHtml(data.productName || items[0]?.productDescription)}</td> |
| | | <td colspan="2" class="left">订单编号: ${escapeHtml(data.salesContractNo)}</td> |
| | | </tr> |
| | | ${renderRows(pageItems, startIndex)} |
| | |
| | | ? ` |
| | | <tr class="total-row"> |
| | | <td colspan="3" class="left">小计:</td> |
| | | <td>${totalQuantity || ""}</td> |
| | | <td>${totalArea ? totalArea.toFixed(2) : ""}</td> |
| | | <td>${subtotalQuantity || totalQuantity || ""}</td> |
| | | <td>${subtotalArea ? subtotalArea.toFixed(2) : totalArea ? totalArea.toFixed(2) : ""}</td> |
| | | <td></td> |
| | | <td>${formatMoney(totalAmount)}</td> |
| | | <td>${formatMoney(subtotalAmount || totalAmount)}</td> |
| | | <td></td> |
| | | </tr> |
| | | <tr class="total-row"> |
| | |
| | | </tr> |
| | | <tr class="large-row other-fee-content-row"> |
| | | <td colspan="5" class="left other-fee-cell"> |
| | | ${ |
| | | renderOtherFeeNames(otherFees) || |
| | | renderOtherFeeUnitPrices(otherFees) || |
| | | renderOtherFeeQuantities(otherFees) || |
| | | renderOtherFeeAmounts(otherFees) |
| | | ? `${renderOtherFeeNames(otherFees)}` |
| | | : "" |
| | | } |
| | | <table class="other-fee-inner"> |
| | | <colgroup> |
| | | <col style="width: 34%;" /> |
| | | <col style="width: 22%;" /> |
| | | <col style="width: 20%;" /> |
| | | <col style="width: 24%;" /> |
| | | </colgroup> |
| | | ${renderOtherFeeRows(otherFees)} |
| | | </table> |
| | | </td> |
| | | <td colspan="3" class="left other-fee-cell">${escapeHtml(normalizeRequirementText(data.orderProcessRequirement))}</td> |
| | | <td colspan="3" class="left other-fee-cell">${escapeHtml(normalizeRequirementText(data.remakes || data.remarks || data.orderProcessRequirement))}</td> |
| | | </tr> |
| | | <tr class="total-row"> |
| | | <td colspan="8" class="left">总金额: ${formatMoney(totalAmount)}元</td> |
| | | <td colspan="8" class="left">总金额: ${escapeHtml(data.totalAmountDisplay || `${formatMoney(totalAmount)}元`)}</td> |
| | | </tr> |
| | | ` |
| | | : ` |
| | |
| | | <span class="customer-sign customer-sign-cell">客户签名:</span> |
| | | </div> |
| | | <div class="footer"> |
| | | <div><b>制单员:</b>${escapeHtml(data.register)}</div> |
| | | <div><b>审核员:</b>${escapeHtml(data.register)}</div> |
| | | <div><b>打印人:</b>${escapeHtml(data.register)}</div> |
| | | <div><b>制单日期:</b>${escapeHtml(formatDisplayDate(data.registerDate || data.entryDate))}</div> |
| | | <div><b>审核日期:</b>${escapeHtml(formatDisplayDate(data.registerDate || data.entryDate))}</div> |
| | | <div class="footer-pair"><span><b>打印时间:</b>${getCurrentDateTime()}</span><span class="footer-page-right">第${pageIndex + 1}页,共${totalPages}页</span></div> |
| | | <div><b>制单员:</b>${escapeHtml(data.orderMaker || data.register)}</div> |
| | | <div><b>审核员:</b>${escapeHtml(data.auditor)}</div> |
| | | <div><b>打印人:</b>${escapeHtml(data.printPeople || data.register)}</div> |
| | | <div><b>制单日期:</b>${escapeHtml(formatDisplayDate(data.orderMakerDate || data.executionDate || data.registerDate || data.entryDate))}</div> |
| | | <div><b>审核日期:</b>${escapeHtml(formatDisplayDate(data.auditDate))}</div> |
| | | <div class="footer-pair"><span><b>打印时间:</b>${escapeHtml(data.printTime || getCurrentDateTime())}</span><span class="footer-page-right">第${pageIndex + 1}页,共${totalPages}页</span></div> |
| | | </div> |
| | | ` |
| | | : "" |