@@ -1,7 +1,7 @@
< script setup lang = "ts" >
import '@/styles/adminDensity.css'
import { computed , reactive , ref } from 'vue'
import { Plus } from '@lucide/vue'
import { Container , Plus } from '@lucide/vue'
import { ElMessage , type FormInstance , type FormRules } from 'element-plus'
import { listAllPlatformWarehouses , type PlatformWarehouseSummaryResource } from '@/modules/warehouses'
import { listWarehouseLogisticsChannels , type OceanLogisticsChannel } from '@/modules/ocean-bookings'
@@ -9,7 +9,7 @@ import AppDialog from '@/shared/components/AppDialog.vue'
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import { getApiErrorDetails , type ApiErrorDetails } from '@/shared/api/http'
import { CONTAINER _SPECIFICATIONS , DEFAULT _CONTAINER _TYPE , applyContainerSpecification , containerSpecification } from '@/shared/domain/containerSpecifications'
import { CONTAINER _SPECIFICATIONS , DEFAULT _CONTAINER _TYPE , applyContainerSpecification } from '@/shared/domain/containerSpecifications'
import { createContainerSimulation } from '../api/platformContainerLoading'
import type { ContainerSimulationCreateRequest } from '../types'
import { SMART _LOADING _CHANNEL _GROUPS } from '../smartLoadingChannelGroups'
@@ -95,14 +95,54 @@ async function saveSimulation() {
< template >
< el-button type = "primary" @click ="openSimulation" > < Plus :size = "16" / > 新增模拟柜 < / el-button >
< AppDialog : class = "{ 'admin-density-dialog': dense }" v-model = "simulationOpen" title="新增模拟柜" width="min(560px, calc(100vw - 28px))" confirm-text="创建模拟柜" cancel-text="取消" :confirm-loading="simulationSaving" @confirm="saveSimulation" >
< section : class = "{ 'density-dialog-section': dense }" data -tone = " work " > < el-form ref = "simulationFormRef" :model = "simulationForm" :rules = "simulationRules" : label -position = " dense ? ' left ' : ' top ' " : label -width = " dense ? ' 120px ' : undefined " class = "simulation-form" : class = "{ 'density-form': dense }" > < template v-if = "dense"><table :class="{ 'density-table': dense, 'density-table--editable': dense }" aria-label="模拟柜资料"><tbody><tr><td><el-form-item label="装柜仓库" prop="warehouseId"><el-select :model-value="simulationForm.warehouseId" filterable placeholder="请选择国内装柜仓库" :loading="warehouseLoading" @update:model-value="selectSimulationWarehouse"><el-option v-for="warehouse in warehouses" :key="String(warehouse.id)" :label="warehouse.warehouseName" :value="String(warehouse.id)" /></el-select></el-form-item></td><td><el-form-item label="物流渠道" prop="channelGroupCode"><el-select v-model="simulationForm.channelGroupCode" filterable :disabled="!simulationForm.warehouseId || simulationChannelsLoading" :loading="simulationChannelsLoading" :placeholder="simulationForm.warehouseId ? '请选择物流渠道' : '请先选择装柜仓库'" no-data-text="当前仓库暂无有效渠道"><el-option v-for="group in simulationChannelGroups" :key="group.code" :label="group.name" :value="group.code" /></el-select></el-form-item></td></tr><tr><td><el-form-item label="柜型" prop="containerType"><el-select :model-value="simulationForm.containerType" @update:model-value="selectSimulationContainerType(String($event || ''))"><el-option v-for="item in CONTAINER_SPECIFICATIONS" :key="item.type" :label="item.type" :value="item.type" /></el-select></el-form-item></td><td><el-form-item label="统一规格"><span>{{ `${containerSpecification(simulationForm.containerType)?.recommendedMinCbm || '—'}– ${containerSpecification(simulationForm.containerType)?.capacityCbm || '—'} m³ / 货重 ≤ ${containerSpecification(simulationForm.containerType)?.maxWeightKg || '—'} kg` }}</span><small :class="{ 'density-dialog-note': dense }">{{ containerSpecification(simulationForm.containerType)?.description }}</small></el-form-item></td></tr></tbody></table></template><template v-else><el-form-item label="装柜仓库" prop="warehouseId"><el-select :model-value="simulationForm.warehouseId" filterable placeholder="请选择国内装柜仓库" :loading="warehouseLoading" @update:model-value="selectSimulationWarehouse"><el-option v-for="warehouse in warehouses" :key="String(warehouse.id)" :label="warehouse.warehouseName" :value="String(warehouse.id)" /></el-select></el-form-item><el-form-item label="物流渠道" prop="channelGroupCode"><el-select v-model="simulationForm.channelGroupCode" filterable :disabled="!simulationForm.warehouseId || simulationChannelsLoading" :loading="simulationChannelsLoading" :placeholder="simulationForm.warehouseId ? '请选择物流渠道' : '请先选择装柜仓库'" no-data-text="当前仓库暂无有效渠道"><el-option v-for="group in simulationChannelGroups" :key="group.code" :label="group.name" :value="group.code" /></el-select></el-form-item><el-form-item label="柜型" prop="containerType"><el-select :model-value="simulationForm.containerType" @update:model-value="selectSimulationContainerType(String($event || ''))"><el-option v-for="item in CONTAINER_SPECIFICATIONS" :key="item.type" :label="item.type" :value="item.type" /></el-select></el-form-item><el-form-item label="统一规格"><el-input :model-value="`${containerSpecification(simulationForm.containerType)?.recommendedMinCbm || '—'}– ${containerSpecification(simulationForm.containerType)?.capacityCbm || '—'} m³ / 货重 ≤ ${containerSpecification(simulationForm.containerType)?.maxWeightKg || '—'} kg`" disabled / > < small > { { containerSpecification ( simulationForm . containerType ) ? . description } } < / small > < / el-form-item > < / template > < / el-form > < / section >
< LoadErrorState v-if = "simulationError" compact title="模拟柜创建失败" :message="simulationError.message" :show-retry="false"><template #details><ApiErrorMeta :details="simulationError" / > < / template > < / LoadErrorState >
< / AppDialog >
< AppDialog
v-model = "simulationOpen"
class = "simulation-create-dialog"
: class = "{ 'admin-density-dialog': dense, 'admin-density-dialog--comfortable': dense }"
title = "新增模拟柜"
width = "min(800px, calc(100vw - 32px))"
confirm -text = " 创建模拟柜 "
cancel -text = " 取消 "
:confirm-loading = "simulationSaving"
: confirm -disabled = " warehouseLoading | | simulationChannelsLoading "
@confirm ="saveSimulation"
>
< template # header >
< div class = "simulation-heading" > < span class = "simulation-heading__icon" > < Container :size = "20" aria -hidden = " true " / > < / span > < span > 新增模拟柜 < / span > < / div >
< / template >
< el-form ref = "simulationFormRef" :model = "simulationForm" :rules = "simulationRules" label -position = " top " class = "simulation-form" >
< div class = "simulation-fields" >
< el-form-item label = "装柜仓库" prop = "warehouseId" >
< el-select :model-value = "simulationForm.warehouseId" filterable placeholder = "请选择国内装柜仓库" :loading = "warehouseLoading" @ update :model-value = "selectSimulationWarehouse" >
< el-option v-for = "warehouse in warehouses" :key="String(warehouse.id)" :label="warehouse.warehouseName" :value="String(warehouse.id)" / >
< / el-select >
< / el-form-item >
< el-form-item label = "物流渠道" prop = "channelGroupCode" >
< el-select v-model = "simulationForm.channelGroupCode" filterable :disabled="!simulationForm.warehouseId || simulationChannelsLoading" :loading="simulationChannelsLoading" :placeholder="simulationForm.warehouseId ? '请选择物流渠道' : '请先选择装柜仓库'" no-data-text="当前仓库暂无有效渠道" >
< el -option v-for = "group in simulationChannelGroups" :key="group.code" :label="group.name" :value="group.code" / >
< / el-select >
< / el-form-item >
< el-form-item label = "柜型" prop = "containerType" class = "simulation-type" >
< el-select :model-value = "simulationForm.containerType" @ update : model -value = " selectSimulationContainerType ( String ( $ event | | ' ' ) ) " >
< el-option v-for = "item in CONTAINER_SPECIFICATIONS" :key="item.type" :label="item.type" :value="item.type" / >
< / el-select >
< / el-form-item >
< / div >
< / el-form >
< LoadErrorState v-if = "simulationError" compact title="模拟柜创建失败" :message="simulationError.message" :show-retry="false"><template #details><ApiErrorMeta :details="simulationError" / > < / template > < / LoadErrorState >
< / AppDialog >
< / template >
< style scoped >
. simulation - form : deep ( . el - select ) , . simulation - form : deep ( . el - input - number ) { width : 100 % ; }
. simulation - heading { display : flex ; align - items : center ; gap : 10 px ; font - size : 16 px ; }
. simulation - heading _ _icon { display : grid ; place - items : center ; width : 34 px ; height : 34 px ; border - radius : 9 px ; color : var ( -- el - color - primary ) ; background : var ( -- el - color - primary - light - 9 ) ; }
. simulation - fields { display : grid ; grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; column - gap : 24 px ; row - gap : 8 px ; }
. simulation - fields > * { min - width : 0 ; }
. simulation - form : deep ( . el - select ) { width : 100 % ; }
. simulation - type { grid - column : 1 / - 1 ; }
. simulation - type : deep ( . el - select ) { max - width : calc ( 50 % - 12 px ) ; }
@ media ( max - width : 600 px ) {
. simulation - fields { grid - template - columns : minmax ( 0 , 1 fr ) ; gap : 4 px ; }
. simulation - type : deep ( . el - select ) { max - width : none ; }
}
< / style >