优化
This commit is contained in:
@@ -43,22 +43,35 @@ const page = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const total = ref(0)
|
||||
const stage = ref<DispatchStage>('BEFORE_LOADING'), section = ref<BeforeLoadingSection>('VEHICLE_INFO')
|
||||
const model = ref<QueryModel>({ dispatchNo: String(route.query.dispatchNo || ''), vehiclePlate: '', status: 'ACTIVE' })
|
||||
const model = ref<QueryModel>({ dispatchNo: String(route.query.dispatchNo || ''), vehiclePlate: '', vehicleStatus: '', status: 'ACTIVE' })
|
||||
const showAdvancedFilters = ref(false)
|
||||
const vehicleStatuses = [
|
||||
{ value: 'WAIT_DEPARTURE', label: '待发车', type: 'warning' },
|
||||
{ value: 'DELIVERING', label: '配送中', type: 'primary' },
|
||||
{ value: 'DELIVERED', label: '已送达', type: 'success' },
|
||||
] as const
|
||||
function vehicleStatusForStage(value: DispatchStage) {
|
||||
if (value === 'BEFORE_LOADING' || value === 'LOADING') return vehicleStatuses[0]
|
||||
return vehicleStatuses.find(item => item.value === value)
|
||||
}
|
||||
const operation = ref<'ROUTE' | undefined>()
|
||||
const action = ref<DispatchAction>('EDIT'), actionNo = ref(''), actionOpen = ref(false), createOpen = ref(false), bolLoadingNo = ref('')
|
||||
const routeOpen = ref(false), routeOrigin = ref<RouteLocation>(routeLocation('')), routeDestinations = ref<RouteLocation[]>([])
|
||||
const sections: Array<{ value: BeforeLoadingSection; label: string }> = [{ value: 'VEHICLE_INFO', label: '车辆信息' }, { value: 'DISPATCH_REVIEW', label: '调度审核' }, { value: 'LOADING_REVIEW', label: '理货员审核' }]
|
||||
const showSections = computed(() => stage.value === 'BEFORE_LOADING' && model.value.status === 'ACTIVE')
|
||||
const fields = computed<QueryField[]>(() => [
|
||||
const showSections = computed(() => stage.value === 'BEFORE_LOADING' && (model.value.status || 'ACTIVE') === 'ACTIVE')
|
||||
const availableFields = computed<QueryField[]>(() => [
|
||||
{ key: 'dispatchNo', label: '排车单号', type: 'input', width: 180, placeholder: '请输入排车单号' },
|
||||
{ key: 'vehiclePlate', label: '车牌号', type: 'input', width: 150, placeholder: '请输入车牌号' },
|
||||
{ key: 'status', label: '单据范围', type: 'select', width: 140, options: [{ value: 'ACTIVE', label: '有效排车' }, { value: 'CANCELLED', label: '已取消' }, { value: 'ALL', label: '全部单据' }] },
|
||||
{ key: 'vehicleStatus', label: '车辆状态', placeholder: '车辆状态', type: 'select', width: 140, options: [...vehicleStatuses], props: { 'aria-label': '车辆状态', onChange: (value: unknown) => { if (value) model.value.status = 'ACTIVE' } } },
|
||||
{ key: 'status', label: '单据范围', placeholder: '单据范围', type: 'select', width: 140, options: [{ value: 'ACTIVE', label: '有效排车' }, { value: 'CANCELLED', label: '已取消' }, { value: 'ALL', label: '全部单据' }], props: { 'aria-label': '单据范围', onChange: (value: unknown) => { if (value && value !== 'ACTIVE') model.value.vehicleStatus = '' } } },
|
||||
])
|
||||
const fields = computed(() => availableFields.value.filter(field => showAdvancedFilters.value || field.key !== 'status'))
|
||||
const columns = computed<DataTableColumn[]>(() => [
|
||||
{ key: 'actions', label: '操作', width: 220, fixed: 'left', slotName: 'actions' },
|
||||
{ key: 'taskType', label: '排车类型', width: 115, slotName: 'taskType' },
|
||||
{ key: 'dispatchNo', prop: 'dispatchNo', label: '排车单号', minWidth: 190 },
|
||||
{ key: 'vehicle', label: '车牌号', minWidth: 130, slotName: 'vehicle' }, { key: 'driver', label: '司机/联系电话', minWidth: 170, slotName: 'driver' },
|
||||
{ key: 'vehicleStatus', label: '车辆状态', minWidth: 110, slotName: 'vehicleStatus' },
|
||||
{ key: 'warehouseName', prop: 'warehouseName', label: '起运仓', minWidth: 160 },
|
||||
...(showSections.value && section.value === 'VEHICLE_INFO' ? [{ key: 'returnReason', label: '退回原因', minWidth: 240, slotName: 'returnReason' }] : []),
|
||||
...(showSections.value && section.value !== 'VEHICLE_INFO' ? [{ key: 'review', label: section.value === 'DISPATCH_REVIEW' ? '调度审核' : '理货员审核', minWidth: 210, slotName: 'review' }] : []),
|
||||
@@ -79,12 +92,27 @@ async function load() {
|
||||
} catch (cause) { if (current === sequence) { rows.value = []; total.value = 0; statistics.value = null; loadError.value = getApiErrorDetails(cause, '排车列表加载失败,请重试') } }
|
||||
finally { if (current === sequence) loading.value = false }
|
||||
}
|
||||
function search(value: QueryModel) { model.value = value; page.value = 1; void load() }
|
||||
function switchStage(value: DispatchStage) { stage.value = value; section.value = 'VEHICLE_INFO'; page.value = 1; void load() }
|
||||
function search(value: QueryModel) {
|
||||
model.value = { ...value, status: value.status || 'ACTIVE' }
|
||||
const selected = vehicleStatuses.find(item => item.value === model.value.vehicleStatus)
|
||||
if (model.value.status !== 'ACTIVE') model.value.vehicleStatus = ''
|
||||
else if (selected && vehicleStatusForStage(stage.value)?.value !== selected.value) {
|
||||
// 车辆运输进度与阶段联动,查询仍由服务端按阶段分页,避免交叉条件恒为空。
|
||||
stage.value = selected.value === 'WAIT_DEPARTURE' ? 'BEFORE_LOADING' : selected.value
|
||||
section.value = 'VEHICLE_INFO'
|
||||
}
|
||||
page.value = 1; void load()
|
||||
}
|
||||
function resetSearch() { search({ dispatchNo: '', vehiclePlate: '', vehicleStatus: '', status: 'ACTIVE' }) }
|
||||
function switchStage(value: DispatchStage) {
|
||||
stage.value = value
|
||||
if (model.value.vehicleStatus) model.value.vehicleStatus = vehicleStatusForStage(value)?.value || ''
|
||||
section.value = 'VEHICLE_INFO'; page.value = 1; void load()
|
||||
}
|
||||
function switchSection(value: BeforeLoadingSection) { section.value = value; page.value = 1; void load() }
|
||||
function openDetail(row: DispatchListRow) { void router.push({ name: 'overseas-dispatch-detail', params: { dispatchNo: row.dispatchNo } }) }
|
||||
const rowActionOrder: DispatchAction[] = ['EDIT', 'SUBMIT_REVIEW', 'DISPATCH_REVIEW', 'LOADING_REVIEW', 'RETURN_TO_REVIEW', 'LOADING_COMPLETE', 'MARK_EXCEPTION', 'CANCEL']
|
||||
function canManageDocuments(row: DispatchListRow) { return (row.taskType || 'DELIVERY') === 'DELIVERY' && row.status === 'ACTIVE' && ['DELIVERING', 'DELIVERED'].includes(row.stage) }
|
||||
function canManageDocuments(row: DispatchListRow) { return (row.taskType || 'DELIVERY') === 'DELIVERY' && row.status === 'ACTIVE' && ['AFTER_LOADING', 'DELIVERING', 'DELIVERED'].includes(row.stage) }
|
||||
function rowActions(row: DispatchListRow): RowActionItem[] {
|
||||
if (showSections.value && section.value !== 'VEHICLE_INFO') {
|
||||
const review = section.value
|
||||
@@ -147,11 +175,12 @@ onBeforeUnmount(() => { sequence++ })
|
||||
<div class="workbench-table is-page-surface"><DataTable v-model:page="page" v-model:page-size="pageSize" appearance="integrated" :data="rows" :columns="columns" :loading="loading" :total="total" :preference-key="preferenceKey" row-key="dispatchNo" empty-text="暂无排车记录" @update:page="load()" @update:page-size="page = 1; load()">
|
||||
<template #toolbar-start><el-button v-if="appointmentReturnTarget(route.query)" link @click="router.push(appointmentReturnTarget(route.query)!)">返回预约工作</el-button><div class="density-status-tabs workbench-list-tabs" role="tablist" aria-label="排车执行阶段"><button v-for="item in dispatchStages" :key="item.value" role="tab" :aria-selected="stage === item.value" :class="{ 'is-active': stage === item.value }" @click="switchStage(item.value)">{{ item.label }} <span>{{ statistics?.stageCounts[item.value] ?? '—' }}</span></button></div></template>
|
||||
<template #toolbar-end><el-button v-if="access.can(dispatchActionPermissions.CREATE)" @click="createTransport('PICKUP')">安排到仓取货</el-button><el-button v-if="access.can(dispatchActionPermissions.CREATE)" @click="createTransport('LOCAL_TRUCK')">安排本土卡车</el-button><el-button v-if="access.can(dispatchActionPermissions.CREATE) || access.can(dispatchActionPermissions.ADD_CARGO)" type="primary" @click="createOpen = true">智能排车</el-button></template>
|
||||
<template #filters><div class="integrated-query-group"><div v-if="showSections" class="density-status-tabs" role="tablist" aria-label="装车前审核分区"><button v-for="item in sections" :key="item.value" role="tab" :aria-selected="section === item.value" :class="{ 'is-active': section === item.value }" @click="switchSection(item.value)">{{ item.label }}</button></div><QueryToolbar v-model="model" :fields="fields" :loading="loading" ariaLabel="排车列表筛选" preference-key="overseas-dispatches-query" :search-on-reset="false" @search="search" @reset="search" /></div></template>
|
||||
<template #filters><div class="integrated-query-group"><div v-if="showSections" class="density-status-tabs" role="tablist" aria-label="装车前审核分区"><button v-for="item in sections" :key="item.value" role="tab" :aria-selected="section === item.value" :class="{ 'is-active': section === item.value }" @click="switchSection(item.value)">{{ item.label }}</button></div><QueryToolbar id="dispatch-query-filters" v-model="model" :fields="fields" :available-fields="availableFields" :loading="loading" ariaLabel="排车列表筛选" preference-key="overseas-dispatches-query" :search-on-reset="false" @search="search" @reset="resetSearch"><template #actions><el-button :aria-expanded="showAdvancedFilters" aria-controls="dispatch-query-filters" @click="showAdvancedFilters = !showAdvancedFilters">{{ showAdvancedFilters ? '收起筛选' : '高级筛选' }}{{ model.status === 'CANCELLED' ? ' · 已取消' : model.status === 'ALL' ? ' · 全部单据' : '' }}</el-button></template></QueryToolbar></div></template>
|
||||
<template v-if="loadError" #state><LoadErrorState title="排车列表加载失败" :message="loadError.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="loadError" /></template></LoadErrorState></template>
|
||||
<template #actions="{ row }"><RowActions text-actions :actions="rowActions(row as DispatchListRow)" :max-visible="2" :more-label="`更多操作 · ${row.dispatchNo}`" @action="handleAction($event, row as DispatchListRow)" /><p v-if="!row.actions">操作资格未返回,请刷新核对</p></template>
|
||||
<template #taskType="{ row }">{{ transportLabels[(row.taskType || 'DELIVERY') as keyof typeof transportLabels] }}</template>
|
||||
<template #vehicle="{ row }">{{ row.resources.vehicle?.plate || '—' }}</template><template #driver="{ row }">{{ row.resources.driver?.name || '—' }}<br>{{ row.resources.driver?.phone || '—' }}</template>
|
||||
<template #vehicleStatus="{ row }"><el-tag v-if="row.status === 'ACTIVE' && vehicleStatusForStage(row.stage)" :type="vehicleStatusForStage(row.stage)?.type">{{ vehicleStatusForStage(row.stage)?.label }}</el-tag><span v-else>—</span></template>
|
||||
<template #review="{ row }"><template v-for="review in [section === 'DISPATCH_REVIEW' ? row.reviews.dispatchReview : row.reviews.loadingReview]" :key="review.reviewRound"><div>{{ reviewLabels[review.status as ReviewStatus] }}</div><div v-if="review.reason">{{ review.reason }}</div><div v-if="review.invalidatedReason">{{ review.invalidatedReason }}</div><div>{{ time(review.reviewedAt) }}</div></template></template>
|
||||
<template #returnReason="{ row }">{{ dispatchRejectionReason(row.reviews) || '—' }}</template>
|
||||
<template #counts="{ row }">{{ row.counts.palletCount }}托/{{ row.counts.packageCount }}箱/已拣{{ row.counts.pickedPackageCount }}箱</template><template #planned="{ row }">{{ time(row.plannedDepartureAt) }}</template><template #departure="{ row }">{{ time(row.departedAt) }}</template><template #stage="{ row }">{{ row.status === 'CANCELLED' ? '已取消' : stageLabel(row.stage) }}</template><template #routeMap="{ row }"><el-button link @click="openRoute(row as DispatchListRow)">查看路线</el-button></template>
|
||||
|
||||
Reference in New Issue
Block a user