This commit is contained in:
2026-08-10 16:24:54 +08:00
parent e119b48662
commit 820432a381
52 changed files with 1015 additions and 705 deletions
@@ -1,10 +1,13 @@
<script setup lang="ts">
import { onMounted, reactive, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import { Eye, Pencil, Plus } from '@lucide/vue'
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
import DataTable from '@/shared/components/DataTable.vue'
import StatusBadge from '@/shared/components/StatusBadge.vue'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import AdminPage from '@/shared/components/AdminPage.vue'
import ListPageLayout from '@/shared/components/ListPageLayout.vue'
import { getApiErrorDetails } from '@/shared/api/http'
import { useAccessPreviewStore } from '@/core/access/accessPreview'
import { listOceanBookings, type OceanBookingResource } from '../api/platformOceanBookings'
@@ -41,18 +44,19 @@ function search() { page.value = 1; void load() }
watch([page, pageSize], () => void load()); onMounted(load)
</script>
<template>
<div class="business-page ocean-bookings-page">
<QueryToolbar v-model="query" ariaLabel="订舱筛选" :fields="fields" @search="search" />
<LoadErrorState v-if="error" title="订舱列表加载失败" :message="error.message" @retry="load" />
<section v-else class="surface-panel table-panel">
<AdminPage as="div" class="ocean-bookings-page">
<ListPageLayout aria-label="订舱列表">
<template #toolbar><QueryToolbar v-model="query" class="surface-panel" ariaLabel="订舱筛选" :fields="fields" @search="search" /></template>
<template v-if="error" #state><LoadErrorState title="订舱列表加载失败" :message="error.message" :loading="loading" @retry="load" /></template>
<section v-if="!error" class="surface-panel table-panel">
<DataTable v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :loading="loading" :total="total" preference-key="ocean-bookings" aria-label="订舱列表" row-key="id" 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:ocean-booking:create')" type="primary" @click="open()">新增订舱</el-button></template>
<template #actions="{ row }"><el-button v-if="access.can('platform:firstleg:ocean-booking:view')" link type="primary" @click="open(row.id)">查看</el-button><el-button v-if="access.can('platform:firstleg:ocean-booking:edit')" link @click="open(row.id)">编辑</el-button></template>
<template #toolbar-actions><el-button v-if="access.can('platform:firstleg:ocean-booking:create')" type="primary" @click="open()"><Plus :size="16" />新增订舱</el-button></template>
<template #actions="{ row }"><el-button v-if="access.can('platform:firstleg:ocean-booking:view')" link type="primary" @click="open(row.id)"><Eye :size="15" />查看</el-button><el-button v-if="access.can('platform:firstleg:ocean-booking:edit')" link @click="open(row.id)"><Pencil :size="15" />编辑</el-button></template>
<template #vessel="{ row }">{{ row.vesselName || '—' }}<span v-if="row.voyageNo"> / {{ row.voyageNo }}</span></template>
<template #status="{ row }"><StatusBadge :status="row.status" /></template>
</DataTable>
</section>
</div>
</section>
</ListPageLayout>
</AdminPage>
</template>
<style scoped>.ocean-bookings-page{display:grid;gap:16px}.table-heading{display:flex;align-items:baseline;gap:10px}.table-heading h2{margin:0;font-size:16px}.table-heading span{color:var(--cc-muted);font-size:12px}</style>
<style scoped>.ocean-bookings-page{min-width:0}</style>