feat(admin): streamline appointments and fleet intake

This commit is contained in:
2026-10-09 22:05:51 +08:00
parent 88dc4852c6
commit e1457a8e57
39 changed files with 1215 additions and 165 deletions
@@ -0,0 +1,37 @@
<script setup lang="ts">
import { ref, watch, onBeforeUnmount } from 'vue'
import AppDialog from '@/shared/components/AppDialog.vue'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
import { getInquiryFulfillment } from '../api/capacityOffers'
import type { CapacityInquiry } from '../capacityOfferTypes'
import TripBookingFulfillmentDialog from './TripBookingFulfillmentDialog.vue'
const dialog = ref<InstanceType<typeof TripBookingFulfillmentDialog> | null>(null)
const activeMode = ref<'incoming' | 'receipt' | 'bind' | 'view'>('view')
const open = defineModel<boolean>({ default: false })
const props = defineProps<{ inquiry: CapacityInquiry | null; mode: 'incoming' | 'receipt' | 'bind' | 'view' }>()
const emit = defineEmits<{ saved: [] }>()
const loaded = ref<Awaited<ReturnType<typeof getInquiryFulfillment>> | null>(null)
const error = ref<ApiErrorDetails | null>(null), loading = ref(false)
let generation = 0
async function load() {
if (!props.inquiry || !open.value) return
const current = ++generation; loading.value = true; error.value = null
try { const value = await getInquiryFulfillment(props.inquiry.bookingNo); if (current === generation) loaded.value = value }
catch (cause) { if (current === generation) error.value = getApiErrorDetails(cause, '本票履约进度读取失败') }
finally { if (current === generation) loading.value = false }
}
watch(() => [open.value, props.inquiry?.bookingNo, props.mode], () => { generation++; if (!open.value || dialog.value?.hasPending) return; activeMode.value = props.mode; loaded.value = null; void load() }, { immediate: true })
onBeforeUnmount(() => { generation++ })
</script>
<template>
<AppDialog class="admin-density-dialog" v-if="!loaded" v-model="open" title="读取本票处理进度" width="1080px" :show-confirm="false">
<p v-if="loading">正在读取本票真实履约资料…</p>
<LoadErrorState v-if="error" title="读取未完成" :message="error.message" @retry="load"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState>
</AppDialog>
<TripBookingFulfillmentDialog v-else ref="dialog" v-model="open" pool :booking="loaded.booking" :initial-preview="loaded.preview" :mode="activeMode"
:arrival-at="inquiry?.estimatedArrivalAt" :instructions="inquiry?.cargo.remark"
:trip="{ tripNo: loaded.booking.tripNo, recordVersion: loaded.preview.tripRecordVersion, plannedDepartureAt: loaded.plannedDepartureAt }"
@saved="emit('saved')" />
</template>