优化
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { Boxes, Eye, Pencil, Plus, RefreshCcw, Sparkles } from '@lucide/vue'
|
||||
import { Boxes, Eye, Pencil, Plus, Sparkles } from '@lucide/vue'
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
||||
import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
||||
import { listAllPlatformWarehouses, type PlatformWarehouseSummaryResource } from '@/modules/warehouses'
|
||||
import AdminPage from '@/shared/components/AdminPage.vue'
|
||||
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
||||
import AppDrawer from '@/shared/components/AppDrawer.vue'
|
||||
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
|
||||
import ListPageLayout from '@/shared/components/ListPageLayout.vue'
|
||||
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
|
||||
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
|
||||
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
||||
@@ -174,23 +176,30 @@ onMounted(() => { void Promise.all([loadWarehouses(), loadRows()]) })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="container-page">
|
||||
<header class="page-header"><div><h1>货柜与智能排柜</h1><p>维护平台货柜资料,从柜次进入智能排柜并推送预装清单。</p></div><el-button v-if="canCreate" type="primary" @click="openCreate"><Plus :size="16" />新增货柜</el-button></header>
|
||||
<LoadErrorState v-if="warehouseError" title="装柜仓库加载失败" :message="warehouseError.message" compact @retry="loadWarehouses"><template #details><ApiErrorMeta :details="warehouseError" /></template></LoadErrorState>
|
||||
<QueryToolbar v-model="filters" class="surface-panel" ariaLabel="货柜筛选" :fields="queryFields" preference-key="container-loading-query" @search="search" @reset="search" />
|
||||
<LoadErrorState v-if="loadError" title="货柜列表加载失败" :message="loadError.message" :loading="loading" @retry="loadRows"><template #details><ApiErrorMeta :details="loadError" /></template></LoadErrorState>
|
||||
<DataTable v-else v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :total="total" :loading="loading" preference-key="container-loading-table" empty-text="暂无货柜">
|
||||
<template #toolbar-start><div><h2>货柜列表</h2><p>共 {{ total }} 个柜次</p></div></template>
|
||||
<template #toolbar-end><el-button :loading="loading" aria-label="刷新货柜列表" title="刷新" @click="loadRows"><RefreshCcw :size="16" /></el-button></template>
|
||||
<template #actions="{ row }"><div class="row-actions"><el-button link type="primary" :aria-label="`查看 ${row.cabinetNo}`" @click="openDetail(row)"><Eye :size="15" />查看</el-button><el-button v-if="canEdit && row.planStatus !== 'COMPLETED'" link type="primary" @click="openEdit(row)"><Pencil :size="15" />编辑</el-button><el-button v-if="canSmartLoading && row.planStatus === 'EDITING'" link type="primary" @click="goWorkbench(row)"><Sparkles :size="15" />排柜</el-button></div></template>
|
||||
<template #cabinet="{ row }"><strong>{{ row.cabinetNo }}</strong><small>{{ row.bookingNo }}</small></template>
|
||||
<template #containerNo="{ row }">{{ row.containerNo || '待录入' }}</template>
|
||||
<template #status="{ row }"><el-tag :type="row.planStatus === 'COMPLETED' ? 'success' : row.planStatus === 'LOADING' ? 'warning' : 'info'">{{ statusText(row.planStatus) }}</el-tag></template>
|
||||
<template #route="{ row }">{{ row.departurePortName || row.departurePortCode || '—' }} → {{ row.destinationPortName || row.destinationPortCode || '—' }}</template>
|
||||
<template #capacity="{ row }">{{ row.capacityCbm ? `${row.capacityCbm} m³` : '—' }} / {{ row.maxWeightKg ? `${row.maxWeightKg} kg` : '—' }}</template>
|
||||
<template #vessel="{ row }">{{ [row.vesselName, row.voyageNo].filter(Boolean).join(' / ') || '—' }}</template>
|
||||
<template #estimatedSailingAt="{ row }">{{ formatTime(row.estimatedSailingAt) }}</template>
|
||||
</DataTable>
|
||||
<AdminPage as="div">
|
||||
<section class="container-page">
|
||||
<ListPageLayout ariaLabel="货柜列表">
|
||||
<template #toolbar>
|
||||
<QueryToolbar v-model="filters" class="surface-panel" ariaLabel="货柜筛选" :fields="queryFields" preference-key="container-loading-query" @search="search" @reset="search" />
|
||||
</template>
|
||||
<template v-if="warehouseError || loadError" #state>
|
||||
<LoadErrorState v-if="warehouseError" title="装柜仓库加载失败" :message="warehouseError.message" compact @retry="loadWarehouses"><template #details><ApiErrorMeta :details="warehouseError" /></template></LoadErrorState>
|
||||
<LoadErrorState v-else-if="loadError" title="货柜列表加载失败" :message="loadError.message" :loading="loading" @retry="loadRows"><template #details><ApiErrorMeta :details="loadError" /></template></LoadErrorState>
|
||||
</template>
|
||||
<section v-if="!warehouseError && !loadError" class="surface-panel table-panel">
|
||||
<DataTable v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :total="total" :loading="loading" preference-key="container-loading-table" empty-text="暂无货柜">
|
||||
<template #toolbar-actions><el-button v-if="canCreate" type="primary" @click="openCreate"><Plus :size="16" />新增货柜</el-button></template>
|
||||
<template #actions="{ row }"><div class="row-actions"><el-button link type="primary" :aria-label="`查看 ${row.cabinetNo}`" @click="openDetail(row)"><Eye :size="15" />查看</el-button><el-button v-if="canEdit && row.planStatus !== 'COMPLETED'" link type="primary" @click="openEdit(row)"><Pencil :size="15" />编辑</el-button><el-button v-if="canSmartLoading && row.planStatus === 'EDITING'" link type="primary" @click="goWorkbench(row)"><Sparkles :size="15" />排柜</el-button></div></template>
|
||||
<template #cabinet="{ row }"><strong>{{ row.cabinetNo }}</strong><small>{{ row.bookingNo }}</small></template>
|
||||
<template #containerNo="{ row }">{{ row.containerNo || '待录入' }}</template>
|
||||
<template #status="{ row }"><el-tag :type="row.planStatus === 'COMPLETED' ? 'success' : row.planStatus === 'LOADING' ? 'warning' : 'info'">{{ statusText(row.planStatus) }}</el-tag></template>
|
||||
<template #route="{ row }">{{ row.departurePortName || row.departurePortCode || '—' }} → {{ row.destinationPortName || row.destinationPortCode || '—' }}</template>
|
||||
<template #capacity="{ row }">{{ row.capacityCbm ? `${row.capacityCbm} m³` : '—' }} / {{ row.maxWeightKg ? `${row.maxWeightKg} kg` : '—' }}</template>
|
||||
<template #vessel="{ row }">{{ [row.vesselName, row.voyageNo].filter(Boolean).join(' / ') || '—' }}</template>
|
||||
<template #estimatedSailingAt="{ row }">{{ formatTime(row.estimatedSailingAt) }}</template>
|
||||
</DataTable>
|
||||
</section>
|
||||
</ListPageLayout>
|
||||
|
||||
<AppDrawer v-model="detailOpen" title="货柜详情" size="min(760px, 94vw)" :loading="detailLoading" :show-confirm="false" cancel-text="关闭">
|
||||
<LoadErrorState v-if="detailError" title="货柜详情加载失败" :message="detailError.message" @retry="detailTarget && openDetail(detailTarget)"><template #details><ApiErrorMeta :details="detailError" /></template></LoadErrorState>
|
||||
@@ -223,9 +232,10 @@ onMounted(() => { void Promise.all([loadWarehouses(), loadRows()]) })
|
||||
<el-form-item label="预计到港时间"><el-date-picker v-model="form.estimatedPortArrivalAt" type="datetime" value-format="YYYY-MM-DDTHH:mm:ss" :disabled="transportOnly" /></el-form-item>
|
||||
</el-form>
|
||||
</AppDrawer>
|
||||
</section>
|
||||
</section>
|
||||
</AdminPage>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.container-page { display: grid; gap: 16px; min-width: 0; }.page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }.page-header h1,.page-header p,.container-page h2 { margin: 0; }.page-header p,.container-page small,.container-page h2 + p { display: block; margin-top: 4px; color: var(--cc-muted); }.row-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; }.row-actions :deep(.el-button + .el-button) { margin-left: 0; }.form-grid { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 0 16px; margin-top: 16px; }.form-grid :deep(.el-select),.form-grid :deep(.el-date-editor),.form-grid :deep(.el-input-number) { width: 100%; }.details :deep(.el-descriptions__label) { width: 120px; }@media(max-width:720px){.page-header { flex-direction: column; }.page-header .el-button { width: 100%; min-height: 44px; }.form-grid { grid-template-columns: 1fr; }.details :deep(.el-descriptions__body table),.details :deep(tbody),.details :deep(tr),.details :deep(td){display:block;width:100%!important}.row-actions { min-width: 180px; }}
|
||||
.container-page { display: grid; gap: 16px; min-width: 0; }.container-page small { display: block; margin-top: 4px; color: var(--cc-muted); }.row-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; }.row-actions :deep(.el-button + .el-button) { margin-left: 0; }.form-grid { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 0 16px; margin-top: 16px; }.form-grid :deep(.el-select),.form-grid :deep(.el-date-editor),.form-grid :deep(.el-input-number) { width: 100%; }.details :deep(.el-descriptions__label) { width: 120px; }@media(max-width:720px){.form-grid { grid-template-columns: 1fr; }.details :deep(.el-descriptions__body table),.details :deep(tbody),.details :deep(tr),.details :deep(td){display:block;width:100%!important}.row-actions { min-width: 180px; }}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user