@@ -36,6 +36,7 @@ import type {
} from '../types'
import { oceanBookingStatusLabel } from '../status'
import { bookingContainerError , createBlankBookingContainer , selectBookingContainerType } from '../containerRequirements'
import { isActiveBookingAgent } from '../bookingAgents'
const partyTypes = [
{ value : 'SHIPPER' , label : '发货人' } ,
@@ -88,9 +89,7 @@ const selectableCustomers = computed(() => customers.value.filter((customer) =>
customer . status === 'ACTIVE' || String ( customer . id ) === String ( form . data . customerId )
) ) )
const shippingCompanies = computed ( ( ) => partners . value . filter ( ( partner ) => partner . types . includes ( 'CARRIER' ) ) )
const selectableBookingAgents = computed ( ( ) => bookingSuppliers . value . filter ( ( supplier ) => (
supplier . status === 'ACTIVE' || String ( supplier . id ) === String ( form . data . bookingAgentId )
) ) )
const selectableBookingAgents = computed ( ( ) => bookingSuppliers . value . filter ( isActiveBookingAgent ) )
const channelUnavailable = computed ( ( ) => Boolean ( form . data . warehouseId ) && ! channelsLoading . value && ! channelsError . value && channels . value . length === 0 )
function blankParties ( ) : OceanBookingParty [ ] {
@@ -140,7 +139,7 @@ async function loadOptions() {
] )
customers . value = customerResult . records . filter ( ( customer ) => customer . status === 'ACTIVE' )
partners . value = partnerResult . records
bookingSuppliers . value = supplierResult . records
bookingSuppliers . value = supplierResult . records . filter ( isActiveBookingAgent )
warehouses . value = warehouseResult . records . filter ( ( warehouse ) => warehouse . status === 'ACTIVE' && warehouse . warehouseType === 'DOMESTIC' )
} catch ( cause ) {
optionsError . value = getApiErrorDetails ( cause , '客户、船公司或订舱代理选项加载失败' ) . message
@@ -197,13 +196,10 @@ function selectShippingCompany(partnerId: string) {
form . data . shippingCompanyName = partner ? . partnerName || null
}
function selectBookingAgent ( supplierId : string ) {
const supplier = bookingSuppliers . value . find ( ( item ) => String ( item . id ) === supplierId )
form . data . bookingAgentId = supplierId || null
const supplier = selectableBookingAgents . value . find ( ( item ) => String ( item . id ) === supplierId )
form . data . bookingAgentId = supplier ? String ( supplier . id ) : null
form . data . bookingAgentName = supplier ? . name || null
}
function bookingAgentLabel ( supplier : Supplier ) {
return ` ${ supplier . name } ( ${ supplier . scope === 'INTERNATIONAL' ? '国外' : '国内' } ) `
}
function applyDetail ( value : OceanBookingDetail ) {
detail . value = value
form . expectedVersion = value . version
@@ -379,7 +375,7 @@ onMounted(() => { void load(); void loadOptions() })
< el-form-item label = "物流渠道" prop = "channelCode" > < el-select :model-value = "form.data.channelCode" filterable : disabled = "!form.data.warehouseId || channelsLoading || !!channelsError || channelUnavailable" :loading = "channelsLoading" : placeholder = "form.data.warehouseId ? '请选择物流渠道' : '请先选择装柜仓库'" no -data -text = " 该仓库暂无有效物流渠道 " style = "width:100%" @ update : model -value = " selectChannel ( String ( $ event | | ' ' ) ) " > < el-option v-if = "form.data.channelCode && !channels.some((channel) => channel.channelCode === form.data.channelCode)" :label="selectedChannelName || form.data.channelCode" :value="form.data.channelCode" /><el-option v-for="channel in channels" :key="channel.channelCode" :label="channel.channelName" :value="channel.channelCode"><span>{{ channel.channelName }}</span><small class="channel-code">{{ channel.channelCode }}</small></el-option></el-select><div v-if="channelsError" class="field-error"><span>{{ channelsError }}</span><el-button link type="primary" :loading="channelsLoading" @click="loadChannels(form.data.warehouseId)">重新加载</el-button></div><div v-else-if="channelUnavailable" class="field-hint" > 该仓库暂无有效物流渠道 , 请更换仓库或联系管理员 。 < / div > < / el -form -item >
< el-form-item label = "提单号" prop = "billOfLadingNo" > < el-input v-model = "form.data.billOfLadingNo" maxlength="128" placeholder="请输入提单号" / > < / el-form-item >
< el-form-item label = "船公司" > < el-select :model-value = "form.data.shippingCompanyId" filterable clearable placeholder = "请选择船公司" :loading = "optionsLoading" style = "width:100%" @ update : model -value = " selectShippingCompany ( String ( $ event | | ' ' ) ) " > < el-option v-if = "form.data.shippingCompanyId && !shippingCompanies.some((partner) => String(partner.id) === String(form.data.shippingCompanyId))" :label="form.data.shippingCompanyName || '船公司名称缺失'" :value="String(form.data.shippingCompanyId)" /><el-option v-for="partner in shippingCompanies" :key="String(partner.id)" :label="partner.partnerName" :value="String(partner.id)" / > < / el-select > < / el-form-item >
< el-form-item label = "订舱代理" > < el-select :model-value = "form.data.bookingAgentId" filterable clearable placeholder = "请选择订舱代理" :loading = "optionsLoading" no -data -text = " 暂无启用的订舱供应商 " style = "width:100%" @ update : model -value = " selectBookingAgent ( String ( $ event | | ' ' ) ) " > < el-option v-if = "form.data.bookingAgentId && !selectableBookingAgents.some((supplier) => String(supplier.id) === String(form.data.bookingAgentId))" :label="form.data.bookingAgentName || '订舱代理名称缺失'" :value="String(form.data.bookingAgentId)" /><el-option v-for="supplier in selectableBookingAgents" :key="String(supplier.id)" :label="bookingAgentLabel( supplier) " :value="String(supplier.id)" / > < / el-select > < / el-form-item >
< el-form-item label = "订舱代理" > < el-select :model-value = "form.data.bookingAgentId" filterable clearable placeholder = "请选择订舱代理" :loading = "optionsLoading" no -data -text = " 暂无启用的订舱代理 " style = "width:100%" @ update : model -value = " selectBookingAgent ( String ( $ event | | ' ' ) ) " > < el-option v-if = "!editable && form.data.bookingAgentId && !selectableBookingAgents.some((supplier) => String(supplier.id) === String(form.data.bookingAgentId))" :label="form.data.bookingAgentName || '订舱代理名称缺失'" :value="String(form.data.bookingAgentId)" /><el-option v-for="supplier in selectableBookingAgents" :key="String(supplier.id)" :label="supplier.name " :value="String(supplier.id)" / > < / el-select > < / el-form-item >
< / div >
< / section >
< section class = "booking-group" aria -label = " 航线船期 " >
@@ -478,5 +474,5 @@ onMounted(() => { void load(); void loadOptions() })
< style scoped >
. channel - code { display : block ; margin - left : 8 px ; color : var ( -- cc - muted ) ; font - size : 11 px } . field - error , . field - hint { display : flex ; align - items : center ; justify - content : space - between ; gap : 8 px ; margin - top : 5 px ; color : var ( -- cc - muted ) ; font - size : 12 px ; line - height : 20 px } . field - error { color : var ( -- el - color - danger ) }
. booking - detail { min - width : 0 } . detail - heading { display : flex ; min - width : 0 ; align - items : flex - start ; gap : 16 px } . booking - page - toolbar { min - width : 0 ; flex : 1 } . section - title p , . history - panel p { margin : 5 px 0 0 ; color : var ( -- cc - muted ) ; font - size : 13 px } . heading - status { display : flex ; align - items : center ; gap : 8 px } . surface - panel { padding : 20 px } . surface - panel h2 { margin : 0 ; font - size : 16 px } . section - title { display : flex ; justify - content : space - between ; gap : 12 px ; align - items : flex - start ; margin - bottom : 18 px } . actions { display : flex ; flex - wrap : wrap ; gap : 8 px } . booking - groups { display : grid ; grid - template - columns : minmax ( 0 , 1.4 fr ) repeat ( 2 , minmax ( 0 , 1 fr ) ) ; gap : 16 px } . booking - group { min - width : 0 ; overflow : hidden ; border : 1 px solid # e8edf3 ; border - radius : 8 px ; background : # fff } . booking - group > h3 { margin : 0 ; padding : 14 px 16 px ; border - bottom : 1 px solid # eef2f6 ; color : # 1 f2937 ; font - size : 14 px } . booking - group _ _body { padding : 16 px } . booking - group _ _body -- fields , . booking - terms { display : grid ; grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; column - gap : 12 px } . booking - field -- wide { grid - column : 1 / - 1 } . booking - terms : deep ( . el - select ) { width : 100 % } . party - grid { display : grid ; grid - template - columns : repeat ( 3 , minmax ( 0 , 1 fr ) ) ; gap : 12 px ; margin - top : 16 px } . subsection { display : grid ; gap : 10 px ; padding : 14 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 6 px } . subsection h3 { margin : 0 ; font - size : 14 px } . required - mark { margin - right : 4 px ; color : var ( -- el - color - danger ) } . container - table - wrap { overflow - x : auto ; margin - bottom : 10 px } . container - table { width : 100 % ; min - width : 780 px ; table - layout : fixed ; border - collapse : collapse ; font - size : 12 px } . container - table th , . container - table td { padding : 7 px 6 px ; border - bottom : 1 px solid # eef2f6 ; text - align : left ; vertical - align : middle } . container - table th { background : # fafafa ; color : var ( -- cc - muted ) ; font - weight : 650 ; white - space : nowrap } . container - table th : first - child , . container - table td : first - child { width : 56 px } . container - table th : nth - child ( 2 ) , . container - table td : nth - child ( 2 ) { width : 180 px } . container - table th : nth - child ( 3 ) , . container - table td : nth - child ( 3 ) { width : 90 px } . container - table th : nth - child ( 4 ) , . container - table td : nth - child ( 4 ) { width : 110 px } . container - table th : nth - child ( 5 ) , . container - table td : nth - child ( 5 ) , . container - table th : nth - child ( 6 ) , . container - table td : nth - child ( 6 ) { width : 100 px } . container - table td : deep ( . el - select ) , . container - table td : deep ( . el - input ) { width : 100 % ; min - width : 0 } . container - table _ _action { text - align : center ! important } . container - table _ _action : deep ( . el - button ) { width : 28 px ; height : 28 px } . container - table _ _specification { color : var ( -- cc - muted ) ; white - space : nowrap } . container - actions { display : flex ; align - items : center ; gap : 10 px ; margin - bottom : 18 px ; color : var ( -- cc - muted ) ; font - size : 12 px } . add - container { margin : 0 } . history - panel strong { font - size : 14 px } @ media ( max - width : 1599 px ) { . booking - groups { grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) } . booking - group : last - child { grid - column : 1 / - 1 } } @ media ( max - width : 720 px ) { . booking - groups , . party - grid { grid - template - columns : 1 fr } . booking - group : last - child { grid - column : auto } . detail - heading { flex - direction : column } . booking - page - toolbar { width : 100 % } . section - title { flex - direction : column } . actions { width : 100 % } } @ media ( max - width : 520 px ) { . booking - group _ _body -- fields , . booking - terms { grid - template - columns : 1 fr } . booking - field -- wide { grid - column : auto } } @ media ( max - width : 420 px ) { . surface - panel { padding : 12 px } . booking - group _ _body { padding : 14 px } . actions : deep ( . el - button ) { min - height : 44 px } }
. booking - detail { min - width : 0 ; max - width : 1880 px } . detail - heading { display : flex ; min - width : 0 ; align - items : flex - start ; gap : 16 px } . booking - page - toolbar { min - width : 0 ; flex : 1 } . section - title p , . history - panel p { margin : 5 px 0 0 ; color : var ( -- cc - muted ) ; font - size : 13 px } . heading - status { display : flex ; align - items : center ; gap : 8 px } . surface - panel { padding : 16 px } . surface - panel h2 { margin : 0 ; font - size : 16 px } . section - title { display : flex ; justify - content : space - between ; gap : 12 px ; align - items : flex - start ; margin - bottom : 16 px } . actions { display : flex ; flex - wrap : wrap ; gap : 8 px } . booking - groups { display : grid ; grid - template - columns : minmax ( 0 , 1.5 fr ) repeat ( 2 , minmax ( 0 , 1 fr ) ) ; gap : 14 px } . booking - group { min - width : 0 ; overflow : hidden ; border : 1 px solid # e8edf3 ; border - radius : 10 px ; background : # fff } . booking - group > h3 { margin : 0 ; padding : 12 px 14 px ; border - bottom : 1 px solid # eef2f6 ; color : # 1 f2937 ; font - size : 14 px } . booking - group _ _body { padding : 12 px 14 px } . booking - group _ _body -- fields , . booking - terms { display : grid ; grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; column - gap : 10 px ; row - gap : 8 px } . booking - field -- wide { grid - column : 1 / - 1 } . booking - terms : deep ( . el - select ) { width : 100 % } . party - grid { display : grid ; grid - template - columns : repeat ( 3 , minmax ( 0 , 1 fr ) ) ; gap : 10 px ; margin - top : 14 px } . subsection { display : grid ; gap : 10 px ; padding : 12 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 6 px } . subsection h3 { margin : 0 ; font - size : 14 px } . required - mark { margin - right : 4 px ; color : var ( -- el - color - danger ) } . container - table - wrap { overflow - x : auto ; margin - bottom : 10 px } . container - table { width : 100 % ; min - width : 780 px ; table - layout : fixed ; border - collapse : collapse ; font - size : 12 px } . container - table th , . container - table td { padding : 7 px 6 px ; border - bottom : 1 px solid # eef2f6 ; text - align : left ; vertical - align : middle } . container - table th { background : # fafafa ; color : var ( -- cc - muted ) ; font - weight : 650 ; white - space : nowrap } . container - table th : first - child , . container - table td : first - child { width : 56 px } . container - table th : nth - child ( 2 ) , . container - table td : nth - child ( 2 ) { width : 180 px } . container - table th : nth - child ( 3 ) , . container - table td : nth - child ( 3 ) { width : 90 px } . container - table th : nth - child ( 4 ) , . container - table td : nth - child ( 4 ) { width : 110 px } . container - table th : nth - child ( 5 ) , . container - table td : nth - child ( 5 ) , . container - table th : nth - child ( 6 ) , . container - table td : nth - child ( 6 ) { width : 100 px } . container - table td : deep ( . el - select ) , . container - table td : deep ( . el - input ) { width : 100 % ; min - width : 0 } . container - table _ _action { text - align : center ! important } . container - table _ _action : deep ( . el - button ) { width : 28 px ; height : 28 px } . container - table _ _specification { color : var ( -- cc - muted ) ; white - space : nowrap } . container - actions { display : flex ; align - items : center ; gap : 10 px ; margin - bottom : 14 px ; color : var ( -- cc - muted ) ; font - size : 12 px } . add - container { margin : 0 } . history - panel strong { font - size : 14 px } @ media ( max - width : 1599 px ) { . booking - groups { grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) } . booking - group : last - child { grid - column : 1 / - 1 } } @ media ( max - width : 720 px ) { . booking - groups , . party - grid { grid - template - columns : 1 fr } . booking - group : last - child { grid - column : auto } . detail - heading { flex - direction : column } . booking - page - toolbar { width : 100 % } . section - title { flex - direction : column } . actions { width : 100 % } } @ media ( max - width : 520 px ) { . booking - group _ _body -- fields , . booking - terms { grid - template - columns : 1 fr } . booking - field -- wide { grid - column : auto } } @ media ( max - width : 420 px ) { . surface - panel { padding : 12 px } . booking - group _ _body { padding : 12 px } . actions : deep ( . el - button ) { min - height : 44 px } }
< / style >