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 getCurrentDateTime = () => {
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 toNumber = (value) => {
const num = Number(value);
return Number.isFinite(num) ? num : 0;
};
const formatMoney = (value) => {
const num = toNumber(value);
return num.toFixed(2);
};
const formatArea = (value) => {
const num = toNumber(value);
return num ? num.toFixed(2) : "";
};
const formatQty = (value) => {
const num = toNumber(value);
return num ? String(num) : "";
};
const getItemAmount = (item) => {
const fromPrice = toNumber(item?.taxInclusiveUnitPrice) * toNumber(item?.quantity);
const amount = toNumber(item?.taxInclusiveTotalPrice || item?.amount || fromPrice);
return amount;
};
const getItemArea = (item) =>
toNumber(item?.area || item?.settleTotalArea || item?.actualTotalArea);
const getDeliveryAddress = (data) =>
data?.deliveryAddress || data?.shippingAddress || data?.address || data?.shipAddress || "";
const normalizeRequirementText = (value) => {
const text = String(value ?? "").trim();
if (!text) return "";
return text
.replace(/^加工要求和备注[::]\s*/g, "")
.replace(/^加工要求[::]\s*/g, "")
.replace(/^备注[::]\s*/g, "");
};
const extractOtherFees = (data, items) => {
const source = [];
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);
if (Array.isArray(data?.salesProductProcessList)) source.push(...data.salesProductProcessList);
(Array.isArray(items) ? items : []).forEach((item) => {
if (Array.isArray(item?.salesProductProcessList)) source.push(...item.salesProductProcessList);
if (Array.isArray(item?.otherAmounts)) source.push(...item.otherAmounts);
});
const map = new Map();
source.forEach((fee) => {
const name = String(fee?.processName || fee?.name || fee?.itemName || "").trim();
if (!name) return;
const quantity = toNumber(fee?.quantity || fee?.num);
const unitPrice = toNumber(fee?.unitPrice || fee?.price);
const amount =
toNumber(fee?.amount || fee?.totalPrice) || (quantity && unitPrice ? quantity * unitPrice : 0);
const key = name;
if (!map.has(key)) {
map.set(key, { name, quantity: 0, unitPrice: 0, amount: 0 });
}
const row = map.get(key);
row.quantity += quantity;
row.unitPrice = unitPrice || row.unitPrice;
row.amount += amount;
});
return Array.from(map.values());
};
const renderOtherFeeNames = (rows) =>
(Array.isArray(rows) ? rows : [])
.map((row) => escapeHtml(row.name))
.filter(Boolean)
.join("
");
const renderOtherFeeUnitPrices = (rows) =>
(Array.isArray(rows) ? rows : [])
.map((row) => (row.unitPrice ? formatMoney(row.unitPrice) : ""))
.filter(Boolean)
.join("
");
const renderOtherFeeQuantities = (rows) =>
(Array.isArray(rows) ? rows : [])
.map((row) => (row.quantity ? String(row.quantity) : ""))
.filter(Boolean)
.join("
");
const renderOtherFeeAmounts = (rows) =>
(Array.isArray(rows) ? rows : [])
.map((row) => (row.amount ? formatMoney(row.amount) : ""))
.filter(Boolean)
.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;
};
const renderRows = (items, startIndex) => {
const list = Array.isArray(items) ? items : [];
if (list.length === 0) {
return `
| 客户名称: | ${escapeHtml(data.customerName)} | 项目名称: | ${escapeHtml(data.projectName)} | 业 务 员: ${escapeHtml(data.salesman)} |
| 制单日期: | ${escapeHtml(formatDisplayDate(data.registerDate || data.entryDate))} | 交货日期: | ${escapeHtml(formatDisplayDate(data.deliveryDate))} | |
| 送货地址: | ${escapeHtml(getDeliveryAddress(data))} | |||
| 序号 | 楼层编号 | 宽(弧长)*高 | 数量 | 结算面积 | 单价 | 金额 | 加工要求 |
|---|---|---|---|---|---|---|---|
| 产品名称: ${escapeHtml(items[0]?.productDescription)} | 订单编号: ${escapeHtml(data.salesContractNo)} | ||||||
| 小计: | ${totalQuantity || ""} | ${totalArea ? totalArea.toFixed(2) : ""} | ${formatMoney(totalAmount)} | ||||
| 合计: | ${totalQuantity || ""} | ${totalArea ? totalArea.toFixed(2) : ""} | ${formatMoney(totalAmount)} | ||||
|
其他费用
单价
数量
金额
|
加工要求和备注: | ||||||
| ${ renderOtherFeeNames(otherFees) || renderOtherFeeUnitPrices(otherFees) || renderOtherFeeQuantities(otherFees) || renderOtherFeeAmounts(otherFees) ? `${renderOtherFeeNames(otherFees)}` : "" } | ${escapeHtml(normalizeRequirementText(data.orderProcessRequirement))} | ||||||
| 总金额: ${formatMoney(totalAmount)}元 | |||||||
| 下页续... | |||||||