export interface PrintableCargoRow { sku: string name: string expectedPackageCount?: number generatedCartonMarks?: string[] } const escapeHtml = (value: string) => value.replace(/[&<>"']/g, char => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[char]!) /** Generate labels in memory only. The later order request carries these same identities. */ export function prepareTransferCartonLabels(rows: PrintableCargoRow[], newMark: () => string = () => { const bytes = crypto.getRandomValues(new Uint8Array(16)) return `BX-${Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('').toUpperCase()}` }) { const total = rows.reduce((sum, row) => sum + Number(row.expectedPackageCount || 0), 0) if (!rows.length || rows.some(row => !Number.isSafeInteger(row.expectedPackageCount) || Number(row.expectedPackageCount) < 1) || total > 5000) { throw new Error('请填写货物的预计箱数(正整数),单次最多打印 5000 箱') } let index = 0 const labels = rows.flatMap(row => { const count = Number(row.expectedPackageCount) const marks = row.generatedCartonMarks ||= [] while (marks.length < count) marks.push(newMark()) return marks.slice(0, count).map(mark => `
仓储转运箱唛
${escapeHtml(mark)}
${++index} / ${total}
SKU:${escapeHtml(row.sku)}
${escapeHtml(row.name)}
`) }) return `仓储转运箱唛${labels.join('')}` }