111 lines
10 KiB
Vue
111 lines
10 KiB
Vue
<script setup lang="ts">
|
|
import '@/styles/adminWorkbench.css'
|
|
import '@/styles/adminDensity.css'
|
|
import { computed, ref, onMounted, watch } from 'vue'
|
|
import { listPlatformWarehouses, type PlatformWarehouseResource } from '@/modules/warehouses'
|
|
import type { FormInstance } from 'element-plus'
|
|
import FormSection from '@/shared/components/FormSection.vue'
|
|
import { transportDemandRules, type TransportDemandForm, type TransportDemandKind } from '../transportDemandForm'
|
|
|
|
const props = withDefaults(defineProps<{
|
|
model: TransportDemandForm
|
|
kind: TransportDemandKind
|
|
disabled?: boolean
|
|
submitting?: boolean
|
|
canSubmit?: boolean
|
|
editing?: boolean
|
|
}>(), { disabled: false, submitting: false, canSubmit: true, editing: false })
|
|
const emit = defineEmits<{ submit: []; cancel: [] }>()
|
|
const formRef = ref<FormInstance>()
|
|
const warehouses = ref<PlatformWarehouseResource[]>([]), warehouseError = ref('')
|
|
async function loadWarehouses() {
|
|
if (props.kind !== 'looseboard') return
|
|
try { warehouses.value = (await listPlatformWarehouses({page: 1, size: 200, warehouseType: 'OVERSEAS', status: 'ACTIVE'})).records; warehouseError.value = '' }
|
|
catch (cause) { warehouseError.value = cause instanceof Error ? cause.message : '仓库读取失败' }
|
|
}
|
|
function chooseWarehouse() {
|
|
const warehouse = warehouses.value.find(row => String(row.id) === String(props.model.operatingWarehouseId))
|
|
props.model.deliveryContactName = warehouse?.contactName || ''; props.model.deliveryContactPhone = warehouse?.contactPhone || ''
|
|
}
|
|
onMounted(loadWarehouses)
|
|
watch([() => props.model.operatingWarehouseId, warehouses], chooseWarehouse, { immediate: true })
|
|
const rules = computed(() => transportDemandRules(props.kind, props.model))
|
|
const isTruck = computed(() => props.kind === 'truck')
|
|
defineExpose({
|
|
validate: () => formRef.value?.validate() ?? Promise.resolve(false),
|
|
clearValidate: (fields?: string | string[]) => formRef.value?.clearValidate(fields),
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<el-form ref="formRef" class="transport-demand-form admin-density admin-workbench density-form" :model="model" :rules="rules" label-position="top" :disabled="disabled || submitting">
|
|
<slot name="customer" />
|
|
<FormSection v-if="kind === 'looseboard'" class="density-form-section" title="入仓安排">
|
|
<div class="transport-demand-grid">
|
|
<el-form-item v-if="kind === 'looseboard' && model.destinationType === 'PRIVATE'" label="目的地邮编" prop="destinationPostalCode"><el-input v-model.trim="model.destinationPostalCode" maxlength="32" /></el-form-item>
|
|
<el-form-item class="transport-demand-wide" label="送货方式" prop="deliveryMode"><el-radio-group v-model="model.deliveryMode"><el-radio-button value="DELIVERY_TO_WAREHOUSE">送货到仓</el-radio-button><el-radio-button value="WAREHOUSE_PICKUP">仓库上门取货</el-radio-button></el-radio-group></el-form-item>
|
|
<el-form-item label="收货仓库" prop="operatingWarehouseId"><el-select v-model="model.operatingWarehouseId" filterable placeholder="请选择收货仓库"><el-option v-for="warehouse in warehouses" :key="String(warehouse.id)" :value="String(warehouse.id)" :label="warehouse.warehouseName" /></el-select><span v-if="warehouseError" role="alert">{{ warehouseError }} <el-button link @click="loadWarehouses">重试</el-button></span></el-form-item>
|
|
<template v-if="model.deliveryMode === 'DELIVERY_TO_WAREHOUSE'">
|
|
<el-form-item label="到仓联系人" prop="deliveryContactName"><el-input v-model="model.deliveryContactName" readonly placeholder="随收货仓库带出,未维护请联系仓库" /></el-form-item>
|
|
<el-form-item label="到仓联系电话" prop="deliveryContactPhone"><el-input v-model="model.deliveryContactPhone" readonly placeholder="随收货仓库带出,未维护请联系仓库" /></el-form-item>
|
|
<el-form-item label="预计到货时间" prop="estimatedArrivalAt"><el-date-picker v-model="model.estimatedArrivalAt" type="datetime" value-format="YYYY-MM-DDTHH:mm:ss" format="YYYY-MM-DD HH:mm" /></el-form-item>
|
|
<el-form-item label="物流跟踪号" prop="trackingNo"><el-input v-model.trim="model.trackingNo" maxlength="255" /></el-form-item>
|
|
</template>
|
|
</div>
|
|
</FormSection>
|
|
|
|
<FormSection class="density-form-section" title="运输信息">
|
|
<div class="transport-demand-grid">
|
|
<el-form-item v-if="isTruck" class="transport-demand-wide" label="车辆类型" prop="vehicleType">
|
|
<el-select v-model="model.vehicleType" placeholder="请选择车辆类型"><el-option label="15拖" value="PALLET_15" /><el-option label="30拖" value="PALLET_30" /></el-select>
|
|
</el-form-item>
|
|
<el-form-item v-if="isTruck || model.deliveryMode === 'WAREHOUSE_PICKUP'" :label="isTruck ? 'B点取货地' : '起运地'" prop="origin"><el-input v-model.trim="model.origin" maxlength="255" placeholder="城市 / 港口 / 州" /></el-form-item>
|
|
<el-form-item :label="isTruck ? 'C点送达地' : '目的地'" prop="destination"><el-input v-model.trim="model.destination" maxlength="255" placeholder="城市 / 州" /></el-form-item>
|
|
<el-form-item v-if="isTruck || model.deliveryMode === 'WAREHOUSE_PICKUP'" :label="isTruck ? 'B点联系人' : '起运地联系人'" prop="originContactName"><el-input v-model.trim="model.originContactName" maxlength="128" /></el-form-item>
|
|
<el-form-item :label="isTruck ? 'C点联系人' : '目的地联系人'" prop="destinationContactName"><el-input v-model.trim="model.destinationContactName" maxlength="128" /></el-form-item>
|
|
<el-form-item v-if="isTruck || model.deliveryMode === 'WAREHOUSE_PICKUP'" :label="isTruck ? 'B点联系电话' : '起运地联系电话'" prop="originContactPhone"><el-input v-model.trim="model.originContactPhone" type="tel" maxlength="128" /></el-form-item>
|
|
<el-form-item :label="isTruck ? 'C点联系电话' : '目的地联系电话'" prop="destinationContactPhone"><el-input v-model.trim="model.destinationContactPhone" type="tel" maxlength="128" /></el-form-item>
|
|
<el-form-item v-if="isTruck || model.deliveryMode === 'WAREHOUSE_PICKUP'" :label="isTruck ? 'B点取货地址' : '起运详细地址'" prop="originAddress"><el-input v-model.trim="model.originAddress" maxlength="500" /></el-form-item>
|
|
<el-form-item :label="isTruck ? 'C点送达地址' : '目的详细地址'" prop="destinationAddress"><el-input v-model.trim="model.destinationAddress" maxlength="500" /></el-form-item>
|
|
</div>
|
|
</FormSection>
|
|
<FormSection class="density-form-section" title="货物信息">
|
|
<div class="transport-demand-grid" :class="kind === 'looseboard' ? 'transport-demand-cargo-four' : 'transport-demand-cargo-three'">
|
|
<el-form-item v-if="kind === 'looseboard'" label="商品名称"><el-input v-model.trim="model.productName" maxlength="255" /></el-form-item>
|
|
<el-form-item v-if="kind === 'looseboard'" label="预计托数" prop="estimatedPalletCount"><el-input-number v-model="model.estimatedPalletCount" :min="0" :precision="0" controls-position="right" /></el-form-item>
|
|
<el-form-item v-if="isTruck" label="托数" prop="estimatedPalletCount"><el-input-number v-model="model.estimatedPalletCount" :min="1" :precision="0" controls-position="right" /></el-form-item>
|
|
<el-form-item label="总重量 (kg)" prop="totalWeightKg"><el-input-number v-model="model.totalWeightKg" :min="0" :precision="3" controls-position="right" /></el-form-item>
|
|
<el-form-item label="总体积 (m³)" prop="totalVolumeCbm"><el-input-number v-model="model.totalVolumeCbm" :min="0" :precision="6" controls-position="right" /></el-form-item>
|
|
<el-form-item v-if="kind === 'looseboard'" label="件数" prop="packageCount"><el-input-number v-model="model.packageCount" :min="0" :precision="0" controls-position="right" /></el-form-item>
|
|
</div>
|
|
</FormSection>
|
|
<FormSection class="density-form-section" title="费用与时效">
|
|
<div class="transport-demand-grid">
|
|
<el-form-item label="预算总价" prop="budgetAmount"><div class="transport-demand-budget">
|
|
<el-input-number v-model="model.budgetAmount" :min="0" :precision="2" controls-position="right" />
|
|
<el-select v-model="model.currency" aria-label="预算币种" placeholder="请选择预算币种"><el-option label="USD" value="USD" /><el-option label="CNY" value="CNY" /></el-select>
|
|
</div></el-form-item>
|
|
<div />
|
|
<el-form-item :label="isTruck ? 'B点取货时间' : '取货时间'" prop="pickupAt"><el-date-picker v-model="model.pickupAt" type="datetime" format="YYYY-MM-DD HH:mm" time-format="HH:mm" value-format="YYYY-MM-DDTHH:mm:ss" placeholder="请选择取货日期和时间" @change="formRef?.validateField('deliveryAt').catch(() => undefined)" /></el-form-item>
|
|
<el-form-item :label="isTruck ? 'C点送达时间' : '送货时间'" prop="deliveryAt"><el-date-picker v-model="model.deliveryAt" type="datetime" format="YYYY-MM-DD HH:mm" time-format="HH:mm" value-format="YYYY-MM-DDTHH:mm:ss" placeholder="请选择送货日期和时间" /></el-form-item>
|
|
<el-form-item class="transport-demand-wide" label="备注"><el-input v-model="model.remark" type="textarea" :rows="3" maxlength="1000" show-word-limit /></el-form-item>
|
|
</div>
|
|
</FormSection>
|
|
<footer class="transport-demand-actions density-actions">
|
|
<el-button :disabled="submitting" @click="emit('cancel')">取消</el-button>
|
|
<el-button v-if="canSubmit" type="primary" :loading="submitting" :disabled="disabled" @click="emit('submit')">{{ editing ? '保存修改' : '提交订单' }}</el-button>
|
|
</footer>
|
|
</el-form>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.transport-demand-form { width: 100%; min-width: 0; margin: 0; }
|
|
.transport-demand-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--admin-space-6); }
|
|
.transport-demand-cargo-three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
.transport-demand-cargo-four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
|
.transport-demand-wide { grid-column: 1 / -1; }
|
|
.transport-demand-form :deep(.el-form-item) { min-width: 0; }
|
|
.transport-demand-budget { display: grid; width: 100%; grid-template-columns: minmax(0, 1fr) 100px; gap: var(--admin-space-3); }
|
|
.transport-demand-actions { justify-content: flex-end; flex-wrap: wrap; padding: var(--admin-space-5) 0; }
|
|
</style>
|