| | |
| | | <el-table-column label="产品大类" prop="productCategory" /> |
| | | <el-table-column label="规格型号" prop="specificationModel" /> |
| | | <el-table-column label="单位" prop="unit" /> |
| | | <el-table-column label="产品状态" |
| | | width="100px" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | |
| | | <el-tag v-if="scope.row.approveStatus === 1 && (!scope.row.shippingDate || !scope.row.shippingCarNumber)" |
| | | type="success">充足</el-tag> |
| | | <el-tag v-else-if="scope.row.approveStatus === 0 && (scope.row.shippingDate || scope.row.shippingCarNumber)" |
| | | type="success">已出库</el-tag> |
| | | <el-tag v-else type="danger">不足</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="发货状态" width="140" align="center"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getShippingStatusType(scope.row)" size="small"> |
| | | {{ getShippingStatusText(scope.row) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="快递公司" prop="expressCompany" show-overflow-tooltip /> |
| | | <el-table-column label="快递单号" prop="expressNumber" show-overflow-tooltip /> |
| | | <el-table-column label="发货车牌" minWidth="100px" align="center"> |
| | | <template #default="scope"> |
| | | <div> |
| | | <el-tag type="success" v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</el-tag> |
| | | <el-tag v-else type="info">-</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="发货日期" |
| | | minWidth="100px" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <div> |
| | | <div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div> |
| | | <el-tag v-else |
| | | type="info">-</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="数量" prop="quantity" /> |
| | | <el-table-column label="税率(%)" prop="taxRate" /> |
| | | <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="sensitiveAmountFormatter" /> |
| | | <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" :formatter="sensitiveAmountFormatter" /> |
| | | <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="sensitiveAmountFormatter" /> |
| | | <!--操作--> |
| | | <el-table-column Width="60px" label="操作" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | :disabled="!canShip(scope.row)" |
| | | @click="openDeliveryForm(scope.row)"> |
| | | 发货 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <el-table-column label="录入人" prop="entryPersonName" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="录入日期" prop="entryDate" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="签订日期" prop="executionDate" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="发货状态" prop="shippingStatus" width="140" align="center" show-overflow-tooltip /> |
| | | <el-table-column label="发货日期" prop="shippingDate" width="140" align="center" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="操作" min-width="140" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="openForm('edit', scope.row)" |
| | | :disabled="scope.row.approvalStatus === 3 && scope.row.entryPerson !== userStore.id" |
| | | >编辑</el-button> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">附件</el-button> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="openDeliveryForm(scope.row)" |
| | | :disabled="scope.row.shippingStatus === '已发货'" |
| | | > |
| | | 发货 |
| | | </el-button> |
| | | <el-button link type="primary" @click="openForm('edit', scope.row)" :disabled="!scope.row.isEdit || scope.row.hasProductionRecord">编辑</el-button> |
| | | <el-button link type="primary" @click="downLoadFile(scope.row)">附件</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | v-model="deliveryForm.type" |
| | | placeholder="请选择发货类型" |
| | | style="width: 100%" |
| | | @change="handleShippingTypeChange" |
| | | > |
| | | <el-option label="货车" value="货车" /> |
| | | <el-option label="快递" value="快递" /> |
| | |
| | | </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%" |
| | | v-model="deliveryForm.shippingDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="请选择发货日期" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24" v-if="deliveryForm.type === '货车'"> |
| | | <el-form-item label="发货车牌号:" prop="shippingCarNumber"> |
| | | <el-input |
| | | v-model="deliveryForm.shippingCarNumber" |
| | | placeholder="请输入发货车牌号" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24" v-else> |
| | | <el-form-item label="快递公司:" prop="expressCompany"> |
| | | <el-input |
| | | v-model="deliveryForm.expressCompany" |
| | | placeholder="请输入快递公司" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30" v-if="deliveryForm.type === '快递'"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="快递单号:" prop="expressNumber"> |
| | | <el-input |
| | | v-model="deliveryForm.expressNumber" |
| | | placeholder="请输入快递单号" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="发货图片:"> |
| | | <el-upload |
| | | v-model:file-list="deliveryFileList" |
| | | :action="upload.url" |
| | | multiple |
| | | ref="deliveryFileUpload" |
| | | auto-upload |
| | | :headers="upload.headers" |
| | | :data="{ type: 9 }" |
| | | :before-upload="handleDeliveryBeforeUpload" |
| | | :on-error="handleDeliveryUploadError" |
| | | :on-success="handleDeliveryUploadSuccess" |
| | | :on-remove="handleDeliveryRemove" |
| | | list-type="picture-card" |
| | | :limit="9" |
| | | accept="image/png,image/jpeg,image/jpg" |
| | | > |
| | | <el-icon class="avatar-uploader-icon"><Plus /></el-icon> |
| | | <template #tip> |
| | | <div class="el-upload__tip"> |
| | | 支持 jpg、jpeg、png 格式,最多上传 9 张,单张大小不超过 10MB |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | }); |
| | | const total = ref(0); |
| | | const fileList = ref([]); |
| | | const deliveryFileList = ref([]); |
| | | |
| | | // 审批人节点(仿采购台账审批人) |
| | | const approverNodes = ref([{ id: 1, userId: null }]); |
| | |
| | | const currentDeliveryRow = ref(null); |
| | | const deliveryFormData = reactive({ |
| | | deliveryForm: { |
| | | type: "货车", // 货车, 快递 |
| | | shippingDate: "", |
| | | shippingCarNumber: "", |
| | | expressCompany: "", |
| | | expressNumber: "", // 快递单号 |
| | | shippingImages: "", // 发货图片,多个用逗号分隔 |
| | | type: "", // 货车, 快递 |
| | | }, |
| | | deliveryRules: { |
| | | 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" } |
| | | ], |
| | | }, |
| | | }); |
| | |
| | | delLedgerFile(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | }); |
| | | } |
| | | } |
| | | // 发货图片上传前校检 |
| | | function handleDeliveryBeforeUpload(file) { |
| | | // 校检文件类型 |
| | | const isImage = file.type === 'image/png' || file.type === 'image/jpeg' || file.type === 'image/jpg'; |
| | | if (!isImage) { |
| | | proxy.$modal.msgError("只能上传 jpg、jpeg、png 格式的图片!"); |
| | | return false; |
| | | } |
| | | // 校检文件大小 |
| | | const isLt10M = file.size / 1024 / 1024 < 10; |
| | | if (!isLt10M) { |
| | | proxy.$modal.msgError("上传图片大小不能超过 10MB!"); |
| | | return false; |
| | | } |
| | | proxy.$modal.loading("正在上传图片,请稍候..."); |
| | | return true; |
| | | } |
| | | // 发货图片上传失败 |
| | | function handleDeliveryUploadError(err) { |
| | | proxy.$modal.msgError("上传图片失败"); |
| | | proxy.$modal.closeLoading(); |
| | | } |
| | | // 发货图片上传成功回调 |
| | | function handleDeliveryUploadSuccess(res, file, uploadFiles) { |
| | | proxy.$modal.closeLoading(); |
| | | if (res.code === 200) { |
| | | file.tempId = res.data.tempId; |
| | | proxy.$modal.msgSuccess("上传成功"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg); |
| | | proxy.$refs.deliveryFileUpload.handleRemove(file); |
| | | } |
| | | } |
| | | // 移除发货图片 |
| | | function handleDeliveryRemove(file) { |
| | | // 从文件列表中移除 |
| | | const index = deliveryFileList.value.findIndex(item => item.uid === file.uid); |
| | | if (index > -1) { |
| | | deliveryFileList.value.splice(index, 1); |
| | | } |
| | | } |
| | | // 提交表单 |
| | |
| | | return total.toFixed(2); |
| | | }; |
| | | |
| | | // 发货类型校验:货车时要求车牌,快递时要求快递公司 |
| | | const validateShippingCarNumber = (value, callback) => { |
| | | if (deliveryForm.value.type === "货车") { |
| | | if (!value) return callback(new Error("请输入发货车牌号")); |
| | | } |
| | | callback(); |
| | | }; |
| | | const validateExpressCompany = (value, callback) => { |
| | | if (deliveryForm.value.type === "快递") { |
| | | if (!value) return callback(new Error("请输入快递公司")); |
| | | } |
| | | callback(); |
| | | }; |
| | | |
| | | |
| | | const mathNum = () => { |
| | | console.log("productForm.value", productForm.value); |
| | |
| | | isCalculating.value = false; |
| | | }; |
| | | /** |
| | | * 获取发货状态文本 |
| | | * @param row 行数据 |
| | | */ |
| | | const getShippingStatusText = (row) => { |
| | | // 如果已发货(有发货日期或车牌号),显示"已发货" |
| | | if (row.shippingDate || row.shippingCarNumber) { |
| | | return '已发货'; |
| | | } |
| | | |
| | | // 获取发货状态字段 |
| | | const status = row.shippingStatus; |
| | | |
| | | // 如果状态为空或未定义,默认为"待发货" |
| | | if (status === null || status === undefined || status === '') { |
| | | return '待发货'; |
| | | } |
| | | |
| | | // 状态是字符串 |
| | | const statusStr = String(status).trim(); |
| | | const statusTextMap = { |
| | | '待发货': '待发货', |
| | | '待审核': '待审核', |
| | | '审核中': '审核中', |
| | | '审核拒绝': '审核拒绝', |
| | | '审核通过': '审核通过', |
| | | '已发货': '已发货' |
| | | }; |
| | | return statusTextMap[statusStr] || '待发货'; |
| | | }; |
| | | |
| | | /** |
| | | * 获取发货状态标签类型(颜色) |
| | | * @param row 行数据 |
| | | */ |
| | | const getShippingStatusType = (row) => { |
| | | // 如果已发货(有发货日期或车牌号),显示绿色 |
| | | if (row.shippingDate || row.shippingCarNumber) { |
| | | return 'success'; |
| | | } |
| | | |
| | | // 获取发货状态字段 |
| | | const status = row.shippingStatus; |
| | | |
| | | // 如果状态为空或未定义,默认为灰色(待发货) |
| | | if (status === null || status === undefined || status === '') { |
| | | return 'info'; |
| | | } |
| | | |
| | | // 状态是字符串 |
| | | const statusStr = String(status).trim(); |
| | | const typeTextMap = { |
| | | '待发货': 'info', |
| | | '待审核': 'info', |
| | | '审核中': 'warning', |
| | | '审核拒绝': 'danger', |
| | | '审核通过': 'success', |
| | | '已发货': 'success' |
| | | }; |
| | | return typeTextMap[statusStr] || 'info'; |
| | | }; |
| | | |
| | | /** |
| | | * 判断是否可以发货 |
| | | * 只有在产品状态是充足,发货状态是待发货和审核拒绝的时候才可以发货 |
| | | * @param row 行数据 |
| | | */ |
| | | const canShip = (row) => { |
| | | // 产品状态必须是充足(approveStatus === 1) |
| | | if (row.approveStatus !== 1) { |
| | | return false; |
| | | } |
| | | |
| | | // 获取发货状态 |
| | | const shippingStatus = row.shippingStatus; |
| | | |
| | | // 如果已发货(有发货日期或车牌号),不能再次发货 |
| | | if (row.shippingDate || row.shippingCarNumber) { |
| | | return false; |
| | | } |
| | | |
| | | // 发货状态必须是"待发货"或"审核拒绝" |
| | | const statusStr = shippingStatus ? String(shippingStatus).trim() : ''; |
| | | return statusStr === '待发货' || statusStr === '审核拒绝'; |
| | | }; |
| | | |
| | | /** |
| | | * 下载文件 |
| | | * |
| | | * @param row 下载文件的相关信息对象 |
| | |
| | | |
| | | // 打开发货弹框 |
| | | const openDeliveryForm = (row) => { |
| | | // 检查是否可以发货 |
| | | if (!canShip(row)) { |
| | | proxy.$modal.msgWarning("只有在产品状态是充足,发货状态是待发货或审核拒绝的时候才可以发货"); |
| | | return; |
| | | } |
| | | |
| | | currentDeliveryRow.value = row; |
| | | deliveryForm.value = { |
| | | type: "货车", |
| | | shippingDate: getCurrentDate(), |
| | | shippingCarNumber: "", |
| | | expressCompany: "", |
| | | expressNumber: "", // 初始化快递单号为空 |
| | | shippingImages: "", // 初始化图片为空 |
| | | type: "", |
| | | }; |
| | | deliveryFileList.value = []; // 初始化文件列表为空 |
| | | deliveryFormVisible.value = true; |
| | | }; |
| | | |
| | |
| | | const submitDelivery = () => { |
| | | proxy.$refs["deliveryFormRef"].validate((valid) => { |
| | | if (valid) { |
| | | let tempFileIds = []; |
| | | if (deliveryFileList.value !== null && deliveryFileList.value.length > 0) { |
| | | tempFileIds = deliveryFileList.value.map((item) => item.tempId); |
| | | } |
| | | // 保存当前展开的行ID,以便发货后重新加载子表格数据 |
| | | const currentExpandedKeys = [...expandedRowKeys.value]; |
| | | const salesLedgerId = currentDeliveryRow.value.salesLedgerId; |
| | | addShippingInfo({ |
| | | salesLedgerId: currentDeliveryRow.value.id, |
| | | salesLedgerId: salesLedgerId, |
| | | salesLedgerProductId: currentDeliveryRow.value.id, |
| | | type: deliveryForm.value.type, |
| | | shippingDate: deliveryForm.value.shippingDate, |
| | | shippingCarNumber: deliveryForm.value.type === "货车" ? deliveryForm.value.shippingCarNumber : "", |
| | | expressCompany: deliveryForm.value.type === "快递" ? deliveryForm.value.expressCompany : "", |
| | | expressNumber: deliveryForm.value.type === "快递" ? deliveryForm.value.expressNumber : "", |
| | | tempFileIds: tempFileIds, |
| | | }) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("发货成功"); |
| | | closeDeliveryDia(); |
| | | getList(); |
| | | // 刷新主表数据 |
| | | getList().then(() => { |
| | | // 如果之前有展开的行,重新加载这些行的子表格数据 |
| | | if (currentExpandedKeys.length > 0) { |
| | | // 使用 Promise.all 并行加载所有展开行的子表格数据 |
| | | const loadPromises = currentExpandedKeys.map(ledgerId => { |
| | | return productList({ salesLedgerId: ledgerId, type: 1 }).then((res) => { |
| | | const index = tableData.value.findIndex((item) => item.id === ledgerId); |
| | | if (index > -1) { |
| | | tableData.value[index].children = res.data; |
| | | } |
| | | }); |
| | | }); |
| | | Promise.all(loadPromises).then(() => { |
| | | // 恢复展开状态 |
| | | expandedRowKeys.value = currentExpandedKeys; |
| | | }); |
| | | } |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("发货失败,请重试"); |
| | | }); |
| | | } |
| | | }); |
| | | }; |
| | |
| | | // 关闭发货弹框 |
| | | const closeDeliveryDia = () => { |
| | | proxy.resetForm("deliveryFormRef"); |
| | | deliveryFileList.value = []; // 清空文件列表 |
| | | deliveryForm.value.shippingImages = ""; // 清空图片 |
| | | deliveryForm.value.expressNumber = ""; // 清空快递单号 |
| | | deliveryFormVisible.value = false; |
| | | currentDeliveryRow.value = null; |
| | | }; |
| | | |
| | | // 发货类型切换时清空对应字段 |
| | | const handleShippingTypeChange = (val) => { |
| | | if (val === "货车") { |
| | | deliveryForm.value.expressCompany = ""; |
| | | deliveryForm.value.expressNumber = ""; |
| | | } else { |
| | | deliveryForm.value.shippingCarNumber = ""; |
| | | } |
| | | const currentFactoryName = ref(""); |
| | | const getCurrentFactoryName = async () => { |
| | | let res = await userStore.getInfo(); |
| | | currentFactoryName.value = res.user.currentFactoryName; |
| | | }; |
| | | |
| | | onMounted(() => { |