This commit is contained in:
2026-10-19 10:23:38 +08:00
parent 4bb21641d9
commit 8ae1e5d0d4
18 changed files with 575 additions and 28 deletions
@@ -10,6 +10,7 @@ import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/compone
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
import TripPlanDialog from '../components/TripPlanDialog.vue'
import PickupDemandPanel from '../components/PickupDemandPanel.vue'
import { useAccessPreviewStore } from '@/core/access/accessPreview'
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
import { listTrips, type TripQuery } from '../api/trips'
@@ -17,6 +18,8 @@ import { overseasMasterDataPermissions as permission } from '../permissions'
import { tripStatusLabels, type FleetTrip, type TripDetail } from '../tripTypes'
const route = useRoute(), router = useRouter(), access = useAccessPreviewStore()
const workTab = ref('trips'), pickupVisited = ref(false)
watch(workTab, value => { if (value === 'pickups') pickupVisited.value = true })
const rows = ref<FleetTrip[]>([]), total = ref(0), page = ref(1), size = ref(20), loading = ref(false), editorOpen = ref(false)
const error = ref<ApiErrorDetails | null>(null), filters = ref<QueryModel>({ keyword: '', status: '' })
let applied: Omit<TripQuery, 'page' | 'size'> = {}, sequence = 0
@@ -24,7 +27,7 @@ const fields: QueryField[] = [{ key: 'keyword', type: 'input', label: '关键词
{ key: 'status', type: 'select', label: '状态', placeholder: '全部状态', width: 150, options: Object.entries(tripStatusLabels).map(([value, label]) => ({ value, label })) }]
const columns: DataTableColumn[] = [
{ key: 'actions', label: '操作', width: 85, fixed: 'left', slotName: 'actions' }, { key: 'tripNo', label: '车次号', minWidth: 215 },
{ key: 'status', label: '状态', slotName: 'status', width: 120 }, { key: 'warehouseName', label: '起运仓', minWidth: 160 },
{ key: 'purpose', label: '任务类型', slotName: 'purpose', width: 110 }, { key: 'status', label: '状态', slotName: 'status', width: 120 }, { key: 'warehouseName', label: '起运仓', minWidth: 160 },
{ key: 'vehiclePlate', label: '车牌', minWidth: 130 }, { key: 'driverName', label: '司机', minWidth: 110 },
{ key: 'departure', label: '计划发车', slotName: 'departure', minWidth: 175 }, { key: 'end', label: '司机预计结束', slotName: 'end', minWidth: 175 },
{ key: 'route', label: '路线', slotName: 'route', minWidth: 240 }, { key: 'remark', label: '备注', minWidth: 180 },
@@ -46,12 +49,15 @@ watch([page, size], load); onMounted(load); onBeforeUnmount(() => { sequence++ }
</script>
<template>
<AdminPage class="admin-density"><ListPageLayout aria-label="车次管理">
<DataTable appearance="integrated" :stripe="false" column-settings-mode="show" :results-visible="true" preference-key="fleet-trips-table" v-model:page="page" v-model:page-size="size" :data="rows" :columns="columns" :total="total" :loading="loading" row-key="tripNo" empty-text="暂无车次,先建立计划再关联排车单">
<el-tabs v-model="workTab" class="density-element-tabs"><el-tab-pane label="车次管理" name="trips" /><el-tab-pane label="待取货" name="pickups" /></el-tabs>
<PickupDemandPanel v-if="pickupVisited" v-show="workTab === 'pickups'" />
<DataTable v-show="workTab === 'trips'" appearance="integrated" :stripe="false" column-settings-mode="show" :results-visible="true" preference-key="fleet-trips-table" v-model:page="page" v-model:page-size="size" :data="rows" :columns="columns" :total="total" :loading="loading" row-key="tripNo" empty-text="暂无车次,先建立计划再关联排车单">
<template #toolbar-start><el-button v-if="appointmentReturnTarget(route.query)" link @click="router.push(appointmentReturnTarget(route.query)!)">返回预约工作</el-button><h1>车次管理</h1></template>
<template #filters><QueryToolbar v-model="filters" :fields="fields" ariaLabel="车次查询" preference-key="fleet-trips-query" :loading="loading" @search="search" @reset="search" /></template>
<template #notices><LoadErrorState v-if="error" title="车次加载失败" :message="error.message" @retry="load"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState></template>
<template #toolbar-actions><el-button v-if="access.can(permission.tripCreate)" type="primary" @click="editorOpen = true">新建车次</el-button></template>
<template #actions="{ row }"><div class="density-actions row-actions admin-text-actions"><el-button class="density-action" @click="view(row.tripNo)">详情</el-button></div></template>
<template #purpose="{ row }">{{ row.tripPurpose === 'PICKUP' ? '入仓取货' : '出库派送' }}</template>
<template #status="{ row }">{{ tripStatusLabels[row.status as keyof typeof tripStatusLabels] }}</template>
<template #departure="{ row }">{{ time(row.plannedDepartureAt) }}</template><template #end="{ row }">{{ time(row.expectedDriverEndAt) }}</template>
<template #route="{ row }">{{ row.stops.map((stop: FleetTrip['stops'][number]) => stop.name).join(' → ') }}</template>