From c2bbeb7cdc685bee3f83d5be52078585d843ce2b Mon Sep 17 00:00:00 2001 From: jiangpeng Date: Fri, 24 Apr 2026 15:38:14 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E4=BB=98=E6=AC=BE=E5=8D=95?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E6=B7=BB=E5=8A=A0=E5=AF=BC=E5=87=BAPDF?= =?UTF-8?q?=E5=92=8C=E6=89=93=E5=8D=B0=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BB=98?= =?UTF-8?q?=E6=AC=BE=E5=8D=95=E5=88=97=E8=A1=A8=E5=AF=BC=E5=87=BA=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=BA=94=E4=BB=98=E5=8D=95=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../payment/components/DetailDrawer.vue | 128 ++++++++++++++- .../controller/OmsPaymentBillController.java | 31 ++-- .../sip/service/IOmsPaymentBillService.java | 2 + .../impl/OmsPaymentBillServiceImpl.java | 148 ++++++++++++++++++ 4 files changed, 288 insertions(+), 21 deletions(-) diff --git a/oms_web/oms_vue/src/views/finance/payment/components/DetailDrawer.vue b/oms_web/oms_vue/src/views/finance/payment/components/DetailDrawer.vue index b9bae330..f4a33544 100644 --- a/oms_web/oms_vue/src/views/finance/payment/components/DetailDrawer.vue +++ b/oms_web/oms_vue/src/views/finance/payment/components/DetailDrawer.vue @@ -12,6 +12,11 @@
采购-付款单 +
+ 导出PDF + 打印 +
+
@@ -94,6 +99,8 @@
特别说明: {{ detail.remark }}
+
+
附件: @@ -101,7 +108,7 @@
- +
附件补充: @@ -112,7 +119,6 @@
-
采购-应付单 @@ -143,6 +149,8 @@ 流转意见
+
+
@@ -153,6 +161,7 @@ import FileUpload from "@/components/FileUpload"; import EditForm from "@/views/finance/payable/components/EditForm.vue"; import FlowOpinionTimeline from "@/views/finance/components/FlowOpinionTimeline.vue"; import { listCompletedFlows } from "@/api/flow"; +import { exportElementToPDF } from "@/views/approve/finance/pdfUtils"; export default { name: "DetailDrawer", @@ -180,6 +189,7 @@ export default { approveLogs: [], approveLogsTimer: null, approveLogsLoading: false, + pdfExporting: false, }; }, beforeDestroy() { @@ -276,6 +286,114 @@ export default { this.approveLogsLoading = false; }); }, + async handleExportPDF() { + if (!this.$refs.pdfExportArea) { + this.$modal.msgWarning("未找到可导出的内容"); + return; + } + this.pdfExporting = true; + let exportWrapper = null; + try { + await this.$nextTick(); + const sourceEl = this.$refs.pdfExportArea; + const sourceWidth = Math.ceil(sourceEl.getBoundingClientRect().width) || 1000; + + // 在屏幕外克隆导出区域,避免抽屉滚动容器导致底部内容被裁剪 + exportWrapper = document.createElement("div"); + exportWrapper.style.position = "fixed"; + exportWrapper.style.left = "-10000px"; + exportWrapper.style.top = "0"; + exportWrapper.style.width = `${sourceWidth}px`; + exportWrapper.style.background = "#F8F5F0"; + exportWrapper.style.overflow = "visible"; + exportWrapper.style.zIndex = "-1"; + exportWrapper.innerHTML = sourceEl.outerHTML; + document.body.appendChild(exportWrapper); + + await new Promise(resolve => setTimeout(resolve, 60)); + const exportTarget = exportWrapper.firstElementChild || exportWrapper; + exportTarget.querySelectorAll(".export-exclude").forEach(node => node.remove()); + const fileName = `付款单详情-${this.detail && this.detail.paymentBillCode ? this.detail.paymentBillCode : ""}.pdf`; + await exportElementToPDF(exportTarget, fileName); + this.$modal.msgSuccess("PDF导出成功"); + } catch (error) { + console.error("PDF导出失败:", error); + this.$modal.msgError("PDF导出失败,请稍后重试"); + } finally { + if (exportWrapper && exportWrapper.parentNode) { + exportWrapper.parentNode.removeChild(exportWrapper); + } + this.pdfExporting = false; + } + }, + handlePrint() { + const exportArea = this.$refs.pdfExportArea; + if (!exportArea) { + this.$modal.msgWarning("未找到可打印的内容"); + return; + } + + const printWindow = window.open("", "_blank"); + if (!printWindow) { + this.$modal.msgError("打印窗口被拦截,请允许弹窗后重试"); + return; + } + + const styleContent = Array.from(document.querySelectorAll("style, link[rel='stylesheet']")) + .map(node => node.outerHTML) + .join(""); + + const html = ` + + + + + 付款单详情打印 + ${styleContent} + + + + + + + `; + + printWindow.document.open(); + printWindow.document.write(html); + printWindow.document.close(); + printWindow.focus(); + printWindow.onload = () => { + printWindow.print(); + printWindow.close(); + }; + } }, }; @@ -307,6 +425,12 @@ export default { margin-bottom: 20px; } +.section-actions { + display: flex; + justify-content: flex-end; + margin-bottom: 10px; +} + .red-text{ color: red; } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/OmsPaymentBillController.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/OmsPaymentBillController.java index 1acec693..6265418a 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/OmsPaymentBillController.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/OmsPaymentBillController.java @@ -1,29 +1,27 @@ package com.ruoyi.sip.controller; -import java.lang.reflect.Array; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - +import com.ruoyi.common.annotation.Log; import com.ruoyi.common.config.flow.ProcessConfig; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.sip.domain.OmsFinAttachment; +import com.ruoyi.sip.domain.OmsPaymentBill; import com.ruoyi.sip.flowable.service.TodoService; import com.ruoyi.sip.service.IOmsFinAttachmentService; +import com.ruoyi.sip.service.IOmsPaymentBillService; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.*; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.sip.domain.OmsPaymentBill; -import com.ruoyi.sip.service.IOmsPaymentBillService; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; import org.springframework.web.multipart.MultipartFile; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + /** * 采购付款单Controller * @@ -113,12 +111,7 @@ public class OmsPaymentBillController extends BaseController @ResponseBody public AjaxResult export(OmsPaymentBill omsPaymentBill) { - List list = omsPaymentBillService.selectOmsPaymentBillList(omsPaymentBill); - ExcelUtil util = new ExcelUtil(OmsPaymentBill.class); - todoService.fillApproveNode(list, - Arrays.asList(processConfig.getDefinition().getFinancePayment(), processConfig.getDefinition().getFinanceRefund()) - , OmsPaymentBill::getPaymentBillCode, (a, b) -> a.setApproveNode(b.get(a.getPaymentBillCode()))); - return util.exportExcel(list, "采购付款单数据"); + return omsPaymentBillService.exportExcelWithPayableDetails(omsPaymentBill); } /** diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IOmsPaymentBillService.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IOmsPaymentBillService.java index c759e29a..031cf8a0 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IOmsPaymentBillService.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IOmsPaymentBillService.java @@ -66,6 +66,8 @@ public interface IOmsPaymentBillService */ public int deleteOmsPaymentBillById(Long id); + AjaxResult exportExcelWithPayableDetails(OmsPaymentBill omsPaymentBill); + PaymentBillDetailDTO query(Long id); AjaxResult returnPaymentBill(Long id); diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/OmsPaymentBillServiceImpl.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/OmsPaymentBillServiceImpl.java index c171dff9..1c01915b 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/OmsPaymentBillServiceImpl.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/OmsPaymentBillServiceImpl.java @@ -1,5 +1,6 @@ package com.ruoyi.sip.service.impl; +import com.alibaba.excel.EasyExcel; import java.math.BigDecimal; import java.util.*; import java.util.function.Function; @@ -17,9 +18,11 @@ import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.enums.ApproveStatusEnum; import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.DictUtils; import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.mail.TemplateMailUtil; +import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.sip.domain.*; import com.ruoyi.sip.domain.dto.PaymentBillDetailDTO; import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO; @@ -29,6 +32,7 @@ import com.ruoyi.sip.flowable.domain.Todo; import com.ruoyi.sip.flowable.service.TodoCommonTemplate; import com.ruoyi.sip.flowable.service.TodoService; import com.ruoyi.sip.service.*; +import lombok.extern.slf4j.Slf4j; import org.flowable.engine.ManagementService; import org.flowable.engine.runtime.ProcessInstance; import org.springframework.beans.factory.annotation.Autowired; @@ -45,6 +49,7 @@ import org.springframework.web.multipart.MultipartFile; * @author ruoyi * @date 2025-10-22 */ +@Slf4j @Service @Transactional(rollbackFor = Exception.class) public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoCommonTemplate @@ -108,6 +113,149 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC return omsPaymentBillMapper.selectOmsPaymentBillList(omsPaymentBill); } + @Override + public AjaxResult exportExcelWithPayableDetails(OmsPaymentBill omsPaymentBill) { + List list = omsPaymentBillMapper.selectOmsPaymentBillList(omsPaymentBill); + todoService.fillApproveNode(list, + Arrays.asList(processConfig.getDefinition().getFinancePayment(), processConfig.getDefinition().getFinanceRefund()) + , OmsPaymentBill::getPaymentBillCode, (a, b) -> a.setApproveNode(b.get(a.getPaymentBillCode()))); + + List> payableDetailsGroup = new ArrayList<>(); + int maxPayableCount = 0; + for (OmsPaymentBill bill : list) { + List payableDetails = Collections.emptyList(); + if (bill.getId() != null) { + PaymentBillDetailDTO detailDTO = this.query(bill.getId()); + if (detailDTO != null && detailDTO.getPayableDetails() != null) { + payableDetails = detailDTO.getPayableDetails(); + } + } + payableDetailsGroup.add(payableDetails); + maxPayableCount = Math.max(maxPayableCount, payableDetails.size()); + } + + List> header = buildExportHeader(maxPayableCount); + List> data = buildExportData(list, payableDetailsGroup, maxPayableCount); + + try { + ExcelUtil util = new ExcelUtil<>(OmsPaymentBill.class); + String fileName = util.encodingFilename("采购付款单数据"); + String filePath = util.getAbsoluteFile(fileName); + EasyExcel.write(filePath).head(header).sheet("采购付款单数据").doWrite(data); + return AjaxResult.success(fileName); + } catch (Exception e) { + log.error("导出采购付款单失败", e); + return AjaxResult.error("导出采购付款单失败:" + e.getMessage()); + } + } + + private List> buildExportHeader(int maxPayableCount) { + List> header = new ArrayList<>(); + Collections.addAll(header, + Collections.singletonList("项目编号"), + Collections.singletonList("项目名称"), + Collections.singletonList("付款单编号"), + Collections.singletonList("备注"), + Collections.singletonList("预计付款时间"), + Collections.singletonList("制造商名称"), + Collections.singletonList("合同编号"), + Collections.singletonList("含税总价"), + Collections.singletonList("未税总价"), + Collections.singletonList("税额"), + Collections.singletonList("实际付款时间"), + Collections.singletonList("付款状态"), + Collections.singletonList("审批状态"), + Collections.singletonList("审批节点"), + Collections.singletonList("审批时间"), + Collections.singletonList("支付方式"), + Collections.singletonList("应付单编号"), + Collections.singletonList("账户名称"), + Collections.singletonList("银行账号"), + Collections.singletonList("银行开户行"), + Collections.singletonList("银行行号") + ); + for (int i = 1; i <= maxPayableCount; i++) { + header.add(Collections.singletonList("应付单" + i + "-项目编号")); + header.add(Collections.singletonList("应付单" + i + "-项目名称")); + header.add(Collections.singletonList("应付单" + i + "-采购应付单编号")); + header.add(Collections.singletonList("应付单" + i + "-含税总价")); + header.add(Collections.singletonList("应付单" + i + "-本次付款金额")); + header.add(Collections.singletonList("应付单" + i + "-本次付款比例")); + } + return header; + } + + private List> buildExportData(List list, + List> payableDetailsGroup, + int maxPayableCount) { + List> data = new ArrayList<>(); + for (int i = 0; i < list.size(); i++) { + OmsPaymentBill bill = list.get(i); + List payableDetails = payableDetailsGroup.get(i); + List row = new ArrayList<>(); + Collections.addAll(row, + bill.getProjectCode(), + bill.getProjectName(), + bill.getPaymentBillCode(), + resolvePaymentBillTypeDesc(bill.getPaymentBillType()), + formatDateTime(bill.getPaymentTime()), + bill.getVendorName(), + bill.getOrderCode(), + bill.getTotalPriceWithTax(), + bill.getTotalPriceWithoutTax(), + bill.getTaxAmount(), + formatDateTime(bill.getActualPaymentTime()), + DictUtils.getDictLabel("payment_status", bill.getPaymentStatus()), + DictUtils.getDictLabel("approve_status", bill.getApproveStatus()), + bill.getApproveNode(), + formatDateTime(bill.getApproveTime()), + DictUtils.getDictLabel("payment_method", bill.getPaymentMethod()), + bill.getPayableBillCode(), + bill.getPayName(), + bill.getPayBankNumber(), + bill.getPayBankOpenAddress(), + bill.getBankNumber() + ); + for (int index = 0; index < maxPayableCount; index++) { + if (index < payableDetails.size()) { + PaymentBillPayableDetailDTO detail = payableDetails.get(index); + row.add(detail.getProjectCode()); + row.add(detail.getProjectName()); + row.add(detail.getPayableBillCode()); + row.add(detail.getTotalPriceWithTax()); + row.add(detail.getPaymentAmount()); + row.add(detail.getPaymentRate()); + } else { + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + } + } + data.add(row); + } + return data; + } + + private String formatDateTime(Date date) { + return date == null ? "" : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", date); + } + + private String resolvePaymentBillTypeDesc(String paymentBillType) { + if (OmsPaymentBill.PaymentBillTypeEnum.FROM_PAYABLE.getCode().equals(paymentBillType)) { + return OmsPaymentBill.PaymentBillTypeEnum.FROM_PAYABLE.getDesc(); + } + if (OmsPaymentBill.PaymentBillTypeEnum.PRE_PAYMENT.getCode().equals(paymentBillType)) { + return OmsPaymentBill.PaymentBillTypeEnum.PRE_PAYMENT.getDesc(); + } + if (OmsPaymentBill.PaymentBillTypeEnum.REFUND.getCode().equals(paymentBillType)) { + return OmsPaymentBill.PaymentBillTypeEnum.REFUND.getDesc(); + } + return paymentBillType; + } + /** * 新增采购付款单 *