feat(fleet): select versioned sales quotes and isolate cost drafts

This commit is contained in:
2026-10-03 13:20:35 +08:00
parent 3440f9dd11
commit 5641ea0f7e
15 changed files with 288 additions and 31 deletions
@@ -34,6 +34,8 @@ const financeStatus = computed(() => financeTarget.value ? financeStates.value[f
const canSubmitFinance = computed(() => access.can(vehicleCareFinanceSubmitPermission) && access.can('platform:supplier:list')
&& !!financeStatus.value && ['UNLINKED', 'VOIDED'].includes(financeStatus.value.status))
let request = 0, operationEpoch = 0, supplierRequest = 0, disposed = false
let financeRequest = 0, financeBatch = 0
const financeVersions = new Map<string, number>()
watch([() => props.vehicleId, () => props.recordType], () => {
operationEpoch++; supplierRequest++; financeOpen.value = false; financeTarget.value = null
financeOpening.value = false; financeSaving.value = false; pendingFinance.value = null
@@ -74,12 +76,17 @@ function actions(): RowActionItem[] { return [{ key: 'edit', label: access.can(p
visible: access.can(permission.vehicleRecordEdit) || (meterRecord.value && access.can(permission.vehicleRecordUpload)) },
{ key: 'finance', label: '财务', visible: costRecord.value, disabled: financeOpening.value || financeSaving.value }] }
async function loadFinance() {
const batch = ++financeBatch
if (!costRecord.value || !rows.value.length) { financeLoading.value = false; return }
const revision = ++financeRequest, numbers = rows.value.map(row => row.recordNo)
for (const number of numbers) financeVersions.set(number, revision)
const scope = request; financeLoading.value = true; financeError.value = null; financeStates.value = {}
try { const result = await listVehicleCareFinance(props.vehicleId, rows.value.map(row => row.recordNo))
if (!disposed && scope === request) financeStates.value = Object.fromEntries(result.map(row => [row.recordNo, row]))
} catch (cause) { if (!disposed && scope === request) financeError.value = getApiErrorDetails(cause, '财务状态未确认') }
finally { if (scope === request) financeLoading.value = false }
try { const result = await listVehicleCareFinance(props.vehicleId, numbers)
if (!disposed && scope === request && batch === financeBatch) {
for (const row of result) if (financeVersions.get(row.recordNo) === revision) financeStates.value[row.recordNo] = row
}
} catch (cause) { if (!disposed && scope === request && batch === financeBatch) financeError.value = getApiErrorDetails(cause, '财务状态未确认') }
finally { if (scope === request && batch === financeBatch) financeLoading.value = false }
}
async function openFinance(row: VehicleCareRecord) {
if (financeOpening.value || financeSaving.value) return
@@ -93,10 +100,14 @@ async function openFinance(row: VehicleCareRecord) {
financeOpening.value = true; financeSaveError.value = null
try {
const current = await getVehicleCare(vehicleId, row.recordNo)
if (disposed || scope !== operationEpoch) return
const revision = ++financeRequest
financeVersions.set(row.recordNo, revision)
const statuses = await listVehicleCareFinance(vehicleId, [row.recordNo])
if (disposed || scope !== operationEpoch) return
financeTarget.value = current; financeStates.value[row.recordNo] = statuses[0]!
ledgerCostNo.value = statuses[0]?.finance?.costNo ?? ''
financeTarget.value = current
if (financeVersions.get(row.recordNo) === revision) financeStates.value[row.recordNo] = statuses[0]!
ledgerCostNo.value = financeStates.value[row.recordNo]?.finance?.costNo ?? ''
if (!pendingFinance.value) { supplierId.value = ''; businessDate.value = new Date(current.details.occurredAt).toLocaleDateString('en-CA'); suppliers.value = [] }
financeOpen.value = true
} catch (cause) { if (!disposed && scope === operationEpoch) financeError.value = getApiErrorDetails(cause, '财务详情读取失败') }