| | |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form-item label="销售订单号:"> |
| | | <el-form-item label="发货单号:"> |
| | | <el-input |
| | | v-model="searchForm.shippingNo" |
| | | placeholder="请输入" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px" |
| | | @change="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="销售合同号:"> |
| | | <el-input |
| | | v-model="searchForm.salesContractNo" |
| | | placeholder="请输入" |
| | |
| | | <el-form-item label="车牌号:"> |
| | | <el-input |
| | | v-model="searchForm.shippingCarNumber" |
| | | placeholder="请输入" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px" |
| | | @change="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="快递单号:"> |
| | | <el-input |
| | | v-model="searchForm.expressNumber" |
| | | placeholder="请输入" |
| | | clearable |
| | | prefix-icon="Search" |
| | |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :row-key="(row) => row.id" |
| | | :row-key="(row) => `${row.source || 'shipping'}-${row.stockOutRecordId ?? row.id}`" |
| | | style="width: 100%" |
| | | height="calc(100vh - 21.5em)" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="序号" type="index" width="60" /> |
| | | <el-table-column |
| | | label="销售订单" |
| | | prop="salesContractNo" |
| | | show-overflow-tooltip |
| | | align="center" |
| | | type="selection" |
| | | :selectable="isRowSelectable" |
| | | width="55" |
| | | /> |
| | | <el-table-column align="center" label="序号" type="index" width="60" /> |
| | | <el-table-column label="来源" prop="source" align="center" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="isOilOutRow(scope.row) ? 'success' : 'info'" |
| | | size="small" |
| | | > |
| | | {{ isOilOutRow(scope.row) ? "油品出库" : "发货单" }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="发货订单号" |
| | | prop="shippingNo" |
| | |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="客户对接人" |
| | | prop="contactPerson" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="对接人电话" |
| | | prop="contactPhone" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="产品名称" |
| | | prop="productName" |
| | | show-overflow-tooltip |
| | |
| | | <el-table-column |
| | | label="规格型号" |
| | | prop="specificationModel" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="批号" show-overflow-tooltip> |
| | | <!-- 油品出库行的批号是 outBatchNo(batch_no),发货单行没有该字段 --> |
| | | <template #default="scope"> |
| | | {{ |
| | | isOilOutRow(scope.row) |
| | | ? scope.row.outBatchNo || "--" |
| | | : scope.row.batchNo || "--" |
| | | }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="出库类别" |
| | | prop="outCategory" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="储罐号" prop="tankNo" show-overflow-tooltip /> |
| | | <el-table-column |
| | | label="油库" |
| | | prop="oilDepotName" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="快递公司" |
| | | prop="expressCompany" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="快递单号" |
| | | prop="expressNumber" |
| | | label="司机姓名" |
| | | prop="driverName" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="发货类型:" prop="type"> |
| | | <el-select |
| | | v-model="form.type" |
| | | placeholder="请选择发货类型" |
| | | style="width: 100%" |
| | | @change="handleShippingTypeChange" |
| | | > |
| | | <el-option label="货车" value="货车" /> |
| | | <el-option label="快递" value="快递" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="发货日期:" prop="shippingDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24" v-if="form.type === '货车'"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="发货车牌号:" prop="shippingCarNumber"> |
| | | <el-input |
| | | v-model="form.shippingCarNumber" |
| | | placeholder="请输入发货车牌号" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24" v-else> |
| | | <el-form-item label="快递公司:" prop="expressCompany"> |
| | | <el-input |
| | | v-model="form.expressCompany" |
| | | placeholder="请输入快递公司" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30" v-if="form.type === '快递'"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="快递单号:" prop="expressNumber"> |
| | | <el-input |
| | | v-model="form.expressNumber" |
| | | placeholder="请输入快递单号" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | |
| | | > |
| | | <div v-if="detailRow" class="detail-wrapper"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="销售订单">{{ |
| | | detailRow.salesContractNo || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="发货订单号">{{ |
| | | detailRow.shippingNo || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="客户名称">{{ |
| | | detailRow.customerName || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="客户对接人">{{ |
| | | detailRow.contactPerson || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="对接人电话">{{ |
| | | detailRow.contactPhone || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="产品名称">{{ |
| | | detailRow.productName || "--" |
| | |
| | | <el-descriptions-item label="规格型号">{{ |
| | | detailRow.specificationModel || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="发货类型">{{ |
| | | detailRow.type || "--" |
| | | <el-descriptions-item label="出库类别">{{ |
| | | detailRow.outCategory || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="储罐号">{{ |
| | | detailRow.tankNo || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="油库">{{ |
| | | detailRow.oilDepotName || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="发货日期">{{ |
| | | detailRow.shippingDate || "--" |
| | |
| | | <el-descriptions-item label="发货车牌号">{{ |
| | | detailRow.shippingCarNumber || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="快递公司">{{ |
| | | detailRow.expressCompany || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="快递单号" :span="2">{{ |
| | | detailRow.expressNumber || "--" |
| | | <el-descriptions-item label="司机姓名">{{ |
| | | detailRow.driverName || "--" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="出库单号" :span="2">{{ |
| | | detailRow.outboundBatches || "--" |
| | |
| | | /> |
| | | <el-table-column |
| | | label="发货数量" |
| | | prop="deliveryQuantity" |
| | | prop="totalQuantity" |
| | | min-width="120" |
| | | align="center" |
| | | /> |
| | |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const salesOrderOptions = ref([]); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | |
| | | const dialogFormVisible = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | salesContractNo: "", // 销售订单号 |
| | | shippingNo: "", // 发货单号(两类来源都匹配) |
| | | salesContractNo: "", // 销售合同号(只匹配发货单行) |
| | | shippingCarNumber: "", // 车牌号 |
| | | expressNumber: "", // 快递单号 |
| | | }, |
| | | form: { |
| | | id: null, |
| | | salesContractNo: "", |
| | | customerName: "", |
| | | specificationModel: "", |
| | | productName: "", |
| | | type: "货车", // 货车, 快递 |
| | | shippingDate: "", |
| | | shippingCarNumber: "", |
| | | expressCompany: "", |
| | | expressNumber: "", // 快递单号 |
| | | }, |
| | | rules: { |
| | | salesContractNo: [ |
| | | { required: true, message: "请选择销售订单", trigger: "change" }, |
| | | ], |
| | | customerName: [ |
| | | { required: true, message: "请输入客户名称", trigger: "blur" }, |
| | | ], |
| | | type: [{ required: true, message: "请选择发货类型", trigger: "change" }], |
| | | shippingDate: [ |
| | | { required: true, message: "请选择发货时间", trigger: "change" }, |
| | | ], |
| | | shippingCarNumber: [ |
| | | { |
| | | validator: (_, value, callback) => |
| | | validateShippingCarNumber(value, callback), |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | expressCompany: [ |
| | | { |
| | | validator: (_, value, callback) => |
| | | validateExpressCompany(value, callback), |
| | | trigger: "blur", |
| | | }, |
| | | { required: true, message: "请输入发货车牌号", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | }); |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 销售订单变化时自动填充客户名称 |
| | | const handleSalesOrderChange = (value) => { |
| | | const selectedOrder = salesOrderOptions.value.find( |
| | | (item) => item.salesContractNo === value |
| | | ); |
| | | if (selectedOrder) { |
| | | form.value.customerName = selectedOrder.customerName; |
| | | } |
| | | }; |
| | | // 油品出库行来自 stock_out_record,id 与 shipping_info 会撞号, |
| | | // 发货/删除/详情等接口背后都是 shipping_info,不能用于这类行 |
| | | const isOilOutRow = (row) => row?.source === "oilOut"; |
| | | const isRowSelectable = (row) => !isOilOutRow(row); |
| | | |
| | | // 表格选择数据 |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | selectedRows.value = selection.filter((item) => !isOilOutRow(item)); |
| | | }; |
| | | |
| | | // 打开弹框 |
| | |
| | | if (type === "edit" && row) { |
| | | form.value = { |
| | | id: row.id ?? null, |
| | | salesContractNo: row.salesContractNo ?? "", |
| | | customerName: row.customerName ?? "", |
| | | type: row.type || "货车", |
| | | shippingDate: row.shippingDate || getCurrentDate(), |
| | | shippingCarNumber: row.shippingCarNumber ?? "", |
| | | expressCompany: row.expressCompany ?? "", |
| | | expressNumber: row.expressNumber ?? "", |
| | | }; |
| | | deliveryFileList.value = row.storageBlobVOs || []; |
| | | } |
| | |
| | | detailRow.value = row || null; |
| | | detailProductList.value = []; |
| | | detailDialogVisible.value = true; |
| | | if (!row?.id) return; |
| | | // 油品出库行不走发货单详情接口(id 会撞号),直接用列表行数据展示 |
| | | if (!row?.id || isOilOutRow(row)) return; |
| | | try { |
| | | const res = await getDeliveryDetail(row.id); |
| | | const detailData = res?.data; |
| | |
| | | productName: item.productName ?? row.productName ?? "--", |
| | | specificationModel: |
| | | item.specificationModel ?? item.model ?? row.specificationModel ?? "--", |
| | | deliveryQuantity: |
| | | totalQuantity: |
| | | item.totalQuantity ?? |
| | | row.totalQuantity ?? |
| | | item.deliveryQuantity ?? |
| | | item.quantity ?? |
| | | item.shippingQuantity ?? |
| | |
| | | if (valid) { |
| | | const payload = { |
| | | id: form.value.id, |
| | | type: form.value.type, |
| | | shippingDate: form.value.shippingDate, |
| | | shippingCarNumber: |
| | | form.value.type === "货车" ? form.value.shippingCarNumber : "", |
| | | expressCompany: |
| | | form.value.type === "快递" ? form.value.expressCompany : "", |
| | | expressNumber: |
| | | form.value.type === "快递" ? form.value.expressNumber : "", |
| | | shippingCarNumber: form.value.shippingCarNumber, |
| | | storageBlobDTOs: deliveryFileList.value || [], |
| | | }; |
| | | deductStock(payload).then((res) => { |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 发货类型校验:货车时要求车牌,快递时要求快递公司 |
| | | const validateShippingCarNumber = (value, callback) => { |
| | | if (form.value.type === "货车") { |
| | | if (!value) return callback(new Error("请输入发货车牌号")); |
| | | } |
| | | callback(); |
| | | }; |
| | | const validateExpressCompany = (value, callback) => { |
| | | if (form.value.type === "快递") { |
| | | if (!value) return callback(new Error("请输入快递公司")); |
| | | } |
| | | callback(); |
| | | }; |
| | | |
| | | // 发货图片上传前校检 |
| | | function handleDeliveryBeforeUpload(file) { |
| | | // 校检文件类型 |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 发货类型切换时清空对应字段 |
| | | const handleShippingTypeChange = (val) => { |
| | | if (val === "货车") { |
| | | form.value.expressCompany = ""; |
| | | form.value.expressNumber = ""; |
| | | } else { |
| | | form.value.shippingCarNumber = ""; |
| | | } |
| | | }; |
| | | |
| | | // 获取审核状态文本 |
| | | const getApprovalStatusText = (status) => { |