feat(transport): unify client truck and looseboard demand forms
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { Package } from '@lucide/vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
||||
import { ElMessage, type FormInstance } from 'element-plus'
|
||||
import TransportDemandForm from './TransportDemandForm.vue'
|
||||
import { createTransportDemandForm, transportDemandError, buildTransportDemand, type TransportDemandForm as DemandFormModel } from '../transportDemandForm'
|
||||
import DataTable, { type DataTableColumn } from '@/components/common/DataTable.vue'
|
||||
import QueryToolbar, { type QueryField, type QueryModel } from '@/components/common/QueryToolbar.vue'
|
||||
import type { TableAction } from '@/components/common/tableActions'
|
||||
@@ -33,27 +34,7 @@ type PageMode = 'list' | 'create' | 'detail'
|
||||
|
||||
interface ColumnDefinition { key: string; label: string; width?: number }
|
||||
|
||||
interface BusinessForm {
|
||||
productName: string
|
||||
estimatedPalletCount: number
|
||||
origin: string
|
||||
originAddress: string
|
||||
destination: string
|
||||
destinationAddress: string
|
||||
packageCount: number
|
||||
totalWeightKg: number
|
||||
totalVolumeCbm: number
|
||||
budgetAmount?: number
|
||||
currency: string
|
||||
vehicleType: '' | 'PALLET_15' | 'PALLET_30'
|
||||
originContactName: string
|
||||
originContactPhone: string
|
||||
destinationContactName: string
|
||||
destinationContactPhone: string
|
||||
pickupAt: string
|
||||
deliveryAt: string
|
||||
remark: string
|
||||
}
|
||||
type BusinessForm = DemandFormModel
|
||||
|
||||
const configuration = computed(() => ({
|
||||
trucking: {
|
||||
@@ -133,19 +114,6 @@ const queryFields = computed<QueryField[]>(() => [
|
||||
])
|
||||
|
||||
const form = reactive<BusinessForm>(emptyForm())
|
||||
const rules = computed<FormRules<BusinessForm>>(() => ({
|
||||
origin: [{ required: true, message: '请输入起运地', trigger: 'blur' }],
|
||||
destination: [{ required: true, message: '请输入目的地', trigger: 'blur' }],
|
||||
...(props.kind === 'trucking' ? { vehicleType: [{ required: true, message: '请选择车辆类型', trigger: 'change' }] } : {}),
|
||||
originContactName: [{ required: true, message: '请输入起运地联系人', trigger: 'blur' }],
|
||||
originContactPhone: [{ required: true, message: '请输入起运地联系电话', trigger: 'blur' }],
|
||||
destinationContactName: [{ required: true, message: '请输入目的地联系人', trigger: 'blur' }],
|
||||
destinationContactPhone: [{ required: true, message: '请输入目的地联系电话', trigger: 'blur' }],
|
||||
pickupAt: [{ required: true, message: '请选择取货时间', trigger: 'change' }],
|
||||
deliveryAt: [{ required: true, message: '请选择送货时间', trigger: 'change' }, {
|
||||
validator: (_rule: unknown, value: string, callback: (error?: Error) => void) => callback(value && form.pickupAt && value < form.pickupAt ? new Error('送货时间不能早于取货时间') : undefined), trigger: 'change',
|
||||
}],
|
||||
}))
|
||||
|
||||
const detailFields = computed(() => {
|
||||
if (!detail.value) return []
|
||||
@@ -177,14 +145,7 @@ const tableColumns = computed<DataTableColumn[]>(() => [
|
||||
|
||||
const detailStatus = computed(() => detail.value ? statusLabel(detail.value.summary.status) : '—')
|
||||
|
||||
function emptyForm(): BusinessForm {
|
||||
return {
|
||||
productName: '', estimatedPalletCount: 0, origin: '', originAddress: '',
|
||||
destination: '', destinationAddress: '', packageCount: 0,
|
||||
totalWeightKg: 0, totalVolumeCbm: 0, currency: 'USD',
|
||||
remark: '', vehicleType: '', originContactName: '', originContactPhone: '', destinationContactName: '', destinationContactPhone: '', pickupAt: '', deliveryAt: '',
|
||||
}
|
||||
}
|
||||
function emptyForm(): BusinessForm { return createTransportDemandForm() }
|
||||
|
||||
function resetForm() { Object.assign(form, emptyForm()); submitKey.value = ''; formRef.value?.clearValidate() }
|
||||
function read(source: object, key: string) { return Reflect.get(source, key) as unknown }
|
||||
@@ -287,35 +248,15 @@ async function loadDetail() {
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
if (props.kind === 'looseboard' && form.pickupAt && form.deliveryAt && form.deliveryAt < form.pickupAt) { ElMessage.error('送达时间不能早于取货时间'); return }
|
||||
const failure = transportDemandError(props.kind === 'trucking' ? 'truck' : 'looseboard', form)
|
||||
if (failure) { ElMessage.error(failure); return }
|
||||
if (!await formRef.value?.validate().catch(() => false)) return
|
||||
submitting.value = true
|
||||
const stableSubmitKey = submitKey.value || idempotencyKey()
|
||||
submitKey.value = stableSubmitKey
|
||||
try {
|
||||
const base = {
|
||||
origin: form.origin, originAddress: form.originAddress || undefined,
|
||||
destination: form.destination, destinationAddress: form.destinationAddress || undefined,
|
||||
packageCount: form.packageCount,
|
||||
totalWeightKg: form.totalWeightKg, totalVolumeCbm: form.totalVolumeCbm,
|
||||
budgetAmount: form.budgetAmount, currency: form.currency || undefined,
|
||||
remark: form.remark || undefined,
|
||||
idempotencyKey: stableSubmitKey,
|
||||
}
|
||||
if (props.kind === 'trucking') {
|
||||
if (!form.vehicleType) return
|
||||
await createTransport('trucking', { ...base, vehicleType: form.vehicleType,
|
||||
originContactName: form.originContactName, originContactPhone: form.originContactPhone,
|
||||
destinationContactName: form.destinationContactName, destinationContactPhone: form.destinationContactPhone,
|
||||
pickupAt: form.pickupAt, deliveryAt: form.deliveryAt,
|
||||
})
|
||||
} else {
|
||||
await createTransport('looseboard', { ...base, productName: form.productName || undefined, estimatedPalletCount: form.estimatedPalletCount,
|
||||
originContactName: form.originContactName, originContactPhone: form.originContactPhone,
|
||||
destinationContactName: form.destinationContactName, destinationContactPhone: form.destinationContactPhone,
|
||||
pickupAt: form.pickupAt, deliveryAt: form.deliveryAt,
|
||||
})
|
||||
}
|
||||
if (props.kind === 'trucking') await createTransport('trucking', { ...buildTransportDemand('truck', form), idempotencyKey: stableSubmitKey })
|
||||
else await createTransport('looseboard', { ...buildTransportDemand('looseboard', form), idempotencyKey: stableSubmitKey })
|
||||
ElMessage.success('订单提交成功')
|
||||
resetForm()
|
||||
if (props.createPage) await router.push({ name: listRouteName.value })
|
||||
@@ -383,64 +324,8 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<el-card v-else-if="kind === 'looseboard'" shadow="never" class="form-card looseboard-form-card">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-position="top">
|
||||
<div class="form-grid two-col lower-grid">
|
||||
<el-form-item label="起运地" prop="origin"><el-input v-model.trim="form.origin" maxlength="255" placeholder="城市 / 港口 / 州" /></el-form-item>
|
||||
<el-form-item label="目的地" prop="destination"><el-input v-model.trim="form.destination" maxlength="255" placeholder="城市 / 州" /></el-form-item>
|
||||
<el-form-item label="起运地联系人" prop="originContactName"><el-input v-model.trim="form.originContactName" maxlength="128" placeholder="请输入起运地联系人" /></el-form-item>
|
||||
<el-form-item label="目的地联系人" prop="destinationContactName"><el-input v-model.trim="form.destinationContactName" maxlength="128" placeholder="请输入目的地联系人" /></el-form-item>
|
||||
<el-form-item label="起运地联系电话" prop="originContactPhone"><el-input v-model.trim="form.originContactPhone" type="tel" maxlength="128" placeholder="请输入起运地联系电话" /></el-form-item>
|
||||
<el-form-item label="目的地联系电话" prop="destinationContactPhone"><el-input v-model.trim="form.destinationContactPhone" type="tel" maxlength="128" placeholder="请输入目的地联系电话" /></el-form-item>
|
||||
</div>
|
||||
<div class="form-section cargo-section"><h3><span class="section-icon"><Package :size="14" /></span>托载</h3><div class="form-grid cargo-grid">
|
||||
<el-form-item label="商品名称"><el-input v-model.trim="form.productName" placeholder="请输入商品名称" /></el-form-item>
|
||||
<el-form-item label="预计托数"><el-input-number v-model="form.estimatedPalletCount" :min="0" controls-position="right" placeholder="请输入预计托数" /></el-form-item>
|
||||
<el-form-item label="总重量 (kg)"><el-input-number v-model="form.totalWeightKg" :min="0" :precision="2" controls-position="right" placeholder="请输入总重量" /></el-form-item>
|
||||
<el-form-item label="总体积 (m³)"><el-input-number v-model="form.totalVolumeCbm" :min="0" :precision="3" controls-position="right" placeholder="请输入总体积" /></el-form-item>
|
||||
</div></div>
|
||||
<div class="form-grid two-col lower-grid">
|
||||
<el-form-item label="预算总价"><el-input-number v-model="form.budgetAmount" :min="0" :precision="2" controls-position="right" placeholder="0.00" /></el-form-item>
|
||||
<el-form-item label="预算币种"><el-select v-model="form.currency"><el-option label="USD" value="USD" /><el-option label="CNY" value="CNY" /></el-select></el-form-item>
|
||||
<el-form-item label="取货时间" prop="pickupAt"><el-date-picker v-model="form.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="送货时间" prop="deliveryAt"><el-date-picker v-model="form.deliveryAt" type="datetime" format="YYYY-MM-DD HH:mm" time-format="HH:mm" value-format="YYYY-MM-DDTHH:mm:ss" placeholder="请选择送货时间" /></el-form-item>
|
||||
</div>
|
||||
<el-collapse class="looseboard-extra"><el-collapse-item title="补充信息(选填)" name="extra"><div class="form-grid two-col">
|
||||
<el-form-item label="件数"><el-input-number v-model="form.packageCount" :min="0" :precision="0" controls-position="right" placeholder="请输入件数" /></el-form-item>
|
||||
<el-form-item label="备注"><el-input v-model="form.remark" type="textarea" maxlength="1000" :rows="2" placeholder="请输入备注(选填)" /></el-form-item>
|
||||
<el-form-item label="起运地址补充"><el-input v-model.trim="form.originAddress" maxlength="500" placeholder="请输入详细起运地址(选填)" /></el-form-item>
|
||||
<el-form-item label="目的地址补充"><el-input v-model.trim="form.destinationAddress" maxlength="500" placeholder="请输入详细目的地址(选填)" /></el-form-item>
|
||||
</div></el-collapse-item></el-collapse>
|
||||
<div class="form-actions"><el-button @click="returnToList">取消</el-button><el-button v-if="canCreate" type="primary" :loading="submitting" @click="submit">提交订单</el-button></div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card v-else shadow="never" class="form-card">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="140px">
|
||||
<el-form-item v-if="kind === 'trucking'" label="车辆类型" prop="vehicleType"><el-select v-model="form.vehicleType" placeholder="请选择车辆类型"><el-option label="15拖" value="PALLET_15" /><el-option label="30拖" value="PALLET_30" /></el-select></el-form-item>
|
||||
<el-form-item label="起运地" prop="origin"><el-input v-model.trim="form.origin" maxlength="255" placeholder="请输入起运地" /></el-form-item>
|
||||
<el-form-item label="起运地址"><el-input v-model.trim="form.originAddress" maxlength="500" placeholder="请输入详细起运地址" /></el-form-item>
|
||||
<template v-if="kind === 'trucking'">
|
||||
<el-form-item label="起运地联系人" prop="originContactName"><el-input v-model.trim="form.originContactName" maxlength="128" placeholder="请输入起运地联系人" /></el-form-item>
|
||||
<el-form-item label="起运地联系电话" prop="originContactPhone"><el-input v-model.trim="form.originContactPhone" type="tel" maxlength="128" placeholder="请输入起运地联系电话" /></el-form-item>
|
||||
</template>
|
||||
<el-form-item label="目的地" prop="destination"><el-input v-model.trim="form.destination" maxlength="255" placeholder="请输入目的地" /></el-form-item>
|
||||
<el-form-item label="目的地址"><el-input v-model.trim="form.destinationAddress" maxlength="500" placeholder="请输入详细目的地址" /></el-form-item>
|
||||
<template v-if="kind === 'trucking'">
|
||||
<el-form-item label="目的地联系人" prop="destinationContactName"><el-input v-model.trim="form.destinationContactName" maxlength="128" placeholder="请输入目的地联系人" /></el-form-item>
|
||||
<el-form-item label="目的地联系电话" prop="destinationContactPhone"><el-input v-model.trim="form.destinationContactPhone" type="tel" maxlength="128" placeholder="请输入目的地联系电话" /></el-form-item>
|
||||
</template>
|
||||
<el-form-item label="件数"><el-input-number v-model="form.packageCount" :min="0" placeholder="请输入件数" /></el-form-item>
|
||||
<el-form-item label="总重量(kg)"><el-input-number v-model="form.totalWeightKg" :min="0" :precision="2" placeholder="请输入总重量" /></el-form-item>
|
||||
<el-form-item label="总体积(m³)"><el-input-number v-model="form.totalVolumeCbm" :min="0" :precision="3" placeholder="请输入总体积" /></el-form-item>
|
||||
<template v-if="kind === 'trucking'">
|
||||
<el-form-item label="取货时间" prop="pickupAt"><el-date-picker v-model="form.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="送货时间" prop="deliveryAt"><el-date-picker v-model="form.deliveryAt" type="datetime" format="YYYY-MM-DD HH:mm" time-format="HH:mm" value-format="YYYY-MM-DDTHH:mm:ss" placeholder="请选择送货日期和时间" /></el-form-item>
|
||||
</template>
|
||||
<el-form-item class="budget-form-item" label="预算金额"><el-input-number v-model="form.budgetAmount" :min="0" :precision="2" placeholder="请输入预算金额" /><el-select v-model="form.currency" class="currency"><el-option label="USD" value="USD" /><el-option label="CNY" value="CNY" /></el-select></el-form-item>
|
||||
<el-form-item label="备注"><el-input v-model="form.remark" type="textarea" :rows="4" maxlength="1000" show-word-limit placeholder="请输入其他要求" /></el-form-item>
|
||||
<el-form-item><el-button @click="returnToList">取消</el-button><el-button v-if="canCreate" type="primary" :loading="submitting" @click="submit">提交订单</el-button></el-form-item>
|
||||
</el-form>
|
||||
<TransportDemandForm ref="formRef" :model="form" :kind="kind === 'trucking' ? 'truck' : 'looseboard'" :submitting="submitting" :can-submit="canCreate" @submit="submit" @cancel="returnToList" />
|
||||
</el-card>
|
||||
</section>
|
||||
</template>
|
||||
@@ -472,44 +357,7 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
|
||||
.arrangement-grid div { grid-template-columns: 124px minmax(0, 1fr); }
|
||||
.arrangement-grid dt { white-space: normal; overflow-wrap: anywhere; }
|
||||
.detail-grid dd { min-width: 0; margin: 0; overflow-wrap: anywhere; color: var(--navy); font-size: 12px; font-weight: 600; line-height: 1.4; }
|
||||
.form-card :deep(.el-form) { max-width: 860px; }
|
||||
.form-card :deep(.el-input), .form-card :deep(.el-textarea), .form-card :deep(.el-select), .form-card :deep(.el-date-editor) { width: 100%; }
|
||||
.form-card .currency { width: 110px; margin-left: 12px; }
|
||||
|
||||
.warehouse-load-error { color: #b42318; font-size: 12px; }
|
||||
.looseboard-form-card { padding: 0; border: 1px solid #e7ebf1; border-radius: 10px; background: #fff; box-shadow: 0 8px 22px rgb(31 45 61 / 4%); }
|
||||
.looseboard-form-card :deep(.el-card__body) { padding: 0; }
|
||||
.looseboard-form-card :deep(.el-form) { max-width: none; }
|
||||
.looseboard-form-card :deep(.el-form-item) { margin-bottom: 16px; }
|
||||
.looseboard-form-card :deep(.el-form-item__label) { height: auto; padding-bottom: 7px; color: #27364d; font-size: 13px; font-weight: 600; line-height: 1.2; }
|
||||
.looseboard-form-card :deep(.el-input__wrapper), .looseboard-form-card :deep(.el-textarea__inner), .looseboard-form-card :deep(.el-select__wrapper), .looseboard-form-card :deep(.el-input-number) { min-height: 36px; border-radius: 8px; box-shadow: 0 0 0 1px #e1e6ed inset; }
|
||||
.looseboard-form-card :deep(.el-input-number) { width: 100%; }
|
||||
.form-section { padding: 25px 30px 5px; }
|
||||
.form-section h3 { display: flex; align-items: center; gap: 7px; margin: 0 0 15px; color: #27364d; font-size: 14px; }
|
||||
.form-section h3 em { color: #e05252; font-style: normal; }
|
||||
.section-icon { display: inline-flex; width: 20px; height: 20px; align-items: center; justify-content: center; border-radius: 5px; background: #fff3e0; color: #dd8d2c; }
|
||||
.mode-buttons :deep(.el-radio-group) { display: flex; gap: 10px; }
|
||||
.mode-buttons :deep(.el-radio-button__inner) { display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 18px; border: 1px solid #dce3eb; border-radius: 8px !important; color: #4b5563; box-shadow: none; }
|
||||
.mode-buttons :deep(.el-radio-button:first-child .el-radio-button__inner) { border-left: 1px solid #dce3eb; }
|
||||
.mode-buttons :deep(.el-radio-button__original-radio:checked + .el-radio-button__inner) { border-color: #5965d8; background: #f0f2ff; color: #4f5bd5; box-shadow: none; }
|
||||
.form-grid { display: grid; gap: 0 22px; padding: 0 30px; }
|
||||
.two-col { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); max-width: 1180px; }
|
||||
.two-col > .el-form-item { min-width: 0; }
|
||||
.cargo-section { margin-top: 4px; padding-top: 7px; background: #fafafa; border-top: 1px solid #f0f2f5; border-bottom: 1px solid #f0f2f5; }
|
||||
.cargo-grid { grid-template-columns: minmax(0, 1.35fr) repeat(3, minmax(150px, .9fr)); max-width: 1180px; }
|
||||
.lower-grid { padding-top: 20px; }
|
||||
.lower-grid :deep(.el-date-editor) { width: 100%; }
|
||||
.form-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 5px; padding: 20px 30px 25px; border-top: 1px solid #f0f2f5; }
|
||||
.looseboard-extra { margin: 0 30px; }
|
||||
.looseboard-form-card .form-actions { padding-right: max(30px, calc(100% - 1150px)); }
|
||||
.form-actions .el-button { min-width: 80px; height: 36px; border-radius: 7px; }
|
||||
.form-actions .el-button--primary { background: linear-gradient(135deg, #6774df, #7553aa); border: 0; box-shadow: 0 5px 12px rgb(103 116 223 / 24%); }
|
||||
|
||||
@media (min-width: 1400px) {
|
||||
.looseboard-form-card :deep(.el-input), .looseboard-form-card :deep(.el-select), .looseboard-form-card :deep(.el-date-editor) { max-width: 560px; }
|
||||
.cargo-grid :deep(.el-input), .cargo-grid :deep(.el-input-number) { max-width: 300px; }
|
||||
.lower-grid :deep(.el-input-number), .lower-grid :deep(.el-date-editor) { max-width: 560px; }
|
||||
}
|
||||
.form-card :deep(.el-card__body) { padding: 0; }
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.business-orders { gap: 14px; }
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
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 rules = computed(() => transportDemandRules(props.kind, props.model))
|
||||
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" :model="model" :rules="rules" label-position="top" :disabled="disabled || submitting">
|
||||
<slot name="customer" />
|
||||
<section class="transport-demand-section">
|
||||
<h3>运输信息</h3>
|
||||
<div class="transport-demand-grid">
|
||||
<el-form-item v-if="kind === 'truck'" 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 label="起运地" prop="origin"><el-input v-model.trim="model.origin" maxlength="255" placeholder="城市 / 港口 / 州" /></el-form-item>
|
||||
<el-form-item label="目的地" prop="destination"><el-input v-model.trim="model.destination" maxlength="255" placeholder="城市 / 州" /></el-form-item>
|
||||
<el-form-item label="起运地联系人" prop="originContactName"><el-input v-model.trim="model.originContactName" maxlength="128" placeholder="请输入起运地联系人" /></el-form-item>
|
||||
<el-form-item label="目的地联系人" prop="destinationContactName"><el-input v-model.trim="model.destinationContactName" maxlength="128" placeholder="请输入目的地联系人" /></el-form-item>
|
||||
<el-form-item label="起运地联系电话" prop="originContactPhone"><el-input v-model.trim="model.originContactPhone" type="tel" maxlength="128" placeholder="请输入起运地联系电话" /></el-form-item>
|
||||
<el-form-item label="目的地联系电话" prop="destinationContactPhone"><el-input v-model.trim="model.destinationContactPhone" type="tel" maxlength="128" placeholder="请输入目的地联系电话" /></el-form-item>
|
||||
<el-form-item label="起运详细地址"><el-input v-model.trim="model.originAddress" maxlength="500" placeholder="街道 / 门牌等补充信息(选填)" /></el-form-item>
|
||||
<el-form-item label="目的详细地址"><el-input v-model.trim="model.destinationAddress" maxlength="500" placeholder="街道 / 门牌等补充信息(选填)" /></el-form-item>
|
||||
</div>
|
||||
</section>
|
||||
<section class="transport-demand-section">
|
||||
<h3>货物信息</h3>
|
||||
<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" placeholder="请输入商品名称(选填)" /></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" placeholder="请输入预计托数" /></el-form-item>
|
||||
<el-form-item v-if="kind === 'truck'" label="件数" prop="packageCount"><el-input-number v-model="model.packageCount" :min="0" :precision="0" controls-position="right" placeholder="请输入件数" /></el-form-item>
|
||||
<el-form-item label="总重量 (kg)" prop="totalWeightKg"><el-input-number v-model="model.totalWeightKg" :min="0" :precision="3" controls-position="right" placeholder="请输入总重量" /></el-form-item>
|
||||
<el-form-item label="总体积 (m³)" prop="totalVolumeCbm"><el-input-number v-model="model.totalVolumeCbm" :min="0" :precision="6" controls-position="right" placeholder="请输入总体积" /></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" placeholder="请输入件数" /></el-form-item>
|
||||
</div>
|
||||
</section>
|
||||
<section class="transport-demand-section">
|
||||
<h3>费用与时效</h3>
|
||||
<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" placeholder="请输入预算总价(选填)" />
|
||||
<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="取货时间" 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="送货时间" 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 placeholder="请输入其他要求(选填)" /></el-form-item>
|
||||
</div>
|
||||
</section>
|
||||
<footer class="transport-demand-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 { --el-component-size: 36px; width: 100%; max-width: 1180px; margin: 0; background: #fff; }
|
||||
.transport-demand-section { padding: 20px 24px 0; border-bottom: 1px solid #e7ebf1; }
|
||||
.transport-demand-section h3 { margin: 0 0 16px; color: #27364d; font-size: 14px; font-weight: 600; }
|
||||
.transport-demand-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 24px; }
|
||||
.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; margin-bottom: 18px; }
|
||||
.transport-demand-form :deep(.el-form-item__label) { height: auto; padding-bottom: 6px; font-size: 13px; line-height: 20px; }
|
||||
.transport-demand-form :deep(.el-input), .transport-demand-form :deep(.el-input-number), .transport-demand-form :deep(.el-select), .transport-demand-form :deep(.el-date-editor) { width: 100%; }
|
||||
.transport-demand-budget { display: grid; width: 100%; grid-template-columns: minmax(0, 1fr) 100px; gap: 10px; }
|
||||
.transport-demand-actions { display: flex; justify-content: flex-end; gap: 10px; padding: 18px 24px; }
|
||||
.transport-demand-actions :deep(.el-button + .el-button) { margin-left: 0; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user