This commit is contained in:
2026-08-14 12:50:42 +08:00
parent 87c6d2c4ca
commit 590a457dcd
36 changed files with 242 additions and 95 deletions
@@ -111,11 +111,11 @@ async function loadOptions() {
optionsError.value = ''
try {
const [customerResult, partnerResult, warehouseResult] = await Promise.all([
listPlatformTenants({ page: 1, size: 200 }),
listPlatformTenants({ page: 1, size: 200, status: 'ACTIVE' }),
listPlatformPartners({ page: 1, size: 200, status: 'ACTIVE' }),
listPlatformWarehouses({ page: 1, size: 200, status: 'ACTIVE' }),
])
customers.value = customerResult.records
customers.value = customerResult.records.filter((customer) => customer.status === 'ACTIVE')
partners.value = partnerResult.records
warehouses.value = warehouseResult.records
} catch (cause) {
@@ -126,7 +126,8 @@ async function loadOptions() {
}
function selectCustomer(customerId: string) {
form.data.customerId = customerId
form.data.customerName = customers.value.find((customer) => String(customer.id) === customerId)?.tenantName || ''
const customer = customers.value.find((item) => String(item.id) === customerId)
form.data.customerName = customer ? customer.legalName?.trim() || customer.tenantName : ''
}
function selectWarehouse(value: unknown) {
const warehouseId = String(value || '')
@@ -277,7 +278,7 @@ onMounted(() => { void load(); void loadOptions() })
<section class="booking-group" aria-label="基本信息">
<h3>基本信息</h3><div class="booking-group__body">
<el-form-item label="订舱号"><el-input :model-value="detail?.bookingNo || '保存后生成'" disabled /></el-form-item>
<el-form-item label="客户" prop="customerId"><el-select :model-value="form.data.customerId" filterable placeholder="请选择客户" :loading="optionsLoading" :disabled="!isNew" style="width:100%" @update:model-value="selectCustomer(String($event || ''))"><el-option v-for="customer in selectableCustomers" :key="String(customer.id)" :label="customer.tenantName" :value="String(customer.id)" /></el-select></el-form-item>
<el-form-item label="客户" prop="customerId"><el-select :model-value="form.data.customerId" filterable placeholder="请选择客户" :loading="optionsLoading" :disabled="!isNew" style="width:100%" @update:model-value="selectCustomer(String($event || ''))"><el-option v-if="form.data.customerId && !selectableCustomers.some((customer) => String(customer.id) === String(form.data.customerId))" :label="form.data.customerName || '当前客户'" :value="String(form.data.customerId)" /><el-option v-for="customer in selectableCustomers" :key="String(customer.id)" :label="customer.legalName?.trim() || customer.tenantName" :value="String(customer.id)" /></el-select></el-form-item>
<el-form-item label="状态"><el-input :model-value="detail ? statusLabel(detail.status) : '待创建'" disabled /></el-form-item>
<el-form-item label="渠道编码" prop="channelCode"><el-input v-model="form.data.channelCode" placeholder="请输入渠道编码" /></el-form-item>
<el-form-item label="渠道名称" prop="channelName"><el-input v-model="form.data.channelName" placeholder="请输入渠道名称" /></el-form-item>
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { onMounted, reactive, ref, watch } from 'vue'
import { computed, 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'
@@ -11,6 +11,7 @@ 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 { listPlatformTenants, type PlatformTenantResource } from '@/modules/iam'
import { listOceanBookings, type OceanBookingResource } from '../api/platformOceanBookings'
import type { OceanBookingQuery, OceanBookingStatus } from '../types'
import { oceanBookingStatusLabel, oceanBookingStatusOptions } from '../status'
@@ -23,11 +24,15 @@ const error = ref<ReturnType<typeof getApiErrorDetails> | null>(null)
const page = ref(1)
const pageSize = ref(20)
const total = ref(0)
const query = reactive<QueryModel>({ keyword: '', status: '' })
const fields: QueryField[] = [
{ key: 'keyword', type: 'input', label: '关键词', placeholder: '订舱号/订单号/客户', width: 220 },
const customers = ref<PlatformTenantResource[]>([])
const customersLoading = ref(false)
const query = reactive<QueryModel>({ customerId: '', keyword: '', status: '' })
const activeCustomers = computed(() => customers.value.filter((customer) => customer.status === 'ACTIVE'))
const fields = computed<QueryField[]>(() => [
{ key: 'customerId', type: 'select', label: '客户', placeholder: '全部客户', width: 220, options: activeCustomers.value.map((customer) => ({ label: customer.legalName?.trim() || customer.tenantName, value: String(customer.id) })), props: { filterable: true, loading: customersLoading.value } },
{ key: 'keyword', type: 'input', label: '关键词', placeholder: '订舱号/订单号', width: 220 },
{ key: 'status', type: 'select', label: '状态', options: oceanBookingStatusOptions },
]
])
const columns = [
{ key: 'actions', label: '操作', fixed: 'left', width: 170, slotName: 'actions', hideable: false, movable: false },
{ prop: 'bookingNo', label: '订舱号', minWidth: 150 },
@@ -43,10 +48,11 @@ const columns = [
{ prop: 'updatedAt', label: '更新时间', minWidth: 155, slotName: 'updatedAt' },
]
function formatDateTime(value?: string | null) { return value ? value.replace('T', ' ').slice(0, 16) : '—' }
async function load() { loading.value = true; error.value = null; try { const result = await listOceanBookings({ page: page.value, size: pageSize.value, keyword: String(query.keyword || '') || undefined, status: (query.status || undefined) as OceanBookingStatus | undefined } satisfies OceanBookingQuery); rows.value = result.records; total.value = result.total } catch (e) { error.value = getApiErrorDetails(e) } finally { loading.value = false } }
async function loadCustomers() { customersLoading.value = true; try { const result = await listPlatformTenants({ page: 1, size: 200, status: 'ACTIVE' }); customers.value = result.records.filter((customer) => customer.status === 'ACTIVE') } catch { customers.value = [] } finally { customersLoading.value = false } }
async function load() { loading.value = true; error.value = null; try { const result = await listOceanBookings({ page: page.value, size: pageSize.value, customerId: String(query.customerId || '') || undefined, keyword: String(query.keyword || '') || undefined, status: (query.status || undefined) as OceanBookingStatus | undefined } satisfies OceanBookingQuery); rows.value = result.records; total.value = result.total } catch (e) { error.value = getApiErrorDetails(e) } finally { loading.value = false } }
function open(id?: string) { void router.push(id ? `/ocean-bookings/${id}` : '/ocean-bookings/new') }
function search() { if (page.value === 1) void load(); else page.value = 1 }
watch([page, pageSize], () => void load()); onMounted(load)
watch([page, pageSize], () => void load()); onMounted(() => { void load(); void loadCustomers() })
</script>
<template>
<AdminPage as="div" class="ocean-bookings-page">