fix(dispatch): align dispatch actions and native return workflows

This commit is contained in:
2026-10-18 16:37:37 +08:00
parent 4806f88d7c
commit a5a1976924
29 changed files with 854 additions and 150 deletions
@@ -4,6 +4,7 @@ import { physicalWeightKg } from '../dispatchPhysicalWeight'
import '@/styles/adminDensity.css'
import { computed, onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useAccessPreviewStore } from '@/core/access/accessPreview'
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
@@ -11,6 +12,7 @@ import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import { getDispatch, type DispatchItemDto, type DispatchSummaryDto } from '../api/dispatches'
import OverseasDetailShell from '../components/OverseasDetailShell.vue'
import { formatOverseasDateTime } from '../lastMilePresentation'
import { overseasWarehousePermissions as permission } from '../permissions'
interface DetailField { label: string; value: string | number }
interface RelatedOrderRow {
@@ -24,10 +26,24 @@ interface RelatedOrderRow {
const route = useRoute()
const router = useRouter()
const access = useAccessPreviewStore()
const dispatchNo = computed(() => String(route.params.dispatchNo || ''))
const detail = ref<DispatchSummaryDto | null>(null)
const loading = ref(false)
const loadError = ref<ApiErrorDetails | null>(null)
const actionBlockReasons = computed(() => {
const actions = detail.value?.actions
if (!actions) return detail.value ? ['操作资格暂未返回,请刷新详情'] : []
return [...new Set([actions.editBlockReason, actions.cancelBlockReason, actions.removePalletBlockReason, actions.transferBlockReason].filter(Boolean))]
})
function openTrip() {
if (!detail.value?.workflow || !access.can('platform:fleet:trip:list')) return
void router.push({ name: 'overseas-master-data-trip-detail', params: { tripNo: detail.value.workflow.tripNo }, query: { tab: 'overview' } })
}
function openOutbound() {
if (!detail.value?.actions?.outboundNo || !access.can(permission.outboundList)) return
void router.push({ name: 'overseas-outbounds', query: { documentNo: detail.value.actions.outboundNo } })
}
const dispatchStatusLabels: Record<string, string> = {
PENDING_DEPARTURE: '待发车',
@@ -138,6 +154,7 @@ onMounted(load)
<OverseasDetailShell class="admin-density" dense title="排车详情" reference-label="排车单号" :reference-value="detail?.dispatchNo || dispatchNo" :back-text="inquiryReturnTarget(route.query) ? '返回原拼车登记' : undefined" :back-label="inquiryReturnTarget(route.query) ? '返回原拼车登记' : '返回排车列表'" domain="排车详情" :pending="false" :status-text="detail ? dispatchStatus(detail.status) : '加载中'" @back="back">
<LoadErrorState v-if="loadError" title="排车详情加载失败" :message="loadError.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="loadError" /></template></LoadErrorState>
<div v-else v-loading="loading" class="dispatch-detail" :aria-busy="loading">
<section v-if="detail" class="detail-section" aria-label="排车操作提示"><p v-for="reason in actionBlockReasons" :key="String(reason)">{{ reason }}</p><div class="density-actions"><el-button v-if="detail.workflow && access.can('platform:fleet:trip:list')" class="density-action" @click="openTrip">处理原车次 {{ detail.workflow.tripNo }}</el-button><el-button v-if="detail.actions?.outboundNo && access.can(permission.outboundList)" class="density-action" @click="openOutbound">查看原出库 {{ detail.actions.outboundNo }}</el-button></div></section>
<div class="summary-grid">
<section class="detail-section" aria-labelledby="dispatch-vehicle-heading"><h2 id="dispatch-vehicle-heading">车辆信息</h2><dl class="detail-fields density-fields"><div v-for="field in vehicleFields" :key="field.label"><dt>{{ field.label }}</dt><dd>{{ field.value }}</dd></div></dl></section>
<section class="detail-section" aria-labelledby="dispatch-info-heading"><h2 id="dispatch-info-heading">排车信息</h2><dl class="detail-fields density-fields"><div v-for="field in dispatchFields" :key="field.label"><dt>{{ field.label }}</dt><dd>{{ field.value }}</dd></div></dl></section>