fix: align audit and dispatch workflows and release failed requests

This commit is contained in:
2026-10-22 23:10:09 +08:00
parent 9cdcb9c077
commit 4a3456756f
124 changed files with 1296 additions and 2120 deletions
@@ -85,9 +85,8 @@ async function assign() {
busy.value = true; error.value = null
try { detail.value = await assignTransport(props.dispatchNo, { recordVersion: trip.value.recordVersion, vehicleId: vehicleId.value, driverId: driverId.value, reason: reason.value.trim() || '分配运输车辆及司机', ...(detail.value?.taskType === 'PICKUP' ? { dispatchRecordVersion: detail.value.dispatchRecordVersion, reviewPhotos: { vehicleFileIds: [...vehiclePhotos.value], driverPhotoFileIds: [...driverPhotos.value], licenseFileIds: [...licensePhotos.value] }, masterLicenseFileId: activeMasterLicense.value?.fileId || null } : {}) }); editingResources.value = false; emit('saved'); ElMessage.success('车辆司机及审核照片已保存') }
catch (cause) { error.value = getApiErrorDetails(cause, '保存未完成,已上传照片保留,请核对后重试') }
finally { busy.value = false }
finally { pending.value = null; busy.value = false }
}
/** 每次业务命令保留原版本与幂等键,结果未知只重试原请求。 */
async function execute() {
if (!pending.value || busy.value) return
const request = pending.value; busy.value = true; error.value = null
@@ -96,8 +95,8 @@ async function execute() {
else if (request.kind === 'release') await releaseTransport(props.dispatchNo, request.body as Parameters<typeof releaseTransport>[1])
else await commandTransport(props.dispatchNo, request.suffix, request.body)
pending.value = null; pickupOpen.value = false; releaseOpen.value = false; await load(); emit('saved'); ElMessage.success('运输操作已保存')
} catch (cause) { if (cause instanceof ApiResponseError) { pending.value = null; await load() }; error.value = getApiErrorDetails(cause, '运输操作未完成') }
finally { busy.value = false }
} catch (cause) { error.value = getApiErrorDetails(cause, '运输操作未完成') }
finally { pending.value = null; busy.value = false }
}
async function command(action: 'depart' | 'complete' | 'arrive' | 'cancel', row?: PickupTask) {
if (!trip.value || locked.value) return
@@ -121,7 +120,7 @@ async function upload(event: Event, pickup: boolean) {
const row = selected.value, suffix = pickup && row ? `pickup/${encodeURIComponent(row.customerId)}/${encodeURIComponent(row.transferNo)}` : 'truck'
const result = await uploadTransport(props.dispatchNo, suffix, file); (pickup ? evidence.value : truckEvidence.value).push(result)
} catch (cause) { error.value = getApiErrorDetails(cause, '凭证上传失败') }
finally { busy.value = false; input.value = '' }
finally { pending.value = null; busy.value = false; input.value = '' }
}
async function picked() {
if (!selected.value || !trip.value || (!arrivalMode.value && !validPickupQuantity.value) || !evidence.value.length || locked.value) return
@@ -134,12 +133,12 @@ async function release() {
if (!trip.value || !actualEnd.value || !endLocation.value.trim() || locked.value) return
pending.value = { suffix: 'release', kind: 'release', body: { recordVersion: trip.value.recordVersion, resourceKind: releaseKind.value, actualEndAt: actualEnd.value, endLocation: endLocation.value.trim(), vehicleStatus: releaseKind.value === 'VEHICLE' ? 'IN_SERVICE' : null, idempotencyKey: crypto.randomUUID(), reason: reason.value.trim() || '确认资源实际任务结束' } }; await execute()
}
onBeforeRouteLeave(() => !locked.value || window.confirm('运输请求尚待核对,离开会丢失原请求。确认离开?'))
onBeforeRouteLeave(() => !locked.value || window.confirm('运输操作正在提交,确认离开?'))
</script>
<template>
<section class="transport-execution admin-density admin-workbench" aria-label="运输任务执行">
<LoadErrorState v-if="error" title="操作未完成" :message="error.message" :show-retry="false"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState>
<el-button v-if="pending" :loading="busy" @click="execute">核对原请求</el-button>
<template v-if="detail && trip">
<header class="transport-toolbar">
<div class="transport-identity"><Truck :size="18" aria-hidden="true" /><strong>{{ transportLabels[detail.taskType] }}</strong><el-tag :type="trip.status === 'CANCELLED' ? 'info' : trip.status === 'COMPLETED' ? 'success' : 'primary'">{{ detail.taskType === 'PICKUP' ? pickupStage : { PLANNED: '待发车', IN_TRANSIT: '运输中', COMPLETED: '已完成', CANCELLED: '已取消' }[trip.status] }}</el-tag></div>