| | |
| | | <div class="search_form"> |
| | | <el-form :inline="true" :model="searchForm" style="width: 100%"> |
| | | <el-row justify="space-between"> |
| | | <el-col :span="20"> |
| | | <el-form-item label="回款登记"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="客户名称"> |
| | | <el-input |
| | | v-model="searchForm.searchText" |
| | | style="width: 240px" |
| | | placeholder="输入客户名称/合同号搜索" |
| | | v-model="searchForm.customerName" |
| | | placeholder="请输入" |
| | | @change="handleQuery" |
| | | clearable |
| | | prefix-icon="Search" |
| | | @change="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | <el-button type="primary" @click="handleQuery"> 搜索 </el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item style="float: right; margin-right: unset"> |
| | | <el-button type="primary" @click="openForm('add')"> |
| | | 新增回款 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div class="actions"> |
| | | <div></div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')"> |
| | | 新增回款 |
| | | </el-button> |
| | | <el-button icon="Download" @click="handleOut"> 导出 </el-button> |
| | | </div> |
| | | </div> |
| | | <el-table |
| | | :data="tableData" |
| | | border |
| | |
| | | :summary-method="summarizeMainTable" |
| | | :expand-row-keys="expandedRowKeys" |
| | | @expand-change="expandChange" |
| | | height="calc(100vh - 18.5em)" |
| | | |
| | | height="calc(100vh - 21.5em)" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column type="expand"> |
| | |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="回款日期" prop="receiptPaymentDate" /> |
| | | <el-table-column label="回款日期" prop="receiptPaymentDate" width="130"/> |
| | | <el-table-column label="回款金额" prop="receiptPaymentAmount"> |
| | | <template #default="scope"> |
| | | <el-input |
| | | v-model="scope.row.receiptPaymentAmount" |
| | | :disabled="!scope.row.editType" |
| | | ></el-input> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | v-model="scope.row.receiptPaymentAmount" |
| | | :disabled="!scope.row.editType" |
| | | :precision="2" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="回款方式" prop="receiptPaymentType"> |
| | |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="登记人" prop="registrant" /> |
| | | <el-table-column label="登记日期" prop="createTime" /> |
| | | <el-table-column label="操作" width="150"> |
| | | <el-table-column label="登记人" prop="registrant" width="90"/> |
| | | <el-table-column label="登记日期" prop="createTime" width="130"/> |
| | | <el-table-column label="操作" width="150" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | |
| | | size="small" |
| | | @click="changeEditType(scope.row)" |
| | | v-if="!scope.row.editType" |
| | | :disabled="scope.row.registrant !== userStore.nickName" |
| | | >编辑</el-button |
| | | > |
| | | <el-button |
| | |
| | | size="small" |
| | | @click="saveReceiptPayment(scope.row)" |
| | | v-if="scope.row.editType" |
| | | :disabled="scope.row.registrant !== userStore.nickName" |
| | | >保存</el-button |
| | | > |
| | | <el-button |
| | |
| | | type="primary" |
| | | size="small" |
| | | @click="delReceiptRecord(scope.row)" |
| | | :disabled="scope.row.registrant !== userStore.nickName" |
| | | >删除</el-button |
| | | > |
| | | </template> |
| | |
| | | label="销售合同号" |
| | | prop="salesContractNo" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="客户合同号" |
| | | prop="customerContractNo" |
| | | show-overflow-tooltip |
| | | width="240" |
| | | /> |
| | | <el-table-column |
| | | label="客户名称" |
| | | prop="customerName" |
| | | show-overflow-tooltip |
| | | width="240" |
| | | /> |
| | | <el-table-column |
| | | label="项目名称" |
| | | prop="projectName" |
| | | show-overflow-tooltip |
| | | /> |
| | | label="回款状态" |
| | | prop="statusName" |
| | | width="120" |
| | | > |
| | | <template #default="{ row }"> |
| | | <el-tag :type="getStatusTagType(row.statusName)" disable-transitions> |
| | | {{ row.statusName || "--" }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="产品大类" |
| | | prop="productCategory" |
| | | show-overflow-tooltip |
| | | width="100" |
| | | /> |
| | | <el-table-column |
| | | label="发票号" |
| | | prop="invoiceNo" |
| | | show-overflow-tooltip |
| | | width="200" |
| | | /> |
| | | <el-table-column |
| | | label="发票金额(元)" |
| | | prop="invoiceTotal" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | | width="200" |
| | | /> |
| | | <el-table-column label="税率" prop="taxRate" show-overflow-tooltip /> |
| | | <el-table-column label="税率(%)" prop="taxRate" show-overflow-tooltip /> |
| | | <el-table-column |
| | | label="回款金额(元)" |
| | | prop="receiptPaymentAmountTotal" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | | width="200" |
| | | /> |
| | | <el-table-column |
| | | label="待回款金额(元)" |
| | | prop="noReceiptAmount" |
| | | show-overflow-tooltip |
| | | width="200" |
| | | > |
| | | <template #default="{ row, column }"> |
| | | <el-text type="danger"> |
| | |
| | | </div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="新增发票号页面" |
| | | width="70%" |
| | | title="新增回款页面" |
| | | width="90%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | <el-table |
| | | :data="dialogTableData" |
| | | border |
| | | style="width: 100%" |
| | | max-height="500px" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="销售合同号:" prop="salesContractNo"> |
| | | <el-input |
| | | v-model="form.salesContractNo" |
| | | placeholder="自动填充" |
| | | disabled |
| | | <el-table-column align="center" label="序号" type="index" width="60" /> |
| | | <el-table-column |
| | | label="销售合同号" |
| | | prop="salesContractNo" |
| | | show-overflow-tooltip |
| | | width="200" |
| | | /> |
| | | <el-table-column |
| | | label="客户名称" |
| | | prop="customerName" |
| | | show-overflow-tooltip |
| | | width="200" |
| | | /> |
| | | <el-table-column |
| | | label="产品大类" |
| | | prop="productCategory" |
| | | show-overflow-tooltip |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="规格型号" |
| | | prop="specification" |
| | | show-overflow-tooltip |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="发票号" |
| | | prop="invoiceNo" |
| | | show-overflow-tooltip |
| | | width="180" |
| | | /> |
| | | <el-table-column |
| | | label="发票金额(元)" |
| | | prop="invoiceTotal" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="税率(%)" |
| | | prop="taxRate" |
| | | show-overflow-tooltip |
| | | width="100" |
| | | /> |
| | | <el-table-column |
| | | label="待回款金额(元)" |
| | | prop="noReceiptAmount" |
| | | show-overflow-tooltip |
| | | width="150" |
| | | > |
| | | <template #default="{ row }"> |
| | | <el-text type="danger"> |
| | | {{ formattedNumber(row, null, row.noReceiptAmount) }} |
| | | </el-text> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="本次回款金额(元)" width="180"> |
| | | <template #default="scope"> |
| | | <el-input-number |
| | | :step="0.01" |
| | | :min="0" |
| | | :max="scope.row.noReceiptAmount" |
| | | style="width: 100%" |
| | | :precision="2" |
| | | v-model="scope.row.receiptPaymentAmount" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="回款方式" width="150"> |
| | | <template #default="scope"> |
| | | <el-select |
| | | v-model="scope.row.receiptPaymentType" |
| | | placeholder="请选择" |
| | | clearable |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in receipt_payment_type" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客户名称:" prop="customerName"> |
| | | <el-input |
| | | v-model="form.customerName" |
| | | placeholder="自动填充" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="发票号:" prop="invoiceNo"> |
| | | <el-input |
| | | v-model="form.invoiceNo" |
| | | placeholder="自动填充" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="发票金额(元):" prop="invoiceTotal"> |
| | | <el-input |
| | | type="number" |
| | | v-model="form.invoiceTotal" |
| | | placeholder="自动填充" |
| | | :step="0.01" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="税率:" prop="taxRate"> |
| | | <el-input |
| | | type="number" |
| | | v-model="form.taxRate" |
| | | placeholder="自动填充" |
| | | :step="0.01" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="本次回款金额:" prop="receiptPaymentAmount"> |
| | | <el-input |
| | | type="number" |
| | | min="0" |
| | | v-model="form.receiptPaymentAmount" |
| | | placeholder="请输入" |
| | | :step="0.01" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="回款形式:" prop="receiptPaymentType"> |
| | | <el-select |
| | | v-model="form.receiptPaymentType" |
| | | placeholder="请选择" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in receipt_payment_type" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="登记人:" prop="registrant"> |
| | | <el-input |
| | | v-model="form.registrant" |
| | | placeholder="请输入" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="来款日期:" prop="receiptPaymentDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.receiptPaymentDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="请选择" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="回款日期" width="180"> |
| | | <template #default="scope"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="scope.row.receiptPaymentDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="请选择" |
| | | clearable |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="登记人" width="120"> |
| | | <template #default="scope"> |
| | | <el-input |
| | | v-model="scope.row.registrant" |
| | | placeholder="自动填充" |
| | | disabled |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | |
| | | |
| | | <script setup> |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { ref } from "vue"; |
| | | import { onMounted, ref } from "vue"; |
| | | import { |
| | | receiptPaymentSaveOrUpdate, |
| | | bindInvoiceNoRegPage, |
| | | invoiceInfo, |
| | | receiptPaymentHistoryListNoPage, |
| | | receiptPaymentDel, |
| | | } from "../../../api/salesManagement/receiptPayment.js"; |
| | |
| | | |
| | | // 用户信息表单弹框数据 |
| | | const dialogFormVisible = ref(false); |
| | | const dialogTableData = ref([]); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | searchText: "", |
| | | status: false, |
| | | status: true, |
| | | customerName: "", |
| | | }, |
| | | form: { |
| | | salesContractNo: "", |
| | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | |
| | | const getStatusTagType = (statusName = '') => { |
| | | const normalized = statusName.trim(); |
| | | if (!normalized) return 'info'; |
| | | return normalized === '未完成回款' ? 'danger' : 'success'; |
| | | }; |
| | | // 查询列表 |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | expandedRowKeys.value = []; |
| | | tableLoading.value = true; |
| | | bindInvoiceNoRegPage({ ...searchForm, ...page }) |
| | | .then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | if (expandedRowKeys.value.length > 0) { |
| | | const arr = [] |
| | | const index = tableData.value.findIndex(item => item.id === expandedRowKeys.value[0]); |
| | | if (index > -1) { |
| | | arr.push(tableData.value[index]); |
| | | expandChange(tableData.value[index], arr) |
| | | } |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | |
| | | // 表格选择数据 |
| | | const handleSelectionChange = (selection) => { |
| | | console.log("selection", selection); |
| | | selectedRows.value = selection.filter( |
| | | (item) => item.customerContractNo !== null |
| | | ); |
| | | selectedRows.value = selection; |
| | | }; |
| | | // 主表合计方法 |
| | | const summarizeMainTable = (param) => { |
| | |
| | | }; |
| | | // 打开弹框 |
| | | const openForm = () => { |
| | | form.value = {}; |
| | | if (selectedRows.value.length !== 1) { |
| | | proxy.$modal.msgError("请选择一条数据"); |
| | | // 至少选择一条数据 |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgError("请选择数据"); |
| | | return; |
| | | } |
| | | // |
| | | console.log("(selectedRows.value", selectedRows.value); |
| | | if (selectedRows.value[0].noReceiptAmount === 0) { |
| | | proxy.$modal.msgError("待回款金额为0元"); |
| | | |
| | | // 校验是否为相同销售合同号 |
| | | const firstContractNo = selectedRows.value[0].salesContractNo; |
| | | const isSameContract = selectedRows.value.every( |
| | | (item) => item.salesContractNo === firstContractNo |
| | | ); |
| | | if (!isSameContract) { |
| | | proxy.$modal.msgError("请选择相同销售合同号的数据进行回款"); |
| | | return; |
| | | } |
| | | invoiceInfo({ id: selectedRows.value[0].id }).then((res) => { |
| | | form.value = { ...res.data }; |
| | | form.value.invoiceLedgerId = form.value.id; |
| | | form.value.id = ""; |
| | | form.value.registrant = userStore.nickName; |
| | | |
| | | // 过滤出有待回款金额的记录 |
| | | const validRows = selectedRows.value.filter( |
| | | (item) => Number(item.noReceiptAmount) > 0 |
| | | ); |
| | | if (validRows.length === 0) { |
| | | proxy.$modal.msgWarning("所选数据均无需再回款"); |
| | | return; |
| | | } |
| | | |
| | | // 直接使用外部表格数据,为每条记录添加回款相关字段 |
| | | dialogTableData.value = validRows.map((row) => { |
| | | return { |
| | | ...row, |
| | | invoiceLedgerId: row.id, |
| | | receiptPaymentAmount: row.noReceiptAmount || "", |
| | | receiptPaymentType: "", |
| | | receiptPaymentDate: "", |
| | | registrant: userStore.nickName, |
| | | }; |
| | | }); |
| | | |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | // 提交表单 |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate((valid) => { |
| | | if (valid) { |
| | | receiptPaymentSaveOrUpdate(form.value).then((res) => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | // 校验表格数据 |
| | | const invalidRows = dialogTableData.value.filter((row) => { |
| | | return ( |
| | | !row.receiptPaymentAmount || |
| | | row.receiptPaymentAmount <= 0 || |
| | | !row.receiptPaymentType || |
| | | !row.receiptPaymentDate |
| | | ); |
| | | }); |
| | | |
| | | if (invalidRows.length > 0) { |
| | | proxy.$modal.msgError("请完善所有必填项:回款金额、回款方式、回款日期"); |
| | | return; |
| | | } |
| | | |
| | | // 校验回款金额不能超过待回款金额 |
| | | const exceedRows = dialogTableData.value.filter((row) => { |
| | | return Number(row.receiptPaymentAmount) > Number(row.noReceiptAmount); |
| | | }); |
| | | |
| | | if (exceedRows.length > 0) { |
| | | proxy.$modal.msgError("回款金额不能超过待回款金额"); |
| | | return; |
| | | } |
| | | |
| | | // 组合成数组批量提交 |
| | | const submitDataList = dialogTableData.value.map((row) => { |
| | | return { |
| | | invoiceLedgerId: row.invoiceLedgerId, |
| | | receiptPaymentAmount: row.receiptPaymentAmount, |
| | | receiptPaymentType: row.receiptPaymentType, |
| | | receiptPaymentDate: row.receiptPaymentDate, |
| | | registrant: row.registrant, |
| | | }; |
| | | }); |
| | | |
| | | receiptPaymentSaveOrUpdate(submitDataList) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | getList(); |
| | | }) |
| | | .catch((error) => { |
| | | console.error("提交失败:", error); |
| | | proxy.$modal.msgError("提交失败,请重试"); |
| | | }); |
| | | }; |
| | | // 关闭弹框 |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogTableData.value = []; |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | |
| | |
| | | receiptPaymentType: row.receiptPaymentType, |
| | | receiptPaymentAmount: row.receiptPaymentAmount, |
| | | }; |
| | | receiptPaymentSaveOrUpdate(updateData).then((res) => { |
| | | // 子表编辑保存也按数组提交(与批量新增保持一致) |
| | | receiptPaymentSaveOrUpdate([updateData]).then((res) => { |
| | | row.editType = !row.editType; |
| | | getList(); |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | }); |
| | | }; |
| | | |
| | | getList(); |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | const ids = selectedRows.value.map((item) => item.id); |
| | | proxy.download( |
| | | `/receiptPayment/export`, |
| | | { ids: `${ids}` }, |
| | | "回款登记档案.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | ::v-deep(.el-checkbox__label) { |
| | | font-weight: bold; |
| | | } |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |