This commit is contained in:
2026-10-13 21:27:46 +08:00
parent 90ef9893f3
commit d28408f678
4 changed files with 35 additions and 3 deletions
@@ -8,6 +8,11 @@ const compiled = ts.transpileModule(source, { compilerOptions: { target: ts.Scri
const exports = {}
new Function('exports', compiled)(exports)
test('多次签收的字符串箱数按数值累计:三箱加四箱等于七箱', () => {
assert.equal(exports.receiptPrintableBoxCount([{ boxCount: '3' }, { boxCount: '4' }]), 7)
assert.equal(exports.receiptPrintableBoxCount([{ boxCount: '3', labels: [{}, {}, {}] }, { boxCount: '4', labels: [{}, {}, {}, {}] }]), 7)
})
test('签收箱号只包含箱子和托盘签收,包裹实物记录不重复展示为箱子', () => {
const receipts = [{ receiptNo: 'PARCEL-1', unitType: 'PARCEL' }, { receiptNo: 'BOX-1', unitType: 'BOX' }, { receiptNo: 'PALLET-1', unitType: 'PALLET' }]
const cartons = [{ receiptNo: 'PARCEL-1', cartonMark: 'RP-1' }, { receiptNo: 'BOX-1', cartonMark: 'RC-1' }, { receiptNo: 'PALLET-1', cartonMark: 'RC-2' }, { receiptNo: 'UNKNOWN', cartonMark: 'RP-UNKNOWN' }]
@@ -1,5 +1,9 @@
import type { ReturnPallet, ReturnReceipt, ReturnReceiptCarton } from '../api/returnOrders'
export function receiptPrintableBoxCount(receipts: ReturnReceipt[]) {
return receipts.reduce((total, receipt) => total + Number(receipt.labels?.length || receipt.boxCount || 1), 0)
}
export function receiptPhysicalDetails(pallets: ReturnPallet[], boxes: ReturnReceiptCarton[]) {
const signedBoxMarks = new Set(boxes.map(box => box.cartonMark))
return pallets.filter(unit => unit.unitType !== 'BOX' || !signedBoxMarks.has(unit.unitCode || unit.palletCode))
@@ -223,6 +223,29 @@ test('两托各两箱合并为一次四页打印,每箱条码保留且模板
assert.deepEqual(calls.errors, [])
})
test('同一托盘分两次签收三箱和四箱,打印全部七个独立箱唛', async () => {
const { print, calls } = printHarness()
const receipts = [3, 4].map((count, batch) => ({
palletCode: 'PLT-SHARED', boxCount: String(count),
labels: Array.from({ length: count }, (_, index) => ({ cartonMark: `BATCH-${batch}-${index}`, printableHtml: labelHtml(`BATCH-${batch}-${index}`) })),
printableHtml: 'old-batch-template',
}))
await print(receipts)
assert.equal((calls.html.match(/<section class="return-label">/g) || []).length, 7)
for (const receipt of receipts) for (const label of receipt.labels) assert.ok(calls.html.includes(`data-barcode="${label.cartonMark}"`))
assert.equal(calls.printed, 1)
assert.deepEqual(calls.errors, [])
})
test('打印以完整箱唛列表为准,不使用可能只包含最后一批的汇总模板', async () => {
const { print, calls } = printHarness()
const labels = Array.from({ length: 7 }, (_, index) => ({ cartonMark: `RC-${index}`, printableHtml: labelHtml(`RC-${index}`) }))
await print({ labels, printableHtml: 'last-four-boxes-only' })
assert.equal((calls.html.match(/<section class="return-label">/g) || []).length, 7)
assert.equal(calls.printed, 1)
assert.deepEqual(calls.errors, [])
})
test('待审核退货可编辑,完成入库后从独立新增页发起贴标', () => {
assert.match(view, /row\.status === 'PENDING_REVIEW'.*key: 'edit'/)
assert.match(view, /if \(editingReturnNo\.value\) await updateReturnOrder\(editingReturnNo\.value, payload\)/)
@@ -11,7 +11,7 @@ import { getMerchantWarehouses, type MerchantWarehouse } from '@/modules/first-l
import { createIdempotencyKey } from '@/utils/idempotencyKey'
import { createReturnOrder, downloadReturnPhoto, getReturnOrder, listReturnOrders, updateReturnOrder, type ReturnOrderDetail, type ReturnOrderSummary, type ReturnReceipt } from '../api/returnOrders'
import { getReturnInventoryLabel } from '../api/returnInventory'
import { formatReturnVolume, receiptBoxDetails, receiptPhysicalDetails, receiptTrackingNo } from '../utils/returnReceiptDisplay'
import { formatReturnVolume, receiptBoxDetails, receiptPhysicalDetails, receiptPrintableBoxCount, receiptTrackingNo } from '../utils/returnReceiptDisplay'
const props = withDefaults(defineProps<{ createPage?: boolean; detailPage?: boolean; returnNo?: string }>(), { createPage: false, detailPage: false, returnNo: '' })
const router = useRouter()
@@ -35,7 +35,7 @@ const signedBoxDetails = computed(() => receiptBoxDetails(selected.value?.receip
const physicalDetails = computed(() => receiptPhysicalDetails(selected.value?.pallets || [], signedBoxDetails.value))
const printableReceipts = computed(() => selected.value?.receipts.filter(item => item.unitType !== 'PARCEL' && (item.cartonMark || item.labels?.length)) || [])
const parcelReceipts = computed(() => selected.value?.receipts.filter(item => item.unitType === 'PARCEL') || [])
const printableBoxCount = computed(() => printableReceipts.value.reduce((total, receipt) => total + (receipt.labels?.length || receipt.boxCount || 1), 0))
const printableBoxCount = computed(() => receiptPrintableBoxCount(printableReceipts.value))
const photoUrls = reactive<Record<string, string>>({})
const rows = ref<ReturnOrderSummary[]>([])
const total = ref(0)
@@ -204,7 +204,7 @@ async function printReturnLabel(receipt: ReturnReceipt | ReturnReceipt[]) {
const labels = [...new Map(groups.flat().map(label => [label.cartonMark, label])).values()]
if (!labels.length) { popup.close(); ElMessage.warning('暂无可打印的唛头'); return }
const printStyles = [...new Set(labels.flatMap(label => label.printableHtml.match(/<style\b[^>]*>[\s\S]*?<\/style>/gi) || []))].join('')
const printableHtml = (receipts.length === 1 ? receipts[0]?.printableHtml : undefined) || `<!doctype html><html><head><meta charset="utf-8"><title>退货箱唛</title>${printStyles}<style>.return-label{break-after:page}.return-label:last-child{break-after:auto}.return-label .label{page-break-after:auto}</style></head><body>${labels.map((label) => {
const printableHtml = (receipts.length === 1 && !receipts[0]?.labels?.length ? receipts[0]?.printableHtml : undefined) || `<!doctype html><html><head><meta charset="utf-8"><title>退货箱唛</title>${printStyles}<style>.return-label{break-after:page}.return-label:last-child{break-after:auto}.return-label .label{page-break-after:auto}</style></head><body>${labels.map((label) => {
const html = label.printableHtml || ''
const bodyStart = html.indexOf('<body')
const contentStart = bodyStart < 0 ? 0 : html.indexOf('>', bodyStart) + 1