fix: complete October 22 workflow feedback and request failure recovery
This commit is contained in:
@@ -85,7 +85,6 @@ const canCreateOrder = computed(() => auth.hasPermission('order:first-leg:create
|
||||
const canEditOrder = computed(() => auth.hasPermission('order:first-leg:edit'))
|
||||
const canCancelOrder = computed(() => auth.hasPermission('order:first-leg:cancel'))
|
||||
const cancellingOrderId = ref('')
|
||||
const pendingCancellation = shallowRef<{ id: string; expectedVersion: number; reason: string; businessNo: string; statusLabel: string }>()
|
||||
|
||||
function canOfferCancellation(order: FirstLegOrder) {
|
||||
return canCancelOrder.value && ['DRAFT', 'PENDING_REVIEW', 'WAIT_MEASURE'].includes(order.status)
|
||||
@@ -95,40 +94,20 @@ async function cancelOrder(order: FirstLegOrder) {
|
||||
if (!canOfferCancellation(order) || cancellingOrderId.value) return
|
||||
cancellingOrderId.value = order.id
|
||||
try {
|
||||
let command = pendingCancellation.value
|
||||
if (command && command.id !== order.id) {
|
||||
ElMessage.warning(`请先处理订单 ${command.businessNo} 未确认的取消结果`)
|
||||
return
|
||||
}
|
||||
if (!command) {
|
||||
const target = await store.prepareCancellation(order.id)
|
||||
const { value } = await ElMessageBox.prompt(`订单:${target.businessNo};当前状态:${target.statusLabel}。请填写取消原因。`, '取消订单', {
|
||||
const target = await store.prepareCancellation(order.id)
|
||||
const { value } = await ElMessageBox.prompt(
|
||||
`订单:${target.businessNo};当前状态:${target.statusLabel}。请填写取消原因。`, '取消订单', {
|
||||
type: 'warning', inputType: 'textarea', confirmButtonText: '确认取消订单', cancelButtonText: '返回',
|
||||
inputValidator: value => Boolean(value?.trim()) && value.trim().length <= 500 || '请填写 1–500 字取消原因',
|
||||
})
|
||||
command = { ...target, reason: value.trim() }
|
||||
pendingCancellation.value = command
|
||||
} else {
|
||||
await ElMessageBox.confirm(`订单:${command.businessNo};原状态:${command.statusLabel};原因:${command.reason}。将查询当前状态并重试原取消请求。`, '重试取消订单', {
|
||||
type: 'warning', confirmButtonText: '重试原请求', cancelButtonText: '返回',
|
||||
})
|
||||
}
|
||||
await store.cancelOrder(command.id, command.expectedVersion, command.reason)
|
||||
pendingCancellation.value = undefined
|
||||
ElMessage.success('订单已取消')
|
||||
await loadOrderPage()
|
||||
await store.cancelOrder(target.id, target.expectedVersion, value.trim())
|
||||
ElMessage.success('订单已取消'); await loadOrderPage()
|
||||
if (isDetailPage.value) await router.push({ name: 'first-leg-orders' })
|
||||
} catch (error) {
|
||||
if (error === 'cancel' || error === 'close') return
|
||||
if (error instanceof ApiError && (error.code === 'A0409' || error.status === 409)) {
|
||||
pendingCancellation.value = undefined
|
||||
ElMessage.error(`${error.message}。请刷新订单后重新确认取消。`)
|
||||
} else {
|
||||
ElMessage.error(error instanceof Error ? error.message : '取消失败,请重试原请求')
|
||||
}
|
||||
} finally {
|
||||
cancellingOrderId.value = ''
|
||||
}
|
||||
ElMessage.error(error instanceof Error ? error.message : '取消失败,请重新操作')
|
||||
void loadOrderPage()
|
||||
} finally { cancellingOrderId.value = '' }
|
||||
}
|
||||
const canSubmitOrder = computed(() => auth.hasPermission('order:first-leg:submit'))
|
||||
const canConfirmInboundFee = computed(() => auth.hasPermission('order:first-leg:edit'))
|
||||
@@ -242,7 +221,6 @@ const tablePageSize = ref(10)
|
||||
const downloadingMarks = ref(false)
|
||||
const exportingOrders = ref(false)
|
||||
const batchSubmitting = ref(false)
|
||||
const pendingBatchSubmissionIds = ref<string[]>([])
|
||||
const selectedOrders = ref<FirstLegOrder[]>([])
|
||||
const selectedOrderCount = computed(() => selectedOrders.value.length)
|
||||
const selectedDraftOrders = computed(() => selectedOrders.value.filter((order) => order.status === 'DRAFT'))
|
||||
@@ -1368,7 +1346,7 @@ function getOrderRowActions(row: object): TableAction[] {
|
||||
actions.push({ key: 'edit', label: '编辑', loading: openingEditor.value, run: () => openEdit(order) })
|
||||
}
|
||||
if (canOfferCancellation(order)) {
|
||||
actions.push({ key: 'cancel', label: pendingCancellation.value?.id === order.id ? '重试取消' : '取消订单', loading: cancellingOrderId.value === order.id, disabled: Boolean(cancellingOrderId.value), run: () => cancelOrder(order) })
|
||||
actions.push({ key: 'cancel', label: '取消订单', loading: cancellingOrderId.value === order.id, disabled: Boolean(cancellingOrderId.value), run: () => cancelOrder(order) })
|
||||
}
|
||||
if (eligibleCustomsDetail(order)) {
|
||||
actions.push({ key: 'customs', label: '报关资料', run: () => openCustomsDocuments(order) })
|
||||
@@ -1751,14 +1729,14 @@ function handleOrderSelectionChange(rows: FirstLegOrder[]) {
|
||||
}
|
||||
|
||||
async function submitSelectedDraftOrders() {
|
||||
const ids = [...new Set([...pendingBatchSubmissionIds.value, ...selectedDraftOrders.value.map(order => order.id)])]
|
||||
const ids = [...new Set(selectedDraftOrders.value.map(order => order.id))]
|
||||
if (batchSubmitting.value || !ids.length) return
|
||||
if (companySubmissionBlocked.value) {
|
||||
ElMessage.warning('企业资料审核通过后才能提交订单')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await ElMessageBox.confirm(`确认提交 ${ids.length} 条草稿订单吗?${pendingBatchSubmissionIds.value.length ? '上次结果未确认的订单将使用原提交命令重试。' : ''}`, '批量提交订单', {
|
||||
await ElMessageBox.confirm(`确认提交 ${ids.length} 条草稿订单吗?`, '批量提交订单', {
|
||||
type: 'warning',
|
||||
confirmButtonText: '确认提交',
|
||||
cancelButtonText: '取消',
|
||||
@@ -1771,7 +1749,6 @@ async function submitSelectedDraftOrders() {
|
||||
batchSubmitting.value = true
|
||||
try {
|
||||
const results = await Promise.allSettled(ids.map(id => store.submitSaved(id, companyAuditLoaded.value ? tenantStore.company.auditStatus : undefined)))
|
||||
pendingBatchSubmissionIds.value = ids.filter((id, index) => results[index]?.status === 'rejected' && store.hasPendingSubmission(id))
|
||||
const successCount = results.filter((result) => result.status === 'fulfilled').length
|
||||
const failures = results.filter((result): result is PromiseRejectedResult => result.status === 'rejected')
|
||||
await searchOrders(appliedFilters.value)
|
||||
@@ -2024,7 +2001,6 @@ async function saveDraft() {
|
||||
if (!await validateEditorForm()) return
|
||||
saving.value = true
|
||||
try {
|
||||
if (!await confirmSubmissionEdit()) return
|
||||
const order = await store.saveDraft(cloneDraft(form), tenantStore.company.companyName, editingId.value, editingSession.value)
|
||||
editingId.value = order.id
|
||||
editingSession.value = store.beginDraftEdit(order)
|
||||
@@ -2039,20 +2015,6 @@ async function saveDraft() {
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmSubmissionEdit() {
|
||||
if (!editingId.value || !store.hasPendingSubmission(editingId.value)) return true
|
||||
try {
|
||||
await ElMessageBox.confirm('上次提交结果尚未确认。确认重新读取订单并按当前表单重新编辑吗?只有服务端仍为草稿时才能开始新的提交决定。', '重新编辑订单', {
|
||||
type: 'warning', center: true, confirmButtonText: '确认重新编辑', cancelButtonText: '返回',
|
||||
})
|
||||
} catch (error) {
|
||||
if (error === 'cancel' || error === 'close') return false
|
||||
throw error
|
||||
}
|
||||
editingSession.value = await store.beginNewSubmissionEdit(editingId.value)
|
||||
return true
|
||||
}
|
||||
|
||||
async function submitOrder() {
|
||||
if (saving.value) return
|
||||
if (companySubmissionBlocked.value) {
|
||||
@@ -2071,14 +2033,12 @@ async function submitOrder() {
|
||||
}
|
||||
return
|
||||
}
|
||||
const retry = store.isSubmissionRetry(editingId.value, cloneDraft(form))
|
||||
if (!retry && !await validateEditorForm()) return
|
||||
if (!await validateEditorForm()) return
|
||||
|
||||
try {
|
||||
saving.value = true
|
||||
if (!retry && !await confirmSubmissionEdit()) return
|
||||
const knownCompanyAuditStatus = companyAuditLoaded.value ? tenantStore.company.auditStatus : undefined
|
||||
const savedOrder = await store.saveDraftForSubmission(cloneDraft(form), tenantStore.company.companyName, editingId.value, editingSession.value)
|
||||
const savedOrder = await store.saveDraft(cloneDraft(form), tenantStore.company.companyName, editingId.value, editingSession.value)
|
||||
editingId.value = savedOrder.id
|
||||
editingSession.value = store.beginDraftEdit(savedOrder)
|
||||
await store.submitSaved(savedOrder.id, knownCompanyAuditStatus)
|
||||
@@ -2156,7 +2116,7 @@ async function searchOrders(model: QueryModel) {
|
||||
</el-popover>
|
||||
<el-button :loading="downloadingMarks" :disabled="selectedOrderCount === 0" @click="downloadShippingMarks"><Download :size="16" />下载唛头</el-button>
|
||||
<el-button :loading="exportingOrders" :disabled="selectedOrderCount === 0" @click="exportOrderInformation"><Download :size="16" />导出订单信息</el-button>
|
||||
<el-button v-if="canSubmitOrder" :loading="batchSubmitting" :disabled="(selectedDraftOrders.length === 0 && pendingBatchSubmissionIds.length === 0) || companySubmissionBlocked" @click="submitSelectedDraftOrders"><Send :size="17" />{{ pendingBatchSubmissionIds.length ? '重试批量提交' : '批量提交草稿' }}</el-button>
|
||||
<el-button v-if="canSubmitOrder" :loading="batchSubmitting" :disabled="selectedDraftOrders.length === 0 || companySubmissionBlocked" @click="submitSelectedDraftOrders"><Send :size="17" />批量提交草稿</el-button>
|
||||
<el-button v-if="auth.hasPermission('order:first-leg:create')" @click="openBatchImport"><Upload :size="17" />批量导入订单</el-button>
|
||||
<el-button v-if="props.showCreateAction && auth.hasPermission('order:first-leg:create')" type="primary" :loading="pageDataLoading" :disabled="pageDataLoading || availableWarehouses.length === 0" @click="openCreate"><FilePlus2 :size="17" />创建订单</el-button>
|
||||
|
||||
@@ -2423,7 +2383,7 @@ async function searchOrders(model: QueryModel) {
|
||||
<el-button link type="primary" class="detail-back-action" @click="router.push({ name: 'first-leg-orders' })">← 返回列表</el-button>
|
||||
<div><h2>{{ detailOrder.businessSummary.inboundCode || (detailOrder.status === 'CANCELLED' ? (detailOrder.orderNo || '—') : detailOrder.status === 'DRAFT' ? '入仓码提交后生成' : '入仓码待生成') }}</h2><p v-if="detailOrder.status === 'CANCELLED'">订单已取消。</p><p v-else>{{ getFirstLegTransportModeLabel(detailOrder.transportMode) }} · {{ detailOrder.origin || '起运地待更新' }} → {{ detailOrder.destination || '目的地待更新' }}</p></div>
|
||||
</div>
|
||||
<div class="detail-heading-actions"><el-tag :type="getFirstLegStatusTone(detailOrder.status)" effect="light">{{ getFirstLegStatusLabel(detailOrder.status) }}</el-tag><el-button v-if="canEditOrder && canClientEditFirstLegOrder(detailOrder.status)" type="primary" plain :loading="openingEditor" @click="openEdit(detailOrder)"><Pencil :size="16" />编辑草稿</el-button><el-button v-if="canOfferCancellation(detailOrder)" type="danger" plain :loading="cancellingOrderId === detailOrder.id" :disabled="!!cancellingOrderId" @click="cancelOrder(detailOrder)">{{ pendingCancellation?.id === detailOrder.id ? '重试取消' : '取消订单' }}</el-button></div>
|
||||
<div class="detail-heading-actions"><el-tag :type="getFirstLegStatusTone(detailOrder.status)" effect="light">{{ getFirstLegStatusLabel(detailOrder.status) }}</el-tag><el-button v-if="canEditOrder && canClientEditFirstLegOrder(detailOrder.status)" type="primary" plain :loading="openingEditor" @click="openEdit(detailOrder)"><Pencil :size="16" />编辑草稿</el-button><el-button v-if="canOfferCancellation(detailOrder)" type="danger" plain :loading="cancellingOrderId === detailOrder.id" :disabled="!!cancellingOrderId" @click="cancelOrder(detailOrder)">取消订单</el-button></div>
|
||||
</div>
|
||||
<section class="detail-section">
|
||||
<h3>订单与运输</h3>
|
||||
|
||||
Reference in New Issue
Block a user