| | |
| | | :model="formState" |
| | | label-position="top" |
| | | ref="formRef"> |
| | | <div class="form-section-title">出库信息</div> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="出库类别" |
| | | prop="outCategory" |
| | | :rules="[{ required: true, message: '请选择出库类别', trigger: 'change' }]"> |
| | | <el-select v-model="formState.outCategory" |
| | | placeholder="请选择" |
| | | clearable |
| | | :disabled="hasBoundLedger" |
| | | style="width: 100%"> |
| | | <el-option label="客存" |
| | | value="客存" /> |
| | | <el-option label="代储" |
| | | value="代储" /> |
| | | <el-option label="销售" |
| | | value="销售" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="储库名称" |
| | | prop="oilDepotId" |
| | | :rules="[{ required: true, message: '请选择储库名称', trigger: 'change' }]"> |
| | | <el-select v-model="formState.oilDepotId" |
| | | placeholder="请选择" |
| | | clearable |
| | | :disabled="isStorageBound" |
| | | popper-class="oil-depot-select-popper" |
| | | style="width: 100%" |
| | | @change="depotChange"> |
| | | <el-option v-for="item in oilDepotList" |
| | | :key="item.id" |
| | | :label="`${item.depotName}-${item.company || ''}`" |
| | | :value="item.id"> |
| | | <div class="oil-depot-option"> |
| | | <div class="oil-depot-option-title">{{ item.depotName }}-{{ item.company }}</div> |
| | | <div class="oil-depot-option-line">负责人:{{ item.chargePerson }}</div> |
| | | <div class="oil-depot-option-line">联系电话:{{ item.phone }}</div> |
| | | <div class="oil-depot-option-line">启用日期:{{ item.enableDate }}</div> |
| | | </div> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="储罐号" |
| | | prop="tankId" |
| | | :rules="[{ required: true, message: '请选择储罐号', trigger: 'change' }]"> |
| | | <el-select v-model="formState.tankId" |
| | | placeholder="请选择" |
| | | clearable |
| | | :disabled="isStorageBound" |
| | | popper-class="tank-select-popper" |
| | | style="width: 100%" |
| | | @change="tankChange"> |
| | | <el-option v-for="item in tankList" |
| | | :key="item.id" |
| | | :label="item.tankNo" |
| | | :value="item.id"> |
| | | <div class="tank-option"> |
| | | <div class="tank-option-title">{{ item.tankNo }}</div> |
| | | <div class="tank-option-line">大类:{{ item.category }}</div> |
| | | <div class="tank-option-line">油品:{{ item.oilProduct }}</div> |
| | | <div class="tank-option-line">罐容:{{ item.capacity }}</div> |
| | | <div class="tank-option-line">库存余量(m³):{{ item.remaining }}</div> |
| | | <div class="tank-option-line">租客信息:{{ item.tenantInfo || '--' }}</div> |
| | | </div> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="出库日期" |
| | | prop="outDate" |
| | | :rules="[{ required: true, message: '请选择出库日期', trigger: 'change' }]"> |
| | | <el-date-picker v-model="formState.outDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | placeholder="请选择" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="油品" |
| | | prop="oilProduct" |
| | | :rules="isStorageBound ? [] : [{ required: true, message: '请选择油品', trigger: 'change' }]"> |
| | | <el-input :model-value="formState.oilProduct" |
| | | readonly |
| | | placeholder="--" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="客户名称" |
| | | prop="customerId" |
| | | :rules="[{ required: true, message: '请选择客户名称', trigger: 'change' }]"> |
| | | <el-select v-model="formState.customerId" |
| | | placeholder="请选择" |
| | | clearable |
| | | filterable |
| | | :disabled="hasBoundLedger" |
| | | popper-class="customer-select-popper" |
| | | style="width: 100%" |
| | | @change="customerChange"> |
| | | <el-option v-for="item in customerList" |
| | | :key="item.id" |
| | | :label="item.customerName" |
| | | :value="item.id"> |
| | | <div class="customer-option"> |
| | | <div class="customer-option-title">{{ item.customerName }}</div> |
| | | <div class="customer-option-line">银行基本户:{{ item.basicBankAccount }}</div> |
| | | <div class="customer-option-line">银行账号:{{ item.bankAccount }}</div> |
| | | <div class="customer-option-line">地址及联系方式:{{ item.addressPhone }}</div> |
| | | </div> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="客户对接人" |
| | | prop="contactPerson" |
| | | :rules="[{ required: true, message: '请输入客户对接人', trigger: 'blur' }]"> |
| | | <el-input v-model="formState.contactPerson" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="对接人电话" |
| | | prop="contactPhone" |
| | | :rules="[ |
| | | { required: true, message: '请输入对接人电话', trigger: 'blur' }, |
| | | { pattern: /^1[3-9]\d{9}$/, message: '请输入有效的11位手机号码', trigger: 'blur' } |
| | | ]"> |
| | | <el-input v-model="formState.contactPhone" |
| | | placeholder="请输入11位数字" |
| | | maxlength="11" |
| | | @input="phoneInput('contactPhone')" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- 一次出库可分摊给多个客户:各台账明细都要含本次出库规格,分摊数量之和 = 出库吨位 --> |
| | | <div class="form-section-title">销售台账绑定</div> |
| | | <el-row v-for="(ledger, index) in ledgerRows" |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- 批次候选是按产品规格去库存里捞的,所以放在规格后面,选完规格再选批次 --> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="单位" |
| | |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <div class="form-section-title">出库信息</div> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="出库类别" |
| | | prop="outCategory" |
| | | :rules="[{ required: true, message: '请选择出库类别', trigger: 'change' }]"> |
| | | <el-select v-model="formState.outCategory" |
| | | placeholder="请选择" |
| | | clearable |
| | | :disabled="hasBoundLedger" |
| | | style="width: 100%"> |
| | | <el-option label="客存" |
| | | value="客存" /> |
| | | <el-option label="代储" |
| | | value="代储" /> |
| | | <el-option label="销售" |
| | | value="销售" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="储库名称" |
| | | prop="oilDepotId" |
| | | :rules="[{ required: true, message: '请选择储库名称', trigger: 'change' }]"> |
| | | <el-select v-model="formState.oilDepotId" |
| | | placeholder="请选择" |
| | | clearable |
| | | :disabled="isStorageBound" |
| | | popper-class="oil-depot-select-popper" |
| | | style="width: 100%" |
| | | @change="depotChange"> |
| | | <el-option v-for="item in oilDepotList" |
| | | :key="item.id" |
| | | :label="`${item.depotName}-${item.company || ''}`" |
| | | :value="item.id"> |
| | | <div class="oil-depot-option"> |
| | | <div class="oil-depot-option-title">{{ item.depotName }}-{{ item.company }}</div> |
| | | <div class="oil-depot-option-line">负责人:{{ item.chargePerson }}</div> |
| | | <div class="oil-depot-option-line">联系电话:{{ item.phone }}</div> |
| | | <div class="oil-depot-option-line">启用日期:{{ item.enableDate }}</div> |
| | | </div> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="储罐号" |
| | | prop="tankId" |
| | | :rules="[{ required: true, message: '请选择储罐号', trigger: 'change' }]"> |
| | | <el-select v-model="formState.tankId" |
| | | placeholder="请选择" |
| | | clearable |
| | | :disabled="isStorageBound" |
| | | popper-class="tank-select-popper" |
| | | style="width: 100%" |
| | | @change="tankChange"> |
| | | <el-option v-for="item in tankList" |
| | | :key="item.id" |
| | | :label="item.tankNo" |
| | | :value="item.id"> |
| | | <div class="tank-option"> |
| | | <div class="tank-option-title">{{ item.tankNo }}</div> |
| | | <div class="tank-option-line">大类:{{ item.category }}</div> |
| | | <div class="tank-option-line">油品:{{ item.oilProduct }}</div> |
| | | <div class="tank-option-line">罐容:{{ item.capacity }}</div> |
| | | <div class="tank-option-line">库存余量(m³):{{ item.remaining }}</div> |
| | | <div class="tank-option-line">租客信息:{{ item.tenantInfo || '--' }}</div> |
| | | </div> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="出库日期" |
| | | prop="outDate" |
| | | :rules="[{ required: true, message: '请选择出库日期', trigger: 'change' }]"> |
| | | <el-date-picker v-model="formState.outDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | placeholder="请选择" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="油品" |
| | | prop="oilProduct" |
| | | :rules="isStorageBound ? [] : [{ required: true, message: '请输入油品', trigger: 'change' }]"> |
| | | <!-- 选完「产品 + 规格型号」自动写入,也能自己改 --> |
| | | <el-input v-model="formState.oilProduct" |
| | | placeholder="选完产品与规格型号后自动生成" |
| | | @input="handleOilProductInput" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="出库批次" |
| | | prop="batchNo" |
| | | :rules="[{ required: true, message: '油品出库必须选择出库批次', trigger: 'change' }]"> |
| | | <!-- 批次候选是按产品规格去库存里捞的,选完上面的规格这里才有得选 --> |
| | | <el-select v-model="formState.batchNo" |
| | | placeholder="请选择" |
| | | clearable |
| | |
| | | :label="item" |
| | | :value="item" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="客户名称" |
| | | prop="customerId" |
| | | :rules="[{ required: true, message: '请选择客户名称', trigger: 'change' }]"> |
| | | <el-select v-model="formState.customerId" |
| | | placeholder="请选择" |
| | | clearable |
| | | filterable |
| | | :disabled="hasBoundLedger" |
| | | popper-class="customer-select-popper" |
| | | style="width: 100%" |
| | | @change="customerChange"> |
| | | <el-option v-for="item in customerList" |
| | | :key="item.id" |
| | | :label="item.customerName" |
| | | :value="item.id"> |
| | | <div class="customer-option"> |
| | | <div class="customer-option-title">{{ item.customerName }}</div> |
| | | <div class="customer-option-line">银行基本户:{{ item.basicBankAccount }}</div> |
| | | <div class="customer-option-line">银行账号:{{ item.bankAccount }}</div> |
| | | <div class="customer-option-line">地址及联系方式:{{ item.addressPhone }}</div> |
| | | </div> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="客户对接人" |
| | | prop="contactPerson" |
| | | :rules="[{ required: true, message: '请输入客户对接人', trigger: 'blur' }]"> |
| | | <el-input v-model="formState.contactPerson" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="对接人电话" |
| | | prop="contactPhone" |
| | | :rules="[ |
| | | { required: true, message: '请输入对接人电话', trigger: 'blur' }, |
| | | { pattern: /^1[3-9]\d{9}$/, message: '请输入有效的11位手机号码', trigger: 'blur' } |
| | | ]"> |
| | | <el-input v-model="formState.contactPhone" |
| | | placeholder="请输入11位数字" |
| | | maxlength="11" |
| | | @input="phoneInput('contactPhone')" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | ? [{ required: true, message: '请输入车挂牌号', trigger: 'blur' }] |
| | | : []"> |
| | | <el-input v-model="formState.trailerPlateNo" |
| | | :readonly="!!formState.vehicleId" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | |
| | | // 未绑定卖油台账时走「产品大类树 + 规格型号」,与销售台账选产品的方式一致 |
| | | const productOptions = ref([]); |
| | | const modelOptions = ref([]); |
| | | |
| | | // 油品默认由「产品 + 规格型号」两级拼出来(两级都选完才有值)。 |
| | | // autoOilProduct 记住自动写进去的值,用来判断用户有没有手改过——手改过就不再覆盖 |
| | | const autoOilProduct = ref(""); |
| | | |
| | | const oilProductLabel = (productName, model) => |
| | | [productName, model].filter(Boolean).join(" / "); |
| | | |
| | | const syncOilProduct = next => { |
| | | const current = formState.value.oilProduct; |
| | | if (!current || current === autoOilProduct.value) { |
| | | formState.value.oilProduct = next || undefined; |
| | | } |
| | | autoOilProduct.value = next || ""; |
| | | }; |
| | | |
| | | // 手改过之后 autoOilProduct 就对不上了,后面的产品/规格联动不再覆盖它 |
| | | const handleOilProductInput = () => { |
| | | autoOilProduct.value = ""; |
| | | }; |
| | | |
| | | // 出库批次候选取该规格的入库批次 |
| | | const batchNoOptions = ref([]); |
| | | // 销售类出库的可用量提示(上次剩余 + 当前库存) |
| | |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // 车辆选择改变:车牌号、车挂牌号与司机信息由车辆主数据带出,出库时司机可手动覆盖 |
| | | // 车辆选择改变:车牌号与司机信息由车辆主数据带出,出库时司机可手动覆盖。 |
| | | // 车挂牌号是挂车自己的牌、不在车辆主数据里,始终手填,不参与联动。 |
| | | const vehicleChange = id => { |
| | | const vehicle = vehicleList.value.find(item => item.id === id); |
| | | if (vehicle) { |
| | | formState.value.truckPlateNo = vehicle.plateNumber || ""; |
| | | // 车挂牌号与车牌号是同一个牌,选了车辆就带出并置为只读,避免手填出两个不一致的值 |
| | | formState.value.trailerPlateNo = vehicle.plateNumber || ""; |
| | | formState.value.driverName = vehicle.driverName || ""; |
| | | formState.value.driverPhone = vehicle.driverPhone || ""; |
| | | } else { |
| | | if (!vehicle) { |
| | | formState.value.truckPlateNo = ""; |
| | | formState.value.trailerPlateNo = ""; |
| | | return; |
| | | } |
| | | formState.value.truckPlateNo = vehicle.plateNumber || ""; |
| | | formState.value.driverName = vehicle.driverName || ""; |
| | | formState.value.driverPhone = vehicle.driverPhone || ""; |
| | | }; |
| | | |
| | | const salesLedgerLabel = item => |
| | |
| | | }; |
| | | |
| | | const ledgerProductLabel = item => |
| | | [item.productName, item.model].filter(Boolean).join(" / "); |
| | | oilProductLabel(item.productName, item.model); |
| | | |
| | | const clearProduct = () => { |
| | | formState.value.productId = undefined; |
| | |
| | | formState.value.productName = ""; |
| | | formState.value.model = ""; |
| | | formState.value.unit = ""; |
| | | formState.value.oilProduct = undefined; |
| | | // 油品是产品 + 规格拼出来的,产品一清空它也跟着清空,手改过的不动 |
| | | syncOilProduct(""); |
| | | formState.value.batchNo = undefined; |
| | | batchNoOptions.value = []; |
| | | }; |
| | |
| | | formState.value.productName = item.productName; |
| | | formState.value.model = item.model; |
| | | formState.value.unit = item.unit; |
| | | formState.value.oilProduct = item.productName || item.model || undefined; |
| | | syncOilProduct(oilProductLabel(item.productName, item.model)); |
| | | formState.value.batchNo = undefined; |
| | | fetchBatchNoOptions(); |
| | | proxy.$refs["formRef"]?.validateField("productModelId"); |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 规格型号改变:产品名称/规格/单位由规格主数据带出,油品取产品名称 |
| | | // 规格型号改变:产品名称/规格/单位由规格主数据带出 |
| | | const handleProductModelChange = value => { |
| | | const item = modelOptions.value.find(row => row.id === value); |
| | | formState.value.productName = item?.productName || ""; |
| | | formState.value.model = item?.model || ""; |
| | | formState.value.unit = item?.unit || ""; |
| | | formState.value.oilProduct = item?.productName || undefined; |
| | | // 本租户「油品」按「产品名称 / 规格型号」展示,库存明细、出库台账的油品列取的就是它 |
| | | syncOilProduct(oilProductLabel(item?.productName, item?.model)); |
| | | formState.value.batchNo = undefined; |
| | | fetchBatchNoOptions(); |
| | | proxy.$refs["formRef"]?.validateField("productModelId"); |