Merge remote-tracking branch 'origin/release/test' into dev

# Conflicts:
#	src/modules/first-leg/views/QuickOrderView.vue
This commit is contained in:
2026-09-04 12:36:56 +08:00
7 changed files with 160 additions and 73 deletions
@@ -200,8 +200,9 @@ const inboundBilling = ref<MerchantInboundBilling | null>(null)
const inboundBillingLoading = ref(false)
const inboundBillingUnavailable = ref(false)
const inboundBillingUnavailableMessage = ref('还未测量推送')
const openFeeDialogWithDetail = ref(false)
const inboundBillingError = ref('')
const inboundBillingOrderId = ref('')
const feeConfirmationOpen = ref(false)
const customsByOrder = reactive<Record<string, MerchantCustomsContainer | null | undefined>>({})
const customsEligibilityPending = new Set<string>()
const customsDialogOpen = ref(false)
@@ -650,12 +651,16 @@ watch(isCreatePage, (isCreate, wasCreate) => {
}, { immediate: true })
watch(detailOpen, (open) => {
if (!open) {
if (!open && !feeConfirmationOpen.value) {
resetInboundBillingState()
if (detailOrder.value) releaseProductImagePreviews(detailOrder.value.items)
}
})
watch(feeConfirmationOpen, (open) => {
if (!open && !detailOpen.value) resetInboundBillingState()
})
onBeforeUnmount(() => {
resetInboundBillingState()
channelRequestSequence += 1
@@ -1195,8 +1200,8 @@ async function openEdit(order: FirstLegOrder) {
}
}
async function openDetail(order: FirstLegOrder, showFeeDialog = false) {
openFeeDialogWithDetail.value = showFeeDialog
async function openDetail(order: FirstLegOrder) {
feeConfirmationOpen.value = false
detailId.value = order.id
detailCargoPage.value = 1
detailOpen.value = true
@@ -1216,7 +1221,11 @@ async function openDetail(order: FirstLegOrder, showFeeDialog = false) {
}
function openFeeConfirmation(order: FirstLegOrder) {
void openDetail(order, true)
detailOpen.value = false
resetInboundBillingState()
inboundBillingUnavailableMessage.value = '未推送计费重'
feeConfirmationOpen.value = true
void loadInboundBilling(order, '未推送计费重')
}
async function retryDetail() {
@@ -1226,6 +1235,7 @@ async function retryDetail() {
function resetInboundBillingState() {
inboundBillingRequestSequence += 1
inboundBillingOrderId.value = ''
inboundBilling.value = null
inboundBillingLoading.value = false
inboundBillingUnavailable.value = false
@@ -1235,21 +1245,24 @@ function resetInboundBillingState() {
function isCurrentInboundBillingRequest(sequence: number, orderId: string) {
return sequence === inboundBillingRequestSequence
&& detailOpen.value
&& detailId.value === orderId
&& inboundBillingOrderId.value === orderId
&& (detailOpen.value || feeConfirmationOpen.value)
}
async function loadInboundBilling(order: FirstLegOrder) {
async function loadInboundBilling(order: FirstLegOrder, unavailableMessage = '还未测量推送') {
const sequence = ++inboundBillingRequestSequence
inboundBillingOrderId.value = order.id
inboundBilling.value = null
inboundBillingLoading.value = false
inboundBillingUnavailable.value = false
inboundBillingUnavailableMessage.value = '还未测量推送'
inboundBillingUnavailableMessage.value = unavailableMessage
inboundBillingError.value = ''
if (order.status === 'DRAFT') {
inboundBillingUnavailable.value = true
inboundBillingUnavailableMessage.value = '订单提交后可查看入库结果'
inboundBillingUnavailableMessage.value = feeConfirmationOpen.value
? '未推送计费重'
: '订单提交后可查看入库结果'
return
}
@@ -1262,7 +1275,9 @@ async function loadInboundBilling(order: FirstLegOrder) {
if (!isCurrentInboundBillingRequest(sequence, order.id)) return
if (error instanceof ApiError && error.code === 'A0404') {
inboundBillingUnavailable.value = true
inboundBillingUnavailableMessage.value = error.message || '还未测量推送'
inboundBillingUnavailableMessage.value = feeConfirmationOpen.value
? '未推送计费重'
: error.message || unavailableMessage
} else {
inboundBillingError.value = error instanceof Error ? error.message : '入库与费用加载失败'
}
@@ -1272,8 +1287,12 @@ async function loadInboundBilling(order: FirstLegOrder) {
}
async function retryInboundBilling() {
const order = detailId.value ? store.getById(detailId.value) : undefined
if (order) await loadInboundBilling(order)
const order = inboundBillingOrderId.value ? store.getById(inboundBillingOrderId.value) : undefined
if (order) await loadInboundBilling(order, feeConfirmationOpen.value ? '未推送计费重' : '还未测量推送')
}
function handleInboundFeeConfirmed() {
if (!feeConfirmationOpen.value) void retryInboundBilling()
}
async function confirmDiscardChanges() {
@@ -1782,7 +1801,7 @@ async function searchOrders(model: QueryModel) {
<template #actions="{ row }">
<div class="order-row-actions">
<el-button link type="primary" @click="openDetail(row as FirstLegOrder)"><Eye :size="15" />详情</el-button>
<el-button v-if="(row as FirstLegOrder).status === 'WAIT_SPLIT'" link type="primary" @click="openFeeConfirmation(row as FirstLegOrder)">确认计费重</el-button>
<el-button link type="primary" @click="openFeeConfirmation(row as FirstLegOrder)">确认计费重</el-button>
<el-button v-if="canEditOrder && canClientEditFirstLegOrder((row as FirstLegOrder).status)" link type="primary" :loading="openingEditor" @click="openEdit(row as FirstLegOrder)"><Pencil :size="15" />编辑</el-button>
<el-button v-if="eligibleCustomsDetail(row as FirstLegOrder)" link type="primary" @click="openCustomsDocuments(row as FirstLegOrder)"><FileText :size="15" />报关资料</el-button>
</div>
@@ -1848,7 +1867,7 @@ async function searchOrders(model: QueryModel) {
<span>更新于 {{ formatDateTime(order.updatedAt) }}</span>
<div>
<el-button link type="primary" @click="openDetail(order)"><Eye :size="15" />详情</el-button>
<el-button v-if="order.status === 'WAIT_SPLIT'" link type="primary" @click="openFeeConfirmation(order)">确认计费重</el-button>
<el-button link type="primary" @click="openFeeConfirmation(order)">确认计费重</el-button>
<el-button v-if="canEditOrder && canClientEditFirstLegOrder(order.status)" link type="primary" :loading="openingEditor" @click="openEdit(order)"><Pencil :size="15" />编辑</el-button>
<el-button v-if="eligibleCustomsDetail(order)" link type="primary" @click="openCustomsDocuments(order)"><FileText :size="15" />报关资料</el-button>
</div>
@@ -2156,19 +2175,32 @@ async function searchOrders(model: QueryModel) {
<OrderProgressPanel :order="detailOrder" />
<InboundBillingPanel
:data="inboundBilling"
:auto-open="openFeeDialogWithDetail"
:loading="inboundBillingLoading"
:unavailable="inboundBillingUnavailable"
:unavailable-message="inboundBillingUnavailableMessage"
:error="inboundBillingError"
:can-confirm="canConfirmInboundFee"
@retry="retryInboundBilling"
@confirmed="retryInboundBilling"
@confirmed="handleInboundFeeConfirmed"
/>
</template>
</div>
<template #footer><div v-if="detailOrder" class="editor-actions"><el-button @click="detailOpen = false">关闭</el-button><el-button v-if="canEditOrder && canClientEditFirstLegOrder(detailOrder.status)" :loading="openingEditor" @click="openEdit(detailOrder)"><Pencil :size="16" />编辑草稿</el-button></div></template>
</el-dialog>
<InboundBillingPanel
v-if="feeConfirmationOpen"
dialog-only
auto-open
:data="inboundBilling"
:loading="inboundBillingLoading"
:unavailable="inboundBillingUnavailable"
unavailable-message="未推送计费重"
:error="inboundBillingError"
:can-confirm="canConfirmInboundFee"
@retry="retryInboundBilling"
@confirmed="handleInboundFeeConfirmed"
@closed="feeConfirmationOpen = false"
/>
<CustomsDocumentsDialog
v-model="customsDialogOpen"
:order-id="customsDialogOrderId"