This commit is contained in:
2026-08-19 09:14:35 +08:00
parent c188482c24
commit 80cfca5056
36 changed files with 854 additions and 1044 deletions
+62 -2
View File
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed, reactive, ref, watch } from 'vue'
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
import { CircleDollarSign, PencilLine, RefreshCw } from '@lucide/vue'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { Check, CircleDollarSign, PencilLine, RefreshCw, Send } from '@lucide/vue'
import { firstLegBusinessTypeLabel, firstLegTaxModeLabel } from '@/shared/utils/firstLegBusinessLabels'
import { useAccessPreviewStore } from '@/core/access/accessPreview'
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
@@ -14,8 +14,11 @@ import {
} from '@/shared/api/http'
import {
adjustPublishedInboundFee,
confirmInboundFee,
createFeeActionIdempotencyKey,
createFeeAdjustmentIdempotencyKey,
getLatestInboundFee,
sendInboundFee,
} from './api'
import type { AdjustPublishedInboundFeeRequest, InboundFeeSnapshot } from './types'
@@ -34,6 +37,7 @@ const emit = defineEmits<{
const access = useAccessPreviewStore()
const loading = ref(false)
const adjusting = ref(false)
const feeAction = ref<'confirm' | 'send' | null>(null)
const notFound = ref(false)
const loadError = ref<ApiErrorDetails | null>(null)
const adjustmentError = ref<ApiErrorDetails | null>(null)
@@ -65,6 +69,8 @@ const adjustmentRules: FormRules = {
const canView = computed(() => access.can('firstleg:fba-pricing:view'))
const canAdjust = computed(() => access.can('firstleg:fba-pricing:adjust'))
const canConfirm = computed(() => access.can('firstleg:fba-pricing:confirm'))
const canSend = computed(() => access.can('firstleg:inbound:send-fee'))
const customerContextId = computed(() => props.customerId || props.tenantId || '')
const normalizedInboundId = computed(() => {
const identifier = String(props.inboundId ?? '').trim()
@@ -171,6 +177,44 @@ function openAdjustment() {
adjustOpen.value = true
}
async function transitionFee(action: 'confirm' | 'send') {
if (!snapshot.value || feeAction.value) return
const confirming = action === 'confirm'
const expectedStatus = confirming ? 'CALCULATED' : 'CONFIRMED'
if (snapshot.value.feeStatus !== expectedStatus) return
try {
await ElMessageBox.confirm(
confirming
? '确认后费用金额与计费依据将进入已确认状态,下一步需要发送费用。是否继续?'
: '发送后费用将正式发布,并进入客户应收应付费用来源。是否继续?',
confirming ? '确认头程费用' : '发送头程费用',
{
type: confirming ? 'warning' : 'success',
confirmButtonText: confirming ? '确认费用' : '确认发送',
cancelButtonText: '取消',
},
)
} catch {
return
}
feeAction.value = action
adjustmentError.value = null
try {
const key = createFeeActionIdempotencyKey(action)
const result = confirming
? await confirmInboundFee(customerContextId.value, normalizedInboundId.value, key)
: await sendInboundFee(customerContextId.value, normalizedInboundId.value, key)
snapshot.value = result
emit('changed', result)
ElMessage.success(confirming ? '费用已确认,请继续发送费用' : '费用已发送并发布')
} catch (error) {
adjustmentError.value = getApiErrorDetails(error, confirming ? '费用确认失败,请刷新后重试' : '费用发送失败,请刷新后重试')
await loadFee()
} finally {
feeAction.value = null
}
}
function adjustmentPayload(): AdjustPublishedInboundFeeRequest {
return {
expectedFeeVersion: adjustmentForm.expectedFeeVersion,
@@ -261,6 +305,22 @@ defineExpose({ reload: loadFee })
type="primary"
@click="openAdjustment"
><PencilLine :size="16" />调整初算费用</el-button>
<el-button
v-if="canConfirm && snapshot?.feeStatus === 'CALCULATED'"
data-testid="confirm-fee-button"
type="primary"
:loading="feeAction === 'confirm'"
:disabled="Boolean(feeAction)"
@click="transitionFee('confirm')"
><Check :size="16" />确认费用</el-button>
<el-button
v-if="canSend && snapshot?.feeStatus === 'CONFIRMED'"
data-testid="send-fee-button"
type="primary"
:loading="feeAction === 'send'"
:disabled="Boolean(feeAction)"
@click="transitionFee('send')"
><Send :size="16" />发送费用</el-button>
</div>
</header>