diff --git a/src/modules/first-leg/api/customs.ts b/src/modules/first-leg/api/customs.ts index 6e7d15f..1f2b507 100644 --- a/src/modules/first-leg/api/customs.ts +++ b/src/modules/first-leg/api/customs.ts @@ -33,6 +33,8 @@ export interface MerchantCustomsDocument { inboundCodes: string[] frozen: boolean completion: MerchantCustomsFile | null + receiptStatus: 'PENDING' | 'CONFIRMED' | 'REJECTED' | null + receiptRejectReason: string | null } export interface MerchantCustomsContainer { @@ -47,6 +49,7 @@ export interface MerchantCustomsContainer { version: number taxRefundCount: number coveredTaxRefundCount: number + actualBoxCount: number inbounds: MerchantCustomsInbound[] documents: MerchantCustomsDocument[] startedAt?: string | null @@ -190,6 +193,24 @@ export function downloadMerchantCustomsCompletion(document: MerchantCustomsDocum ) } +export function confirmMerchantCustomsReceipt(document: MerchantCustomsDocument) { + return apiRequest({ + method: 'POST', + url: `/merchant/v1/customs/documents/${encodedId(document.documentId)}/receipt/confirm`, + headers: { 'Idempotency-Key': createIdempotencyKey(`merchant-customs-receipt-confirm-${document.documentId}`) }, + data: { expectedVersion: document.completion?.version ?? 0, confirm: true, remark: null }, + }) +} + +export function rejectMerchantCustomsReceipt(document: MerchantCustomsDocument, reason: string) { + return apiRequest({ + method: 'POST', + url: `/merchant/v1/customs/documents/${encodedId(document.documentId)}/receipt/reject`, + headers: { 'Idempotency-Key': createIdempotencyKey(`merchant-customs-receipt-reject-${document.documentId}`) }, + data: { expectedVersion: document.completion?.version ?? 0, confirm: false, remark: reason }, + }) +} + export function merchantCustomsErrorMeta(error: unknown): ApiErrorMeta | null { if (!(error instanceof ApiError)) return null return { code: error.code, requestId: error.requestId ?? null, traceId: error.traceId ?? null } diff --git a/src/modules/first-leg/components/CustomsDocumentsDialog.vue b/src/modules/first-leg/components/CustomsDocumentsDialog.vue index 0a975dd..fdab2a1 100644 --- a/src/modules/first-leg/components/CustomsDocumentsDialog.vue +++ b/src/modules/first-leg/components/CustomsDocumentsDialog.vue @@ -5,11 +5,13 @@ import { Download, FileText, LockKeyhole, Pencil, Trash2, Upload } from '@lucide import { MERCHANT_CUSTOMS_STATUS_LABELS, deleteMerchantCustomsDocument, + confirmMerchantCustomsReceipt, downloadMerchantCustomsCompletion, downloadMerchantCustomsSource, getMerchantCustomsForOrder, merchantCustomsErrorMessage, replaceMerchantCustomsDocument, + rejectMerchantCustomsReceipt, updateMerchantCustomsDocumentInbounds, uploadMerchantCustomsDocument, validateMerchantCustomsFile, @@ -207,6 +209,32 @@ async function downloadFile(document: MerchantCustomsDocument, kind: 'source' | } } +async function confirmReceipt(document: MerchantCustomsDocument) { + try { + await ElMessageBox.confirm('确认已核对整份报关行回执吗?确认后将进入整柜报关完成汇总。', '确认报关行回执', { type: 'warning' }) + mutating.value = true + await confirmMerchantCustomsReceipt(document) + ElMessage.success('回执确认成功') + await loadDetail() + } catch (error) { + if (error === 'cancel' || error === 'close') return + ElMessage.error(merchantCustomsErrorMessage(error, '回执确认失败')) + } finally { mutating.value = false } +} + +async function rejectReceipt(document: MerchantCustomsDocument) { + try { + const reason = await ElMessageBox.prompt('请填写打回原因', '打回报关行回执', { inputValidator: (value) => value.trim() ? true : '请输入打回原因' }) + mutating.value = true + await rejectMerchantCustomsReceipt(document, reason.value) + ElMessage.success('回执已打回') + await loadDetail() + } catch (error) { + if (error === 'cancel' || error === 'close') return + ElMessage.error(merchantCustomsErrorMessage(error, '回执打回失败')) + } finally { mutating.value = false } +} + function formatDateTime(value: string | null | undefined) { if (!value) return '-' const date = new Date(value) @@ -246,6 +274,10 @@ function formatSize(bytes: number) { 资料覆盖 {{ detail.coveredTaxRefundCount }} / {{ detail.taxRefundCount }} 票 +
+ 实际箱数 + {{ detail.actualBoxCount }} +
{{ merchantStatusLabel }} @@ -286,7 +318,12 @@ function formatSize(bytes: number) {
源文件 - 完成文件 + 报关行回执 + + {{ item.receiptStatus === 'CONFIRMED' ? '已确认' : item.receiptStatus === 'REJECTED' ? `已打回:${item.receiptRejectReason || '待补充'}` : '待确认' }}