This commit is contained in:
2026-10-30 17:59:48 +08:00
parent d6ef770e48
commit ad72ab8406
10 changed files with 209 additions and 42 deletions
@@ -3,7 +3,7 @@ import { computed, onMounted, reactive, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, type FormInstance } from 'element-plus'
import TransportDemandForm from './TransportDemandForm.vue'
import { requireOrderBudget } from '../api/orderBudgets'
import OrderFundingStatus from './OrderFundingStatus.vue'
import { createTransportDemandForm, transportDemandError, buildTransportDemand, type TransportDemandForm as DemandFormModel } from '../transportDemandForm'
import DataTable, { type DataTableColumn } from '@/components/common/DataTable.vue'
import QueryToolbar, { type QueryField, type QueryModel } from '@/components/common/QueryToolbar.vue'
@@ -67,6 +67,7 @@ function transportColumns(looseboard: boolean): ColumnDefinition[] {
{ key: 'pickupAt', label: pickupLabel, width: 165 }, { key: 'deliveryAt', label: deliveryLabel, width: 165 },
]),
{ key: 'status', label: '状态', width: 130 },
...(!looseboard ? [{ key: 'failureReason', label: '失败 / 拒绝原因', width: 240 }] : []),
{ key: 'fleetArrangement', label: '承运安排', width: 190 },
]
}
@@ -105,6 +106,8 @@ const queryFields = computed<QueryField[]>(() => [
type: 'select',
placeholder: '全部',
options: [
{ label: '订单受理中', value: 'FUNDING_PENDING' },
{ label: '订单处理失败', value: 'FUNDING_FAILED' },
{ label: '待审核', value: 'PENDING_REVIEW' },
{ label: '已通过', value: 'APPROVED' },
{ label: '已拒绝', value: 'REJECTED' },
@@ -144,7 +147,7 @@ const tableColumns = computed<DataTableColumn[]>(() => [
...configuration.value.columns.map((column) => ({
...column,
prop: column.key,
slotName: ['orderNo', 'status', 'fleetArrangement'].includes(column.key) ? column.key : undefined,
slotName: ['orderNo', 'status', 'failureReason', 'fleetArrangement'].includes(column.key) ? column.key : undefined,
formatter: (row: object) => displayCell(row, column.key),
})),
])
@@ -164,10 +167,10 @@ function localMinute(value: unknown) { return value ? String(value).replace('T',
function transportTypeLabel(value: unknown) { return ({ PORT_PICKUP: '港口提柜', WAREHOUSE_TO_WAREHOUSE: '仓到仓', WAREHOUSE_TO_DOOR: '仓到门' } as Record<string, string>)[String(value)] || text(value) }
function statusLabel(value: unknown) {
if (poolOrderStatusLabels[String(value)]) return poolOrderStatusLabels[String(value)]
return ({ PENDING_REVIEW: '待审核', APPROVED: '已通过', REJECTED: '已拒绝', PENDING_ACCEPTANCE: '待接单', PROCESSING: '处理中', IN_TRANSIT: '运输中', COMPLETED: '已完成', CANCELLED: '已取消' } as Record<string, string>)[String(value)] || text(value)
return ({ FUNDING_PENDING: '订单受理中', FUNDING_FAILED: '订单处理失败', PENDING_REVIEW: '待审核', APPROVED: '已通过', REJECTED: '已拒绝', PENDING_ACCEPTANCE: '待接单', PROCESSING: '处理中', IN_TRANSIT: '运输中', COMPLETED: '已完成', CANCELLED: '已取消' } as Record<string, string>)[String(value)] || text(value)
}
function statusTone(value: unknown) {
return ({ APPROVED: 'success', COMPLETED: 'success', REJECTED: 'danger', CANCELLED: 'info', PENDING_REVIEW: 'warning', PENDING_ACCEPTANCE: 'warning', PROCESSING: 'primary', IN_TRANSIT: 'primary' } as Record<string, 'success' | 'warning' | 'danger' | 'info' | 'primary'>)[String(value)] || 'info'
return ({ APPROVED: 'success', COMPLETED: 'success', REJECTED: 'danger', CANCELLED: 'info', FUNDING_PENDING: 'warning', FUNDING_FAILED: 'danger', PENDING_REVIEW: 'warning', PENDING_ACCEPTANCE: 'warning', PROCESSING: 'primary', IN_TRANSIT: 'primary' } as Record<string, 'success' | 'warning' | 'danger' | 'info' | 'primary'>)[String(value)] || 'info'
}
function displayCell(candidate: unknown, key: string) {
const row = candidate as BusinessRow
@@ -264,15 +267,17 @@ async function submit() {
try {
if (props.kind === 'trucking') {
const payload = { ...buildTransportDemand('truck', form), idempotencyKey: stableSubmitKey }
await requireOrderBudget('trucking', stableSubmitKey, payload.budgetAmount!, payload.currency)
await createTransport('trucking', payload)
}
else await createTransport('looseboard', { ...buildTransportDemand('looseboard', form), idempotencyKey: stableSubmitKey })
ElMessage.success('订单提交成功')
ElMessage.success(props.kind === 'trucking' ? '本土卡订单已受理,资金校验完成后进入平台审核' : '订单提交成功')
resetForm()
if (props.createPage) await router.push({ name: listRouteName.value })
else { mode.value = 'list'; await load() }
} catch (cause) { if (/已释放|已过期/.test(errorMessage(cause))) submitKey.value = ''; ElMessage.error(errorMessage(cause)) }
} catch (cause) {
if (/已释放|已过期/.test(errorMessage(cause))) submitKey.value = ''
ElMessage.error(errorMessage(cause))
}
finally { submitting.value = false }
}
@@ -298,6 +303,7 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
<template v-if="error" #error><div class="business-load-error" role="alert"><span>{{ error }}</span><el-button size="small" @click="load">重新加载</el-button></div></template>
<template #orderNo="{ row }"><button class="business-order-link" type="button" @click="openDetail(row)">{{ (row as BusinessRow).orderNo }}</button></template>
<template #status="{ row }"><el-tag :type="statusTone((row as BusinessRow).status)" effect="light" size="small">{{ statusLabel((row as BusinessRow).status) }}</el-tag></template>
<template #failureReason="{ row }"><OrderFundingStatus v-if="['FUNDING_FAILED', 'REJECTED'].includes((row as BusinessRow).status)" kind="trucking" :order-no="(row as BusinessRow).orderNo" :status="(row as BusinessRow).status" :can-retry="false" compact /><span v-else>—</span></template>
<template #fleetArrangement="{ row }"><template v-if="(row as TransportSummary).fleetArrangement"><div>{{ poolOrderStatusLabels[(row as TransportSummary).fleetArrangement!.fulfillmentStage] || '待核对履约进度' }}</div><small>{{ dateTime((row as TransportSummary).fleetArrangement!.plannedDepartureAt) }}</small></template><span v-else>—</span></template>
</DataTable>
</div>
@@ -308,6 +314,8 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
<div class="business-detail-heading-main"><el-button link type="primary" @click="returnToList">← 返回列表</el-button><div><h2>{{ detail?.summary.orderNo || '订单详情' }}</h2></div></div>
<el-tag :type="statusTone(detail?.summary.status)" effect="light">{{ detailStatus }}</el-tag>
</header>
<el-button :disabled="loading" @click="loadDetail">刷新</el-button>
<OrderFundingStatus v-if="kind === 'trucking' && detail" kind="trucking" :order-no="detail.summary.orderNo" :status="detail.summary.status" :can-retry="canCreate" @changed="loadDetail" />
<div v-if="error" class="business-detail-error" role="alert"><strong>{{ error }}</strong><el-button size="small" @click="loadDetail">重新加载</el-button></div>
<section v-else class="business-detail-section">
<h3>订单信息</h3>