修复财务页面竞态并整理采购与运输展示

This commit is contained in:
2026-10-30 18:50:53 +08:00
parent 19a618c9d2
commit 7704532e8f
29 changed files with 591 additions and 217 deletions
@@ -90,6 +90,7 @@ const receiptValidationError = ref<string | null>(null)
const receiptError = ref<ApiErrorDetails | null>(null)
const receiptForm = ref({ receivedDate: new Date().toISOString().slice(0, 10), amount: 0, paymentMethod: 'BANK_TRANSFER' as 'BANK_TRANSFER' | 'CASH' | 'OTHER', remark: '' })
const actionBusy = ref(false)
const actionError = ref<ApiErrorDetails | null>(null)
const exportSubmitting = ref(false)
const createPermission = computed(() => props.kind === 'receivable' ? 'platform:finance:settlement-ar:create' : 'platform:finance:settlement-ap:create')
@@ -459,12 +460,19 @@ async function performAction(row: SettlementRow, action: 'VOID' | 'REOPEN') {
}).then((result) => result.value.trim()).catch(() => null)
if (reason === null) return
actionBusy.value = true
actionError.value = null
try {
await actionFinanceSettlement(row.id, { action, reason, expectedVersion: row.version })
ElMessage.success(action === 'VOID' ? '结算单已作废' : '结算单已重开')
if (detailMode.value) await loadDetail(row.id)
else await load()
} catch (cause) { error.value = getApiErrorDetails(cause, `${action === 'VOID' ? '作废' : '重开'}结算单失败`) }
} catch (cause) {
const details = getApiErrorDetails(cause, `${action === 'VOID' ? '作废' : '重开'}结算单失败`)
if (props.kind === 'receivable' && action === 'REOPEN' && details.message === '原对账单已生成其他有效应收结算单') {
details.message = '已有新的应收单,无法重开'
}
actionError.value = details
}
finally { actionBusy.value = false }
}
@@ -524,6 +532,7 @@ onMounted(() => {
<OperationErrorToast v-if="createOpen || paymentOpen" :details="error" />
<OperationErrorToast :message="receiptValidationError" />
<OperationErrorToast :details="receiptError" />
<OperationErrorToast :details="actionError" />
<el-result v-if="!canView" icon="warning" :title="`无权访问${title}`" sub-title="请联系管理员开通结算单查看权限" />
<DetailPageLayout v-else-if="detailMode" class="settlement-detail-page surface-panel finance-density-detail workbench-panel is-flush is-page-surface" :aria-label="`${title}详情`">
<template #header><div class="density-detail-header"><div class="density-detail-heading"><el-button link class="density-back" aria-label="返回列表" @click="backToList"><ArrowLeft :size="16" />返回列表</el-button><h1 class="density-detail-title">{{ detail?.settlementNo || '—' }}</h1><StatusBadge v-if="detail" :status="financeStatusLabel(detail.status)" /></div><div class="finance-detail-actions">
@@ -674,7 +683,7 @@ onMounted(() => {
</template>
<AppDialog class="admin-density-dialog admin-workbench is-dialog" v-model="createOpen" :title="`生成${title}`" width="min(600px, 94vw)" fullscreenable :confirm-loading="createBusy" @confirm="submitCreate">
<section class="density-dialog-section workbench-evidence" data-tone="work" aria-label="结算单生成设置"><h3 class="density-dialog-section__title">生成设置</h3>
<section class="density-dialog-section workbench-evidence" aria-label="结算单生成设置"><h3 class="density-dialog-section__title">生成设置</h3>
<el-form class="density-form" label-position="left" label-width="120px" :disabled="createBusy"><table class="density-table density-table--editable"><tbody>
<tr><td><el-form-item label="客户"><el-select v-model="createForm.customerId" filterable placeholder="请选择客户"><el-option v-for="item in activeCustomers" :key="String(item.id)" :label="item.tenantName" :value="String(item.id)" /></el-select></el-form-item></td></tr>
<tr><td><el-form-item label="币种"><span>CNY</span></el-form-item></td></tr>