统一客户端采购与运输新增页样式及必填提示
This commit is contained in:
@@ -281,8 +281,8 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section v-loading="loading" class="business-orders client-ui" :aria-busy="loading">
|
||||
<header v-if="mode === 'create'" class="page-head" :class="{ 'looseboard-page-head': props.kind === 'looseboard' }">
|
||||
<section v-loading="loading" class="business-orders client-ui" :class="{ 'business-orders--create': mode === 'create' }" :aria-busy="loading">
|
||||
<header v-if="mode === 'create'" class="page-head">
|
||||
<div>
|
||||
<h2>{{ configuration.title }}下单</h2>
|
||||
|
||||
@@ -344,7 +344,6 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
|
||||
<style scoped>
|
||||
.business-orders { display: grid; gap: var(--client-section-gap); }
|
||||
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 24px; }
|
||||
.looseboard-page-head { max-width: 1180px; padding-right: 30px; box-sizing: border-box; }
|
||||
.page-head h2 { margin: 0; color: #111827; font-size: 26px; }
|
||||
.page-head p { margin: 7px 0 0; color: #64748b; font-size: 14px; }
|
||||
.business-table-card { overflow: hidden; border: 1px solid var(--client-border); border-radius: var(--client-radius); background: #fff; }
|
||||
@@ -369,6 +368,11 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
|
||||
.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-card__body) { padding: 0; }
|
||||
.business-orders--create { --client-action: #2f7bff; --client-action-hover: #1d5fe0; --client-border: #d5dce8; --client-control-height: 44px; --client-font-size: 14px; width: 100%; min-width: 0; gap: 12px; background: #f4f7fc; }
|
||||
.business-orders--create .page-head { flex-wrap: wrap; gap: 16px; }
|
||||
.business-orders--create .page-head h2 { color: #1f2937; font-weight: 700; }
|
||||
.business-orders--create .page-head :deep(.el-button) { height: auto; min-height: 44px; padding: 10px 18px; border-radius: 6px; color: #1d5fe0; font-size: 14px; box-shadow: none; }
|
||||
.business-orders--create .form-card { min-width: 0; overflow: visible; border: 0; border-radius: 0; background: transparent; box-shadow: none; }
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.business-orders { gap: 14px; }
|
||||
|
||||
@@ -14,6 +14,8 @@ const props = withDefaults(defineProps<{
|
||||
const emit = defineEmits<{ submit: []; cancel: [] }>()
|
||||
const formRef = ref<FormInstance>()
|
||||
const rules = computed(() => transportDemandRules(props.kind, props.model))
|
||||
const isCreate = computed(() => !props.editing)
|
||||
const createPopperClass = computed(() => isCreate.value ? 'transport-create-popper' : undefined)
|
||||
defineExpose({
|
||||
validate: () => formRef.value?.validate() ?? Promise.resolve(false),
|
||||
clearValidate: (fields?: string | string[]) => formRef.value?.clearValidate(fields),
|
||||
@@ -21,50 +23,54 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-form ref="formRef" class="transport-demand-form" :model="model" :rules="rules" label-position="top" :disabled="disabled || submitting">
|
||||
<el-form ref="formRef" class="transport-demand-form" :class="{ 'transport-demand-form--create': isCreate }" :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>
|
||||
<div class="transport-demand-grid transport-demand-route-grid">
|
||||
<el-form-item v-if="kind === 'truck'" class="transport-demand-wide transport-demand-vehicle" label="车辆类型" prop="vehicleType">
|
||||
<el-select v-model="model.vehicleType" :popper-class="createPopperClass" :placeholder="isCreate ? '请选择车辆类型' : ''"><el-option label="15拖" value="PALLET_15" /><el-option label="30拖" value="PALLET_30" /></el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '取货地' : '起运地'" prop="origin"><el-input v-model.trim="model.origin" maxlength="255" placeholder="城市 / 港口 / 州" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '送达地' : '目的地'" prop="destination"><el-input v-model.trim="model.destination" maxlength="255" placeholder="城市 / 州" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '取货联系人' : '起运地联系人'" prop="originContactName"><el-input v-model.trim="model.originContactName" maxlength="128" placeholder="" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '送达联系人' : '目的地联系人'" prop="destinationContactName"><el-input v-model.trim="model.destinationContactName" maxlength="128" placeholder="" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '取货联系电话' : '起运地联系电话'" prop="originContactPhone"><el-input v-model.trim="model.originContactPhone" type="tel" maxlength="128" placeholder="" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '送达联系电话' : '目的地联系电话'" prop="destinationContactPhone"><el-input v-model.trim="model.destinationContactPhone" type="tel" maxlength="128" placeholder="" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '取货地址' : '起运详细地址'"><el-input v-model.trim="model.originAddress" maxlength="500" placeholder="街道 / 门牌等补充信息(选填)" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '送达地址' : '目的详细地址'"><el-input v-model.trim="model.destinationAddress" maxlength="500" placeholder="街道 / 门牌等补充信息(选填)" /></el-form-item>
|
||||
<el-form-item v-if="!isCreate" :label="kind === 'truck' ? '送达地' : '目的地'" prop="destination"><el-input v-model.trim="model.destination" maxlength="255" placeholder="城市 / 州" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '取货联系人' : '起运地联系人'" prop="originContactName"><el-input v-model.trim="model.originContactName" maxlength="128" :placeholder="isCreate ? (kind === 'truck' ? '请输入取货联系人姓名' : '请输入起运地联系人姓名') : ''" /></el-form-item>
|
||||
<el-form-item v-if="!isCreate" :label="kind === 'truck' ? '送达联系人' : '目的地联系人'" prop="destinationContactName"><el-input v-model.trim="model.destinationContactName" maxlength="128" placeholder="" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '取货联系电话' : '起运地联系电话'" prop="originContactPhone"><el-input v-model.trim="model.originContactPhone" type="tel" maxlength="128" :placeholder="isCreate ? (kind === 'truck' ? '请输入取货联系电话' : '请输入起运地联系电话') : ''" /></el-form-item>
|
||||
<template v-if="isCreate">
|
||||
<el-form-item :label="kind === 'truck' ? '送达地' : '目的地'" prop="destination"><el-input v-model.trim="model.destination" maxlength="255" placeholder="城市 / 州" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '送达联系人' : '目的地联系人'" prop="destinationContactName"><el-input v-model.trim="model.destinationContactName" maxlength="128" :placeholder="kind === 'truck' ? '请输入送达联系人姓名' : '请输入目的地联系人姓名'" /></el-form-item>
|
||||
</template>
|
||||
<el-form-item :label="kind === 'truck' ? '送达联系电话' : '目的地联系电话'" prop="destinationContactPhone"><el-input v-model.trim="model.destinationContactPhone" type="tel" maxlength="128" :placeholder="isCreate ? (kind === 'truck' ? '请输入送达联系电话' : '请输入目的地联系电话') : ''" /></el-form-item>
|
||||
<el-form-item class="transport-demand-address" :label="kind === 'truck' ? '取货地址' : '起运详细地址'"><el-input v-model.trim="model.originAddress" maxlength="500" placeholder="街道 / 门牌等补充信息(选填)" /></el-form-item>
|
||||
<el-form-item class="transport-demand-address" :label="kind === 'truck' ? '送达地址' : '目的详细地址'"><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="estimatedPalletCount"><el-input-number v-model="model.estimatedPalletCount" :min="1" :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 class="transport-demand-grid" :class="kind === 'looseboard' && !isCreate ? '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="isCreate ? '请输入商品名称(选填)' : ''" /></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="isCreate ? '请输入预计托数' : ''" /></el-form-item>
|
||||
<el-form-item v-if="kind === 'truck'" label="托数" prop="estimatedPalletCount"><el-input-number v-model="model.estimatedPalletCount" :min="1" :precision="0" controls-position="right" :placeholder="isCreate ? '请输入托数' : ''" /></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="isCreate ? '请输入总重量' : ''" /></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="isCreate ? '请输入总体积' : ''" /></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="isCreate ? '请输入件数' : ''" /></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>
|
||||
<el-input-number v-model="model.budgetAmount" :min="0" :precision="2" controls-position="right" :placeholder="isCreate ? (kind === 'truck' ? '请输入预算总价' : '请输入预算总价(选填)') : ''" />
|
||||
<el-select v-model="model.currency" :popper-class="createPopperClass" 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="kind === 'truck' ? '取货时间' : '取货时间'" 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="kind === 'truck' ? '送达时间' : '送货时间'" 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>
|
||||
<el-form-item :label="kind === 'truck' ? '取货时间' : '取货时间'" prop="pickupAt"><el-date-picker v-model="model.pickupAt" :popper-class="createPopperClass" type="datetime" format="YYYY-MM-DD HH:mm" time-format="HH:mm" value-format="YYYY-MM-DDTHH:mm:ss" :placeholder="isCreate ? '请选择取货日期和时间' : ''" @change="formRef?.validateField('deliveryAt').catch(() => undefined)" /></el-form-item>
|
||||
<el-form-item :label="kind === 'truck' ? '送达时间' : '送货时间'" prop="deliveryAt"><el-date-picker v-model="model.deliveryAt" :popper-class="createPopperClass" type="datetime" format="YYYY-MM-DD HH:mm" time-format="HH:mm" value-format="YYYY-MM-DDTHH:mm:ss" :placeholder="isCreate ? (kind === 'truck' ? '请选择送达日期和时间' : '请选择送货日期和时间') : ''" /></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="!isCreate" :placeholder="isCreate ? '请输入运输要求或其他补充信息(选填)' : ''" /><span v-if="isCreate" class="transport-demand-character-count">{{ model.remark.length }} / 1000</span></el-form-item>
|
||||
</div>
|
||||
</section>
|
||||
<footer class="transport-demand-actions">
|
||||
<el-button :disabled="submitting" @click="emit('cancel')">取消</el-button>
|
||||
<el-button :disabled="submitting" @click="emit('cancel')">{{ isCreate ? '返回列表' : '取消' }}</el-button>
|
||||
<el-button v-if="canSubmit" type="primary" :loading="submitting" :disabled="disabled" @click="emit('submit')">{{ editing ? '保存修改' : '提交订单' }}</el-button>
|
||||
</footer>
|
||||
</el-form>
|
||||
@@ -84,4 +90,49 @@ defineExpose({
|
||||
.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; }
|
||||
|
||||
.transport-demand-form--create {
|
||||
--el-component-size: 44px;
|
||||
--el-color-primary: #2f7bff;
|
||||
--el-text-color-regular: #1f2937;
|
||||
--el-text-color-placeholder: #b0b7c3;
|
||||
max-width: none;
|
||||
min-width: 0;
|
||||
background: transparent;
|
||||
color: #1f2937;
|
||||
font: 14px/1.5 "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif;
|
||||
}
|
||||
.transport-demand-form--create .transport-demand-section { margin-bottom: 12px; padding: 0; border: 0; }
|
||||
.transport-demand-form--create .transport-demand-section h3 { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; color: #1f2937; font-size: 18px; font-weight: 700; }
|
||||
.transport-demand-form--create .transport-demand-section h3::before { content: ''; width: 9px; height: 9px; flex: 0 0 9px; border-radius: 50%; background: #2f7bff; }
|
||||
.transport-demand-form--create .transport-demand-section:nth-of-type(2) h3::before { background: #0ea5a4; }
|
||||
.transport-demand-form--create .transport-demand-grid { min-width: 0; gap: 12px 20px; padding: 16px; border: 1px solid #e3e8f0; border-radius: 10px; background: #fff; }
|
||||
.transport-demand-form--create .transport-demand-route-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
|
||||
.transport-demand-form--create .transport-demand-route-grid > .el-form-item { grid-column: span 2; }
|
||||
.transport-demand-form--create .transport-demand-route-grid > .transport-demand-vehicle { grid-column: 1 / -1; }
|
||||
.transport-demand-form--create .transport-demand-route-grid > .transport-demand-address { grid-column: span 3; }
|
||||
.transport-demand-form--create :deep(.el-form-item) { margin: 0; }
|
||||
.transport-demand-form--create .transport-demand-vehicle { width: calc((100% - 40px) / 3); }
|
||||
.transport-demand-form--create :deep(.el-form-item__label) { height: auto; margin-bottom: 6px; padding: 0; color: #374151; font-size: 14px; font-weight: 600; line-height: 20px; }
|
||||
.transport-demand-form--create :deep(.el-form-item.is-required .el-form-item__label::before) { color: #e5484d; }
|
||||
/* Show validation beside the label without adding height below the control. */
|
||||
.transport-demand-form--create :deep(.el-form-item__content) { min-width: 0; line-height: 20px; }
|
||||
.transport-demand-form--create :deep(.el-form-item__error) { position: absolute; top: auto; bottom: calc(100% + 6px); right: 0; left: auto; width: auto; max-width: calc(100% - 120px); padding: 0; font-size: 12px; line-height: 20px; text-align: right; }
|
||||
.transport-demand-form--create :deep(.el-input__wrapper), .transport-demand-form--create :deep(.el-select__wrapper), .transport-demand-form--create :deep(.el-textarea__inner) { border: 1px solid #d5dce8; border-radius: 6px; background: #fff; box-shadow: none; font-family: inherit; font-size: 14px; }
|
||||
.transport-demand-form--create :deep(.el-input__wrapper), .transport-demand-form--create :deep(.el-select__wrapper) { min-height: 44px; padding: 10px 14px; }
|
||||
.transport-demand-form--create :deep(.el-input__inner) { height: 22px; color: #1f2937; line-height: 22px; }
|
||||
.transport-demand-form--create :deep(.el-input-number .el-input__wrapper) { padding-right: 40px; }
|
||||
.transport-demand-form--create :deep(.el-input-number.is-controls-right .el-input-number__increase), .transport-demand-form--create :deep(.el-input-number.is-controls-right .el-input-number__decrease) { width: 32px; }
|
||||
.transport-demand-form--create :deep(.el-textarea__inner) { min-height: 110px; padding: 11px 14px; color: #1f2937; line-height: 20px; resize: vertical; }
|
||||
.transport-demand-form--create :deep(.el-input__inner::placeholder), .transport-demand-form--create :deep(.el-textarea__inner::placeholder) { color: var(--el-text-color-placeholder); opacity: 1; }
|
||||
.transport-demand-form--create :deep(.el-input__wrapper.is-focus), .transport-demand-form--create :deep(.el-select__wrapper.is-focused), .transport-demand-form--create :deep(.el-textarea__inner:focus) { outline: 2px solid #2f7bff; outline-offset: 0; }
|
||||
.transport-demand-form--create :deep(.el-form-item.is-error .el-input__wrapper), .transport-demand-form--create :deep(.el-form-item.is-error .el-select__wrapper), .transport-demand-form--create :deep(.el-form-item.is-error .el-textarea__inner) { border-color: #e5484d; box-shadow: none; }
|
||||
.transport-demand-form--create :deep(.el-input.is-disabled .el-input__wrapper), .transport-demand-form--create :deep(.el-select__wrapper.is-disabled), .transport-demand-form--create :deep(.el-textarea.is-disabled .el-textarea__inner) { background: #f6f9ff; }
|
||||
.transport-demand-form--create :deep(.el-input.is-disabled .el-input__inner), .transport-demand-form--create :deep(.el-textarea.is-disabled .el-textarea__inner) { color: #98a2b3; -webkit-text-fill-color: #98a2b3; }
|
||||
.transport-demand-character-count { width: 100%; margin-top: 4px; color: #6b7280; font-size: 13px; text-align: right; }
|
||||
.transport-demand-form--create .transport-demand-actions { flex-wrap: wrap; gap: 12px; padding: 0; }
|
||||
.transport-demand-form--create .transport-demand-actions :deep(.el-button) { height: auto; min-height: 44px; margin-left: 0; padding: 10px 18px; border-radius: 6px; color: #1d5fe0; font-size: 14px; box-shadow: none; }
|
||||
.transport-demand-form--create .transport-demand-actions :deep(.el-button--primary) { padding: 12px 28px; color: #fff; }
|
||||
.transport-demand-form--create .transport-demand-actions :deep(.el-button.is-disabled) { color: #98a2b3; }
|
||||
:global(.transport-create-popper.el-popper) { --el-color-primary: #2f7bff; border: 1px solid #d5dce8; box-shadow: none; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user