@@ -5,12 +5,18 @@ import { ArrowLeft, Download, Eye, Plus, Search, Trash2, Upload } from '@lucide/
import SingleLineText from '@/components/common/SingleLineText.vue'
import {
createDiscard , createRelabel , createTransfer , getDiscard , getRelabel , getTransfer ,
confirmRelabelCompletion , downloadRelabelCompletionPhoto , uploadRelabelShippingLabel ,
listDiscardCandidates , listDiscards , listLastlegOrders , listRelabelInventoryCandidates , listRelabels , listTransfers ,
type RelabelInventoryCandidate ,
type RelabelCreate ,
type RelabelDetail ,
} from '../api/warehouseServices'
import { getMerchantWarehouses , type MerchantWarehouse } from '@/modules/first-leg/api/firstLeg'
import {
getMerchantWarehouseDetail ,
getMerchantWarehouses ,
type MerchantWarehouse ,
type MerchantWarehouseDetail ,
} from '@/modules/first-leg/api/firstLeg'
type ServiceType = 'labeling' | 'transfer' | 'disposal' | 'relabel'
type PageMode = 'list' | 'create' | 'detail'
@@ -22,21 +28,31 @@ interface ServiceConfig { title: string; createTitle: string; numberLabel: strin
const props = defineProps < { service : ServiceType } > ( )
const configs : Record < ServiceType , ServiceConfig > = {
labeling : { title : '贴标申请' , createTitle : '新增贴标申请' , numberLabel : '贴标申请单号' , emptyText : '暂无贴标申请' , columns : [ '操作' , '贴标申请单号' , '客户单号' , '海外操作仓' , '贴标要求' , 'SKU 数' , '总箱数' , '状态' , '创建时间' ] } ,
transfer : { title : '仓储转运单' , createTitle : '新增仓储转运单' , numberLabel : '转运单号' , emptyText : '暂无仓储转运订单' , columns : [ '操作' , '转运单号' , '进仓编号' , '发货 箱数' , '操作 仓' , 'FBA 目的仓' , '派送 方式' , '是否换标' , '状态' , '创建时间' ] } ,
transfer : { title : '仓储转运单' , createTitle : '新增仓储转运单' , numberLabel : '转运单号' , emptyText : '暂无仓储转运订单' , columns : [ '操作' , '转运单号' , '进仓编号' , '入库 箱数' , '中转 仓' , 'FBA 目的仓' , '入仓 方式' , '是否换标' , '状态' , '创建时间' ] } ,
disposal : { title : '货物废弃' , createTitle : '新增货物废弃申请' , numberLabel : '废弃申请单号' , emptyText : '暂无货物废弃申请' , columns : [ '操作' , '废弃申请单号' , '进仓编号' , '操作仓' , 'SKU 汇总' , '废弃数量' , '预估费用' , '状态' , '创建时间' ] } ,
relabel : { title : '退货换标' , createTitle : '新建退货换标单' , numberLabel : '退货换标单号' , emptyText : '暂无退货换标订单' , columns : [ '操作' , '退货换标单号' , '来源 FBA 仓' , '目的 FBA 仓' , 'SKU 汇总' , '退件总数' , '是否换标' , '换标状态' , '尾程状态' , '创建时间' ] } ,
}
const config = computed ( ( ) => configs [ props . service ] )
const statusOptions = computed ( ( ) => props . service === 'labeling'
? [ { label : '待处理' , value : 'PENDING_PROCESSING' } , { label : '处理中' , value : 'PROCESSING' } , { label : '已完成' , value : 'COMPLETED' } , { label : '已拒绝' , value : 'REJECTED' } , { label : '已取消' , value : 'CANCELLED' } ]
? [ { label : '待处理' , value : 'PENDING_PROCESSING' } , { label : '处理中' , value : 'PROCESSING' } , { label : '待客户确认' , value : 'CUSTOMER_CONFIRM_PENDING' } , { label : '待出库' , value : 'READY_FOR_OUTBOUND' } , { label : '已完成' , value : 'COMPLETED' } , { label : '已拒绝' , value : 'REJECTED' } , { label : '已取消' , value : 'CANCELLED' } ]
: props . service === 'disposal'
? [ { label : '待审核' , value : 'PENDING_REVIEW' } , { label : '已通过' , value : 'APPROVED' } , { label : '已拒绝' , value : 'REJECTED' } ]
: [ { label : '待审核' , value : 'PENDING_REVIEW' } , { label : '已通过' , value : 'APPROVED' } , { label : '待分配' , value : 'PENDING_ASSIGNMENT' } , { label : '已分配' , value : 'ALLOCATED' } , { label : '已出库' , value : 'OUTBOUNDED' } , { label : '部分收货' , value : 'PARTIALLY_RECEIVED' } , { label : '已收货' , value : 'RECEIVED' } , { label : '已拒绝' , value : 'REJECTED' } ] )
const mode = ref < PageMode > ( 'list' )
const filters = reactive ( { number : '' , inboundNo : '' , warehouse : '' , destination : '' , status : '' , start : '' , end : '' } )
const form = reactive ( { customerNo : '' , inboundNo : '' , sourceWarehouse : '' , warehouse : '' , destination : '' , address : '' , contact : '' , phone : '' , deliveryMethod : '' , trackingNo : '' , reason : '' , requirement : '' , relabel : false , remark : '' , labelDeadline : '' , estimatedArrivalAt : '' , fbaShipmentNo : '' , volumeCbm : 0.01 , chargeAmount : 0 } )
const transferHasFbaDestination = ref ( false )
const selectedOperationWarehouse = ref < MerchantWarehouseDetail | null > ( null )
const operationWarehouseDetailLoading = ref ( false )
const operationWarehouseAddress = computed ( ( ) => {
const address = selectedOperationWarehouse . value ? . addresses [ 0 ]
if ( ! address ) return ''
return [ address . addressLine1 , address . addressLine2 , address . city , address . stateProvince , address . postalCode , address . countryCode ]
. filter ( Boolean ) . join ( ', ' )
} )
const cargoRows = ref < CargoRow [ ] > ( [ ] )
const labelingMode = ref < LabelingMode > ( 'carton' )
const shippingLabelFile = ref < File | null > ( null )
const skuRelabelRows = ref < SkuRelabelRow [ ] > ( [ ] )
const labelingModeHint = computed ( ( ) => labelingMode . value === 'carton'
? '只替换外箱箱唛,不修改箱内商品 SKU 标签;按箱填写新的 FBA 箱唛和目的仓。'
@@ -90,6 +106,8 @@ function resetForm() {
selectedDiscardOrderId . value = ''
relabelCandidates . value = [ ]
selectedRelabelInboundOrderId . value = ''
transferHasFbaDestination . value = false
selectedOperationWarehouse . value = null
}
async function openCreate ( ) {
resetForm ( ) ; mode . value = 'create'
@@ -109,6 +127,7 @@ function addSkuRelabelRow() {
fbaCartonMark : '' , destinationWarehouseId : source ? . destinationWarehouseId || '' , remark : '' } )
}
function removeSkuRelabelRow ( id : number ) { skuRelabelRows . value = skuRelabelRows . value . filter ( ( row ) => row . id !== id ) }
function selectShippingLabel ( event : Event ) { shippingLabelFile . value = ( event . target as HTMLInputElement ) . files ? . [ 0 ] || null }
function buildSkuRelabelItems ( ) : RelabelCreate [ 'items' ] {
const groups = new Map < string , SkuRelabelRow [ ] > ( )
for ( const row of skuRelabelRows . value ) {
@@ -247,7 +266,8 @@ function warehouseDisplay(value?: string) {
function statusLabel ( value : string ) {
const labels : Record < string , string > = {
PENDING _PROCESSING : '待处理' , PROCESSING : '处理中' , COMPLETED : '已完成' , CANCELLED : '已取消 ' ,
PENDING _PROCESSING : '待处理' , PROCESSING : '处理中' , CUSTOMER _CONFIRM _PENDING : '待客户确认 ' ,
READY _FOR _OUTBOUND : '待出库' , COMPLETED : '已完成' , CANCELLED : '已取消' ,
PENDING _REVIEW : '待审核' , APPROVED : '已通过' , REJECTED : '已拒绝' , PENDING _ASSIGNMENT : '待分配' ,
ALLOCATED : '已分配' , OUTBOUNDED : '已出库' , PARTIALLY _RECEIVED : '部分收货' , RECEIVED : '已收货' ,
@@ -255,10 +275,15 @@ function statusLabel(value: string) {
return labels [ value ] || value || '—'
}
function deliveryMethodLabel ( value : string ) {
const labels : Record < string , string > = { TRUCK : '卡车派送' , EXPRESS : '快递派送' }
const labels : Record < string , string > = {
TRUCK : '卡车派送' , EXPRESS : '快递派送' , TRUCK _PICKUP : '卡车自提' , EXPRESS _PICKUP : '快递自提' ,
WAREHOUSE _PICKUP : '仓库上门提货' , CUSTOMER _DELIVERY : '客户送货到仓' ,
// Keep the legacy value readable for historical applications created before the four-way split.
PICKUP : '仓库自提' ,
}
return labels [ value ] || value || '—'
}
function formatDateTime ( value : string ) {
function formatDateTime ( value ? : string | null ) {
return value ? value . replace ( 'T' , ' ' ) . slice ( 0 , 19 ) : '—'
}
async function load ( ) {
@@ -299,6 +324,13 @@ async function submit() {
if ( props . service === 'labeling' && ( ! form . labelDeadline || ! form . contact || ! form . phone || form . chargeAmount <= 0 ) ) {
ElMessage . warning ( '请填写贴标截止时间、联系人和贴标费用' ) ; return
}
if ( props . service === 'labeling' && labelingMode . value !== 'sku' && ! form . deliveryMethod ) {
ElMessage . warning ( '请选择换标完成后的派送方式' ) ; return
}
if ( props . service === 'labeling' && labelingMode . value !== 'sku' && ( form . deliveryMethod === 'EXPRESS' || form . deliveryMethod === 'EXPRESS_PICKUP' )
&& form . relabel && ! shippingLabelFile . value ) {
ElMessage . warning ( '选择打印面单时必须上传面单文件' ) ; return
}
if ( props . service === 'labeling' && labelingMode . value === 'carton' && cargoRows . value . some ( ( item ) => ! item . shipmentNo || ! item . cartonMark || ! item . fbaCartonMark ) ) {
ElMessage . warning ( '请上传关联面单,确保每箱的我方箱唛和 FBA 箱唛完整' ) ; return
}
@@ -308,9 +340,15 @@ async function submit() {
if ( props . service === 'disposal' && ! form . reason ) {
ElMessage . warning ( '请选择废弃原因' ) ; return
}
if ( ( props . service === 'transfer' || props . service === 'relabel' ) && ( ! form . destination || ! form . address || ! form . deliveryMethod || ! form . estimatedArrivalAt || ! form . fbaShipmentNo || form . volumeCbm <= 0 ) ) {
if ( props . service === 'relabel' && ( ! form . destination || ! form . address || ! form . deliveryMethod || ! form . estimatedArrivalAt || ! form . fbaShipmentNo || form . volumeCbm <= 0 ) ) {
ElMessage . warning ( '请填写完整的派送信息、体积、预计到达时间和 FBA 货件号' ) ; return
}
if ( props . service === 'transfer' && ( ! form . warehouse || ! form . deliveryMethod || ! form . address || ! form . estimatedArrivalAt || form . volumeCbm <= 0 ) ) {
ElMessage . warning ( form . deliveryMethod === 'WAREHOUSE_PICKUP' ? '请填写中转仓、提货地址和预计入仓时间' : '请选择中转仓并确认预计入仓时间' ) ; return
}
if ( props . service === 'transfer' && transferHasFbaDestination . value && ( ! form . destination || ! form . fbaShipmentNo ) ) {
ElMessage . warning ( '已选择有 FBA 去向,请填写 FBA 目的仓和货件编号' ) ; return
}
try { await ElMessageBox . confirm ( ` 确认提交 ${ config . value . title } 吗? ` , '提交确认' , { confirmButtonText : '提交' , cancelButtonText : '取消' } ) } catch { return }
saving . value = true
try {
@@ -320,7 +358,10 @@ async function submit() {
const items = labelingMode . value === 'carton'
? cargoRows . value . map ( ( item ) => ( { sourceInventoryBalanceId : item . sourceInventoryBalanceId ! , sourceInventoryPositionId : item . sourceInventoryPositionId ! , sourceInboundOrderId : item . sourceInboundOrderId ! , skuCode : item . sku , productNameZh : item . name , totalPackageCount : item . quantity , notifiedPackageCount : item . quantity , shipmentNo : item . shipmentNo , trackingCode : form . trackingNo || undefined , newSkuCode : undefined , labelRequirement : form . requirement || undefined , cartonMark : item . cartonMark , fbaCartonMark : item . fbaCartonMark , destinationFbaWarehouseCode : item . destinationWarehouseId , operationType : 'CARTON_LABEL' as const , skuItems : [ ] , remark : item . remark || undefined } ) )
: buildSkuRelabelItems ( )
await createRelabel ( { customerOrderNo : sourceInboundOrders || '贴标申请' , operationWarehouseId : form . warehouse , labelDeadline : form . labelDeadline , contactName : form . contact , contactPhone : form . phone , chargeAmount : form . chargeAmount , remark : form . remark || undefined , idempotencyKey , items } )
const created = await createRelabel ( { customerOrderNo : sourceInboundOrders || '贴标申请' , operationWarehouseId : form . warehouse , labelDeadline : form . labelDeadline , contactName : form . contact , contactPhone : form . phone , chargeAmount : form . chargeAmount , 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 } )
if ( shippingLabelFile . value ) await uploadRelabelShippingLabel ( created . application . relabelNo , shippingLabelFile . value )
} else if ( props . service === 'disposal' ) {
const items = cargoRows . value . filter ( ( item ) => item . quantity > 0 ) . map ( ( item ) => {
if ( ! item . sourceOrderId || item . sourceOrderId !== selectedDiscardOrderId . value || item . quantity > Number ( item . availableQuantity || 0 ) ) {
@@ -333,7 +374,7 @@ async function submit() {
const sources = await listLastlegOrders ( form . inboundNo )
if ( sources . records . length === 0 ) throw new Error ( '未找到该入仓码对应的尾程订单' )
const packageCount = cargoRows . value . reduce ( ( sum , item ) => sum + item . quantity , 0 )
await createTransfer ( { inboundCode : form . inboundNo , sourceLastlegOrderIds : sources . records . map ( ( item ) => item . id ) , operatingWarehouseId : primaryWarehouse , fbaWarehouseCode : form . destination , deliveryAddress : form . address , packageCount , volumeCbm : form . volumeCbm , deliveryMethod : form . deliveryMethod , estimatedArrivalAt : form . estimatedArrivalAt , fbaShipmentNo : form . fbaShipmentNo , trackingNo : form . trackingNo || undefined , remark : form . remark || undefined , needRelabel : props . service === 'relabel' || form . relabel , idempotencyKey , items : cargoRows . value . map ( ( item ) => ( { skuCode : item . sku , productNameZh : item . name , packageCount : item . quantity , shippingMark : item . shippingMark || undefined } ) ) } )
await createTransfer ( { inboundCode : form . inboundNo , sourceLastlegOrderIds : sources . records . map ( ( item ) => item . id ) , operatingWarehouseId : primaryWarehouse , fbaWarehouseCode : form . destination || undefined , deliveryAddress : form . address , packageCount , volumeCbm : form . volumeCbm , deliveryMethod : form . deliveryMethod , estimatedArrivalAt : form . estimatedArrivalAt , fbaShipmentNo : form . fbaShipmentNo || undefined , trackingNo : form . trackingNo || undefined , remark : form . remark || undefined , needRelabel : props . service === 'relabel' || form . relabel , idempotencyKey , items : cargoRows . value . map ( ( item ) => ( { skuCode : item . sku , productNameZh : item . name , packageCount : item . quantity , shippingMark : item . shippingMark || undefined } ) ) } )
}
ElMessage . success ( ` ${ config . value . title } 提交成功 ` ) ; mode . value = 'list' ; await load ( )
} catch ( error ) { ElMessage . error ( error instanceof Error ? error . message : '提交失败' ) }
@@ -347,6 +388,25 @@ async function openDetail(value: Record<string, string>) {
mode . value = 'detail'
} catch ( error ) { ElMessage . error ( error instanceof Error ? error . message : '详情加载失败' ) }
}
async function confirmRelabel ( ) {
const relabelNo = selectedRelabelDetail . value ? . application . relabelNo
if ( ! relabelNo ) return
try {
await ElMessageBox . confirm ( '确认仓库上传的换标结果无误并继续出库流程吗?' , '换标完成确认' , { confirmButtonText : '确认并继续' , cancelButtonText : '取消' } )
selectedRelabelDetail . value = await confirmRelabelCompletion ( relabelNo )
ElMessage . success ( '已确认换标完成,订单已进入后续出库流程' )
} catch ( error ) { if ( error !== 'cancel' ) ElMessage . error ( error instanceof Error ? error . message : '确认失败' ) }
}
async function previewCompletionPhoto ( fileId : string ) {
const relabelNo = selectedRelabelDetail . value ? . application . relabelNo
if ( ! relabelNo ) return
try {
const blob = await downloadRelabelCompletionPhoto ( relabelNo , fileId )
const url = URL . createObjectURL ( blob )
window . open ( url , '_blank' , 'noopener,noreferrer' )
window . setTimeout ( ( ) => URL . revokeObjectURL ( url ) , 60 _000 )
} catch ( error ) { ElMessage . error ( error instanceof Error ? error . message : '完工照片加载失败' ) }
}
async function loadWarehouses ( ) {
fbaWarehousesLoading . value = true
fbaWarehousesError . value = ''
@@ -364,6 +424,31 @@ async function loadWarehouses() {
} finally { fbaWarehousesLoading . value = false }
}
function warehouseLabel ( value : MerchantWarehouse ) { return ` ${ value . warehouseName } · ${ value . warehouseCode } ` }
async function selectTransferWarehouse ( ) {
selectedOperationWarehouse . value = null
form . contact = ''
form . phone = ''
if ( form . deliveryMethod === 'CUSTOMER_DELIVERY' ) form . address = ''
if ( ! form . warehouse ) return
operationWarehouseDetailLoading . value = true
try {
const detail = await getMerchantWarehouseDetail ( form . warehouse )
selectedOperationWarehouse . value = detail
form . contact = detail . warehouse . contactName || ''
form . phone = detail . warehouse . contactPhone || ''
if ( form . deliveryMethod === 'CUSTOMER_DELIVERY' ) form . address = operationWarehouseAddress . value
} catch ( error ) {
ElMessage . error ( error instanceof Error ? error . message : '中转仓联系信息加载失败' )
} finally { operationWarehouseDetailLoading . value = false }
}
function selectTransferInboundMethod ( value : string | number | boolean | undefined ) {
form . address = value === 'CUSTOMER_DELIVERY' ? operationWarehouseAddress . value : ''
}
function selectTransferFbaAvailability ( value : string | number | boolean | undefined ) {
if ( value === true ) return
form . destination = ''
form . fbaShipmentNo = ''
}
async function selectOperationWarehouse ( ) {
cargoRows . value = [ ]
skuRelabelRows . value = [ ]
@@ -379,24 +464,20 @@ async function selectOperationWarehouse() {
finally { relabelCandidatesLoading . value = false }
}
function selectRelabelInventory ( inboundOrderId : string ) {
const existing = new Map ( cargoRows . value . map ( ( row ) => [ row . sourceInventoryPositionId , row ] ) )
cargoRows . value = relabelCandidates . value
. filter ( ( candidate ) => String ( candidate . inboundOrderId ) === inboundOrderId )
. flatMap ( ( candidate ) => candidate . positions . map ( ( position ) => {
const previous = existing . get ( String ( position . positionId ) )
return {
id : previous ? . id || ++ cargoSequence , sku : candidate . skuCode || '' , name : candidate . productNameZh || '库存货物' ,
quantity : Math . min ( previous ? . quantity || 1 , position . availablePackages ) , availableQuantity : position . availablePackages ,
. flatMap ( ( candidate ) => candidate . positions . flatMap ( ( position ) => Array . from ( { length : Math . min ( position . availablePackages , 500 ) } , ( ) => ( {
id : ++ cargoSequence , sku : candidate . skuCode || '' , name : candidate . productNameZh || '库存货物' ,
quantity : 1 , availableQuantity : 1 ,
sourceInventoryBalanceId : String ( candidate . inventoryBalanceId ) , sourceInventoryPositionId : String ( position . positionId ) ,
sourceInboundOrderId : String ( candidate . inboundOrderId ) , sourceInboundOrderNo : candidate . inboundOrderNo ,
sourceInboundCode : candidate . inboundCode , sourceWarehouseName : candidate . overseasWarehouseName ,
palletNo : position . palletNo , warehouseLocationCode : position . warehouseLocationCode ,
fnsku : '' , shipmentNo : previous ? . shipmentNo || '' , newSkuCode : previous ? . newSkuCode || '' , shippingMark : '' ,
cartonMark : previous ? . cartonMark || '' , fbaCartonMark : previous ? . fbaCartonMark || '' ,
destinationWarehouseId : previous ? . destinationWarehouseId || candidate . destinationFbaWarehouseCode || '' , remark : previous ? . remark || '' ,
}
} ) )
fnsku : '' , shipmentNo : '' , newSkuCode : '' , shippingMark : '' , cartonMark : '' , fbaCartonMark : '' ,
destinationWarehouseId : candidate . destinationFbaWarehouseCode || '' , remark : '' ,
} ) ) ) ) . slice ( 0 , 500 )
skuRelabelRows . value = [ ]
shippingLabelFile . value = null
if ( labelingMode . value !== 'carton' ) addSkuRelabelRow ( )
}
< / script >
@@ -428,30 +509,43 @@ function selectRelabelInventory(inboundOrderId: string) {
< div class = "warehouse-breadcrumb" > < button type = "button" @click ="mode = 'list'" > {{ config.title }} < / button > < b > / < / b > < strong > 新增 < / strong > < / div >
< div class = "warehouse-page-heading" > < h2 > { { config . createTitle } } < / h2 > < el-button @click ="mode = 'list'" > < ArrowLeft :size = "16" / > 返回列表 < / el-button > < / div >
< form @submit.prevent ="submit" >
< div class = "warehouse-card warehouse-form-section" > < h3 > { { props . service === 'relabel' ? '退货信息' : props . service === 'labeling' ? '订单信息' : '基础与派送 信息' } } < / h3 >
< div class = "warehouse-card warehouse-form-section" > < h3 > { { props . service === 'transfer' ? '入库与转运信息' : props . service === 'relabel' ? '退货信息' : props . service === 'labeling' ? '订单信息' : '基础信息' } } < / h3 >
< div class = "warehouse-form-grid" >
< label v-if = "props.service === 'disposal'" class="warehouse-span-2"><span><i>*</i>选择入库单</span><el-select v-model="selectedDiscardOrderId" filterable :loading="discardCandidatesLoading" placeholder="请选择有可用库存的入库单" @change="selectDiscardInbound"><el-option v-for="candidate in discardCandidates" :key="candidate.orderId" :label="`${candidate.inboundOrderNo || candidate.inboundCode || '—'}| ${candidate.inboundCode || '—'}| ${candidate.overseasWarehouseName || '—'}|可用 ${candidate.availablePackages} 箱`" :value="candidate.orderId" /></el-select><small class="warehouse-hint" > 仅显示一件代发中仍有可用箱数的入库单 。 < / small > < / label >
< label v-if = "props.service === 'transfer' || props.service === 'relabel'"><span><i>*</i>进仓编号</span><el-input v-model="form.inboundNo" placeholder="请输入已有入仓编号" / > < / label >
< label v-if = "props.service === 'relabel'"><span><i>*</i>来源 FBA 仓库</span><el-select v-model="form.sourceWarehouse" :loading="fbaWarehousesLoading" :disabled="Boolean(fbaWarehousesError)" placeholder="请选择平台维护的 FBA 仓"><el-option v-for="warehouse in fbaWarehouses" :key="warehouse.id" :label="warehouseLabel(warehouse)" :value="warehouse.warehouseCode" / > < / el-select > < / label >
< label v-else-if = "props.service === 'disposal'"><span>进仓编号</span><el-input v-model="form.inboundNo" readonly / > < / label >
< label v-else > < span > < i > * < / i > { { props . service === 'labeling' ? '海外操作仓(中转仓)' : '操作仓' } } < / span > < el-select v-model = "form.warehouse" :loading="fbaWarehousesLoading" :disabled="Boolean(fbaWarehousesError)" clearable placeholder="请选择国外中转仓" @change="props.service === 'labeling' && selectOperationWarehouse()"><el-option v-for="warehouse in operationWarehouses" :key="warehouse.id" :label="warehouseLabel(warehouse)" :value="String(warehouse.id)" /></el-select><small v-if="props.service === 'labeling'" class="warehouse-hint" > 选择后仅查询当前客户在该中转仓的可用库存 。 < / small > < / label >
< label v-else > < span > < i > * < / i > { { props . service === 'labeling' ? '海外操作仓(中转仓)' : props . service === 'transfer' ? '入库中转仓' : '操作仓' } } < / span > < el-select v-model = "form.warehouse" :loading="fbaWarehousesLoading || operationWarehouseDetailLoading " :disabled="Boolean(fbaWarehousesError)" clearable placeholder="请选择国外中转仓" @change="props.service === 'labeling' ? selectOperationWarehouse() : props.service === 'transfer' && selectTransferWarehouse() "><el-option v-for="warehouse in operationWarehouses" :key="warehouse.id" :label="warehouseLabel(warehouse)" :value="String(warehouse.id)" /></el-select><small v-if="props.service === 'labeling'" class="warehouse-hint"> 选择后仅查询当前客户在该中转仓的可用库存。</small><small v-else-if="props.service === 'transfer'" class="warehouse-hint" > 本批货物将先进入该仓完成签收和入库 。 < / small > < / label >
< label v-if = "props.service === 'labeling'" class="warehouse-span-2"><span><i>*</i>选择有库存的历史入仓单</span><el-select v-model="selectedRelabelInboundOrderId" filterable clearable :loading="relabelCandidatesLoading" :disabled="!form.warehouse" no-data-text="当前中转仓暂无已入库可用库存" placeholder="请选择曾经下单且当前仍有库存的入仓单" @change="selectRelabelInventory"><el-option v-for="option in relabelInboundOptions" :key="option.value" :label="`${option.inboundOrderNo}|入仓码 ${option.inboundCode}|可用 ${option.availablePackages} 箱`" :value="option.value" /></el-select><small class="warehouse-hint" > 仅显示当前客户在所选中转仓已经完成入库且仍有可用库存的历史入仓单 。 < / small > < / label >
< label v-if = "props.service === 'disposal'"><span>操作仓</span><el-input :model-value="discardCandidates.find((item) => item.orderId === selectedDiscardOrderId)?.overseasWarehouseName || form.warehouse" readonly / > < / label >
< label v-if = "props.service === 'relabel' || props.service === 'transfer' "><span><i>*</i>目的 FBA 仓</span><el-select v-model="form.destination" :loading="fbaWarehousesLoading" :disabled="Boolean(fbaWarehousesError)" placeholder="请选择平台维护的 FBA 仓"><el-option v-for="warehouse in fbaWarehouses" :key="warehouse.id" :label="warehouseLabel(warehouse)" :value="warehouse.warehouseCode" / > < / el-select > < / label >
< label v-if = "props.service === 'transfer' || props.service === 'relabel' "><span><i>*</i>派送方式 </span><el-selec t v-model="form.deliveryMethod " placeholder="请选择"><el-option label="卡车派送" value="卡车派送" /><el-option label="快递派送" value="快递派送" / > < / el-select > < / label >
< div v-if = "props.service === 'transfer'" class="warehouse-choice-field warehouse-span-2 "><span><i>*</i>货物如何送到中转 仓</span><el-radio-group v-model="form.deliveryMethod" @change="selectTransferInboundMethod"><el-radio-button value="WAREHOUSE_PICKUP">仓库上门提货</el-radio-button><el-radio-button value="CUSTOMER_DELIVERY" > 客户送货到仓 < / el -radio -button > < / el-radio-group > < small > 仓库上门提货 : 填写货物当前地址 ; 客户送货到仓 : 下方自动展示中转仓收货信息 。 < / small > < / div >
< label v-if = "props.service === 'transfer' && form.deliveryMethod === 'WAREHOUSE_PICKUP'" class="warehouse-span-2 "><span><i>*</i>提货地址 </span><el-inpu t v-model="form.address " placeholder="请输入仓库上门提货的详细地址" / > < / label >
< div v-if = "props.service === 'transfer' && form.deliveryMethod === 'CUSTOMER_DELIVERY'" v-loading="operationWarehouseDetailLoading" class="warehouse-receiving-card warehouse-span-2" >
< div > < span > 送货地址 < / span > < strong > { { operationWarehouseAddress || '该中转仓暂未维护收货地址' } } < / strong > < / div >
< div > < span > 收货联系人 < / span > < strong > { { form . contact || '未维护' } } < / strong > < / div >
< div > < span > 联系电话 < / span > < strong > { { form . phone || '未维护' } } < / strong > < / div >
< / div >
< label v-if = "props.service === 'relabel'"><span><i>*</i>目的 FBA 仓</span><el-select v-model="form.destination" :loading="fbaWarehousesLoading" :disabled="Boolean(fbaWarehousesError)" placeholder="请选择平台维护的 FBA 仓"><el-option v-for="warehouse in fbaWarehouses" :key="warehouse.id" :label="warehouseLabel(warehouse)" :value="warehouse.warehouseCode" / > < / el-select > < / label >
< label v-if = "props.service === 'relabel'"><span><i>*</i>派送方式</span><el-select v-model="form.deliveryMethod" placeholder="请选择"><el-option label="卡车派送" value="卡车派送" /><el-option label="快递派送" value="快递派送" / > < / el-select > < / label >
< label v-if = "props.service === 'relabel' || props.service === 'disposal'"><span><i>*</i>{{ props.service === 'relabel' ? '退货原因' : '废弃原因' }}</span><el-select v-model="form.reason" placeholder="请选择"><el-option label="客户退货" value="客户退货" /><el-option label="亚马逊移除" value="亚马逊移除" /><el-option label="残损不可售" value="残损不可售" / > < / el-select > < / label >
< label v-if = "props.service === 'labeling'"><span><i>*</i>海外仓签收联系人<em v-if="form.warehouse && !form.contact" class="warehouse-unmaintained">未维护</em></span><el-input v-model="form.contact" placeholder="选择海外操作仓后自动带出" / > < / label >
< label v-if = "props.service === 'labeling'"><span><i>*</i>海外仓联系电话<em v-if="form.warehouse && !form.phone" class="warehouse-unmaintained">未维护</em></span><el-input v-model="form.phone" placeholder="选择海外操作仓后自动带出" / > < / label >
< label v-if = "props.service === 'labeling'"><span><i>*</i>贴标截止时间</span><el-date-picker v-model="form.labelDeadline" type="datetime" value-format="YYYY-MM-DDTHH:mm:ss" placeholder="请选择截止时间" / > < / label >
< label v-if = "props.service === 'labeling'"><span><i>*</i>贴标费用(CNY) </span><el-input-number v-model="form.chargeAmount" :min="0" :precision="2" controls-position="right" placeholder="请输入贴标费用" / > < / label >
< label v-if = "props.service === 'transfer' || props.servic e === 'relabel'" class="warehouse-span-2 "><span><i>*</i>详细派送地址 </span><el-inpu t v-model="form.address " placeholder="请输入派送地址" / > < / label >
< label v-if = "props.service === 'labeling' && labelingMod e ! == 'sku' "><span><i>*</i>换标后派送方式 </span><el-selec t v-model="form.deliveryMethod " placeholder="请选择派送方式"><el-option label="卡车派送" value="TRUCK" /><el-option label="快递派送" value="EXPRESS" /><el-option label="卡车自提" value="TRUCK_PICKUP" /><el-option label="快递自提" value="EXPRESS_PICKUP" /></el-select><small class="warehouse-hint" > 卡车派送进入预排车 ; 其余方式确认换标完成后进入换标出库 。 < / small > < / label >
< div v-if = "props.service === 'labeling' && labelingMode !== 'sku' && (form.deliveryMethod === 'EXPRESS' || form.deliveryMethod === 'EXPRESS_PICKUP')" class="warehouse-checkbox-field"><span>是否打印面单</span><el-checkbox v-model="form.relabel" > 需要仓库打印面单 < / el -checkbox > < / div >
< label v-if = "props.service === 'labeling' && labelingMode !== 'sku' && (form.deliveryMethod === 'EXPRESS' || form.deliveryMethod === 'EXPRESS_PICKUP') && form.relabel"><span><i>*</i>上传面单文件</span><input class="warehouse-native-file" type="file" accept="application/pdf,image/*,.pdf" @change="selectShippingLabel"><small class="warehouse-hint" > 支持 PDF 或图片 , 最大 20 MB 。 < / small > < / label >
< label v-if = "props.service === 'relabel'" class="warehouse-span-2"><span><i>*</i>详细派送地址</span><el-input v-model="form.address" placeholder="请输入派送地址" / > < / label >
< label v-if = "props.service === 'transfer' || props.service === 'relabel'"><span><i>*</i>总体积(CBM) </span><el-input-number v-model="form.volumeCbm" :min="0.0001" :precision="4" controls-position="right" placeholder="请输入总体积" / > < / label >
< label v-if = "props.service === 'transfer' || props.service === 'relabel'"><span><i>*</i>预计到达时间</span><el-date-picker v-model="form.estimatedArrivalAt" type="datetime" value-format="YYYY-MM-DDTHH:mm:ss" placeholder="请选择预计到达时间" / > < / label >
< label v-if = "props.service === 'transfer' || props.service === 'relabel'"><span><i>*</i>FBA 货件编号</span><el-input v-model="form.fbaShipmentNo" placeholder="请输入 FBA 货件编号" / > < / label >
< label v-if = "props.service === 'transfer' || props.service === 'relabel'"><span><i>*</i>{{ props.service === 'transfer' ? '预计入仓时间' : ' 预计到达时间' }} </span><el-date-picker v-model="form.estimatedArrivalAt" type="datetime" value-format="YYYY-MM-DDTHH:mm:ss" : placeholder="props.service === 'transfer' ? '请选择预计入仓时间' : ' 请选择预计到达时间' " / > < / label >
< div v-if = "props.service === 'transfer'" class="warehouse-choice-field warehouse-span-2"><span><i>*</i>是否已有 FBA 去向</span><el-radio-group v-model="transferHasFbaDestination" @change="selectTransferFbaAvailability"><el-radio-button :value="false">暂未确定</el-radio-button><el-radio-button :value="true" > 已有 FBA 去向 < / el -radio -button > < / el-radio-group > < small > 暂未确定也可以提交 , 货物先正常入中转仓 , 后续再补充转运指令 。 < / small > < / div >
< label v-if = "props.service === 'transfer' && transferHasFbaDestination"><span><i>*</i>目的 FBA 仓</span><el-select v-model="form.destination" :loading="fbaWarehousesLoading" :disabled="Boolean(fbaWarehousesError)" filterable placeholder="请选择平台维护的 FBA 仓"><el-option v-for="warehouse in fbaWarehouses" :key="warehouse.id" :label="warehouseLabel(warehouse)" :value="warehouse.warehouseCode" / > < / el-select > < / label >
< label v-if = "props.service === 'transfer' && transferHasFbaDestination"><span><i>*</i>FBA 货件编号</span><el-input v-model="form.fbaShipmentNo" placeholder="请输入 FBA 货件编号" / > < / label >
< label v-if = "props.service === 'relabel'"><span><i>*</i>FBA 货件编号</span><el-input v-model="form.fbaShipmentNo" placeholder="请输入 FBA 货件编号" / > < / label >
< label v-if = "props.service === 'labeling'"><span>贴标要求</span><el-input v-model="form.requirement" placeholder="请输入贴标要求" / > < / label >
< label v-else-if = "props.service !== 'disposal'"><span>物流跟踪号</span><el-input v-model="form.trackingNo" placeholder="请输入物流跟踪号" / > < / label >
< label class = "warehouse-span-2" > < span > 订单备注 < / span > < el-input v-model = "form.remark" type="textarea" :rows="3" placeholder="请输入备注信息" / > < / label >
< div v-if = "props.service === 'transfer'" class="warehouse-checkbox -field warehouse-span-2"><span>是否 换标</span><el-checkbox v-model="form.relabel" > 需要换标 < / el -checkbox > < / div >
< div v-if = "props.service === 'transfer'" class="warehouse-choice -field warehouse-span-2"><span><i>*</i>是否需要 换标</span><el-radio-group v-model="form.relabel"><el-radio-button :value="false">不需要换标</el-radio-button><el-radio-button :value="true">需要换标</el-radio-button></el-radio-group><small v-if="form.relabel" > 提交后将同时生成待处理的换标任务 。 < / small > < / div >
< / div >
< / div >
< div class = "warehouse-card warehouse-form-section" >
@@ -487,6 +581,16 @@ function selectRelabelInventory(inboundOrderId: string) {
< div class = "warehouse-breadcrumb" > < button type = "button" @click ="mode = 'list'" > {{ config.title }} < / button > < b > / < / b > < strong > 订单详情 < / strong > < / div >
< div class = "warehouse-page-heading" > < h2 > { { config . title } } 详情 < / h2 > < el-button @click ="mode = 'list'" > < ArrowLeft :size = "16" / > 返回列表 < / el-button > < / div >
< div class = "warehouse-card warehouse-form-section" > < h3 > 订单概览 < / h3 > < div class = "warehouse-detail-grid" > < div v-for = "(column, index) in config.columns.slice(1)" :key="column" > < span > { { column } } < / span > < strong > { { selectedDetail ? . [ String ( index ) ] || '—' } } < / strong > < / div > < / div > < / div >
< div v-if = "props.service === 'labeling'" class="warehouse-card warehouse-form-section" >
< div class = "warehouse-section-heading" > < h3 > 换标完成与出库 < / h3 > < el-button v-if = "selectedRelabelDetail?.application.status === 'CUSTOMER_CONFIRM_PENDING'" type="primary" @click="confirmRelabel" > 换标完成确认 < / el -button > < / div >
< div class = "warehouse-detail-grid warehouse-fulfillment-grid" >
< div > < span > 派送方式 < / span > < strong > { { deliveryMethodLabel ( selectedRelabelDetail ? . application . deliveryMethod || '' ) || '无需出库' } } < / strong > < / div >
< div > < span > 履约状态 < / span > < strong > { { selectedRelabelDetail ? . application . fulfillmentStatus || '—' } } < / strong > < / div >
< div > < span > 客户确认时间 < / span > < strong > { { formatDateTime ( selectedRelabelDetail ? . application . customerConfirmedAt ) } } < / strong > < / div >
< / div >
< div class = "warehouse-evidence" > < span > 仓库完工照片 < / span > < div v-if = "selectedRelabelDetail?.completionEvidence?.photoFileIds?.length" class="warehouse-photo-actions"><el-button v-for="(fileId, index) in selectedRelabelDetail.completionEvidence.photoFileIds" :key="fileId" size="small" plain @click="previewCompletionPhoto(fileId)"><Eye :size="14" / > 照片 { { index + 1 } } < / el-button > < / div > < strong v-else > 仓库尚未上传完工照片 < / strong > < / div >
< p v-if = "selectedRelabelDetail?.completionEvidence?.completionRemark" class="warehouse-completion-remark" > 完工备注 : {{ selectedRelabelDetail.completionEvidence.completionRemark }} < / p >
< / div >
< div v-if = "props.service === 'labeling'" class="warehouse-card warehouse-form-section" >
< h3 > 换标任务明细 < / h3 >
< div class = "warehouse-table-scroll" > < table class = "warehouse-relabel-detail-table" > < thead > < tr > < th > 换标模式 < / th > < th > 我方箱唛 < / th > < th > 新 FBA 箱唛 < / th > < th > FBA 目的仓 < / th > < th > 任务箱数 < / th > < th > 商品 SKU < / th > < th > SKU 换标明细 < / th > < th > FBA 货件编号 < / th > < th > 贴标要求 < / th > < th > 备注 < / th > < / tr > < / thead > < tbody >
@@ -501,8 +605,10 @@ function selectRelabelInventory(inboundOrderId: string) {
< style scoped >
. warehouse - service - page { color : # 25324 a } . warehouse - breadcrumb { display : flex ; align - items : center ; gap : 9 px ; margin : 0 0 14 px ; color : # 9 aa3b2 ; font - size : 12 px } . warehouse - breadcrumb b { font - weight : 400 } . warehouse - breadcrumb strong { color : # 606 b7c } . warehouse - breadcrumb button { padding : 0 ; border : 0 ; background : transparent ; color : # 4376 b8 ; cursor : pointer } . warehouse - page - heading { display : flex ; align - items : center ; justify - content : space - between ; margin - bottom : 16 px } . warehouse - page - heading h2 { margin : 0 ; color : # 17233 a ; font - size : 22 px ; letter - spacing : 0 } . warehouse - card { margin - bottom : 12 px ; border : 1 px solid # e7ebf1 ; border - radius : 4 px ; background : # fff ; box - shadow : 0 1 px 3 px rgba ( 25 , 42 , 70 , .04 ) } . warehouse - filter - card { padding : 20 px 22 px 16 px } . warehouse - filter - grid { display : grid ; grid - template - columns : repeat ( 4 , minmax ( 180 px , 1 fr ) ) ; gap : 16 px 20 px } . warehouse - filter - grid label , . warehouse - form - grid label { display : flex ; min - width : 0 ; flex - direction : column ; gap : 7 px } . warehouse - filter - grid label > span , . warehouse - form - grid label > span { color : # 596579 ; font - size : 12 px } . warehouse - filter - actions { display : flex ; justify - content : flex - end ; gap : 8 px ; margin - top : 18 px } . warehouse - table - card { overflow : hidden } . warehouse - table - scroll { overflow - x : auto } table { width : 100 % ; min - width : 940 px ; border - collapse : collapse ; font - size : 12 px } th { height : 44 px ; padding : 0 14 px ; border - bottom : 1 px solid # e8edf3 ; background : # f7f9fc ; color : # 4 d5a6e ; font - weight : 650 ; text - align : left ; white - space : nowrap } td { height : 48 px ; padding : 8 px 14 px ; border - bottom : 1 px solid # eef1f5 ; color : # 526176 ; white - space : nowrap } . warehouse - empty { display : grid ; height : 150 px ; color : # a0a9b7 ; place - items : center } . warehouse - link , . warehouse - delete { display : inline - flex ; align - items : center ; gap : 5 px ; padding : 4 px ; border : 0 ; background : transparent ; color : # 2176 d2 ; cursor : pointer } . warehouse - delete { color : # d64545 } . warehouse - pagination { display : flex ; align - items : center ; justify - content : flex - end ; gap : 8 px ; padding : 14 px 18 px ; color : # 778398 ; font - size : 12 px } . warehouse - pagination span { margin - right : 8 px } . warehouse - page - number { width : 28 px ; height : 28 px ; border : 1 px solid # 2176 d2 ; border - radius : 3 px ; background : # 2176 d2 ; color : # fff } . warehouse - form - section { padding : 22 px } . warehouse - form - section h3 { margin : 0 0 18 px ; padding - bottom : 12 px ; border - bottom : 1 px solid # edf0f4 ; color : # 26364 f ; font - size : 15 px ; letter - spacing : 0 } . warehouse - form - grid { display : grid ; grid - template - columns : repeat ( 2 , minmax ( 240 px , 1 fr ) ) ; gap : 18 px 28 px } . warehouse - form - grid i { margin - right : 3 px ; color : # e24b4b ; font - style : normal } . warehouse - span - 2 { grid - column : 1 / - 1 } . warehouse - section - heading { display : flex ; align - items : center ; justify - content : space - between } . warehouse - section - heading h3 { flex : 1 } . warehouse - edit - table td { padding : 9 px 10 px } . warehouse - edit - table : deep ( . el - input - number ) { width : 130 px } . warehouse - hint { margin : 12 px 0 0 ; color : # 8792 a2 ; font - size : 12 px } . warehouse - submit - bar { display : flex ; justify - content : center ; gap : 10 px ; padding : 12 px 0 30 px } . warehouse - detail - grid { display : grid ; grid - template - columns : repeat ( 3 , 1 fr ) ; gap : 24 px } . warehouse - detail - grid div { display : flex ; flex - direction : column ; gap : 7 px } . warehouse - detail - grid span { color : # 8 a95a5 ; font - size : 12 px } . warehouse - detail - grid strong { color : # 334157 ; font - size : 13 px } : deep ( . el - button ) { border - radius : 4 px } : deep ( . el - button span ) { display : inline - flex ; align - items : center ; gap : 6 px } : deep ( . el - select ) , : deep ( . el - date - editor . el - input ) { width : 100 % } @ media ( max - width : 1100 px ) { . warehouse - filter - grid { grid - template - columns : repeat ( 2 , 1 fr ) } . warehouse - detail - grid { grid - template - columns : repeat ( 2 , 1 fr ) } }
. warehouse - checkbox - field { display : flex ; min - height : 32 px ; align - items : center ; justify - content : flex - start ; gap : 16 px } . warehouse - checkbox - field > span { color : # 596579 ; font - size : 12 px } . warehouse - checkbox - field : deep ( . el - checkbox ) { margin - right : 0 }
. warehouse - choice - field { display : grid ; grid - template - columns : 150 px auto 1 fr ; align - items : center ; gap : 14 px ; min - height : 40 px ; padding : 12 px 14 px ; border : 1 px solid # e1e8f2 ; border - radius : 5 px ; background : # f8faff } . warehouse - choice - field > span { color : # 34445 c ; font - size : 13 px ; font - weight : 650 } . warehouse - choice - field > span i { margin - right : 3 px ; color : # e24b4b ; font - style : normal } . warehouse - choice - field > small { color : # 7 a879a ; font - size : 12 px } . warehouse - receiving - card { display : grid ; grid - template - columns : 2 fr 1 fr 1 fr ; gap : 22 px ; padding : 15 px 16 px ; border : 1 px solid # cfe0f5 ; border - radius : 5 px ; background : # f6faff } . warehouse - receiving - card div { display : flex ; min - width : 0 ; flex - direction : column ; gap : 6 px } . warehouse - receiving - card span { color : # 7 c899c ; font - size : 12 px } . warehouse - receiving - card strong { overflow - wrap : anywhere ; color : # 314561 ; font - size : 13 px ; font - weight : 600 }
. warehouse - hidden - input { display : none } . warehouse - label - table { min - width : 1120 px } . warehouse - attachment - tip { margin : 10 px 0 12 px ; color : # 7 d8797 ; font - size : 12 px } . warehouse - mark - mapping { display : flex ; flex - wrap : wrap ; gap : 8 px ; margin : 4 px 0 8 px ; padding : 12 px ; border : 1 px solid # dce7f5 ; border - radius : 5 px ; background : # f7faff } . warehouse - mark - mapping strong { width : 100 % ; color : # 34445 c } . warehouse - mark - mapping span { padding : 5 px 9 px ; border - radius : 3 px ; background : # eaf2fc ; color : # 3 e6593 ; font - size : 12 px }
. warehouse - unmaintained { margin - left : 8 px ; color : # e6a23c ; font - size : 12 px ; font - style : normal }
. warehouse - labeling - tabs { margin - top : - 8 px } . warehouse - tab - actions { align - items : center ; margin : 2 px 0 14 px } . warehouse - tab - actions p { margin : 0 ; color : # 7 d8797 ; font - size : 12 px } . warehouse - tab - actions > div { display : flex ; gap : 8 px } . warehouse - sku - notice { margin : 0 0 14 px ; padding : 10 px 12 px ; border : 1 px solid # f2d39b ; border - radius : 4 px ; background : # fff8e8 ; color : # 8 a6116 ; font - size : 12 px } . warehouse - sku - label - table { min - width : 980 px } . warehouse - sku - label - table : deep ( . el - input - number ) { width : 160 px } : deep ( . warehouse - labeling - tabs > . el - tabs _ _header ) { margin - bottom : 18 px } : deep ( . warehouse - labeling - tabs . el - tabs _ _item ) { height : 42 px ; padding : 0 26 px ; font - weight : 600 } . warehouse - labeling - mode { display : flex ; align - items : center ; gap : 14 px ; margin : 0 0 16 px ; padding : 14 px 16 px ; border : 1 px solid # dce5f5 ; border - radius : 5 px ; background : # f7f9ff } . warehouse - labeling - mode > span { color : # 34445 c ; font - size : 13 px ; font - weight : 650 ; white - space : nowrap } . warehouse - labeling - mode p { margin : 0 ; color : # 71809 a ; font - size : 12 px } . warehouse - labeling - mode : deep ( . el - radio - group ) { display : flex ; flex - shrink : 0 } . warehouse - labeling - mode : deep ( . el - radio - button _ _inner ) { padding : 8 px 14 px }
. warehouse - relabel - detail - table { min - width : 1420 px } . warehouse - relabel - detail - table td strong { color : # 253 f67 }
. warehouse - native - file { min - height : 32 px ; padding : 5 px 8 px ; border : 1 px solid # dcdfe6 ; border - radius : 4 px ; background : # fff ; color : # 606266 } . warehouse - fulfillment - grid { margin - bottom : 18 px } . warehouse - evidence { display : flex ; align - items : center ; gap : 16 px ; padding : 14 px ; border : 1 px solid # e7ebf1 ; border - radius : 4 px ; background : # f8fafc } . warehouse - evidence > span { color : # 71809 a ; font - size : 12 px } . warehouse - evidence > strong { color : # 8 a95a5 ; font - size : 12 px ; font - weight : 400 } . warehouse - photo - actions { display : flex ; flex - wrap : wrap ; gap : 8 px } . warehouse - completion - remark { margin : 10 px 0 0 ; color : # 596579 ; font - size : 12 px }
< / style >