From 8c8fdbc2abc86fbdc5c5126f8f3baf829e2e508a Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Sun, 27 Sep 2026 20:41:38 +0800 Subject: [PATCH] feat(client): show customs clearance results --- src/modules/first-leg/api/customs.ts | 25 +++++++++++++++ .../components/CustomsDocumentsDialog.vue | 31 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/modules/first-leg/api/customs.ts b/src/modules/first-leg/api/customs.ts index 2245062..59070f2 100644 --- a/src/modules/first-leg/api/customs.ts +++ b/src/modules/first-leg/api/customs.ts @@ -58,6 +58,24 @@ export interface MerchantCustomsContainer { completedAt?: string | null } +export type MerchantClearanceResultType = 'INSPECTION' | 'SUPPLEMENT_REQUIRED' | 'RELEASED' | 'DETAINED' | 'OTHER' +export type MerchantClearanceResultStatus = 'OPEN' | 'RESOLVED' | 'CANCELLED' + +export interface MerchantClearanceResult { + id: string + declarationBatchId: string + customsContainerId: string + resultType: MerchantClearanceResultType + resultStatus: MerchantClearanceResultStatus + customsEntryNo: string | null + occurredAt: string + resolution: string | null + evidenceFileId: string | null + recordedByName: string + recordedAt: string + previousResultId: string | null +} + export interface ApiErrorMeta { code: string requestId: string | null @@ -105,6 +123,13 @@ export function getMerchantCustomsForOrder(orderId: string) { }) } +export function getMerchantClearanceResults(orderId: string) { + return apiRequest({ + method: 'GET', + url: `/merchant/v1/customs/orders/${encodedId(orderId)}/clearance-results`, + }) +} + export function uploadMerchantCustomsDocument(planId: string, inboundIds: string[], file: File) { validateMerchantCustomsFile(file) return apiRequest({ diff --git a/src/modules/first-leg/components/CustomsDocumentsDialog.vue b/src/modules/first-leg/components/CustomsDocumentsDialog.vue index a3860a4..89ff1df 100644 --- a/src/modules/first-leg/components/CustomsDocumentsDialog.vue +++ b/src/modules/first-leg/components/CustomsDocumentsDialog.vue @@ -10,6 +10,7 @@ import { downloadMerchantCustomsFinal, downloadMerchantCustomsSource, getMerchantCustomsForOrder, + getMerchantClearanceResults, merchantCustomsErrorMessage, replaceMerchantCustomsDocument, rejectMerchantCustomsReceipt, @@ -18,6 +19,7 @@ import { validateMerchantCustomsFile, type MerchantCustomsContainer, type MerchantCustomsDocument, + type MerchantClearanceResult, } from '@/modules/first-leg/api/customs' const props = defineProps<{ @@ -43,6 +45,7 @@ const uploadInput = ref() const replaceInput = ref() const mutating = ref(false) const downloadingKey = ref('') +const clearanceResults = ref([]) const taxRefundInbounds = computed(() => detail.value?.inbounds.filter((item) => item.taxMode === 'TAX_REFUND') ?? []) const locked = computed(() => Boolean(detail.value?.startedAt) || detail.value?.status === 'DECLARING' || detail.value?.status === 'COMPLETED') @@ -71,6 +74,7 @@ async function loadDetail() { const result = await getMerchantCustomsForOrder(props.orderId) detail.value = result initializeSelection(result) + try { clearanceResults.value = await getMerchantClearanceResults(props.orderId) } catch { clearanceResults.value = [] } emit('updated', result) } catch (error) { detail.value = null @@ -247,6 +251,14 @@ function formatSize(bytes: number) { if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB` return `${(bytes / 1024 / 1024).toFixed(1)} MB` } + +function clearanceResultLabel(value: MerchantClearanceResult) { + return ({ INSPECTION: '查验', SUPPLEMENT_REQUIRED: '补充资料', RELEASED: '放行', DETAINED: '扣留', OTHER: '其他' } as Record)[value.resultType] || value.resultType +} + +function clearanceResultStatusLabel(value: MerchantClearanceResult) { + return value.resultStatus === 'RESOLVED' ? '已处理' : value.resultStatus === 'CANCELLED' ? '已取消' : '待处理' +}