优化
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import ts from 'typescript'
|
||||
const source = readFileSync(new URL('./transferCartonPrinting.ts', import.meta.url), 'utf8')
|
||||
const js = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS } }).outputText
|
||||
const exports = {}
|
||||
new Function('exports', js)(exports)
|
||||
const prepare = exports.prepareTransferCartonLabels
|
||||
|
||||
test('prints forecast counts independently of quantities or order fields and escapes cargo', () => {
|
||||
const rows = [{ sku: 'A<script>', name: '货物 & 品名', expectedPackageCount: 12 }]
|
||||
let next = 0
|
||||
const html = prepare(rows, () => `BX-${++next}`)
|
||||
assert.equal((html.match(/<section /g) || []).length, 12)
|
||||
assert.match(html, /12 \/ 12/)
|
||||
assert.match(html, /A<script>/)
|
||||
assert.equal(rows[0].generatedCartonMarks.length, 12)
|
||||
assert.equal(prepare(rows, () => { throw new Error('must retain labels') }), html)
|
||||
})
|
||||
|
||||
test('adding boxes or rows keeps previously printed identities', () => {
|
||||
const rows = [{ sku: 'A', name: '', expectedPackageCount: 2 }]
|
||||
let next = 0
|
||||
prepare(rows, () => `BX-${++next}`)
|
||||
rows[0].expectedPackageCount = 3
|
||||
rows.push({ sku: 'B', name: '', expectedPackageCount: 1 })
|
||||
const html = prepare(rows, () => `BX-${++next}`)
|
||||
assert.deepEqual(rows[0].generatedCartonMarks, ['BX-1', 'BX-2', 'BX-3'])
|
||||
assert.match(html, /BX-4/)
|
||||
})
|
||||
|
||||
test('invalid or excessive forecasts do not generate any labels', () => {
|
||||
for (const count of [0, -1, 1.5, undefined, 5001]) {
|
||||
const row = { sku: '', name: '', expectedPackageCount: count }
|
||||
assert.throws(() => prepare([row]), /预计箱数/)
|
||||
assert.equal(row.generatedCartonMarks, undefined)
|
||||
}
|
||||
})
|
||||
|
||||
test('print button cannot create, update or submit an order', () => {
|
||||
const view = readFileSync(new URL('../views/WarehouseServiceView.vue', import.meta.url), 'utf8')
|
||||
const handler = view.slice(view.indexOf('function printForecastCartons()'), view.indexOf('async function submit('))
|
||||
assert.match(handler, /prepareTransferCartonLabels\(cargoRows.value\)/)
|
||||
assert.doesNotMatch(handler, /createTransfer|updateTransfer|submitTransfer|getTransferCartonLabel|form\./)
|
||||
assert.match(view, /cartonMarks: item.generatedCartonMarks/)
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
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 => `<section class="label"><div class="title">仓储转运箱唛</div><div class="mark">${escapeHtml(mark)}</div><div>${++index} / ${total}</div><div>SKU:${escapeHtml(row.sku)}</div><div>${escapeHtml(row.name)}</div></section>`)
|
||||
})
|
||||
return `<!doctype html><html><head><meta charset="utf-8"><title>仓储转运箱唛</title><style>@page{size:100mm 100mm;margin:0}body{margin:0;font-family:Arial,sans-serif}.label{box-sizing:border-box;width:100mm;height:100mm;padding:10mm;break-after:page;display:flex;flex-direction:column;justify-content:center;gap:6mm;text-align:center;overflow-wrap:anywhere}.label:last-child{break-after:auto}.title{font-size:22px;font-weight:bold}.mark{font-size:23px;font-weight:bold}</style></head><body>${labels.join('')}</body></html>`
|
||||
}
|
||||
Reference in New Issue
Block a user