| | |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form-item label="客户名称:"> |
| | | <el-input v-model="searchForm.customerName" placeholder="请输入" clearable prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | <el-select |
| | | v-model="searchForm.customerId" |
| | | filterable |
| | | placeholder="请选择客户名称" |
| | | clearable |
| | | style="width: 220px" |
| | | @change="handleQuery" |
| | | > |
| | | <el-option |
| | | v-for="item in customerOption" |
| | | :key="item.id" |
| | | :label="item.customerName" |
| | | :value="item.id" |
| | | > |
| | | {{ item.customerName + "——" + item.taxpayerIdentificationNumber }} |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="销售合同号:"> |
| | | <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search" |
| | |
| | | <el-form-item label="录入日期:"> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="请选择" clearable @change="changeDaterange" /> |
| | | </el-form-item> |
| | | <el-form-item label="发货状态:"> |
| | | <el-select v-model="searchForm.deliveryStatus" placeholder="请选择" clearable style="width: 140px"> |
| | | <el-option label="未发货" :value="1" /> |
| | | <el-option label="审批中" :value="2" /> |
| | | <el-option label="审批失败" :value="3" /> |
| | | <el-option label="已发货" :value="4" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery"> 搜索 </el-button> |
| | |
| | | <el-tag v-else type="danger">不足</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="发货状态" width="140" align="center"> |
| | | <!-- <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> --> |
| | | <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"> |
| | |
| | | <el-table-column label="客户名称" prop="customerName" width="300" show-overflow-tooltip /> |
| | | <el-table-column label="业务员" prop="salesman" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="项目名称" prop="projectName" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="付款方式" prop="paymentMethod" show-overflow-tooltip /> |
| | | <el-table-column label="合同金额(元)" prop="contractAmount" width="220" show-overflow-tooltip |
| | | :formatter="formattedNumber" /> |
| | | <el-table-column label="发货状态" width="140" align="center"> |
| | | <template #default="scope"> |
| | | <el-tag v-if="Number(scope.row.deliveryStatus) === 1" type="info">未发货</el-tag> |
| | | <el-tag v-else-if="Number(scope.row.deliveryStatus) === 2" type="warning">审批中</el-tag> |
| | | <el-tag v-else-if="Number(scope.row.deliveryStatus) === 3" type="danger">审批不通过</el-tag> |
| | | <el-tag v-else-if="Number(scope.row.deliveryStatus) === 4" type="primary">审批通过</el-tag> |
| | | <el-tag v-else-if="Number(scope.row.deliveryStatus) === 5" type="success">已发货</el-tag> |
| | | <el-tag v-else type="info">-</el-tag> |
| | | </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-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客户名称:" prop="customerId"> |
| | | <el-select v-model="form.customerId" placeholder="请选择" clearable :disabled="operationType === 'view'"> |
| | | <el-select v-model="form.customerId" filterable placeholder="请选择" clearable :disabled="operationType === 'view'"> |
| | | <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id"> |
| | | {{ |
| | | item.customerName + "——" + item.taxpayerIdentificationNumber |
| | |
| | | format="YYYY-MM-DD" type="date" placeholder="请选择" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="付款方式"> |
| | | <el-input v-model="form.paymentMethod" placeholder="请输入" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="交货日期:" prop="deliveryDate"> |
| | | <el-date-picker style="width: 100%" v-model="form.deliveryDate" 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="12"> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="交货日期:" prop="entryDate"> |
| | | <el-date-picker style="width: 100%" v-model="form.deliveryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" |
| | | type="date" placeholder="请选择" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-form-item label="产品信息:" prop="entryDate"> |
| | | <el-button v-if="operationType !== 'view'" type="primary" @click="openProductForm('add')">添加</el-button> |
| | |
| | | <el-form-item label="税率(%):" prop="taxRate"> |
| | | <el-select v-model="productForm.taxRate" placeholder="请选择" clearable @change="calculateFromTaxRate" style="width: 100%"> |
| | | <el-option label="1" value="1" /> |
| | | <el-option label="3" value="3" /> |
| | | <el-option label="6" value="6" /> |
| | | <el-option label="9" value="9" /> |
| | | <el-option label="13" value="13" /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | <script setup> |
| | | import { getToken } from "@/utils/auth"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import {onMounted, ref, getCurrentInstance} from "vue"; |
| | | import {onMounted, ref, getCurrentInstance, watch} from "vue"; |
| | | import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import { ArrowDown } from "@element-plus/icons-vue"; |
| | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | customerName: "", // 客户名称 |
| | | customerId: "", // 客户ID(查询下拉) |
| | | salesContractNo: "", // 销售合同编号 |
| | | entryDate: null, // 录入日期 |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | deliveryStatus: undefined, // 发货状态:1未发货 2审批中 3审批失败 4已发货 |
| | | }, |
| | | form: { |
| | | salesContractNo: "", |
| | |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const { form: searchForm } = useFormData(data.searchForm); |
| | | |
| | | // 新增台账:录入日期变更时,交货日期默认保持为录入日期后第 7 天 |
| | | watch( |
| | | () => [operationType.value, form.value?.entryDate], |
| | | () => { |
| | | if (operationType.value !== "add") return; |
| | | const ed = form.value?.entryDate; |
| | | if (!ed) return; |
| | | form.value.deliveryDate = dayjs(ed).add(7, "day").format("YYYY-MM-DD"); |
| | | } |
| | | ); |
| | | // 产品表单弹框数据 |
| | | const productFormVisible = ref(false); |
| | | const productOperationType = ref(""); |
| | |
| | | const params = { ...rest, ...page }; |
| | | // 移除录入日期的默认值设置,只保留范围日期字段 |
| | | delete params.entryDate; |
| | | // 查询客户名称与新增保持一致:先选 customerId,再映射为 customerName 查询 |
| | | const selectedCustomer = (customerOption.value || []).find( |
| | | (item) => String(item?.id ?? "") === String(params.customerId ?? "") |
| | | ); |
| | | if (selectedCustomer?.customerName) { |
| | | params.customerName = String(selectedCustomer.customerName).trim(); |
| | | } else { |
| | | const cn = params.customerName != null ? String(params.customerName).trim() : ""; |
| | | if (cn) { |
| | | params.customerName = cn; |
| | | } else { |
| | | delete params.customerName; |
| | | } |
| | | } |
| | | delete params.customerId; |
| | | return ledgerListPage(params) |
| | | .then((res) => { |
| | | tableLoading.value = false; |
| | |
| | | // } |
| | | // }); |
| | | form.value.entryDate = getCurrentDate(); // 设置默认录入日期为当前日期 |
| | | if (type === "add") { |
| | | form.value.deliveryDate = dayjs(form.value.entryDate).add(7, "day").format("YYYY-MM-DD"); |
| | | } |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | |
| | |
| | | } |
| | | form.value.tempFileIds = tempFileIds; |
| | | form.value.type = 1; |
| | | addOrUpdateSalesLedger(form.value).then((res) => { |
| | | const submitPayload = { ...form.value }; |
| | | delete submitPayload.paymentMethod; |
| | | addOrUpdateSalesLedger(submitPayload).then((res) => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | getList(); |
| | |
| | | * @param row 行数据 |
| | | */ |
| | | const canShip = (row) => { |
| | | |
| | | // 产品状态必须是充足(approveStatus === 1) |
| | | if (row.approveStatus !== 1) { |
| | | return false; |
| | | } |
| | | |
| | | // 如果后端返回了台账级发货状态(deliveryStatus) |
| | | // 1=已发货,则禁止再次发货 |
| | | const deliveryStatus = row.deliveryStatus; |
| | | if ( |
| | | deliveryStatus !== null && |
| | | deliveryStatus !== undefined && |
| | | String(deliveryStatus).trim() !== "" |
| | | ) { |
| | | if (Number(deliveryStatus) === 1) return false; |
| | | } |
| | | |
| | | // 获取发货状态 |
| | | const shippingStatus = row.shippingStatus; |
| | | |
| | |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("请选择数据"); |
| | | return; |
| | | } |
| | | |
| | | // 只允许【未发货/审批失败】进入发货流程 |
| | | const canDeliveryLedgers = selectedRows.value.filter((r) => { |
| | | const status = Number(r.deliveryStatus); |
| | | return status === 1 || status === 3; |
| | | }); |
| | | if (canDeliveryLedgers.length === 0) { |
| | | proxy.$modal.msgWarning("仅未发货或审批失败的台账可以发货"); |
| | | return; |
| | | } |
| | | |
| | | // 已发货台账:弹窗提醒,不能再次发货(4 视为已发货) |
| | | const shippedLedgers = selectedRows.value.filter((r) => Number(r.deliveryStatus) === 4); |
| | | if (shippedLedgers.length === selectedRows.value.length) { |
| | | try { |
| | | await ElMessageBox.alert("所选销售台账均已发货,不能再次发货。", "提示", { |
| | | type: "warning", |
| | | confirmButtonText: "知道了", |
| | | }); |
| | | } catch { |
| | | /* 关闭弹窗 */ |
| | | } |
| | | return; |
| | | } |
| | | if (shippedLedgers.length > 0) { |
| | | try { |
| | | await ElMessageBox.alert( |
| | | "选中的销售台账中包含已发货记录,已发货的不能再次发货,系统将仅为未发货台账处理。", |
| | | "提示", |
| | | { |
| | | type: "warning", |
| | | confirmButtonText: "知道了", |
| | | } |
| | | ); |
| | | } catch { |
| | | return; |
| | | } |
| | | } |
| | | |
| | | const customerNames = selectedRows.value.map((r) => String(r.customerName || "").trim()); |
| | |
| | | try { |
| | | const targets = []; |
| | | for (const ledger of selectedRows.value) { |
| | | |
| | | //如果已经是“审批中(2)”或“已发货(4)”,则跳过,不允许重复操作 |
| | | const status = Number(ledger.deliveryStatus); |
| | | if (status === 2 || status === 4) { |
| | | console.warn(`台账编号 ${ledger.salesContractNo} 状态为 ${status},跳过发货`); |
| | | continue; |
| | | } |
| | | |
| | | let products = []; |
| | | try { |
| | | const res = await productList({ salesLedgerId: ledger.id, type: 1 }); |
| | | products = res?.data || []; |
| | | } catch { |
| | | } catch (error) { |
| | | products = []; |
| | | console.error('请求发生异常', error); |
| | | } |
| | | |
| | | for (const product of products) { |
| | | if (!canShip(product)) continue; |
| | | targets.push({ |
| | |
| | | }); |
| | | } |
| | | } |
| | | |
| | | if (targets.length === 0) { |
| | | proxy.$modal.msgWarning("没有可发货的数据"); |
| | | return; |
| | |
| | | }); |
| | | } |
| | | |
| | | // 打开发货弹框 |
| | | // 打开发货弹框(单条) |
| | | const openDeliveryForm = (row) => { |
| | | // 检查是否可以发货 |
| | | if (!canShip(row)) { |
| | | proxy.$modal.msgWarning("只有在产品状态是充足,发货状态是待发货或审核拒绝的时候才可以发货"); |
| | | // 只允许【未发货/审批失败】发货;已发货/审批中不允许 |
| | | const status = Number(row.deliveryStatus); |
| | | if (status !== 1 && status !== 3) { |
| | | proxy.$modal.msgWarning("只有发货状态为未发货或审批失败的记录才可以发货"); |
| | | return; |
| | | } |
| | | |
| | | |
| | | currentDeliveryRows.value = [row]; |
| | | deliveryForm.value = { |
| | | type: "货车", |
| | |
| | | return; |
| | | } |
| | | |
| | | // 依次发货(避免并发下库存扣减/状态更新互相影响) |
| | | const run = async () => { |
| | | for (const item of targets) { |
| | | const salesLedgerId = item.salesLedgerId; |
| | | if (!salesLedgerId) continue; |
| | | await addShippingInfo({ |
| | | salesLedgerId, |
| | | salesLedgerProductId: item.id, |
| | | type: deliveryForm.value.type, |
| | | approveUserIds, |
| | | }); |
| | | } |
| | | }; |
| | | // 按台账维度去重,每个 salesLedgerId 只调用一次发货接口 |
| | | const uniqueLedgerIds = [...new Set(targets.map((item) => item.salesLedgerId).filter(Boolean))]; |
| | | |
| | | const run = async () => { |
| | | for (const salesLedgerId of uniqueLedgerIds) { |
| | | await addShippingInfo({ |
| | | salesLedgerId, |
| | | type: deliveryForm.value.type, |
| | | approveUserIds, |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | run() |
| | | .then(() => { |
| | |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | customerList().then((res) => { |
| | | customerOption.value = res; |
| | | }); |
| | | userListNoPage().then(res => { |
| | | userList.value = res.data; |
| | | }) |