This commit is contained in:
2026-08-17 19:57:35 +08:00
parent 0f352bbdf9
commit 771ed6f059
4 changed files with 65 additions and 19 deletions
@@ -71,6 +71,9 @@ test('declares the final C02 row and detail contract in the API adapter', () =>
assert.match(unifiedApiSource, /mainStatus: ApiUnifiedOrderMainStatus/)
assert.match(unifiedApiSource, /nextAction: string \| null/)
assert.match(unifiedApiSource, /customerRemark: string \| null/)
for (const field of ['pickupMethod', 'requestedPickupAt', 'containerMode', 'destinationType', 'destinationCode', 'skuNos', 'totalQuantity', 'totalNetWeightKg', 'chargeableVolumeCbm', 'inboundCompletedAt', 'shipmentId', 'referenceId']) {
assert.match(unifiedApiSource, new RegExp(`${field}:`))
}
assert.match(unifiedApiSource, /loadingVersion: number/)
assert.match(unifiedApiSource, /pickingVersion: number/)
assert.match(unifiedApiSource, /summary: MerchantUnifiedOrderRow/)
@@ -99,9 +102,16 @@ test('routes supported filters to C02 without sending DRAFT as a main status', (
assert.match(storeSource, /getMerchantUnifiedOrders\(unifiedQuery\)/)
})
test('maps C02 rows by orderId and leaves absent transport details unknown', () => {
test('maps C02 authoritative status, transport, cargo and pickup snapshots', () => {
assert.match(storeSource, /id: String\(summary\.orderId\)/)
assert.match(storeSource, /transportMode: null/)
assert.match(storeSource, /transportMode: unifiedTransport\(summary\.containerMode\)/)
assert.match(storeSource, /status: summary\.mainStatus/)
assert.match(storeSource, /requestedPickupAt: summary\.requestedPickupAt \?\? ''/)
assert.match(storeSource, /chargeableVolumeCbm: summary\.chargeableVolumeCbm \?\? null/)
assert.match(storeSource, /inboundedAt: summary\.inboundCompletedAt \?\? ''/)
assert.match(storeSource, /pickupMethod: summary\.pickupMethod \?\? 'SELF_EXPRESS'/)
assert.match(storeSource, /destinationType: summary\.destinationType \?\? 'PRIVATE'/)
assert.match(storeSource, /mapped\.requestedPickupAt = summary\.requestedPickupAt/)
assert.match(storeSource, /summary\?\.loading\?\.loadingVersion/)
assert.match(storeSource, /summary\?\.loading\?\.pickingVersion/)
assert.match(storeSource, /summary\?\.inboundId == null \? '' : String\(summary\.inboundId\)/)
+30 -10
View File
@@ -61,6 +61,12 @@ function clientTransport(order: MerchantFirstLegOrder): FirstLegOrder['transport
return 'ROAD'
}
function unifiedTransport(containerMode: MerchantUnifiedOrderRow['containerMode']): FirstLegOrder['transportMode'] {
if (containerMode === 'FULL_CONTAINER') return 'FCL'
if (containerMode === 'LCL') return 'LCL'
return null
}
function apiTransport(draft: FirstLegOrderDraft): FirstLegOrderSaveRequest['transportMode'] {
if (draft.transportMode === 'AIR') return 'AIR'
if (draft.transportMode === 'ROAD') return 'TRUCK'
@@ -342,29 +348,29 @@ function mapOrder(order: MerchantFirstLegOrder, warehouses: PlatformReceivingWar
channelName: order.channelName, carrierId: order.carrierId == null ? '' : String(order.carrierId), carrierName: order.carrierName ?? '',
pricingTaxMode: order.pricingTaxMode ?? 'TAX_INCLUDED', taxMode: order.taxMode, customsInspection: order.customsInspection,
destinationType: order.destinationType, amazonWarehouseCode: order.amazonWarehouseCode ?? '', shipmentId: order.shipmentId ?? '',
receivingTime: order.receivingTime ?? '', submittedAt: order.submittedAt ?? '', completedAt: order.completedAt ?? '',
requestedPickupAt: '', receivingTime: order.receivingTime ?? '', submittedAt: order.submittedAt ?? '', completedAt: order.completedAt ?? '',
}
}
function mapUnifiedOrderRow(summary: MerchantUnifiedOrderRow, warehouses: PlatformReceivingWarehouse[]): FirstLegOrder {
const warehouse = warehouses.find((item) => item.id === String(summary.receivingWarehouseId))
return {
id: String(summary.orderId), orderNo: summary.orderNo, referenceNo: summary.referenceId ?? '', transportMode: null,
id: String(summary.orderId), orderNo: summary.orderNo, referenceNo: summary.referenceId ?? '', transportMode: unifiedTransport(summary.containerMode),
businessType: 'EXPORT', origin: '', destination: summary.destinationWarehouseName ?? '',
receivingWarehouseId: summary.receivingWarehouseId == null ? '' : String(summary.receivingWarehouseId),
receivingWarehouseName: summary.receivingWarehouseName ?? '', receivingWarehouseSnapshot: warehouseSnapshot(warehouse),
expectedDepartureDate: summary.expectedShipDate ?? '', etd: '', eta: '', shipperPartyId: '', shipperPartySnapshot: null,
shipper: '', consigneePartyId: '', consigneePartySnapshot: null, consignee: '', expressCompanyName: summary.expressCompany ?? '',
trackingNumber: summary.delivery?.trackingNo ?? '', skuNos: summary.skuNos ?? [], totalNetWeightKg: summary.totalNetWeightKg ?? null,
totalQuantity: summary.totalQuantity ?? null, chargeableVolumeCbm: null,
inboundedAt: summary.inboundedAt ?? '', businessDate: summary.businessDate ?? '', priority: 'NORMAL', customerRemark: summary.customerRemark ?? '', operatorName: '',
trackingNumber: summary.expressTrackingNo ?? summary.delivery?.trackingNo ?? '', skuNos: summary.skuNos ?? [], totalNetWeightKg: summary.totalNetWeightKg ?? null,
totalQuantity: summary.totalQuantity ?? null, chargeableVolumeCbm: summary.chargeableVolumeCbm ?? null,
inboundedAt: summary.inboundCompletedAt ?? '', businessDate: '', priority: 'NORMAL', customerRemark: summary.customerRemark ?? '', operatorName: '',
status: summary.mainStatus, version: 0, items: [], timeline: [], businessSummary: businessSummary(summary),
createdAt: summary.createdAt, updatedAt: summary.updatedAt, tradeTerm: '', destinationCountryCode: '',
destinationWarehouseId: summary.destinationWarehouseId == null ? '' : String(summary.destinationWarehouseId),
destinationWarehouseName: summary.destinationWarehouseName ?? '', pickupMethod: 'SELF_EXPRESS', channelCode: '',
destinationWarehouseName: summary.destinationWarehouseName ?? '', pickupMethod: summary.pickupMethod ?? 'SELF_EXPRESS', channelCode: '',
channelName: summary.channelName ?? '', pricingTaxMode: 'TAX_INCLUDED', carrierId: '', carrierName: '', taxMode: 'BUY_DECLARATION', customsInspection: false,
destinationType: 'PRIVATE', amazonWarehouseCode: '', shipmentId: summary.shipmentId ?? '',
receivingTime: '', submittedAt: '', completedAt: '',
destinationType: summary.destinationType ?? 'PRIVATE', amazonWarehouseCode: summary.destinationCode ?? '', shipmentId: summary.shipmentId ?? '',
requestedPickupAt: summary.requestedPickupAt ?? '', receivingTime: '', submittedAt: '', completedAt: '',
}
}
@@ -394,7 +400,7 @@ function mapFirstLegOrderRow(row: MerchantFirstLegOrderRow): FirstLegOrder {
destinationWarehouseName: row.destinationWarehouseName ?? '', pickupMethod: 'SELF_EXPRESS', channelCode: '',
channelName: row.channelName ?? '', pricingTaxMode: 'TAX_INCLUDED', carrierId: '', carrierName: '', taxMode: 'BUY_DECLARATION',
customsInspection: false, destinationType: row.destinationType ?? 'PRIVATE', amazonWarehouseCode: '',
shipmentId: row.shipmentId ?? row.internationalOrderNo ?? '', receivingTime: '', submittedAt: '', completedAt: '',
shipmentId: row.shipmentId ?? row.internationalOrderNo ?? '', requestedPickupAt: '', receivingTime: '', submittedAt: '', completedAt: '',
}
}
@@ -405,7 +411,21 @@ function mapUnifiedOrderDetail(detail: MerchantUnifiedOrderDetail, warehouses: P
mapped.status = detail.summary.mainStatus
mapped.businessSummary = businessSummary(detail.summary)
mapped.timeline = unifiedTimeline(detail)
mapped.trackingNumber = detail.summary.delivery?.trackingNo ?? mapped.trackingNumber
const summary = mapUnifiedOrderRow(detail.summary, warehouses)
mapped.referenceNo = summary.referenceNo
mapped.transportMode = summary.transportMode
mapped.expressCompanyName = summary.expressCompanyName
mapped.trackingNumber = summary.trackingNumber
mapped.skuNos = summary.skuNos
mapped.totalNetWeightKg = summary.totalNetWeightKg
mapped.totalQuantity = summary.totalQuantity
mapped.chargeableVolumeCbm = summary.chargeableVolumeCbm
mapped.inboundedAt = summary.inboundedAt
mapped.pickupMethod = summary.pickupMethod
mapped.requestedPickupAt = summary.requestedPickupAt
mapped.destinationType = summary.destinationType
mapped.amazonWarehouseCode = summary.amazonWarehouseCode
mapped.shipmentId = summary.shipmentId
return mapped
}
@@ -137,10 +137,12 @@ test('downloads selected carton labels with one array request', () => {
test('exports every visible order field with normalized dates', () => {
assert.match(source, /function formatExportDateTime\(value: string \| null \| undefined\)/)
assert.match(source, /return `\$\{date\.getFullYear\(\)\}-\$\{pad\(date\.getMonth\(\) \+ 1\)\}-\$\{pad\(date\.getDate\(\)\)\} \$\{pad\(date\.getHours\(\)\)\}:\$\{pad\(date\.getMinutes\(\)\)\}:\$\{pad\(date\.getSeconds\(\)\)\}`/)
for (const label of ['订单号', '入仓码', '渠道', '目的仓', '当前订单状态', '箱数', '快递公司', '快递单号', 'SKUS', '总毛重', '总净重', '总体积', '总数量', '计费单价', '计费体积', '计费重量', '备注', '货件编号', '跟踪编号', '国内仓入库时间', '创建时间']) {
for (const label of ['订单号', '入仓码', '渠道', '运输方式', '交货方式', '预约提货时间', '目的仓', '目的仓类型', '当前订单状态', '箱数', '快递公司', '快递单号', 'SKUS', '总毛重', '总净重', '总体积', '总数量', '计费单价', '计费体积', '计费重量', '备注', '货件编号', '跟踪编号', '国内仓入库时间', '创建时间']) {
assert.match(source, new RegExp(`'${label}'`))
}
assert.match(source, /formatExportDateTime\(order\.inboundedAt\)/)
assert.match(source, /order\.pickupMethod === 'PICKUP' \? formatExportDateTime\(order\.requestedPickupAt\) : '-'/)
assert.match(source, /formatListMetric\(order\.chargeableVolumeCbm, 'm³'\)/)
assert.doesNotMatch(source, /formatExportDateTime\(order\.businessDate\)/)
assert.match(source, /formatExportDateTime\(order\.createdAt\)/)
})
@@ -156,7 +158,7 @@ test('matches the prototype with selectable dense order-list columns', () => {
assert.match(source, />恢复默认<\/el-button>/)
assert.match(source, /const visibleOrderColumns = computed/)
assert.match(source, /:columns="visibleOrderColumns"/)
for (const label of ['入仓码', '渠道', '目的仓', '当前订单状态', '箱数', '快递公司', '快递单号', 'SKUS', '总毛重', '总净重', '总体积', '总数量', '计费单价', '计费体积', '计费重量', '备注', '货件编号', '跟踪编号', '国内仓入库时间']) {
for (const label of ['入仓码', '渠道', '运输方式', '交货方式', '预约提货时间', '目的仓', '目的仓类型', '当前订单状态', '箱数', '快递公司', '快递单号', 'SKUS', '总毛重', '总净重', '总体积', '总数量', '计费单价', '计费体积', '计费重量', '备注', '货件编号', '跟踪编号', '国内仓入库时间']) {
assert.match(source, new RegExp(`label: '${label}'`))
}
assert.match(source, /order\.businessSummary\.totalPackageCount/)
@@ -164,7 +166,8 @@ test('matches the prototype with selectable dense order-list columns', () => {
assert.match(source, /order\.items\.reduce/)
assert.match(source, /<template #chargeableWeight>-<\/template>/)
assert.match(source, /<template #billingUnitPrice>-<\/template>/)
assert.match(source, /<template #chargeableVolume>-<\/template>/)
assert.match(source, /<template #chargeableVolume="\{ row \}">\{\{ formatListMetric\(\(row as FirstLegOrder\)\.chargeableVolumeCbm, 'm³'\) \}\}<\/template>/)
assert.match(source, /pickupMethod === 'PICKUP'[\s\S]{0,160}requestedPickupAt[\s\S]{0,160}: '-'/)
assert.match(source, /inboundedAt/)
assert.doesNotMatch(source, /label: '业务日期'/)
assert.doesNotMatch(source, /<template #businessDate>/)
@@ -94,8 +94,12 @@ const fixedOrderColumns: DataTableColumn[] = [
const selectableOrderColumns: DataTableColumn[] = [
{ key: 'inboundCode', label: '入仓码', width: 176, align: 'left', headerAlign: 'left', showOverflowTooltip: true, slotName: 'inboundCode' },
{ key: 'channel', label: '渠道', width: 150, align: 'left', headerAlign: 'left', showOverflowTooltip: true, slotName: 'channel' },
{ key: 'transportMode', label: '运输方式', width: 104, align: 'center', headerAlign: 'center', slotName: 'transportMode' },
{ key: 'pickupMethod', label: '交货方式', width: 112, align: 'center', headerAlign: 'center', slotName: 'pickupMethod' },
{ key: 'requestedPickupAt', label: '预约提货时间', width: 164, align: 'center', headerAlign: 'center', slotName: 'requestedPickupAt' },
{ key: 'receivingWarehouse', label: '国内收货仓', width: 150, align: 'left', headerAlign: 'left', showOverflowTooltip: true, slotName: 'receivingWarehouse' },
{ key: 'destinationWarehouse', label: '目的仓', width: 120, align: 'left', headerAlign: 'left', showOverflowTooltip: true, slotName: 'destinationWarehouse' },
{ key: 'destinationType', label: '目的仓类型', width: 112, align: 'center', headerAlign: 'center', slotName: 'destinationType' },
{ key: 'status', label: '当前订单状态', width: 126, align: 'center', headerAlign: 'center', slotName: 'status' },
{ key: 'packageCount', label: '箱数', width: 82, align: 'center', headerAlign: 'center', slotName: 'packageCount' },
{ key: 'expressCompany', label: '快递公司', width: 128, align: 'left', headerAlign: 'left', showOverflowTooltip: true, slotName: 'expressCompany' },
@@ -1241,7 +1245,11 @@ function exportOrderInformation() {
displayListValue(order.orderNo),
displayListValue(order.businessSummary.inboundCode),
displayListValue(order.channelName),
order.transportMode ? getFirstLegTransportModeLabel(order.transportMode) : '-',
pickupMethodLabels[order.pickupMethod],
order.pickupMethod === 'PICKUP' ? formatExportDateTime(order.requestedPickupAt) : '-',
displayListValue(order.destinationWarehouseName),
destinationTypeLabels[order.destinationType],
getFirstLegStatusLabel(order.status),
formatListMetric(orderPackageCount(order)),
displayListValue(order.expressCompanyName),
@@ -1252,7 +1260,7 @@ function exportOrderInformation() {
formatListMetric(orderVolume(order), 'm³'),
formatListMetric(orderItemTotal(order, 'pieces')),
'-',
'-',
formatListMetric(order.chargeableVolumeCbm, 'm³'),
'-',
displayListValue(order.customerRemark),
displayListValue(order.shipmentId || uniqueItemValues(order, 'shipmentId')),
@@ -1261,7 +1269,7 @@ function exportOrderInformation() {
formatExportDateTime(order.createdAt),
])
downloadCsv('订单信息.csv', [[
'订单号', '入仓码', '渠道', '目的仓', '当前订单状态', '箱数', '快递公司', '快递单号', 'SKUS',
'订单号', '入仓码', '渠道', '运输方式', '交货方式', '预约提货时间', '目的仓', '目的仓类型', '当前订单状态', '箱数', '快递公司', '快递单号', 'SKUS',
'总毛重', '总净重', '总体积', '总数量', '计费单价', '计费体积', '计费重量', '备注',
'货件编号', '跟踪编号', '国内仓入库时间', '创建时间',
], ...rows])
@@ -1547,8 +1555,12 @@ async function searchOrders(model: QueryModel) {
</template>
<template #inboundCode="{ row }"><span class="table-ellipsis table-code" :title="displayListValue((row as FirstLegOrder).businessSummary.inboundCode)">{{ displayListValue((row as FirstLegOrder).businessSummary.inboundCode) }}</span></template>
<template #channel="{ row }"><span class="table-ellipsis" :title="displayListValue((row as FirstLegOrder).channelName)">{{ displayListValue((row as FirstLegOrder).channelName) }}</span></template>
<template #transportMode="{ row }">{{ (row as FirstLegOrder).transportMode ? getFirstLegTransportModeLabel((row as FirstLegOrder).transportMode) : '-' }}</template>
<template #pickupMethod="{ row }">{{ pickupMethodLabels[(row as FirstLegOrder).pickupMethod] }}</template>
<template #requestedPickupAt="{ row }">{{ (row as FirstLegOrder).pickupMethod === 'PICKUP' && (row as FirstLegOrder).requestedPickupAt ? formatDateTime((row as FirstLegOrder).requestedPickupAt) : '-' }}</template>
<template #receivingWarehouse="{ row }"><span class="table-ellipsis" :title="displayListValue((row as FirstLegOrder).receivingWarehouseName)">{{ displayListValue((row as FirstLegOrder).receivingWarehouseName) }}</span></template>
<template #destinationWarehouse="{ row }"><span class="table-ellipsis" :title="displayListValue((row as FirstLegOrder).destinationWarehouseName)">{{ displayListValue((row as FirstLegOrder).destinationWarehouseName) }}</span></template>
<template #destinationType="{ row }">{{ destinationTypeLabels[(row as FirstLegOrder).destinationType] }}</template>
<template #status="{ row }"><el-tag :type="getFirstLegStatusTone((row as FirstLegOrder).status)" effect="light">{{ getFirstLegStatusLabel((row as FirstLegOrder).status) }}</el-tag></template>
<template #packageCount="{ row }">{{ formatListMetric(orderPackageCount(row as FirstLegOrder)) }}</template>
<template #expressCompany="{ row }"><span class="table-ellipsis" :title="displayListValue((row as FirstLegOrder).expressCompanyName)">{{ displayListValue((row as FirstLegOrder).expressCompanyName) }}</span></template>
@@ -1559,7 +1571,7 @@ async function searchOrders(model: QueryModel) {
<template #volume="{ row }">{{ formatListMetric(orderVolume(row as FirstLegOrder), 'm³') }}</template>
<template #pieces="{ row }">{{ formatListMetric(orderItemTotal(row as FirstLegOrder, 'pieces')) }}</template>
<template #billingUnitPrice>-</template>
<template #chargeableVolume>-</template>
<template #chargeableVolume="{ row }">{{ formatListMetric((row as FirstLegOrder).chargeableVolumeCbm, 'm³') }}</template>
<template #chargeableWeight>-</template>
<template #remark="{ row }"><span class="table-ellipsis" :title="(row as FirstLegOrder).customerRemark">{{ displayListValue((row as FirstLegOrder).customerRemark) }}</span></template>
<template #shipmentId="{ row }"><span class="table-ellipsis table-code" :title="displayListValue((row as FirstLegOrder).shipmentId || uniqueItemValues(row as FirstLegOrder, 'shipmentId'))">{{ displayListValue((row as FirstLegOrder).shipmentId || uniqueItemValues(row as FirstLegOrder, 'shipmentId')) }}</span></template>
@@ -1584,7 +1596,7 @@ async function searchOrders(model: QueryModel) {
<header><button type="button" @click="openDetail(order)">{{ order.orderNo || '未提交草稿' }}</button><el-tag :type="getFirstLegStatusTone(order.status)" effect="light">{{ getFirstLegStatusLabel(order.status) }}</el-tag></header>
<span v-if="order.businessSummary.inboundCode" class="order-reference">入仓码 {{ order.businessSummary.inboundCode }}</span>
<span class="order-reference">{{ order.referenceNo || '无 Reference ID' }}</span>
<dl><div><dt>目的地</dt><dd>{{ order.destination || '待更新' }}</dd></div><div><dt>收货仓</dt><dd>{{ order.receivingWarehouseName || '待更新' }}</dd></div><div><dt>货物摘要</dt><dd>{{ getOrderCargoSummary(order) }}</dd></div><div><dt>运输渠道</dt><dd>{{ order.transportMode ? getFirstLegTransportModeLabel(order.transportMode) : order.channelName || '待更新' }}</dd></div><div v-if="order.businessSummary.cabinetNo || order.businessSummary.containerNo"><dt>柜号 / 柜次</dt><dd>{{ order.businessSummary.cabinetNo || order.businessSummary.containerNo }}</dd></div><div v-if="order.businessSummary.vesselName || order.businessSummary.voyageNo"><dt>船名 / 航次</dt><dd>{{ [order.businessSummary.vesselName, order.businessSummary.voyageNo].filter(Boolean).join(' · ') }}</dd></div><div v-if="order.businessSummary.sailingAt"><dt>预计船期</dt><dd>{{ formatDateTime(order.businessSummary.sailingAt) }}</dd></div></dl>
<dl><div><dt>目的地</dt><dd>{{ order.destination || '待更新' }}</dd></div><div><dt>目的仓类型</dt><dd>{{ destinationTypeLabels[order.destinationType] }}</dd></div><div><dt>收货仓</dt><dd>{{ order.receivingWarehouseName || '待更新' }}</dd></div><div><dt>货物摘要</dt><dd>{{ getOrderCargoSummary(order) }}</dd></div><div><dt>运输方式</dt><dd>{{ order.transportMode ? getFirstLegTransportModeLabel(order.transportMode) : '待更新' }}</dd></div><div><dt>交货方式</dt><dd>{{ pickupMethodLabels[order.pickupMethod] }}</dd></div><div><dt>预约提货时间</dt><dd>{{ order.pickupMethod === 'PICKUP' && order.requestedPickupAt ? formatDateTime(order.requestedPickupAt) : '-' }}</dd></div><div v-if="order.businessSummary.cabinetNo || order.businessSummary.containerNo"><dt>柜号 / 柜次</dt><dd>{{ order.businessSummary.cabinetNo || order.businessSummary.containerNo }}</dd></div><div v-if="order.businessSummary.vesselName || order.businessSummary.voyageNo"><dt>船名 / 航次</dt><dd>{{ [order.businessSummary.vesselName, order.businessSummary.voyageNo].filter(Boolean).join(' · ') }}</dd></div><div v-if="order.businessSummary.sailingAt"><dt>预计船期</dt><dd>{{ formatDateTime(order.businessSummary.sailingAt) }}</dd></div></dl>
<footer><span>更新于 {{ formatDateTime(order.updatedAt) }}</span><div><el-button link type="primary" @click="openDetail(order)"><Eye :size="15" />详情</el-button><el-button v-if="canEditOrder && canClientEditFirstLegOrder(order.status)" link type="primary" :loading="openingEditor" @click="openEdit(order)"><Pencil :size="15" />编辑</el-button></div></footer>
</article>
</div>
@@ -1740,6 +1752,7 @@ async function searchOrders(model: QueryModel) {
<div><dt>运输方式</dt><dd>{{ getFirstLegTransportModeLabel(detailOrder.transportMode) }}</dd></div>
<div><dt>贸易条款</dt><dd>{{ displayValue(detailOrder.tradeTerm) }}</dd></div>
<div><dt>发货方式</dt><dd>{{ pickupMethodLabels[detailOrder.pickupMethod] }}</dd></div>
<div><dt>预约提货时间</dt><dd>{{ detailOrder.pickupMethod === 'PICKUP' && detailOrder.requestedPickupAt ? formatDateTime(detailOrder.requestedPickupAt) : '-' }}</dd></div>
<div><dt>报关方式</dt><dd>{{ taxModeLabels[detailOrder.taxMode] }}</dd></div>
<div><dt>运输渠道</dt><dd>{{ detailOrder.channelName || detailOrder.channelCode || '-' }}<span v-if="detailOrder.channelName && detailOrder.channelCode" class="detail-subline">{{ detailOrder.channelCode }}</span></dd></div>
<div><dt>国内收货仓</dt><dd>{{ detailOrder.receivingWarehouseSnapshot?.name || detailOrder.receivingWarehouseName || '-' }}<span v-if="detailOrder.receivingWarehouseSnapshot" class="detail-subline">{{ detailOrder.receivingWarehouseSnapshot.code || '仓库编码待更新' }} · {{ detailOrder.receivingWarehouseSnapshot.province }}{{ detailOrder.receivingWarehouseSnapshot.city }}{{ detailOrder.receivingWarehouseSnapshot.address }}</span></dd></div>