const PRINT_TITLE = "生产流程卡(成品)";
|
|
const formatDisplayDate = (value) => {
|
if (!value) return "";
|
const date = new Date(value);
|
if (Number.isNaN(date.getTime())) return String(value);
|
const year = date.getFullYear();
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
const day = String(date.getDate()).padStart(2, "0");
|
return `${year}/${month}/${day}`;
|
};
|
|
const getCurrentDate = () => {
|
const date = new Date();
|
const year = date.getFullYear();
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
const day = String(date.getDate()).padStart(2, "0");
|
return `${year}/${month}/${day}`;
|
};
|
|
const escapeHtml = (value) =>
|
String(value ?? "")
|
.replaceAll("&", "&")
|
.replaceAll("<", "<")
|
.replaceAll(">", ">")
|
.replaceAll('"', """)
|
.replaceAll("'", "'");
|
|
const renderRouteHeader = (routeNodes) => {
|
const columns = (Array.isArray(routeNodes) ? routeNodes : [])
|
.sort((a, b) => (a?.dragSort ?? 0) - (b?.dragSort ?? 0))
|
.map((node) => `<th class="route-col">${escapeHtml(node?.processRouteItemName)}</th>`)
|
.join("");
|
return columns || '<th class="route-col">工序</th>';
|
};
|
|
const renderRouteRow = (routeNodes) => {
|
const columns = (Array.isArray(routeNodes) ? routeNodes : [])
|
.sort((a, b) => (a?.dragSort ?? 0) - (b?.dragSort ?? 0))
|
.map(() => '<td class="route-col">次品</td>')
|
.join("");
|
return columns || '<td class="route-col">次品</td>';
|
};
|
|
const renderRouteEmptyCells = (routeNodes) => {
|
const columns = (Array.isArray(routeNodes) ? routeNodes : [])
|
.sort((a, b) => (a?.dragSort ?? 0) - (b?.dragSort ?? 0))
|
.map(() => '<td class="route-col"></td>')
|
.join("");
|
return columns || '<td class="route-col"></td>';
|
};
|
|
const renderItems = (items, startIndex, routeNodes, totalCols) => {
|
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);
|
return list
|
.map(
|
(item, index) => `
|
<tr>
|
<td>${startIndex + index + 1}</td>
|
<td class="no-wrap">${escapeHtml(item?.floorCode)}</td>
|
<td class="no-wrap">${escapeHtml(item?.width)} * ${escapeHtml(item?.height)}</td>
|
<td class="no-wrap">${escapeHtml(item?.quantity)}</td>
|
<td class="no-wrap">${escapeHtml(item?.area)}</td>
|
<td class="no-wrap">${escapeHtml(item?.processRequirement)}</td>
|
${routeEmptyCells}
|
</tr>
|
`
|
)
|
.join("");
|
};
|
|
const splitItemsByPage = (items, pageSize) => {
|
const list = Array.isArray(items) ? items : [];
|
if (list.length === 0) return [[]];
|
const pages = [];
|
for (let i = 0; i < list.length; i += pageSize) {
|
pages.push(list.slice(i, i + pageSize));
|
}
|
return pages;
|
};
|
|
export const printFinishedProcessCard = (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 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 printWindow = window.open("", "_blank", "width=1200,height=900");
|
if (!printWindow) {
|
throw new Error("浏览器拦截了弹窗,请允许弹窗后重试");
|
}
|
|
const html = `
|
<!DOCTYPE html>
|
<html>
|
<head>
|
<meta charset="UTF-8" />
|
<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:last-child { page-break-after: auto; }
|
.table-wrap { position: relative; }
|
.page-mark {
|
position: absolute;
|
left: 0;
|
top: -16px;
|
z-index: 2;
|
font-size: 12px;
|
line-height: 1;
|
background: #fff;
|
padding: 0 2px;
|
}
|
.title { text-align: center; font-size: 18px; font-weight: 700; margin-bottom: 4px; line-height: 1.2; }
|
.sub-title { font-size: 14px; }
|
table { width: 100%; border-collapse: collapse; table-layout: auto; }
|
td, th { border: 0.8px solid #6f7f95; padding: 2px 4px; font-size: 12px; text-align: center; vertical-align: middle; word-break: break-all; }
|
.left { text-align: left; }
|
.no-wrap { white-space: nowrap; word-break: keep-all; }
|
.route-col { min-width: 48px; white-space: nowrap; word-break: keep-all; }
|
.section-title { font-weight: 700; text-align: left; padding-left: 6px; }
|
.sign-label { text-align: left; padding-left: 8px; vertical-align: top; line-height: 1.2; }
|
.sign-blank { vertical-align: top; min-height: 18px; }
|
.order-req-content { min-height: 82px; vertical-align: top; padding-top: 6px; }
|
.sign-row td { height: 18px; }
|
.order-require-title { width: 34px; padding: 0; }
|
.order-require-title-text {
|
display: flex;
|
height: 100%;
|
flex-direction: column;
|
justify-content: center;
|
align-items: center;
|
line-height: 1.25;
|
letter-spacing: 0;
|
font-weight: 500;
|
}
|
.footer { margin-top: 10px; font-size: 12px; line-height: 1.7; padding: 0 2px; }
|
.footer-row { display: flex; justify-content: space-between; }
|
.footer-item { width: 33%; }
|
.continued { text-align: right; font-size: 12px; padding-right: 8px; }
|
@media print {
|
@page { size: A4 portrait; margin: 8mm; }
|
.page { width: 100%; margin: 0; padding: 0; }
|
}
|
</style>
|
</head>
|
<body>
|
${itemPages
|
.map((pageItems, pageIndex) => {
|
const isLastPage = pageIndex === totalPages - 1;
|
const startIndex = pageIndex * pageSize;
|
return `
|
<div class="page">
|
<div class="title">鹤壁天沐钢化玻璃厂<br /><span class="sub-title">生产流程卡(成品)</span></div>
|
<div class="table-wrap">
|
<div class="page-mark">第${pageIndex + 1}页,共${totalPages}页</div>
|
<table>
|
<thead>
|
<tr>
|
<td colspan="5" class="left">订单编号:${escapeHtml(data.salesContractNo)}</td>
|
<td colspan="${totalCols - 5}" class="left">交货日期:${escapeHtml(formatDisplayDate(data.deliveryDate))}</td>
|
</tr>
|
<tr>
|
<td colspan="5" class="left">客户名称:${escapeHtml(data.customerName)}</td>
|
<td colspan="${totalCols - 5}" class="left">工艺流程:${escapeHtml(data.processPathDisplay)}</td>
|
</tr>
|
<tr>
|
<th rowspan="2" style="width:6%;">订序</th>
|
<th rowspan="2" style="width:22%;" class="no-wrap">楼层编号</th>
|
<th rowspan="2" style="width:20%;" class="no-wrap">宽(弧长)*高</th>
|
<th rowspan="2" style="width:8%;" class="no-wrap">数量</th>
|
<th rowspan="2" style="width:8%;" class="no-wrap">面积</th>
|
<th rowspan="2" style="width:20%;" class="no-wrap">明细加工要求</th>
|
${renderRouteHeader(routeNodes)}
|
</tr>
|
<tr>${renderRouteRow(routeNodes)}</tr>
|
</thead>
|
<tbody>
|
<tr>
|
<td colspan="${totalCols}" class="section-title">产品名称:${escapeHtml(productName)}</td>
|
</tr>
|
${renderItems(pageItems, startIndex, routeNodes, totalCols)}
|
${
|
isLastPage
|
? `<tr>
|
<td colspan="3" class="left"><strong>合计:</strong></td>
|
<td>${escapeHtml(data.totalQuantity)}</td>
|
<td>${escapeHtml(data.totalArea)}</td>
|
<td colspan="${signLabelCols}" class="sign-label">完工签名</td>
|
<td colspan="${signBlankCols}" class="sign-blank"></td>
|
</tr>
|
<tr class="sign-row">
|
<td rowspan="3" class="order-require-title">
|
<div class="order-require-title-text">
|
<span>订单</span>
|
<span>加工</span>
|
<span>要求</span>
|
</div>
|
</td>
|
<td colspan="4" rowspan="3" class="left order-req-content">${escapeHtml(data.orderProcessRequirement)}</td>
|
<td colspan="${signLabelCols}" class="sign-label">质检签名</td>
|
<td colspan="${signBlankCols}" class="sign-blank"></td>
|
</tr>
|
<tr class="sign-row">
|
<td colspan="${signLabelCols}" class="sign-label">接收签名</td>
|
<td colspan="${signBlankCols}" class="sign-blank"></td>
|
</tr>
|
<tr class="sign-row">
|
<td colspan="${signLabelCols}" class="sign-label">生产日期</td>
|
<td colspan="${signBlankCols}" class="sign-blank"></td>
|
</tr>`
|
: `<tr><td colspan="${totalCols}" class="continued">下页续...</td></tr>`
|
}
|
</tbody>
|
</table>
|
</div>
|
|
${
|
isLastPage
|
? `<div class="footer">
|
<div class="footer-row">
|
<div class="footer-item">制单员:${escapeHtml(data.register)}</div>
|
<div class="footer-item">审核员:${escapeHtml(data.register)}</div>
|
<div class="footer-item">工艺员:${escapeHtml(data.technician ?? "")}</div>
|
</div>
|
<div class="footer-row">
|
<div class="footer-item">制单日期:${escapeHtml(formatDisplayDate(data.registerDate))}</div>
|
<div class="footer-item">审核日期:${escapeHtml(formatDisplayDate(data.registerDate))}</div>
|
<div class="footer-item">打印日期:${getCurrentDate()}</div>
|
</div>
|
</div>`
|
: ""
|
}
|
</div>`;
|
})
|
.join("")}
|
</body>
|
</html>
|
`;
|
|
printWindow.document.write(html);
|
printWindow.document.close();
|
printWindow.onload = () => {
|
setTimeout(() => {
|
printWindow.focus();
|
printWindow.print();
|
printWindow.close();
|
}, 300);
|
};
|
};
|