优化
This commit is contained in:
@@ -1,18 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { Eye, Pencil, Plus, RefreshCw } from '@lucide/vue'
|
||||
import { Eye, Pencil, Plus } from '@lucide/vue'
|
||||
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
|
||||
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
|
||||
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
|
||||
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
||||
import StatusBadge from '@/shared/components/StatusBadge.vue'
|
||||
import AdminPage from '@/shared/components/AdminPage.vue'
|
||||
import ListPageLayout from '@/shared/components/ListPageLayout.vue'
|
||||
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
||||
import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
||||
import { listTruckAppointments } from '../api/platformTrucking'
|
||||
import { TRUCK_APPOINTMENT_STATUSES, truckAppointmentStatusLabels, type TruckAppointmentQuery, type TruckAppointmentResource, type TruckAppointmentStatus } from '../types'
|
||||
|
||||
const router = useRouter(); const rows = ref<TruckAppointmentResource[]>([]); const loading = ref(false); const loaded = ref(false); const page = ref(1); const pageSize = ref(20); const total = ref(0); const loadError = ref<ApiErrorDetails | null>(null)
|
||||
const router = useRouter(); const rows = ref<TruckAppointmentResource[]>([]); const loading = ref(false); const page = ref(1); const pageSize = ref(20); const total = ref(0); const loadError = ref<ApiErrorDetails | null>(null)
|
||||
const access = useAccessPreviewStore()
|
||||
const filters = ref({ keyword: '', status: '' as TruckAppointmentStatus | '', containerBookingId: '', containerType: '' }); const applied = ref({ ...filters.value })
|
||||
const fields = computed<QueryField[]>(() => [
|
||||
@@ -42,19 +44,19 @@ function statusLabel(value: unknown) {
|
||||
? truckAppointmentStatusLabels[value as TruckAppointmentStatus]
|
||||
: String(value || '—')
|
||||
}
|
||||
async function load() { loading.value = true; loadError.value = null; try { const result = await listTruckAppointments({ page: page.value, size: pageSize.value, ...applied.value } as TruckAppointmentQuery); rows.value = result.records; total.value = result.total; loaded.value = true } catch (error) { rows.value = []; total.value = 0; loadError.value = getApiErrorDetails(error, '拖车预约加载失败,请稍后重试') } finally { loading.value = false } }
|
||||
async function load() { loading.value = true; loadError.value = null; try { const result = await listTruckAppointments({ page: page.value, size: pageSize.value, ...applied.value } as TruckAppointmentQuery); rows.value = result.records; total.value = result.total } catch (error) { rows.value = []; total.value = 0; loadError.value = getApiErrorDetails(error, '拖车预约加载失败,请稍后重试') } finally { loading.value = false } }
|
||||
function search(model: QueryModel) { applied.value = { keyword: String(model.keyword || ''), status: (model.status || '') as TruckAppointmentStatus | '', containerBookingId: '', containerType: String(model.containerType || '') }; page.value = 1; void load() }
|
||||
function reset() { filters.value = { keyword: '', status: '', containerBookingId: '', containerType: '' }; search(filters.value) }
|
||||
onMounted(load)
|
||||
function openDetail(row: TruckAppointmentResource, edit = false) { router.push({ name: 'trucking-detail', params: { id: String(row.id) }, query: edit ? { edit: '1' } : undefined }) }
|
||||
</script>
|
||||
<template>
|
||||
<section class="business-page trucking-page">
|
||||
<QueryToolbar v-model="filters" class="surface-panel" ariaLabel="拖车预约查询" :fields="fields" preference-key="trucking-query" @search="search" @reset="reset" />
|
||||
<section v-if="loadError" class="surface-panel trucking-error" role="alert"><div><strong>拖车预约列表暂时无法加载</strong><p>{{ loadError.message }}</p><ApiErrorMeta :details="loadError" /></div><el-button type="primary" :loading="loading" @click="load">重新加载</el-button></section>
|
||||
<section v-else class="surface-panel table-panel" :aria-busy="loading">
|
||||
<AdminPage as="div" class="trucking-page">
|
||||
<ListPageLayout aria-label="拖车预约列表">
|
||||
<template #toolbar><QueryToolbar v-model="filters" class="surface-panel" ariaLabel="拖车预约查询" :fields="fields" preference-key="trucking-query" @search="search" @reset="reset" /></template>
|
||||
<template v-if="loadError" #state><LoadErrorState title="拖车预约列表暂时无法加载" :message="loadError.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="loadError" /></template></LoadErrorState></template>
|
||||
<section v-if="!loadError" class="surface-panel table-panel" :aria-busy="loading">
|
||||
<DataTable v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :loading="loading" :total="total" preference-key="trucking-appointments" aria-label="拖车预约列表" empty-text="暂无符合筛选条件的拖车预约">
|
||||
<template #toolbar-start><div class="table-heading"><h2>拖车预约列表</h2><span>共 {{ total }} 条</span></div></template>
|
||||
<template #toolbar-actions><el-button v-if="access.can('platform:firstleg:truck-appointment:create')" type="primary" :disabled="loading" @click="router.push({ name: 'trucking-new' })"><Plus :size="16" />新增拖车</el-button></template>
|
||||
<template #company="{ row }">{{ row.carrierName || row.carrierId || '—' }}</template>
|
||||
<template #driver="{ row }">{{ row.driverName || '—' }}<small>{{ row.driverPhone || '—' }}</small></template>
|
||||
@@ -62,12 +64,12 @@ function openDetail(row: TruckAppointmentResource, edit = false) { router.push({
|
||||
<template #status="{ row }"><StatusBadge :status="statusLabel(row.status)" /></template>
|
||||
<template #actions="{ row }"><div class="table-actions"><el-button link type="primary" :aria-label="`查看 ${row.appointmentNo || row.id}`" @click="openDetail(row as TruckAppointmentResource)"><Eye :size="15" />详情</el-button><el-button v-if="access.can('platform:firstleg:truck-appointment:edit')" link type="primary" :aria-label="`编辑 ${row.appointmentNo || row.id}`" @click="openDetail(row as TruckAppointmentResource, true)"><Pencil :size="15" />编辑</el-button></div></template>
|
||||
</DataTable>
|
||||
</section>
|
||||
<div v-if="!loading && loaded && rows.length === 0 && !loadError" class="empty-hint"><RefreshCw :size="16" />暂无拖车预约</div>
|
||||
</section>
|
||||
</section>
|
||||
</ListPageLayout>
|
||||
</AdminPage>
|
||||
</template>
|
||||
<style scoped>
|
||||
.trucking-page { min-width: 0; }
|
||||
.table-panel { overflow:hidden; }.trucking-error { display:flex; min-width:0; align-items:center; justify-content:space-between; gap:16px; padding:18px 20px; border-color:#fecdca; background:#fffafa; }.trucking-error strong { display:block; }.trucking-error p { margin:4px 0 0; color:var(--cc-muted); font-size:12px; }.table-heading { display:flex; align-items:baseline; gap:10px; }.table-heading h2 { margin:0; font-size:16px; }.table-heading span { color:var(--el-text-color-secondary); font-size:13px; }.empty-hint { display:flex; justify-content:center; gap:8px; color:var(--el-text-color-secondary); padding:24px; }
|
||||
.table-panel { overflow:hidden; }
|
||||
small { display:block; color:var(--el-text-color-secondary); margin-top:3px; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user