fix: complete overseas receiving detail facts
This commit is contained in:
@@ -42,6 +42,7 @@ describe('ContainerDetailView empty return', () => {
|
||||
vi.mocked(getContainerOutboundDispatch).mockReset().mockResolvedValue({ aggregate: { dispatchStatus: 'WAITING_FOR_LOADING', gate: { inbounds: [] } }, timeline: [] } as never)
|
||||
vi.mocked(getContainer).mockReset().mockResolvedValue(base as never)
|
||||
vi.mocked(getContainerOverview).mockReset().mockResolvedValue(overview as never)
|
||||
vi.mocked(getConfirmedLoadingList).mockReset().mockResolvedValue({ planNo: 'LP-1', items: [] } as never)
|
||||
vi.mocked(recordTerminalDrayageEmptyReturn).mockReset().mockResolvedValue({ ...base.terminalDrayage, status: 'EMPTY_RETURNED', version: 4, actualEmptyReturnAt: '2026-09-09T12:00:00', allowedActions: [] } as never)
|
||||
})
|
||||
|
||||
@@ -100,6 +101,29 @@ describe('ContainerDetailView empty return', () => {
|
||||
expect(wrapper.find('.detail-section__heading').findAll('button').some((item) => item.text() === '确认还柜')).toBe(false)
|
||||
})
|
||||
|
||||
it('falls back to confirmed loading facts for destination and terminal drayage for unloading time', async () => {
|
||||
vi.mocked(getContainer).mockResolvedValue({
|
||||
...base,
|
||||
destinationWarehouseCode: null,
|
||||
destinationWarehouseName: null,
|
||||
warehouseId: '8',
|
||||
terminalTruckingCompany: null,
|
||||
actualFacts: {},
|
||||
} as never)
|
||||
vi.mocked(getContainerOverview).mockResolvedValue({ ...overview, loadingPlanId: '7001' } as never)
|
||||
vi.mocked(getConfirmedLoadingList).mockResolvedValue({
|
||||
planNo: 'LP-1',
|
||||
items: [{ destinationWarehouse: 'ABE4' }, { destinationWarehouse: 'ABE4' }],
|
||||
} as never)
|
||||
|
||||
const wrapper = await mountDetail()
|
||||
|
||||
expect(getConfirmedLoadingList).toHaveBeenCalledExactlyOnceWith('7001', '8')
|
||||
expect(wrapper.text()).toContain('ABE4')
|
||||
expect(wrapper.text()).toContain('港运车队')
|
||||
expect(wrapper.text()).toContain('2026-09-07 10:00')
|
||||
})
|
||||
|
||||
it.each([
|
||||
['缺权限', false, ['RECORD_EMPTY_RETURN'], ['RECORD_EMPTY_RETURN'], 'UNLOADED'],
|
||||
['缺服务端动作', true, [], [], 'UNLOADED'],
|
||||
|
||||
@@ -164,7 +164,14 @@ const loadingListHeading = computed(() => loadingListMode.value === 'confirmed'
|
||||
const loadingListDescription = computed(() => loadingListMode.value === 'confirmed'
|
||||
? '装柜明细、PDA 证据与报关关联均以当前柜次为边界。'
|
||||
: '核对预装明细与 PDA 作业准备情况,装柜完成后再处理整柜报关。')
|
||||
const overseasDestinationText = computed(() => [detail.value?.destinationWarehouseCode, detail.value?.destinationWarehouseName].filter(Boolean).join(' / ') || '—')
|
||||
const overseasDestinationText = computed(() => {
|
||||
const bookingDestination = [detail.value?.destinationWarehouseCode, detail.value?.destinationWarehouseName]
|
||||
.filter(Boolean).join(' / ')
|
||||
if (bookingDestination) return bookingDestination
|
||||
const destinations = new Set((loadingDetail.value?.items || [])
|
||||
.map((item) => String(item.destinationWarehouse || '').trim()).filter(Boolean))
|
||||
return [...destinations].join('、') || '—'
|
||||
})
|
||||
const plannedChannelName = computed(() => getSmartLoadingChannelGroup(detail.value?.channelGroupCode)?.name || '—')
|
||||
const emptyReturnWarningText = computed(() => {
|
||||
const warning = workbenchDetail.value?.terminalDrayage?.emptyReturnWarning
|
||||
@@ -284,6 +291,9 @@ async function load() {
|
||||
workbenchDetail.value = resource; detail.value = resource; overview.value = aggregate
|
||||
if (activeTab.value === 'loading-list' && !canViewCurrentLoadingList.value) activeTab.value = 'overview'
|
||||
if (isDomestic.value && activeTab.value === 'loading-list') await loadLoadingDetail(resource, aggregate)
|
||||
if (isOverseas.value && resource.planStatus === 'COMPLETED' && canViewLoadingList.value) {
|
||||
await loadLoadingDetail(resource, aggregate)
|
||||
}
|
||||
} catch (cause) { error.value = getApiErrorDetails(cause, '货柜详情加载失败') }
|
||||
finally { loading.value = false }
|
||||
}
|
||||
@@ -515,7 +525,7 @@ onMounted(async () => { await load(); if (isOverseas.value && route.query.action
|
||||
<LoadErrorState v-if="overviewError" compact title="履约摘要加载失败" :message="overviewError.message" :show-retry="false" />
|
||||
<section v-show="activeTab === 'overview'" class="detail-section surface-panel" aria-labelledby="container-information-heading">
|
||||
<header class="detail-section__heading"><h2 id="container-information-heading">货柜信息</h2><PalletLabelPrintDialog v-if="overview?.loadingPlanId && detail.warehouseId" :plan-id="overview.loadingPlanId" :warehouse-id="detail.warehouseId" :disabled="!detail.containerNo || detail.planStatus === 'EDITING'" /></header>
|
||||
<div class="detail-fields"><dl><div><dt>真实订舱</dt><dd><span>{{ detail.oceanBookingId ? (detail.billOfLadingNo || '已关联') : '未关联' }}</span><el-button v-if="canLinkOceanBooking" link type="primary" @click="openOceanBookingLink"><Link2 :size="14" />关联已放舱订舱</el-button></dd></div><div><dt>计划渠道</dt><dd>{{ plannedChannelName }}</dd></div><div><dt>实际渠道</dt><dd>{{ detail.channelName || '待关联订舱' }}</dd></div><div><dt>异常状态</dt><dd>{{ detail.exceptionActive ? '异常' : '正常' }}</dd></div><div><dt>目的仓</dt><dd>{{ detail.destinationWarehouseName || detail.destinationWarehouseCode || '—' }}</dd></div><div><dt>拖车公司</dt><dd>{{ detail.terminalTruckingCompany || '—' }}</dd></div></dl></div>
|
||||
<div class="detail-fields"><dl><div><dt>真实订舱</dt><dd><span>{{ detail.oceanBookingId ? (detail.billOfLadingNo || '已关联') : '未关联' }}</span><el-button v-if="canLinkOceanBooking" link type="primary" @click="openOceanBookingLink"><Link2 :size="14" />关联已放舱订舱</el-button></dd></div><div><dt>计划渠道</dt><dd>{{ plannedChannelName }}</dd></div><div><dt>实际渠道</dt><dd>{{ detail.channelName || '待关联订舱' }}</dd></div><div><dt>异常状态</dt><dd>{{ detail.exceptionActive ? '异常' : '正常' }}</dd></div><div><dt>目的仓</dt><dd>{{ overseasDestinationText }}</dd></div><div><dt>拖车公司</dt><dd>{{ detail.terminalTruckingCompany || workbenchDetail?.terminalDrayage?.fleetSupplierName || '—' }}</dd></div></dl></div>
|
||||
<ContainerOverviewPanel v-if="isDomestic && overview" :overview="overview" :sections="['exception']" :can-manage-documents="canEdit" :can-manage-customs="canManageCustoms" :can-manage-exception="canEdit" @manage-exception="openException" />
|
||||
</section>
|
||||
|
||||
@@ -555,7 +565,7 @@ onMounted(async () => { await load(); if (isOverseas.value && route.query.action
|
||||
|
||||
<section v-if="isOverseas" v-show="activeTab === 'overview'" class="detail-section surface-panel" aria-labelledby="container-overseas-receiving-heading">
|
||||
<header class="detail-section__heading"><h2 id="container-overseas-receiving-heading">提柜、卸柜与还空</h2><el-button v-if="canRecordEmptyReturn" type="primary" :loading="emptyReturnSaving" @click="openEmptyReturn">确认还柜</el-button></header>
|
||||
<div class="detail-fields"><dl><div><dt>码头拖车状态</dt><dd>{{ workbenchDetail?.statusSummary?.terminalDrayageStatus || '—' }}</dd></div><div><dt>码头车队</dt><dd>{{ workbenchDetail?.terminalDrayage?.fleetSupplierName || '—' }}</dd></div><div><dt>预约提柜</dt><dd>{{ formatTime(workbenchDetail?.terminalDrayage?.pickupAppointmentAt) }}</dd></div><div><dt>实际提柜</dt><dd>{{ formatTime(workbenchDetail?.terminalDrayage?.actualPickupAt) }}</dd></div><div><dt>卸柜完成</dt><dd>{{ formatTime(workbenchDetail?.actualFacts?.unloadingCompletedAt as string | null) }}</dd></div><div><dt>实际还柜</dt><dd>{{ formatTime(workbenchDetail?.terminalDrayage?.actualEmptyReturnAt) }}</dd></div></dl></div>
|
||||
<div class="detail-fields"><dl><div><dt>码头拖车状态</dt><dd>{{ workbenchDetail?.statusSummary?.terminalDrayageStatus || '—' }}</dd></div><div><dt>码头车队</dt><dd>{{ workbenchDetail?.terminalDrayage?.fleetSupplierName || '—' }}</dd></div><div><dt>预约提柜</dt><dd>{{ formatTime(workbenchDetail?.terminalDrayage?.pickupAppointmentAt) }}</dd></div><div><dt>实际提柜</dt><dd>{{ formatTime(workbenchDetail?.terminalDrayage?.actualPickupAt) }}</dd></div><div><dt>卸柜完成</dt><dd>{{ formatTime((workbenchDetail?.actualFacts?.unloadingCompletedAt || workbenchDetail?.terminalDrayage?.unloadingCompletedAt) as string | null) }}</dd></div><div><dt>实际还柜</dt><dd>{{ formatTime(workbenchDetail?.terminalDrayage?.actualEmptyReturnAt) }}</dd></div></dl></div>
|
||||
</section>
|
||||
|
||||
<section v-if="isDomestic && activeTab === 'loading-list'" class="detail-section surface-panel" aria-labelledby="container-loading-list-heading">
|
||||
|
||||
Reference in New Issue
Block a user