@@ -397,14 +438,12 @@ onBeforeUnmount(clearPhotoUrls)
签收批次
{{ row.unitType === 'PALLET' ? '托盘' : row.unitType === 'BOX' ? '箱子' : '包裹' }}
- {{ row.trackingNo || '无快递单号' }}
+ {{ row.unitType === 'PARCEL' && row.unitCode === receiptTrackingNo(row) ? '—' : row.unitCode || '—' }}
+ {{ receiptTrackingNo(row) || '无快递单号' }}
{{ startedByLabel(row.startedBy) }}
{{ formatDateTime(row.signedAt) }}
-
- 包裹 {{ receipt.unitCode || receipt.trackingNo || receipt.receiptNo }} SKU 明细
- {{ item.skuCode }} × {{ item.quantity }}
-
+
@@ -461,11 +500,21 @@ onBeforeUnmount(clearPhotoUrls)
.return-detail-section :deep(.el-table .cell) { padding:0 8px; line-height:18px; }
.return-detail-section :deep(.el-table .el-tag) { font-size:12px; }
.return-pallet-list { padding:0 14px 10px; }
+.return-cartons-dialog-body { max-height:65vh; overflow-y:auto; }
.return-pallet-summary { margin-left:12px; color:#7c899c; font-size:12px; font-weight:400; }
+.return-pallet-measurements { margin-bottom:8px; color:#7c899c; font-size:12px; }
.return-photo-grid { display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:12px; padding:0 16px 16px; }
.return-photo { min-width:0; overflow:hidden; padding:0; border:1px solid #dfe6ef; border-radius:6px; color:#526176; background:#fff; cursor:pointer; }
.return-photo img,.return-photo>span { display:flex; width:100%; height:120px; align-items:center; justify-content:center; object-fit:cover; background:#f4f7fb; }
.return-photo small { display:block; overflow:hidden; padding:7px; text-overflow:ellipsis; white-space:nowrap; }
+.return-parcel-items { margin:10px 16px 16px; overflow:hidden; border:1px solid #dfe6ef; border-radius:8px; background:#fbfcfe; }
+.return-parcel-items__head { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 14px; color:#26364f; background:#f3f7fc; border-bottom:1px solid #e7edf5; }
+.return-parcel-items__head span { color:#1764c0; font-size:12px; font-weight:600; }
+.return-parcel-items__list { display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:8px; padding:10px; }
+.return-parcel-item { display:grid; grid-template-columns:minmax(110px,1fr) minmax(100px,1.4fr) auto; align-items:center; gap:10px; min-height:38px; padding:7px 10px; border:1px solid #edf1f5; border-radius:6px; background:#fff; }
+.return-parcel-item__sku { color:#2c3c55; font-weight:600; }
+.return-parcel-item__name { overflow:hidden; color:#8490a1; font-size:12px; text-overflow:ellipsis; white-space:nowrap; }
+.return-parcel-item strong { color:#1764c0; white-space:nowrap; }
@media (max-width: 760px) { .return-create-form { grid-template-columns:1fr; } }
@media (max-width: 1100px) { .return-detail-grid { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media (max-width: 900px) { .return-photo-grid { grid-template-columns:repeat(3,minmax(0,1fr)); } }
diff --git a/src/modules/overseas-warehouse/views/WarehouseServiceView.vue b/src/modules/overseas-warehouse/views/WarehouseServiceView.vue
index de8ff08..d108168 100644
--- a/src/modules/overseas-warehouse/views/WarehouseServiceView.vue
+++ b/src/modules/overseas-warehouse/views/WarehouseServiceView.vue
@@ -26,16 +26,14 @@ import {
} from '@/modules/first-leg/api/firstLeg'
import { loadAllWarehouseRecords } from '@/modules/first-leg/utils/warehousePagination'
import { createIdempotencyKey } from '@/utils/idempotencyKey'
-import { createReturnRelabel, uploadReturnRelabelFile } from '../api/returnOrders'
type ServiceType = 'labeling' | 'transfer' | 'disposal' | 'relabel'
type PageMode = 'list' | 'create' | 'edit' | 'detail'
type LabelingMode = 'carton' | 'sku' | 'carton_and_sku'
type RelabelTemplateType = 'carton' | 'sku' | 'mixed'
-interface CargoRow { id: number; included?: boolean; sku: string; name: string; quantity: number; availableQuantity?: number; sourceOrderId?: string; sourceType?: 'DROPSHIP' | 'RETURN_CARTON'; sourceInventoryBalanceId?: string; sourceInventoryPositionId?: string; sourceInboundOrderId?: string; returnCartonId?: string; sourceInboundOrderNo?: string; sourceInboundCode?: string; sourceWarehouseName?: string; palletNo?: string; warehouseLocationCode?: string; fnsku: string; shipmentNo: string; newSkuCode: string; shippingMark: string; customerCartonMarks: string; cartonMark: string; fbaCartonMark: string; destinationWarehouseId: string; remark: string }
+interface CargoRow { id: number; included?: boolean; sku: string; name: string; quantity: number; availableQuantity?: number; sourceOrderId?: string; sourceType?: 'DROPSHIP' | 'RETURN_CARTON' | 'RETURN_PARCEL'; sourceInventoryBalanceId?: string; sourceInventoryPositionId?: string; sourceInboundOrderId?: string; returnCartonId?: string; sourceInboundOrderNo?: string; sourceInboundCode?: string; sourceWarehouseName?: string; palletNo?: string; warehouseLocationCode?: string; fnsku: string; shipmentNo: string; newSkuCode: string; shippingMark: string; customerCartonMarks: string; cartonMark: string; fbaCartonMark: string; destinationWarehouseId: string; remark: string }
interface SkuRelabelRow { id: number; sourceRowId: number | null; cartonMark: string; originalSku: string; newSku: string; quantity: number; fbaCartonMark: string; destinationWarehouseId: string; remark: string }
interface ImportedRelabelBinding extends SkuRelabelRow { templateType: RelabelTemplateType; selected: boolean; shipmentNo: string }
-interface ReturnRelabelSkuRow { skuCode: string; productNameZh: string; availableQuantity: number; selected: boolean; quantity: number }
interface ServiceConfig { title: string; createTitle: string; numberLabel: string; emptyText: string; columns: string[] }
interface TransferCarton { cartonMark: string; customerCartonMark?: string; cartonIndex: number; totalCartons: number; status: string }
@@ -189,16 +187,23 @@ const selectedDiscardOrderId = ref('')
const discardCandidatesLoading = ref(false)
const relabelCandidates = ref
([])
const selectedRelabelInboundOrderId = ref('')
+const orderInfoCollapsed = ref(false)
+const availableBoxesCollapsed = ref(false)
+const availableSkusCollapsed = ref(false)
const relabelCandidatesLoading = ref(false)
const transferInventoryCandidates = ref([])
const selectedTransferInventory = ref('')
// Snowflake IDs exceed JavaScript's safe integer range. Keep them as strings
// all the way to JSON so the backend receives the exact source order ID.
const selectedTransferSourceOrderIds = ref([])
-const returnRelabelSkuRows = ref([])
const isReturnRelabelSource = computed(() => props.service === 'labeling' && selectedRelabelInboundOrderId.value.startsWith('RETURN_ORDER:'))
const selectedReturnOrderNo = computed(() => isReturnRelabelSource.value ? selectedRelabelInboundOrderId.value.slice('RETURN_ORDER:'.length) : '')
-const requiresBothTotalFiles = computed(() => (props.service === 'labeling' || (props.service === 'transfer' && form.relabel)) && !isReturnRelabelSource.value && labelingMode.value === 'carton_and_sku')
+const hideReturnSkuCartonMark = computed(() => isReturnRelabelSource.value && labelingMode.value === 'sku')
+const selectedReturnCandidates = computed(() => relabelCandidates.value.filter(item => Boolean(item.returnCartonId) && item.inboundOrderNo === selectedReturnOrderNo.value))
+const returnBoxCandidates = computed(() => selectedReturnCandidates.value.filter(item => item.sourceType === 'RETURN_CARTON'))
+const returnLooseCandidates = computed(() => selectedReturnCandidates.value.filter(item => item.sourceType === 'RETURN_PARCEL'))
+const returnSkuOnly = computed(() => isReturnRelabelSource.value && returnLooseCandidates.value.length > 0 && returnBoxCandidates.value.length === 0)
+const requiresBothTotalFiles = computed(() => (props.service === 'labeling' || (props.service === 'transfer' && form.relabel)) && labelingMode.value === 'carton_and_sku')
function inventoryQuantity(value: number | string | null | undefined) {
const quantity = Number(value)
return Number.isFinite(quantity) && quantity > 0 ? quantity : 0
@@ -207,7 +212,7 @@ const relabelInboundOptions = computed(() => {
const grouped = new Map()
for (const candidate of relabelCandidates.value) {
const returnOrderNo = candidate.inboundOrderNo || String(candidate.returnCartonId || '')
- const value = candidate.sourceType === 'RETURN_CARTON' ? `RETURN_ORDER:${returnOrderNo}` : String(candidate.inboundOrderId)
+ const value = candidate.returnCartonId ? `RETURN_ORDER:${returnOrderNo}` : String(candidate.inboundOrderId)
const current = grouped.get(value)
if (current) {
current.availablePackages += inventoryQuantity(candidate.availablePackages)
@@ -215,11 +220,11 @@ const relabelInboundOptions = computed(() => {
}
else grouped.set(value, {
value,
- inboundOrderNo: candidate.sourceType === 'RETURN_CARTON' ? `退货单 ${candidate.inboundOrderNo || '—'}` : (candidate.inboundOrderNo || '—'),
- inboundCode: candidate.sourceType === 'RETURN_CARTON' ? '已签收退货库存' : (candidate.inboundCode || '—'),
+ inboundOrderNo: candidate.returnCartonId ? `退货单 ${candidate.inboundOrderNo || '—'}` : (candidate.inboundOrderNo || '—'),
+ inboundCode: candidate.returnCartonId ? '已签收退货库存' : (candidate.inboundCode || '—'),
availablePackages: inventoryQuantity(candidate.availablePackages),
relabelledPackages: inventoryQuantity(candidate.relabelledPackages),
- quantityUnit: candidate.sourceType === 'RETURN_CARTON' ? '件' : '箱',
+ quantityUnit: candidate.returnCartonId ? '件' : '箱',
})
}
return [...grouped.values()]
@@ -263,7 +268,10 @@ watch(() => cargoRows.value.map((row) => row.sku), (skus) => {
if (sourceSku) row.sku = sourceSku
})
})
-watch(labelingMode, (value) => { if (value !== 'carton' && !skuRelabelRows.value.length) addSkuRelabelRow() })
+watch([returnSkuOnly, labelingMode], ([skuOnly, value]) => {
+ if (skuOnly && value !== 'sku') { labelingMode.value = 'sku'; return }
+ if (value !== 'carton' && !skuRelabelRows.value.length) addSkuRelabelRow()
+})
watch(() => form.destination, (value) => {
if (props.service !== 'labeling') return
for (const row of cargoRows.value) row.destinationWarehouseId = value
@@ -293,6 +301,9 @@ onMounted(() => {
onBeforeUnmount(() => { clearCompletionPhotos(); clearMeasurementPhotos() })
function resetFilters() { Object.assign(filters, { number: '', inboundNo: '', warehouse: '', destination: '', status: '', start: '', end: '', reviewStart: '', reviewEnd: '', completedStart: '', completedEnd: '', measuredStart: '', measuredEnd: '', outboundStart: '', outboundEnd: '' }) }
function resetForm() {
+ orderInfoCollapsed.value = false
+ availableBoxesCollapsed.value = false
+ availableSkusCollapsed.value = false
Object.assign(form, { customerNo: '', inboundNo: '', sourceWarehouse: '', warehouse: '', destination: '', privateDestinationAddress: '', privateDestinationPostalCode: '', privateDestinationContact: '', privateDestinationPhone: '', address: '', contact: '', phone: '', pickupContact: '', pickupPhone: '', relabelContact: '', relabelPhone: '', deliveryMethod: '', relabelDeliveryMethod: '', trackingNo: '', reason: '', requirement: '', relabel: false, remark: '', labelDeadline: '', estimatedArrivalAt: '', estimatedShipAt: '', fbaShipmentNo: '', volumeCbm: 0.01 })
cargoRows.value = []
transferRelabelRows.value = []
@@ -490,7 +501,7 @@ function clearTransferRelabelRows() {
function addSkuRelabelRow() {
const source = cargoRows.value[Math.min(skuRelabelRows.value.length, Math.max(0, cargoRows.value.length - 1))]
skuRelabelRows.value.push({ id: ++skuRelabelSequence, sourceRowId: source?.id || null,
- cartonMark: '', originalSku: source?.sku || '', newSku: '', quantity: 1,
+ cartonMark: hideReturnSkuCartonMark.value ? source?.cartonMark || '' : '', originalSku: source?.sku || '', newSku: '', quantity: 1,
fbaCartonMark: '', destinationWarehouseId: form.destination, remark: '' })
}
function removeSkuRelabelRow(id: number) { skuRelabelRows.value = skuRelabelRows.value.filter((row) => row.id !== id) }
@@ -532,6 +543,16 @@ function chooseCreateTotalFile(scope: 'CARTON_TOTAL' | 'SKU_TOTAL') {
function buildSkuRelabelItems(): RelabelCreate['items'] {
const groups = new Map()
for (const row of skuRelabelRows.value) {
+ if (hideReturnSkuCartonMark.value) {
+ const source = cargoRows.value.find(item => item.id === row.sourceRowId)
+ const candidate = selectedReturnCandidates.value.find(item => String(item.returnCartonId) === source?.returnCartonId)
+ if (candidate?.skuItems?.some(item => item.skuCode === row.originalSku.trim())) row.cartonMark = source?.cartonMark || ''
+ else {
+ const matches = selectedReturnCandidates.value.filter(item => item.skuItems?.some(sku => sku.skuCode === row.originalSku.trim()))
+ if (matches.length !== 1) throw new Error(`请从上方库存明细选择 SKU ${row.originalSku} 的来源库存`)
+ row.cartonMark = matches[0].cartonMark || ''
+ }
+ }
const cartonMark = row.cartonMark.trim().toUpperCase()
if (!cartonMark) throw new Error('请填写每个箱子的我方箱唛')
const rows = groups.get(cartonMark) || []
@@ -546,7 +567,20 @@ function buildSkuRelabelItems(): RelabelCreate['items'] {
throw new Error('填写的箱唛数量超过当前入仓单可用库存箱数')
}
return [...groups.entries()].map(([_, rows], groupIndex) => {
- const source = cargoRows.value.find((item) => item.id === rows[0].sourceRowId) || anchors[groupIndex]
+ const source = isReturnRelabelSource.value
+ ? cargoRows.value.find(item => item.cartonMark === rows[0].cartonMark.trim())
+ : cargoRows.value.find((item) => item.id === rows[0].sourceRowId) || anchors[groupIndex]
+ if (isReturnRelabelSource.value && !source) throw new Error('请选择该退货单实际可用的来源箱号')
+ if (isReturnRelabelSource.value) {
+ const candidate = selectedReturnCandidates.value.find(item => String(item.returnCartonId) === source?.returnCartonId)
+ if (candidate?.sourceType === 'RETURN_PARCEL' && labelingMode.value !== 'sku') throw new Error('散件库存只能贴 SKU,请先合箱后申请箱唛或混贴')
+ const requested = new Map()
+ for (const row of rows) {
+ const quantity = (requested.get(row.originalSku) || 0) + row.quantity
+ requested.set(row.originalSku, quantity)
+ if (quantity > Number(candidate?.skuItems?.find(item => item.skuCode === row.originalSku)?.quantity || 0)) throw new Error(`SKU ${row.originalSku} 超过来源箱可用数量`)
+ }
+ }
if (!source?.returnCartonId && (!source?.sourceInventoryBalanceId || !source.sourceInventoryPositionId || !source.sourceInboundOrderId)) {
throw new Error('来源库存已变化,请重新选择有库存的历史入仓单')
}
@@ -949,48 +983,18 @@ function listRowActions(candidate: object): TableAction[] {
if (canConfirmRelabel.value && props.service === 'labeling' && item.__status === 'CUSTOMER_CONFIRM_PENDING' && !item.__confirmedAt) actions.push({ key: 'confirm-relabel', label: '确认换标', run: () => confirmRelabelFromList(item['0']) })
return actions
}
-async function submitReturnRelabel() {
- const items = returnRelabelSkuRows.value.filter(item => item.selected)
- .map(item => ({ skuCode: item.skuCode, quantity: Number(item.quantity) }))
- if (!selectedReturnOrderNo.value || !items.length) { ElMessage.warning('请至少选择一个需要贴标的 SKU'); return }
- if (items.some(item => item.quantity < 1 || item.quantity > (returnRelabelSkuRows.value.find(row => row.skuCode === item.skuCode)?.availableQuantity || 0))) {
- ElMessage.warning('本次贴标数量必须大于 0,且不能超过该 SKU 的库存总数'); return
- }
- const destination = fbaWarehouses.value.find(warehouse => warehouse.warehouseCode === form.destination)
- if (!destination) { ElMessage.warning('请选择 FBA 目的仓'); return }
- const selectedFile = cartonTotalFile.value || skuTotalFile.value
- const fileScope = cartonTotalFile.value ? 'CARTON_TOTAL' as const : 'SKU_TOTAL' as const
- if (!selectedFile) { ElMessage.warning('请上传箱唛总文件或 SKU 总文件(二选一)'); return }
- try { await ElMessageBox.confirm(`确认提交退货单 ${selectedReturnOrderNo.value} 的贴标申请吗?`, '提交确认', { confirmButtonText: '提交', cancelButtonText: '取消' }) } catch { return }
- saving.value = true
- try {
- const created = await createReturnRelabel(selectedReturnOrderNo.value, {
- items,
- fileScope,
- destinationFbaWarehouseId: String(destination.id),
- destinationFbaWarehouseCode: destination.warehouseCode,
- cartonRemark: form.remark.trim() || undefined,
- idempotencyKey: createIdempotencyKey(),
- })
- await uploadReturnRelabelFile(created.relabelNo, fileScope, selectedFile)
- ElMessage.success(`贴标申请 ${created.relabelNo} 已提交,等待审核`)
- await router.push({ name: 'overseas-labeling' })
- } catch (error) { ElMessage.error(error instanceof Error ? error.message : '退货贴标申请提交失败,请重试') }
- finally { saving.value = false }
-}
watch([page, pageSize], ([nextPage, nextSize], [previousPage, previousSize]) => {
if (nextSize !== previousSize && nextPage !== 1) { page.value = 1; return }
void load()
})
async function submit(action: 'draft' | 'submit' = 'submit') {
- if (isReturnRelabelSource.value) { await submitReturnRelabel(); return }
const primaryWarehouse = props.service === 'relabel' ? form.sourceWarehouse : form.warehouse
const relabelRows = labelingMode.value === 'carton' ? cartonDetailRows.value : skuRelabelRows.value
const invalidCargo = props.service === 'disposal'
? !selectedDiscardOrderId.value || cargoRows.value.every((item) => item.quantity < 1)
|| cargoRows.value.some((item) => item.quantity < 0 || item.quantity > Number(item.availableQuantity || 0))
: (props.service === 'labeling' || props.service === 'relabel') && (relabelRows.length === 0 || (props.service === 'labeling' && labelingMode.value !== 'carton'
- ? skuRelabelRows.value.some((item) => !item.cartonMark || !item.originalSku || !item.newSku || item.quantity < 1
+ ? skuRelabelRows.value.some((item) => (!hideReturnSkuCartonMark.value && !item.cartonMark) || !item.originalSku || !item.newSku || item.quantity < 1
|| (labelingMode.value === 'carton_and_sku' && !item.fbaCartonMark))
: cargoRows.value.some((item) => (props.service !== 'labeling' && !item.sku) || !item.name
|| (props.service !== 'labeling' && item.quantity < 1))))
@@ -1019,7 +1023,7 @@ async function submit(action: 'draft' | 'submit' = 'submit') {
if (props.service === 'labeling' && labelingMode.value === 'carton' && cartonDetailRows.value.some((item) => !item.shipmentNo || !item.cartonMark || !item.fbaCartonMark)) {
ElMessage.warning('请上传关联面单,确保每箱的我方箱唛和 FBA 箱唛完整'); return
}
- if (props.service === 'labeling' && labelingMode.value === 'carton' && cartonDetailRows.value.some((item) => !item.sourceInventoryPositionId)) {
+ if (props.service === 'labeling' && labelingMode.value === 'carton' && cartonDetailRows.value.some((item) => !item.returnCartonId && !item.sourceInventoryPositionId)) {
ElMessage.warning('请选择有库存的历史入仓单'); return
}
if (props.service === 'disposal' && !form.reason) {
@@ -1061,6 +1065,8 @@ async function submit(action: 'draft' | 'submit' = 'submit') {
const items = labelingMode.value === 'carton'
? cartonDetailRows.value.map((item) => ({ sourceInventoryBalanceId: item.sourceInventoryBalanceId, sourceInventoryPositionId: item.sourceInventoryPositionId, sourceInboundOrderId: item.sourceInboundOrderId, returnCartonId: item.returnCartonId, skuCode: item.sku, productNameZh: item.name, totalPackageCount: 1, notifiedPackageCount: 1, shipmentNo: item.shipmentNo, trackingCode: form.trackingNo || undefined, newSkuCode: undefined, labelRequirement: form.requirement || undefined, cartonMark: item.cartonMark, fbaCartonMark: item.fbaCartonMark, destinationFbaWarehouseCode: form.destination, operationType: 'CARTON_LABEL' as const, skuItems: [], remark: item.remark || undefined }))
: buildSkuRelabelItems()
+ const selectedOperationType = labelingMode.value === 'carton' ? 'CARTON_LABEL' : labelingMode.value === 'sku' ? 'SKU_LABEL' : 'CARTON_AND_SKU'
+ if (items.some(item => item.operationType !== selectedOperationType)) throw new Error('一张申请只能选择一种换标类型,请核对绑定明细')
const created = await createRelabel({ customerOrderNo: sourceInboundOrders || '贴标申请', operationWarehouseId: form.warehouse, labelDeadline: form.labelDeadline, contactName: form.contact, contactPhone: form.phone, remark: form.remark || undefined, idempotencyKey, items,
deliveryMethod: labelingMode.value === 'sku' ? undefined : form.deliveryMethod as 'TRUCK' | 'EXPRESS' | 'TRUCK_PICKUP' | 'EXPRESS_PICKUP',
printShippingLabel: labelingMode.value !== 'sku' && (form.deliveryMethod === 'EXPRESS' || form.deliveryMethod === 'EXPRESS_PICKUP') && form.relabel })
@@ -1399,34 +1405,17 @@ function selectRelabelInventory(inboundOrderId: string) {
const rows: CargoRow[] = []
const selectedCandidates = relabelCandidates.value.filter((item) => {
const returnOrderNo = item.inboundOrderNo || String(item.returnCartonId || '')
- return (item.sourceType === 'RETURN_CARTON' ? `RETURN_ORDER:${returnOrderNo}` : String(item.inboundOrderId)) === inboundOrderId
+ return (item.returnCartonId ? `RETURN_ORDER:${returnOrderNo}` : String(item.inboundOrderId)) === inboundOrderId
})
- returnRelabelSkuRows.value = []
if (inboundOrderId.startsWith('RETURN_ORDER:')) {
- const grouped = new Map()
- for (const candidate of selectedCandidates) {
- const skuItems = candidate.skuItems?.length
- ? candidate.skuItems
- : candidate.skuCode ? [{ skuCode: candidate.skuCode, quantity: inventoryQuantity(candidate.availablePackages) }] : []
- for (const item of skuItems) {
- const skuCode = item.skuCode.trim()
- if (!skuCode) continue
- const key = skuCode.toUpperCase()
- const current = grouped.get(key)
- const quantity = inventoryQuantity(item.quantity)
- if (current) current.availableQuantity += quantity
- else grouped.set(key, {
- skuCode,
- productNameZh: candidate.skuCode?.trim().toUpperCase() === key ? (candidate.productNameZh || '') : '',
- availableQuantity: quantity,
- selected: false,
- // 可贴库存和本次申请数量是两个概念;重复换标时默认不应自动带入上次/首个箱子的数量。
- quantity: 0,
- })
- }
- }
- returnRelabelSkuRows.value = [...grouped.values()]
labelingMode.value = 'sku'
+ for (const candidate of selectedCandidates) rows.push({
+ id: ++cargoSequence, sku: candidate.skuItems?.[0]?.skuCode || candidate.skuCode || '',
+ name: candidate.productNameZh || '退货库存', included: false, quantity: 1, availableQuantity: 1,
+ returnCartonId: String(candidate.returnCartonId), sourceInboundOrderNo: candidate.inboundOrderNo,
+ fnsku: '', shipmentNo: candidate.inboundOrderNo || '', newSkuCode: '', shippingMark: '', customerCartonMarks: '',
+ cartonMark: candidate.cartonMark || '', fbaCartonMark: '', destinationWarehouseId: '', remark: '',
+ })
} else for (const candidate of selectedCandidates) {
for (const position of candidate.positions) rows.push(...Array.from({ length: Math.min(inventoryQuantity(position.availablePackages), 500) }, () => ({
id: ++cargoSequence, sku: candidate.skuCode || '', name: candidate.productNameZh || '库存货物',
@@ -1440,7 +1429,7 @@ function selectRelabelInventory(inboundOrderId: string) {
})))
}
cargoRows.value = rows.slice(0, 500)
- if (cargoRows.value.length) cargoRows.value[0].included = true
+ if (cargoRows.value.length && !inboundOrderId.startsWith('RETURN_ORDER:')) cargoRows.value[0].included = true
skuRelabelRows.value = []
importedRelabelBindings.value = []
shippingLabelFile.value = null
@@ -1448,6 +1437,22 @@ function selectRelabelInventory(inboundOrderId: string) {
skuTotalFile.value = null
if (!isReturnRelabelSource.value && labelingMode.value !== 'carton') addSkuRelabelRow()
}
+function addReturnSkuBinding(source: RelabelInventoryCandidate, skuCode: string) {
+ const sku = source.skuItems?.find(item => item.skuCode === skuCode)
+ if (!sku) return
+ const row = skuRelabelRows.value.find(item => item.cartonMark === source.cartonMark && item.originalSku === skuCode)
+ if (row) return
+ const sourceRow = cargoRows.value.find(item => item.returnCartonId === String(source.returnCartonId))
+ skuRelabelRows.value.push({ id: ++skuRelabelSequence, sourceRowId: sourceRow?.id || null, cartonMark: source.cartonMark || '', originalSku: skuCode, newSku: '', quantity: Math.max(1, Number(sku.quantity)), fbaCartonMark: '', destinationWarehouseId: '', remark: '' })
+}
+function addReturnBoxBinding(source: RelabelInventoryCandidate) {
+ if (labelingMode.value !== 'carton') {
+ for (const sku of source.skuItems || []) addReturnSkuBinding(source, sku.skuCode)
+ return
+ }
+ if (cartonDetailRows.value.some(item => item.cartonMark === source.cartonMark)) return
+ cargoRows.value.push({ id: ++cargoSequence, included: true, sku: source.skuItems?.map(item => item.skuCode).join(',') || '', name: source.productNameZh || '退货箱', shipmentNo: selectedReturnOrderNo.value, cartonMark: source.cartonMark || '', fbaCartonMark: '', remark: '', sourceInventoryBalanceId: undefined, sourceInventoryPositionId: undefined, sourceInboundOrderId: undefined, returnCartonId: String(source.returnCartonId), quantity: 1, fnsku: '', newSkuCode: '', shippingMark: '', customerCartonMarks: '', destinationWarehouseId: '' })
+}
@@ -1467,8 +1472,17 @@ function selectRelabelInventory(inboundOrderId: string) {
{{ mode === 'edit' ? `编辑转运草稿 ${editingTransferNo}` : config.createTitle }}
返回列表