From d2bbd5024b31ed5d5e2c6bbaa6b57c63030641a5 Mon Sep 17 00:00:00 2001 From: liuyihe <2513762445@qq.com> Date: Fri, 9 Oct 2026 15:25:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../overseas-warehouse/api/returnOrders.ts | 3 ++- .../views/ReturnInventoryView.vue | 4 ++-- .../views/ReturnOrdersView.vue | 23 +++++++++++++++++++ .../views/WarehouseServiceView.vue | 14 +++++++---- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/modules/overseas-warehouse/api/returnOrders.ts b/src/modules/overseas-warehouse/api/returnOrders.ts index 31b4ea2..be70b82 100644 --- a/src/modules/overseas-warehouse/api/returnOrders.ts +++ b/src/modules/overseas-warehouse/api/returnOrders.ts @@ -19,7 +19,8 @@ export interface ReturnReceipt { export interface ReturnPallet { palletCode: string; unitType: 'PALLET' | 'BOX'; unitCode: string; skuTypes: number; totalQuantity: number; totalBoxCount: number; length?: number; width?: number; height?: number; weight?: number; volumeCbm?: number; items: Array<{ skuCode: string; productNameZh?: string; quantity: number; boxCount: number }> } export interface ReturnPhoto { fileId: number; fileName: string; contentType: string; sizeBytes: number } export interface ReturnPackingDetail { sourceCartonMark: string; targetCartonMark: string; returnNo: string; skuCode: string; quantity: number; createdAt: string } -export interface ReturnOrderDetail { order: ReturnOrderSummary; remark?: string; items: ReturnOrderItem[]; receipts: ReturnReceipt[]; pallets: ReturnPallet[]; photos: ReturnPhoto[]; packingDetails?: ReturnPackingDetail[] } +export interface ReturnReceiptCarton { receiptNo: string; palletCode?: string; cartonMark: string; countStatus: 'PENDING' | 'CONFIRMED' | 'UNRECORDED'; countedAt?: string; items: ReturnReceipt['items'] } +export interface ReturnOrderDetail { order: ReturnOrderSummary; remark?: string; items: ReturnOrderItem[]; receipts: ReturnReceipt[]; pallets: ReturnPallet[]; photos: ReturnPhoto[]; packingDetails?: ReturnPackingDetail[]; cartons?: ReturnReceiptCarton[] } export interface ReturnOrderCreate { overseasWarehouseId: string; warehouseContactName: string; warehouseContactPhone: string; customerReferenceNo?: string; remark?: string; needRelabel: boolean; idempotencyKey: string items: Array<{ skuCode: string; productNameZh?: string; expectedQuantity: number }> diff --git a/src/modules/overseas-warehouse/views/ReturnInventoryView.vue b/src/modules/overseas-warehouse/views/ReturnInventoryView.vue index d506bce..b76a16f 100644 --- a/src/modules/overseas-warehouse/views/ReturnInventoryView.vue +++ b/src/modules/overseas-warehouse/views/ReturnInventoryView.vue @@ -37,7 +37,7 @@ const warehouses = ref([]) const warehouseError = ref('') const warehousesLoading = ref(false) function formatInventoryTime(value?: string) { return value ? value.replace('T', ' ').slice(0, 19) : '—' } -function cartonStatusLabel(value: string) { return ({ AVAILABLE: '可用', MERGED: '已合箱', OUTBOUNDED: '已出库' } as Record)[value] || '—' } +function cartonStatusLabel(value: string) { return ({ PENDING_COUNT: '箱内待清点', AVAILABLE: '可用', MERGED: '已合箱', OUTBOUNDED: '已出库' } as Record)[value] || '—' } function warehouseLabel(warehouseId: string) { const warehouse = warehouses.value.find(item => String(item.id) === String(warehouseId)) return warehouse ? `${warehouse.warehouseName} · ${warehouse.warehouseCode}` : '—' @@ -81,7 +81,7 @@ const queryFields = computed(() => { if (activeTab.value === 'cartons') fields.push( { key: 'cartonMark', label: '箱号 / 箱唛', type: 'input', placeholder: '请输入箱号或箱唛' }, { key: 'returnNo', label: '退货单号', type: 'input', placeholder: '请输入退货单号' }, - { key: 'status', label: '箱状态', type: 'select', options: [{ label: '可用', value: 'AVAILABLE' }, { label: '已合箱', value: 'MERGED' }] }, + { key: 'status', label: '箱状态', type: 'select', options: [{ label: '箱内待清点', value: 'PENDING_COUNT' }, { label: '可用', value: 'AVAILABLE' }, { label: '已合箱', value: 'MERGED' }] }, ) return fields }) diff --git a/src/modules/overseas-warehouse/views/ReturnOrdersView.vue b/src/modules/overseas-warehouse/views/ReturnOrdersView.vue index 87de609..13706fe 100644 --- a/src/modules/overseas-warehouse/views/ReturnOrdersView.vue +++ b/src/modules/overseas-warehouse/views/ReturnOrdersView.vue @@ -24,6 +24,7 @@ const creating = ref(false) const showCreate = ref(false) const editingReturnNo = ref('') const selected = ref() +const showCartons = ref(false) const printableReceipts = computed(() => selected.value?.receipts.filter(item => item.unitType !== 'PARCEL' && (item.cartonMark || item.labels?.length)) || []) const printableBoxCount = computed(() => printableReceipts.value.reduce((total, receipt) => total + (receipt.labels?.length || receipt.boxCount || 1), 0)) const photoUrls = reactive>({}) @@ -393,6 +394,27 @@ onBeforeUnmount(clearPhotoUrls) +
+

签收箱号明细({{ selected.cartons?.length || 0 }} 箱)查看箱号明细

+ +
+ + + +
签收单 {{ box.receiptNo }}
+ + + + + +
{{ box.countStatus === 'PENDING' ? '箱内数量待仓库清点确认' : '未留存原始箱内明细,不以当前库存代替签收数量' }}
+
+
+ +
+ +
+

退货打托照片({{ selected.photos?.length || 0 }} 张)

@@ -472,6 +494,7 @@ 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; } diff --git a/src/modules/overseas-warehouse/views/WarehouseServiceView.vue b/src/modules/overseas-warehouse/views/WarehouseServiceView.vue index c7640d5..d108168 100644 --- a/src/modules/overseas-warehouse/views/WarehouseServiceView.vue +++ b/src/modules/overseas-warehouse/views/WarehouseServiceView.vue @@ -188,6 +188,8 @@ 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('') @@ -300,6 +302,8 @@ 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 = [] @@ -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 }) @@ -1549,12 +1555,12 @@ function addReturnBoxBinding(source: RelabelInventoryCandidate) {