ba7a66196ed069743f328a0bdb03b133813353ad..7f5afc54ecc8a744a332531b6cb77e597ffe4b93
2026-03-27 wujianwei
新增推送
7f5afc 对比 | 目录
2026-03-27 wujianwei
Merge remote-tracking branch 'origin/cwxt_master' into cwxt_master
e7f058 对比 | 目录
2026-03-27 wujianwei
新增推送
279366 对比 | 目录
2026-03-25 sen
修改账款分析表格
7b0839 对比 | 目录
3个文件已添加
8个文件已修改
1160 ■■■■■ 已修改文件
api/src/main/java/com/ruoyi/api/third/controller/ReceivableBillApiController.java 550 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/src/main/java/com/ruoyi/cwgl/domain/dto/PayableBillApiDto.java 221 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/src/main/java/com/ruoyi/cwgl/domain/dto/ReceivableBillApiDto.java 245 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/src/main/resources/mapper/cwgl/PayableFeeManagementMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/src/main/resources/mapper/cwgl/ReceivableFeeManagementMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ui/admin-ui3/src/api/cwgl/analysisManagement.ts 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ui/admin-ui3/src/layout/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ui/admin-ui3/src/main.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ui/admin-ui3/src/views/cwgl/accountAnalysisDetail/index.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ui/admin-ui3/src/views/cwgl/ageAnalysis/index.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ui/admin-ui3/src/views/cwgl/analysisManagement/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/src/main/java/com/ruoyi/api/third/controller/ReceivableBillApiController.java
New file
@@ -0,0 +1,550 @@
package com.ruoyi.api.third.controller;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.cwgl.domain.PayableBillManagement;
import com.ruoyi.cwgl.domain.PayableFeeDetail;
import com.ruoyi.cwgl.domain.PayableFeeManagement;
import com.ruoyi.cwgl.domain.ReceivableBillManagement;
import com.ruoyi.cwgl.domain.ReceivableFeeDetail;
import com.ruoyi.cwgl.domain.ReceivableFeeManagement;
import com.ruoyi.cwgl.domain.dto.PayableBillApiDto;
import com.ruoyi.cwgl.domain.dto.ReceivableBillApiDto;
import com.ruoyi.cwgl.service.IPayableBillManagementService;
import com.ruoyi.cwgl.service.IPayableFeeDetailService;
import com.ruoyi.cwgl.service.IPayableFeeManagementService;
import com.ruoyi.cwgl.service.IReceivableBillManagementService;
import com.ruoyi.cwgl.service.IReceivableFeeDetailService;
import com.ruoyi.cwgl.service.IReceivableFeeManagementService;
import com.ruoyi.system.service.ISystemDataNoService;
import com.ruoyi.common.enums.SystemDataNoEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;
/**
 * 应收账单API接口
 * @author wjw
 */
@RestController
@RequestMapping("/api/third/receivable")
public class ReceivableBillApiController {
    private static Logger logger = LoggerFactory.getLogger(ReceivableBillApiController.class);
    @Autowired
    private IReceivableBillManagementService receivableBillManagementService;
    @Autowired
    private IReceivableFeeManagementService receivableFeeManagementService;
    @Autowired
    private IReceivableFeeDetailService receivableFeeDetailService;
    @Autowired
    private IPayableBillManagementService payableBillManagementService;
    @Autowired
    private IPayableFeeManagementService payableFeeManagementService;
    @Autowired
    private IPayableFeeDetailService payableFeeDetailService;
    @Autowired
    private ISystemDataNoService systemDataNoService;
    /**
     * 添加应收账单接口
     * 其他系统调用此接口添加应收账单、应收账单明细、应收账单费用
     * @param receivableBillApiDto 应收账单API数据传输对象
     * @return 操作结果
     */
    @PostMapping("/addBill")
    public Map<String, String> addReceivableBill(@Valid @RequestBody ReceivableBillApiDto receivableBillApiDto) {
        logger.info("接收应收账单添加请求:{}", receivableBillApiDto);
        Map<String, String> result = new HashMap<>();
        try {
            // 1. 验证数据
//            validateReceivableBillData(receivableBillApiDto);
            // 2. 保存应收账单管理信息
            ReceivableBillManagement billManagement = saveReceivableBillManagement(receivableBillApiDto.getBill());
            // 3. 保存应收费用管理信息和明细
            saveReceivableFeeManagementAndDetails(receivableBillApiDto.getFees(), billManagement.getSystemNo());
            result.put("status", "0000");
            result.put("message", "应收账单添加成功");
            result.put("billNo", billManagement.getSystemNo());
            logger.info("应收账单添加成功,账单编号:{}", billManagement.getSystemNo());
        } catch (Exception e) {
            logger.error("应收账单添加失败:", e);
            result.put("status", "9999");
            result.put("message", "应收账单添加失败:" + e.getMessage());
        }
        return result;
    }
    /**
     * 验证应收账单数据
     */
    private void validateReceivableBillData(ReceivableBillApiDto receivableBillApiDto) {
        if (receivableBillApiDto == null) {
            throw new IllegalArgumentException("请求数据不能为空");
        }
        if (receivableBillApiDto.getBill() == null) {
            throw new IllegalArgumentException("应收账单信息不能为空");
        }
        if (receivableBillApiDto.getFees() == null || receivableBillApiDto.getFees().isEmpty()) {
            throw new IllegalArgumentException("应收费用信息不能为空");
        }
        // 验证总金额与费用明细金额是否匹配
        BigDecimal totalAmount = receivableBillApiDto.getBill().getTotalAmount();
        BigDecimal feeTotalAmount = BigDecimal.ZERO;
        for (ReceivableBillApiDto.ReceivableFeeDto fee : receivableBillApiDto.getFees()) {
            feeTotalAmount = feeTotalAmount.add(fee.getReceivableAmount());
            // 验证费用明细
            if (fee.getFeeDetails() != null) {
                BigDecimal detailTotalAmount = BigDecimal.ZERO;
                for (ReceivableBillApiDto.ReceivableFeeDetailDto detail : fee.getFeeDetails()) {
                    detailTotalAmount = detailTotalAmount.add(detail.getBillingAmount());
                }
                if (fee.getReceivableAmount().compareTo(detailTotalAmount) != 0) {
                    throw new IllegalArgumentException("费用金额与明细金额不匹配,费用金额:" + fee.getReceivableAmount() +
                            ",明细金额:" + detailTotalAmount);
                }
            }
        }
        if (totalAmount.compareTo(feeTotalAmount) != 0) {
            throw new IllegalArgumentException("账单总金额与费用总金额不匹配,账单金额:" + totalAmount +
                    ",费用金额:" + feeTotalAmount);
        }
    }
    /**
     * 保存应收账单管理信息
     */
    private ReceivableBillManagement saveReceivableBillManagement(ReceivableBillApiDto.ReceivableBillDto billDto) {
        ReceivableBillManagement billManagement = new ReceivableBillManagement();
        // 生成系统编号
        String systemNo = systemDataNoService.getNoByKey(SystemDataNoEnum.YSZD);
        // 设置基本信息
        billManagement.setSystemNo(systemNo);
        billManagement.setBillName(billDto.getBillName());
        billManagement.setCustomerName(billDto.getCustomerName());
        billManagement.setPayee(billDto.getPayee());
        billManagement.setResponsiblePerson(billDto.getResponsiblePerson());
        billManagement.setResponsibleLeader(billDto.getResponsibleLeader());
        billManagement.setSettlementMethod(billDto.getSettlementMethod());
        billManagement.setBusinessType(billDto.getBusinessType());
        billManagement.setPromotionRequirement(billDto.getPromotionRequirement());
        billManagement.setIsInternalSettlement(billDto.getIsInternalSettlement());
        billManagement.setInternalSettlementUnit(billDto.getInternalSettlementUnit());
        // 设置金额信息
        billManagement.setDocumentCount(billDto.getDocumentCount());
        billManagement.setTotalAmount(billDto.getTotalAmount());
        billManagement.setCurrency(billDto.getCurrency());
        billManagement.setDiscountAmount(billDto.getDiscountAmount());
        billManagement.setReceivedAmount(billDto.getReceivedAmount() != null ? billDto.getReceivedAmount() : BigDecimal.ZERO);
        billManagement.setPendingAmount(billDto.getPendingAmount() != null ? billDto.getPendingAmount() : billDto.getTotalAmount());
        billManagement.setExchangeRate(billDto.getExchangeRate());
        billManagement.setCnyAmount(billDto.getCnyAmount());
        // 设置日期信息
        billManagement.setPeriodType(billDto.getPeriodType());
        billManagement.setBusinessStartDate(billDto.getBusinessStartDate());
        billManagement.setBusinessEndDate(billDto.getBusinessEndDate());
        billManagement.setBillingStartDate(billDto.getBillingStartDate());
        billManagement.setBillingEndDate(billDto.getBillingEndDate());
        billManagement.setBillGenerateDate(billDto.getBillGenerateDate());
        billManagement.setBillSendDate(billDto.getBillSendDate());
        billManagement.setBillDueDate(billDto.getBillDueDate());
        // 设置其他信息
        billManagement.setSettlementCategory(billDto.getSettlementCategory());
        billManagement.setSettlementPeriod(billDto.getSettlementPeriod());
        billManagement.setStatus(billDto.getStatus() != null ? billDto.getStatus() : "draft");
        billManagement.setRemark(billDto.getRemark());
        billManagement.setCreateTime(DateUtils.getNowDate());
        billManagement.setCreateBy("api_system");
        // 保存账单管理信息
        int rows = receivableBillManagementService.insertReceivableBillManagement(billManagement);
        if (rows <= 0) {
            throw new RuntimeException("保存应收账单管理信息失败");
        }
        return billManagement;
    }
    /**
     * 保存应收费用管理信息和明细
     */
    private void saveReceivableFeeManagementAndDetails(List<ReceivableBillApiDto.ReceivableFeeDto> fees, String billSystemNo) {
        List<ReceivableFeeManagement> feeManagementList = new ArrayList<>();
        List<ReceivableFeeDetail> feeDetailList = new ArrayList<>();
        for (ReceivableBillApiDto.ReceivableFeeDto feeDto : fees) {
            // 生成费用管理记录
            ReceivableFeeManagement feeManagement = new ReceivableFeeManagement();
            // 生成系统编号
            String feeSystemNo = systemDataNoService.getNoByKey(SystemDataNoEnum.YS);
            // 设置费用管理信息
            feeManagement.setSystemNo(feeSystemNo);
            feeManagement.setSerialNumber(feeDto.getSerialNumber());
            feeManagement.setRelatedBillNo(billSystemNo);
            feeManagement.setSourceSystem(feeDto.getSourceSystem());
            feeManagement.setBusinessSector(feeDto.getBusinessSector());
            feeManagement.setDocumentType(feeDto.getDocumentType());
            feeManagement.setDocumentNo(feeDto.getDocumentNo());
            feeManagement.setIsInternalSettlement(feeDto.getIsInternalSettlement());
            feeManagement.setInternalSettlementUnit(feeDto.getInternalSettlementUnit());
            feeManagement.setCustomerName(feeDto.getCustomerName());
            feeManagement.setProjectName(feeDto.getProjectName());
            feeManagement.setBusinessTime(feeDto.getBusinessTime());
            feeManagement.setReceivableConfirmTime(feeDto.getReceivableConfirmTime());
            feeManagement.setReceivableAmount(feeDto.getReceivableAmount());
            feeManagement.setReceivableAmountStr(feeDto.getReceivableAmountStr());
            feeManagement.setStatus(feeDto.getStatus() != null ? feeDto.getStatus() : "confirmed");
            feeManagement.setRemark(feeDto.getRemark());
            feeManagement.setCreateTime(DateUtils.getNowDate());
            feeManagement.setCreateBy("api_system");
            feeManagementList.add(feeManagement);
            // 保存费用明细
            if (feeDto.getFeeDetails() != null && !feeDto.getFeeDetails().isEmpty()) {
                for (ReceivableBillApiDto.ReceivableFeeDetailDto detailDto : feeDto.getFeeDetails()) {
                    ReceivableFeeDetail feeDetail = new ReceivableFeeDetail();
                    feeDetail.setSerialNumber(detailDto.getSerialNumber());
                    feeDetail.setFeeType(detailDto.getFeeType());
                    feeDetail.setFeeName(detailDto.getFeeName());
                    feeDetail.setBillingUnit(detailDto.getBillingUnit());
                    feeDetail.setUnitPrice(detailDto.getUnitPrice());
                    feeDetail.setBillingQuantity(detailDto.getBillingQuantity());
                    feeDetail.setBillingAmount(detailDto.getBillingAmount());
                    feeDetail.setActualAmount(detailDto.getActualAmount() != null ? detailDto.getActualAmount() : BigDecimal.ZERO);
                    feeDetail.setCurrency(detailDto.getCurrency());
                    feeDetail.setFeeRegTime(detailDto.getFeeRegTime());
                    feeDetail.setRemark(detailDto.getRemark());
                    feeDetail.setCreateTime(DateUtils.getNowDate());
                    feeDetail.setCreateBy("api_system");
                    // 注意:这里需要先保存feeManagement获取ID,然后再设置关联关系
                    // 由于是批量保存,这里先收集,后续再处理关联关系
                    feeDetailList.add(feeDetail);
                }
            }
        }
        // 批量保存费用管理信息
        int feeRows = receivableFeeManagementService.insertReceivableFeeManagementBatch(feeManagementList);
        if (feeRows <= 0) {
            throw new RuntimeException("保存应收费用管理信息失败");
        }
        // 处理费用明细的关联关系并保存
        if (!feeDetailList.isEmpty()) {
            // 使用Map存储系统编号和ID的映射关系
            Map<String, Integer> systemNoToIdMap = new HashMap<>();
            for (ReceivableFeeManagement feeManagement : feeManagementList) {
                    // 假设插入后可以通过某种方式获取ID,这里简化处理
                    // 实际项目中可能需要根据业务逻辑获取ID
                    systemNoToIdMap.put(feeManagement.getSystemNo(), feeManagement.getId());
            }
            // 设置费用明细的关联ID
            List<ReceivableFeeDetail> finalFeeDetailList = new ArrayList<>();
            for (int i = 0; i < feeManagementList.size(); i++) {
                ReceivableFeeManagement feeManagement = feeManagementList.get(i);
                Integer feeId = systemNoToIdMap.get(feeManagement.getSystemNo());
                if (feeId != null && i < feeDetailList.size()) {
                    ReceivableFeeDetail feeDetail = feeDetailList.get(i);
                    feeDetail.setReceivableFeeId(feeId);
                    finalFeeDetailList.add(feeDetail);
                }
            }
            // 批量保存费用明细
            int detailRows = receivableFeeDetailService.insertReceivableFeeDetailBatch(finalFeeDetailList);
            if (detailRows <= 0) {
                throw new RuntimeException("保存应收费用明细信息失败");
            }
        }
    }
    /**
     * 添加应付账单接口
     * 其他系统调用此接口添加应付账单、应付账单明细、应付账单费用
     * @param payableBillApiDto 应付账单API数据传输对象
     * @return 操作结果
     */
    @PostMapping("/addPayableBill")
    public Map<String, String> addPayableBill(@Valid @RequestBody PayableBillApiDto payableBillApiDto) {
        logger.info("接收应付账单添加请求:{}", payableBillApiDto);
        Map<String, String> result = new HashMap<>();
        try {
            // 1. 验证数据
//            validatePayableBillData(payableBillApiDto);
            // 2. 保存应付账单管理信息
            PayableBillManagement billManagement = savePayableBillManagement(payableBillApiDto.getBill());
            // 3. 保存应付费用管理信息和明细
            savePayableFeeManagementAndDetails(payableBillApiDto.getFees(), billManagement.getSystemNo());
            result.put("status", "0000");
            result.put("message", "应付账单添加成功");
            result.put("billNo", billManagement.getSystemNo());
            logger.info("应付账单添加成功,账单编号:{}", billManagement.getSystemNo());
        } catch (Exception e) {
            logger.error("应付账单添加失败:", e);
            result.put("status", "9999");
            result.put("message", "应付账单添加失败:" + e.getMessage());
        }
        return result;
    }
    /**
     * 验证应付账单数据
     */
    private void validatePayableBillData(PayableBillApiDto payableBillApiDto) {
        if (payableBillApiDto == null) {
            throw new IllegalArgumentException("请求数据不能为空");
        }
        if (payableBillApiDto.getBill() == null) {
            throw new IllegalArgumentException("应付账单信息不能为空");
        }
        if (payableBillApiDto.getFees() == null || payableBillApiDto.getFees().isEmpty()) {
            throw new IllegalArgumentException("应付费用信息不能为空");
        }
        // 验证总金额与费用明细金额是否匹配
        BigDecimal totalAmount = payableBillApiDto.getBill().getTotalAmount();
        BigDecimal feeTotalAmount = BigDecimal.ZERO;
        for (PayableBillApiDto.PayableFeeDto fee : payableBillApiDto.getFees()) {
            feeTotalAmount = feeTotalAmount.add(fee.getPayableAmount());
            // 验证费用明细
            if (fee.getFeeDetails() != null) {
                BigDecimal detailTotalAmount = BigDecimal.ZERO;
                for (PayableBillApiDto.PayableFeeDetailDto detail : fee.getFeeDetails()) {
                    detailTotalAmount = detailTotalAmount.add(detail.getBillingAmount());
                }
                if (fee.getPayableAmount().compareTo(detailTotalAmount) != 0) {
                    throw new IllegalArgumentException("费用金额与明细金额不匹配,费用金额:" + fee.getPayableAmount() +
                            ",明细金额:" + detailTotalAmount);
                }
            }
        }
        if (totalAmount.compareTo(feeTotalAmount) != 0) {
            throw new IllegalArgumentException("账单总金额与费用总金额不匹配,账单金额:" + totalAmount +
                    ",费用金额:" + feeTotalAmount);
        }
    }
    /**
     * 保存应付账单管理信息
     */
    private PayableBillManagement savePayableBillManagement(PayableBillApiDto.PayableBillDto billDto) {
        PayableBillManagement billManagement = new PayableBillManagement();
        // 生成系统编号
        String systemNo = systemDataNoService.getNoByKey(SystemDataNoEnum.YFZD);
        // 设置基本信息
        billManagement.setSystemNo(systemNo);
        billManagement.setBillName(billDto.getBillName());
        billManagement.setSupplierName(billDto.getSupplierName());
        billManagement.setIsInternalSettlement(billDto.getIsInternalSettlement());
        billManagement.setInternalSettlementUnit(billDto.getInternalSettlementUnit());
        // 设置金额信息
        billManagement.setDocumentCount(billDto.getDocumentCount());
        billManagement.setTotalAmount(billDto.getTotalAmount());
        billManagement.setCurrency(billDto.getCurrency());
        billManagement.setDiscountAmount(billDto.getDiscountAmount());
        billManagement.setPaidAmount(billDto.getPaidAmount() != null ? billDto.getPaidAmount() : BigDecimal.ZERO);
        billManagement.setPendingAmount(billDto.getPendingAmount() != null ? billDto.getPendingAmount() : billDto.getTotalAmount());
        billManagement.setExchangeRate(billDto.getExchangeRate());
        billManagement.setCnyAmount(billDto.getCnyAmount());
        // 设置日期信息
        billManagement.setPeriodType(billDto.getPeriodType());
        billManagement.setBusinessStartDate(billDto.getBusinessStartDate());
        billManagement.setBusinessEndDate(billDto.getBusinessEndDate());
        billManagement.setBillingStartDate(billDto.getBillingStartDate());
        billManagement.setBillingEndDate(billDto.getBillingEndDate());
        billManagement.setBillGenerateDate(billDto.getBillGenerateDate());
        billManagement.setBillSendDate(billDto.getBillSendDate());
        billManagement.setBillDueDate(billDto.getBillDueDate());
        // 设置其他信息
        billManagement.setStatus(billDto.getStatus() != null ? billDto.getStatus() : "draft");
        billManagement.setRemark(billDto.getRemark());
        billManagement.setCreateTime(DateUtils.getNowDate());
        billManagement.setCreateBy("api_system");
        // 保存账单管理信息
        int rows = payableBillManagementService.insertPayableBillManagement(billManagement);
        if (rows <= 0) {
            throw new RuntimeException("保存应付账单管理信息失败");
        }
        return billManagement;
    }
    /**
     * 保存应付费用管理信息和明细
     */
    private void savePayableFeeManagementAndDetails(List<PayableBillApiDto.PayableFeeDto> fees, String billSystemNo) {
        List<PayableFeeManagement> feeManagementList = new ArrayList<>();
        List<PayableFeeDetail> feeDetailList = new ArrayList<>();
        for (PayableBillApiDto.PayableFeeDto feeDto : fees) {
            // 生成费用管理记录
            PayableFeeManagement feeManagement = new PayableFeeManagement();
            // 生成系统编号
            String feeSystemNo = systemDataNoService.getNoByKey(SystemDataNoEnum.YF);
            // 设置费用管理信息
            feeManagement.setSystemNo(feeSystemNo);
            feeManagement.setRelatedBillNo(billSystemNo);
            feeManagement.setSourceSystem(feeDto.getSourceSystem());
            feeManagement.setBusinessSector(feeDto.getBusinessSector());
            feeManagement.setDocumentType(feeDto.getDocumentType());
            feeManagement.setDocumentNo(feeDto.getDocumentNo());
            feeManagement.setIsInternalSettlement(feeDto.getIsInternalSettlement());
            feeManagement.setInternalSettlementUnit(feeDto.getInternalSettlementUnit());
            feeManagement.setSupplierName(feeDto.getSupplierName());
            feeManagement.setProjectName(feeDto.getProjectName());
            feeManagement.setBusinessTime(feeDto.getBusinessTime());
            feeManagement.setPayableConfirmTime(feeDto.getPayableConfirmTime());
            feeManagement.setPayableAmount(feeDto.getPayableAmount());
            feeManagement.setPayableAmountStr(feeDto.getPayableAmountStr());
            feeManagement.setStatus(feeDto.getStatus() != null ? feeDto.getStatus() : "confirmed");
            feeManagement.setRemark(feeDto.getRemark());
            feeManagement.setCreateTime(DateUtils.getNowDate());
            feeManagement.setCreateBy("api_system");
            feeManagementList.add(feeManagement);
            // 保存费用明细
            if (feeDto.getFeeDetails() != null && !feeDto.getFeeDetails().isEmpty()) {
                for (PayableBillApiDto.PayableFeeDetailDto detailDto : feeDto.getFeeDetails()) {
                    PayableFeeDetail feeDetail = new PayableFeeDetail();
                    feeDetail.setFeeType(detailDto.getFeeType());
                    feeDetail.setFeeName(detailDto.getFeeName());
                    feeDetail.setBillingUnit(detailDto.getBillingUnit());
                    feeDetail.setUnitPrice(detailDto.getUnitPrice());
                    feeDetail.setBillingQuantity(detailDto.getBillingQuantity());
                    feeDetail.setBillingAmount(detailDto.getBillingAmount());
                    feeDetail.setActualAmount(detailDto.getActualAmount() != null ? detailDto.getActualAmount() : BigDecimal.ZERO);
                    feeDetail.setCurrency(detailDto.getCurrency());
                    feeDetail.setFeeRegTime(detailDto.getFeeRegTime());
                    feeDetail.setRemark(detailDto.getRemark());
                    feeDetail.setCreateTime(DateUtils.getNowDate());
                    feeDetail.setCreateBy("api_system");
                    // 注意:这里需要先保存feeManagement获取ID,然后再设置关联关系
                    // 由于是批量保存,这里先收集,后续再处理关联关系
                    feeDetailList.add(feeDetail);
                }
            }
        }
        // 批量保存费用管理信息
        int feeRows = payableFeeManagementService.insertPayableFeeManagementBatch(feeManagementList);
        if (feeRows <= 0) {
            throw new RuntimeException("保存应付费用管理信息失败");
        }
        // 处理费用明细的关联关系并保存
        if (!feeDetailList.isEmpty()) {
            // 使用Map存储系统编号和ID的映射关系
            Map<String, Integer> systemNoToIdMap = new HashMap<>();
            // 批量保存费用管理信息并获取ID
            for (PayableFeeManagement feeManagement : feeManagementList) {
                    // 假设插入后可以通过某种方式获取ID,这里简化处理
                    // 实际项目中可能需要根据业务逻辑获取ID
                    systemNoToIdMap.put(feeManagement.getSystemNo(), feeManagement.getId());
            }
            // 设置费用明细的关联ID
            List<PayableFeeDetail> finalFeeDetailList = new ArrayList<>();
            for (int i = 0; i < feeManagementList.size(); i++) {
                PayableFeeManagement feeManagement = feeManagementList.get(i);
                Integer feeId = systemNoToIdMap.get(feeManagement.getSystemNo());
                if (feeId != null && i < feeDetailList.size()) {
                    PayableFeeDetail feeDetail = feeDetailList.get(i);
                    feeDetail.setPayableFeeId(feeId);
                    finalFeeDetailList.add(feeDetail);
                }
            }
            // 批量保存费用明细
            int detailRows = payableFeeDetailService.insertPayableFeeDetailBatch(finalFeeDetailList);
            if (detailRows <= 0) {
                throw new RuntimeException("保存应付费用明细信息失败");
            }
        }
    }
    /**
     * 健康检查接口
     * @return 健康状态
     */
    @GetMapping("/health")
    public Map<String, String> healthCheck() {
        Map<String, String> result = new HashMap<>();
        result.put("status", "0000");
        result.put("message", "应收应付账单API服务正常运行");
        result.put("timestamp", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date()));
        return result;
    }
}
service/src/main/java/com/ruoyi/cwgl/domain/dto/PayableBillApiDto.java
New file
@@ -0,0 +1,221 @@
package com.ruoyi.cwgl.domain.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
 * 应付账单API接口数据传输对象
 */
@Data
public class PayableBillApiDto {
    /**
     * 应付账单管理信息
     */
    @NotNull(message = "应付账单信息不能为空")
    private PayableBillDto bill;
    /**
     * 应付费用管理信息
     */
    @NotNull(message = "应付费用信息不能为空")
    private List<PayableFeeDto> fees;
    /**
     * 应付账单数据传输对象
     */
    @Data
    public static class PayableBillDto {
        /** 账单名称 */
        @NotBlank(message = "账单名称不能为空")
        private String billName;
        /** 供应商名称 */
        @NotBlank(message = "供应商名称不能为空")
        private String supplierName;
        /** 是否内部结算 */
        private String isInternalSettlement;
        /** 内部结算单位 */
        private String internalSettlementUnit;
        /** 单据数量 */
        private Integer documentCount;
        /** 应结算金额 */
        @NotNull(message = "应结算金额不能为空")
        private BigDecimal totalAmount;
        /** 币制 */
        @NotBlank(message = "币制不能为空")
        private String currency;
        /** 减免金额 */
        private BigDecimal discountAmount;
        /** 已付金额 */
        private BigDecimal paidAmount;
        /** 待付金额 */
        private BigDecimal pendingAmount;
        /** 汇率(港币兑人民币) */
        private BigDecimal exchangeRate;
        /** 人民币金额 */
        private BigDecimal cnyAmount;
        /** 周期类型 */
        private String periodType;
        /** 业务期间开始日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date businessStartDate;
        /** 业务期间结束日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date businessEndDate;
        /** 账期开始日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date billingStartDate;
        /** 账期结束日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date billingEndDate;
        /** 账单生成日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date billGenerateDate;
        /** 账单发送日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date billSendDate;
        /** 账单到期日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date billDueDate;
        /** 状态(draft:草稿;generated:已生成;sent:已发送;partial_paid:部分付款;paid:已付款;cancelled:已取消) */
        private String status;
        /** 备注 */
        private String remark;
    }
    /**
     * 应付费用数据传输对象
     */
    @Data
    public static class PayableFeeDto {
        /** 序号(用于与明细表关联) */
        private String serialNumber;
        /** 关联账单编号 */
        private String relatedBillNo;
        /** 来源系统 */
        @NotBlank(message = "来源系统不能为空")
        private String sourceSystem;
        /** 业务板块 */
        private String businessSector;
        /** 单据类型 */
        private String documentType;
        /** 单据编号 */
        @NotBlank(message = "单据编号不能为空")
        private String documentNo;
        /** 是否内部结算 */
        private String isInternalSettlement;
        /** 内部结算单位 */
        private String internalSettlementUnit;
        /** 供应商名称 */
        @NotBlank(message = "供应商名称不能为空")
        private String supplierName;
        /** 项目名称 */
        private String projectName;
        /** 业务发生时间 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date businessTime;
        /** 应付确认时间 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date payableConfirmTime;
        /** 应付金额 */
        @NotNull(message = "应付金额不能为空")
        private BigDecimal payableAmount;
        private String payableAmountStr;
        /** 状态 */
        private String status;
        /** 备注 */
        private String remark;
        /** 应付费用明细列表 */
        private List<PayableFeeDetailDto> feeDetails;
    }
    /**
     * 应付费用明细数据传输对象
     */
    @Data
    public static class PayableFeeDetailDto {
        /** 序号(用于与主表关联) */
        private String serialNumber;
        /** 费用类型 */
        @NotBlank(message = "费用类型不能为空")
        private String feeType;
        /** 费用名称 */
        @NotBlank(message = "费用名称不能为空")
        private String feeName;
        /** 计费单位 */
        private String billingUnit;
        /** 计费单价 */
        @NotNull(message = "计费单价不能为空")
        private BigDecimal unitPrice;
        /** 计费数量 */
        @NotNull(message = "计费数量不能为空")
        private BigDecimal billingQuantity;
        /** 计费金额 */
        @NotNull(message = "计费金额不能为空")
        private BigDecimal billingAmount;
        /** 实付金额 */
        private BigDecimal actualAmount;
        /** 币制 */
        private String currency;
        /** 费用登记时间 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date feeRegTime;
        /** 备注 */
        private String remark;
    }
}
service/src/main/java/com/ruoyi/cwgl/domain/dto/ReceivableBillApiDto.java
New file
@@ -0,0 +1,245 @@
package com.ruoyi.cwgl.domain.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
 * 应收账单API接口数据传输对象
 */
@Data
public class ReceivableBillApiDto {
    /**
     * 应收账单管理信息
     */
    @NotNull(message = "应收账单信息不能为空")
    private ReceivableBillDto bill;
    /**
     * 应收费用管理信息
     */
    @NotNull(message = "应收费用信息不能为空")
    private List<ReceivableFeeDto> fees;
    /**
     * 应收账单数据传输对象
     */
    @Data
    public static class ReceivableBillDto {
        /** 账单名称 */
        @NotBlank(message = "账单名称不能为空")
        private String billName;
        /** 客户名称 */
        @NotBlank(message = "客户名称不能为空")
        private String customerName;
        /** 收款人 */
        private String payee;
        /** 责任人 */
        private String responsiblePerson;
        /** 责任领导 */
        private String responsibleLeader;
        /** 结算方式 */
        private String settlementMethod;
        /** 业务类型 */
        private String businessType;
        /** 推进要求 */
        private String promotionRequirement;
        /** 是否内部结算 */
        private String isInternalSettlement;
        /** 内部结算单位 */
        private String internalSettlementUnit;
        /** 单据数量 */
        private Integer documentCount;
        /** 应结算金额 */
        @NotNull(message = "应结算金额不能为空")
        private BigDecimal totalAmount;
        /** 币制 */
        @NotBlank(message = "币制不能为空")
        private String currency;
        /** 减免金额 */
        private BigDecimal discountAmount;
        /** 已收金额 */
        private BigDecimal receivedAmount;
        /** 待收金额 */
        private BigDecimal pendingAmount;
        /** 汇率(港币兑人民币) */
        private BigDecimal exchangeRate;
        /** 人民币金额 */
        private BigDecimal cnyAmount;
        /** 周期类型 */
        private String periodType;
        /** 业务期间开始日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date businessStartDate;
        /** 业务期间结束日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date businessEndDate;
        /** 账期开始日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date billingStartDate;
        /** 账期结束日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date billingEndDate;
        /** 账单生成日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date billGenerateDate;
        /** 账单发送日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date billSendDate;
        /** 账单到期日期 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date billDueDate;
        /** 结算种类 */
        private String settlementCategory;
        /** 结算期 */
        private String settlementPeriod;
        /** 状态(draft:草稿;generated:已生成;sent:已发送;partial_paid:部分收款;paid:已收款;cancelled:已取消) */
        private String status;
        /** 备注 */
        private String remark;
    }
    /**
     * 应收费用数据传输对象
     */
    @Data
    public static class ReceivableFeeDto {
        /** 序号(用于与明细表关联) */
        private String serialNumber;
        /** 关联账单编号 */
        private String relatedBillNo;
        /** 来源系统 */
        @NotBlank(message = "来源系统不能为空")
        private String sourceSystem;
        /** 业务板块 */
        private String businessSector;
        /** 单据类型 */
        private String documentType;
        /** 单据编号 */
        @NotBlank(message = "单据编号不能为空")
        private String documentNo;
        /** 是否内部结算 */
        private String isInternalSettlement;
        /** 内部结算单位 */
        private String internalSettlementUnit;
        /** 客户名称 */
        @NotBlank(message = "客户名称不能为空")
        private String customerName;
        /** 项目名称 */
        private String projectName;
        /** 业务发生时间 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date businessTime;
        /** 应收确认时间 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date receivableConfirmTime;
        /** 应收金额 */
        @NotNull(message = "应收金额不能为空")
        private BigDecimal receivableAmount;
        private String receivableAmountStr;
        /** 状态 */
        private String status;
        /** 备注 */
        private String remark;
        /** 应收费用明细列表 */
        private List<ReceivableFeeDetailDto> feeDetails;
    }
    /**
     * 应收费用明细数据传输对象
     */
    @Data
    public static class ReceivableFeeDetailDto {
        /** 序号(用于与主表关联) */
        private String serialNumber;
        /** 费用类型 */
        @NotBlank(message = "费用类型不能为空")
        private String feeType;
        /** 费用名称 */
        @NotBlank(message = "费用名称不能为空")
        private String feeName;
        /** 计费单位 */
        private String billingUnit;
        /** 计费单价 */
        @NotNull(message = "计费单价不能为空")
        private BigDecimal unitPrice;
        /** 计费数量 */
        @NotNull(message = "计费数量不能为空")
        private BigDecimal billingQuantity;
        /** 计费金额 */
        @NotNull(message = "计费金额不能为空")
        private BigDecimal billingAmount;
        /** 实收金额 */
        private BigDecimal actualAmount;
        /** 币制 */
        private String currency;
        /** 费用登记时间 */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date feeRegTime;
        /** 备注 */
        private String remark;
    }
}
service/src/main/resources/mapper/cwgl/PayableFeeManagementMapper.xml
@@ -129,11 +129,11 @@
    <insert id="insertPayableFeeManagementBatch" parameterType="java.util.List"  useGeneratedKeys="true" keyProperty="id">
        insert into payable_fee_management
        <trim prefix="(" suffix=") values" suffixOverrides=",">
            id,system_no,related_bill_no,source_system,business_sector,document_type,document_no,is_internal_settlement,internal_settlement_unit,supplier_name,project_name,business_time,payable_confirm_time,payable_amount,payable_amount_str,status,remark,create_by,create_time,update_by,update_time,deleted,
           system_no,related_bill_no,source_system,business_sector,document_type,document_no,is_internal_settlement,internal_settlement_unit,supplier_name,project_name,business_time,payable_confirm_time,payable_amount,payable_amount_str,status,remark,create_by,create_time,update_by,update_time,deleted,
        </trim>
        <foreach item="item" index="index" collection="list" separator=",">
            <trim prefix="(" suffix=") " suffixOverrides=",">
                #{item.id},#{item.systemNo},#{item.relatedBillNo},#{item.sourceSystem},#{item.businessSector},#{item.documentType},#{item.documentNo},#{item.isInternalSettlement},#{item.internalSettlementUnit},#{item.supplierName},#{item.projectName},#{item.businessTime},#{item.payableConfirmTime},#{item.payableAmount},#{item.payableAmountStr},#{item.status},#{item.remark},#{item.createBy},#{item.createTime},#{item.updateBy},#{item.updateTime},#{item.deleted},
             #{item.systemNo},#{item.relatedBillNo},#{item.sourceSystem},#{item.businessSector},#{item.documentType},#{item.documentNo},#{item.isInternalSettlement},#{item.internalSettlementUnit},#{item.supplierName},#{item.projectName},#{item.businessTime},#{item.payableConfirmTime},#{item.payableAmount},#{item.payableAmountStr},#{item.status},#{item.remark},#{item.createBy},#{item.createTime},#{item.updateBy},#{item.updateTime},#{item.deleted},
            </trim>
        </foreach>
    </insert>
service/src/main/resources/mapper/cwgl/ReceivableFeeManagementMapper.xml
@@ -133,11 +133,11 @@
    <insert id="insertReceivableFeeManagementBatch" parameterType="java.util.List"  useGeneratedKeys="true" keyProperty="id">
        insert into receivable_fee_management
        <trim prefix="(" suffix=") values" suffixOverrides=",">
            id,system_no,related_bill_no,source_system,business_sector,document_type,document_no,is_internal_settlement,internal_settlement_unit,customer_name,project_name,business_time,receivable_confirm_time,receivable_amount,receivable_amount_str,status,remark,create_by,create_time,update_by,update_time,deleted,customer_id,
            system_no,related_bill_no,source_system,business_sector,document_type,document_no,is_internal_settlement,internal_settlement_unit,customer_name,project_name,business_time,receivable_confirm_time,receivable_amount,receivable_amount_str,status,remark,create_by,create_time,update_by,update_time,deleted,customer_id,
        </trim>
        <foreach item="item" index="index" collection="list" separator=",">
            <trim prefix="(" suffix=") " suffixOverrides=",">
                #{item.id},#{item.systemNo},#{item.relatedBillNo},#{item.sourceSystem},#{item.businessSector},#{item.documentType},#{item.documentNo},#{item.isInternalSettlement},#{item.internalSettlementUnit},#{item.customerName},#{item.projectName},#{item.businessTime},#{item.receivableConfirmTime},#{item.receivableAmount},#{item.receivableAmountStr},#{item.status},#{item.remark},#{item.createBy},#{item.createTime},#{item.updateBy},#{item.updateTime},#{item.deleted},#{item.customerId},
                #{item.systemNo},#{item.relatedBillNo},#{item.sourceSystem},#{item.businessSector},#{item.documentType},#{item.documentNo},#{item.isInternalSettlement},#{item.internalSettlementUnit},#{item.customerName},#{item.projectName},#{item.businessTime},#{item.receivableConfirmTime},#{item.receivableAmount},#{item.receivableAmountStr},#{item.status},#{item.remark},#{item.createBy},#{item.createTime},#{item.updateBy},#{item.updateTime},#{item.deleted},#{item.customerId},
            </trim>
        </foreach>
    </insert>
ui/admin-ui3/src/api/cwgl/analysisManagement.ts
@@ -23,7 +23,14 @@
        download('/cwgl/receivableBillManagement/customerSummary/export',query);
    })
}
/**
 * 账龄分析列表导出
 */
export const exportAgingAnalysis:requestType = (query) => {
    return new Promise<any>(()=>{
        download('/cwgl/receivableBillManagement/customerSummary/export',query);
    })
}
export const agingAnalysisList:requestType = (query) => {
    return request({
        url: '/cwgl/receivableBillManagement/agingAnalysis',
ui/admin-ui3/src/layout/index.vue
@@ -7,7 +7,7 @@
        <navbar @setLayout="setLayout" />
        <tags-view v-if="needTagsView" />
      </div>
      <el-watermark :content="watermarkContent" zIndex="99999">
      <el-watermark :content="watermarkContent" :zIndex="99999">
        <app-main />
    </el-watermark>
      <settings ref="settingRef" />
ui/admin-ui3/src/main.ts
@@ -15,7 +15,6 @@
import 'default-passive-events'
import elementIcons from '@/components/SvgIcon/svgicon'
import directive from "@/directive";
// pinia store
@@ -40,6 +39,7 @@
app.component('XlsFileImport', XlsFileImport);
app.component('flowLog', flowLog)
app.component('svg-icon', SvgIcon)
app.use(plugins)
ui/admin-ui3/src/views/cwgl/accountAnalysisDetail/index.vue
@@ -1,7 +1,7 @@
<template>
  <basicContainer>
    <div class="account-analysis-detail">
      <avue-crud ref="crudRef" v-model="form" v-model:search="searchForm" v-model:page="page" :option="option"
      <avue-crud ref="crudRef" v-model="form" v-model:search="searchForm" :page="page" :option="option"
        :data="tableData" :table-loading="loading" :row-class-name="rowClassName" @on-load="onLoad"
        @search-change="searchChange" @search-reset="searchReset" @refresh-change="refreshChange"
        @current-change="currentChange" @size-change="sizeChange">
@@ -23,7 +23,7 @@
          <el-button type="primary" link underline="never" icon="View" @click="crudRef.rowView(row)">查看</el-button>
          <el-link type="primary" icon="el-icon-document" v-hasPermi="['cwgl:receivableBillManagement:log']"
            :underline="false" @click="handleFlow(row)" style="margin-left: 12px;">日志</el-link>
            underline="never" @click="handleFlow(row)" style="margin-left: 12px;">日志</el-link>
        </template>
      </avue-crud>
    </div>
@@ -99,7 +99,7 @@
import { agingAnalysisList, listAccountLog, updateAccountAnalysis, receivableBillManagementAccountAnalysis } from "@/api/cwgl/analysisManagement";
import useCurrentInstance from "@/utils/useCurrentInstance";
import OperationLogModal from '@/components/OperationLogModal/index.vue';
import { download } from "@/utils/request";
const { proxy } = useCurrentInstance();
const { sys_account_business } = proxy.useDict('sys_account_business');
@@ -151,8 +151,8 @@
// --- Avue 配置 ---
const option = computed(() => ({
  height: 'auto',
  calcHeight: 30,
  // height: 'auto',
  // calcHeight: 30,
  searchShow: true,
  searchMenuSpan: 6,
  border: true,
@@ -160,11 +160,15 @@
  editBtn: false,
  delBtn: false,
  viewBtn: false,
  showSummary: true,
  dicCache: true,
  menuWidth: 220,
  labelWidth: 150,
  page: true,
  pagination: true,
  searchLabelWidth: 120,
  showSummary: true,
  // 强制指定合计文案(如果 method 返回空,它作为保底)
  sumText: '合计',
  sumColumnList: [
    { name: 'repaymentAmount', type: 'sum' },
    { name: 'ncSettlementAmount', type: 'sum' },
@@ -182,8 +186,8 @@
      detail: true,
      formatter: (row: any, value: any) => dictFormat(sys_account_business, value)
    },
    { label: '账单系统编号', prop: 'systemNo', search: true, width: 140 },
    { label: '结算期', prop: 'settlementPeriod', width: 100 },
    { label: '账单系统编号', prop: 'systemNo', search: true, width: 180 },
    { label: '结算期', prop: 'settlementPeriod', width: 200 },
    {
      label: 'NC账面结算',
      children: [
@@ -250,13 +254,6 @@
    tableData.value = res.rows || [];
    page.total = res.total || 0;
    loading.value = false;
    if (highlightSystemNo.value) {
      nextTick(() => {
        const target = document.querySelector('.highlight-row');
        target?.scrollIntoView({ behavior: 'smooth', block: 'center' });
      });
    }
  }).catch(() => {
    loading.value = false;
  });
@@ -382,8 +379,8 @@
};
/* 导出按钮 */
function handleExport() {
  proxy.download(
    '/wmswh/reportStockcwgl/receivableBillManagement/accountAnalysis/export',
  download(
    '/cwgl/receivableBillManagement/accountAnalysis/export',
    {
      ...form.value,
    },
@@ -430,4 +427,19 @@
.edit-form {
  padding: 10px 20px;
}
/* 强制在合计行的第一个非复选框单元格(责任人列)显示文案 */
:deep(.el-table__footer-wrapper .el-table__cell.avue-crud__color .cell),
:deep(.el-table__footer-wrapper .el-table__cell:nth-child(2) .cell) {
  visibility: visible !important;
}
/* 如果是多选框列导致的遮挡,通过伪元素强行在第二列注入 */
:deep(.el-table__footer-wrapper tr td:nth-child(2) .cell::before) {
  content: '合计';
  font-weight: bold;
  color: #333;
}
</style>
ui/admin-ui3/src/views/cwgl/ageAnalysis/index.vue
@@ -75,7 +75,7 @@
                </el-row>
                <el-row>
                    <el-col :span="24">
                        <el-form-item label="备注"><el-input v-model="editForm.remark" /></el-form-item>
                        <el-form-item label="备注"><el-input v-model="editForm.accountRemark" /></el-form-item>
                    </el-col>
                </el-row>
                <el-row>
@@ -139,7 +139,7 @@
</template>
<script setup name="AgeAnalysis" lang="ts">
import { ref, reactive, onMounted } from 'vue';
import { ref, reactive, onMounted, watch } from 'vue';
import { useRoute } from 'vue-router';
import router from "@/router";
import { agingAnalysisList, addPaymentFeedback, listPaymentFeedback, listAgingLog, receivableBillManagementAging } from "@/api/cwgl/analysisManagement";
@@ -177,34 +177,30 @@
 * Avue 配置项
 */
const option = ref({
    align: 'center',
    headerAlign: 'center',
    searchShow: true,
    searchMenuSpan: 6,
    border: true,
    addBtn: false,
    editBtn: false,
    delBtn: false,
    viewBtn: false,
    menu: true,
    stripe: true,
    columnBtn: true,
    searchIndex: 1,
    searchMenuSpan: 4,
    searchSpan: 5,
    height: 'auto',
    menuWidth: 180,
    dicCache: true,
    menuWidth: 220,
    labelWidth: 150,
    page: true,
    pagination: true,
    searchLabelWidth: 120,
    menuFixed: 'right',
    showSummary: true,
    // --- 合计行配置 ---
    // showSummary: true,
    // sumText: '合计',
    // sumColumnList: [
    //     { name: 'estimateAmount', type: 'sum' },
    //     { name: 'confirmedAmount', type: 'sum' },
    //     { name: 'balanceAmount', type: 'sum' },
    //     { name: 'overdueAmount', type: 'sum' },
    //     { name: 'unInvoicedAmount', type: 'sum' }
    // ],
    // 强制指定合计文案(如果 method 返回空,它作为保底)
    sumText: '合计',
    sumColumnList: [
        // { label: '合计:', name: 'responsiblePerson', type: 'sum',  },
        { name: 'totalAmount', type: 'sum' },
        { name: 'pendingAmount', type: 'sum' },
        { name: 'overdueAmount', type: 'sum' },
        { name: 'unInvoicedAmount', type: 'sum' },
    ],
    column: [
        { label: '责任人', prop: 'responsiblePerson', width: 100 },
@@ -226,9 +222,7 @@
            detail: true,
            formatter: (row: any, value: any) => dictFormat(sys_account_business, value)
        },
        { label: '账单系统编号', prop: 'systemNo', width: 200, search: true },
        // 金额列
        { label: '含暂估应收账款余额', prop: 'totalAmount', width: 160, type: 'number' },
        { label: '已确认应收账款金额', prop: 'totalAmount', width: 160, type: 'number' },
@@ -244,11 +238,18 @@
        { label: '逾期1年以上', prop: 'overdueOver1Year', width: 130 },
        { label: '推进要求', prop: 'promotionRequirement', width: 250, overHidden: true },
        { label: '备注', prop: 'remark', width: 150 },
        { label: '逾期金额所属期', prop: 'overduePeriod', width: 150 },
        { label: '账单是否确认', prop: 'isConfirmed', width: 120 },
        { label: '备注', prop: 'accountRemark', width: 150 },
        {
            label: '逾期金额所属期', width: 200,
            formatter: (row) => {
                if (row.billingStartDate && row.billingEndDate) {
                    return `${row.billingStartDate} 至 ${row.billingEndDate}`;
                }
                return row.periodType || '-';
            }
        },
        { label: '开票日期', prop: 'invoiceDate', width: 120 },
        { label: '未开票金额', prop: 'unInvoicedAmount', width: 120 }
        { label: '未开票金额', prop: 'pendingAmount', width: 120 }
    ]
});
@@ -385,8 +386,8 @@
    onLoad();
};
// 修改 goReturn 方法
const goReturn = () => router.push('/basic/analysisManagement');
// --- 弹窗逻辑 ---
const editVisible = ref(false);
const editForm = ref<any>({});
@@ -510,11 +511,26 @@
    padding-left: 10px;
    border-left: 4px solid #409eff;
}
/* 操作列按钮间距 */
.menu-btn-container .el-link {
    margin-right: 12px;
}
.menu-btn-container .el-link:last-child {
    margin-right: 0;
}
/* 强制在合计行的第一个非复选框单元格(责任人列)显示文案 */
:deep(.el-table__footer-wrapper .el-table__cell.avue-crud__color .cell),
:deep(.el-table__footer-wrapper .el-table__cell:nth-child(2) .cell) {
    visibility: visible !important;
}
/* 如果是多选框列导致的遮挡,通过伪元素强行在第二列注入 */
:deep(.el-table__footer-wrapper tr td:nth-child(2) .cell::before) {
    content: '合计';
    font-weight: bold;
    color: #333;
}
</style>
ui/admin-ui3/src/views/cwgl/analysisManagement/index.vue
@@ -140,7 +140,6 @@
 */
const handleAgeAnalysis = (row: any) => {
    // 可使用 router.push 进行跳转
    console.log(row.customerName);
  router.push('/basic/ageAnalysis?customerName='+row.customerName)
};