package com.ruoyi.cwgl.service.impl; import java.io.File; import java.io.OutputStream; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.enums.SystemDataNoEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.file.DownloadExportUtil; import com.ruoyi.common.utils.file.DownloadExportUtil.ExprotStatus; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.cwgl.domain.ReceivableFeeDetail; import com.ruoyi.cwgl.domain.ReceivableFeeManagementLog; import com.ruoyi.cwgl.domain.vo.ReceivableFeeStatisticsVo; import com.ruoyi.cwgl.service.*; import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.service.ISystemDataNoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.stereotype.Service; import org.springframework.scheduling.annotation.Async; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ruoyi.common.utils.PageUtils; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.annotation.DataSource; import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.core.service.BaseService; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.exception.UtilException; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.cwgl.mapper.ReceivableFeeManagementMapper; import com.ruoyi.cwgl.domain.ReceivableFeeManagement; import com.ruoyi.cwgl.domain.ReceivableBillManagement; import com.ruoyi.cwgl.domain.ReceivableBillSettlementDetail; import com.ruoyi.cwgl.domain.vo.ReceivableBillCreateVo; import com.ruoyi.common.core.text.Convert; import javax.annotation.Resource; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.streaming.SXSSFWorkbook; /** * 应收费用管理Service业务层处理 * * @author ruoyi * @date 2025-12-17 */ @Service @Transactional(rollbackFor = Exception.class) public class ReceivableFeeManagementServiceImpl extends BaseService implements IReceivableFeeManagementService { protected final Logger logger = LoggerFactory.getLogger(getClass()); @Resource private ReceivableFeeManagementMapper receivableFeeManagementMapper; @Autowired private IReceivableFeeDetailService receivableFeeDetailService; @Resource private SysConfigMapper sysConfigMapper; @Autowired private IReceivableBillManagementService receivableBillManagementService; @Autowired ISystemDataNoService systemDataNoService; @Autowired private IReceivableFeeManagementLogService logService; @Autowired private RedisCache redisCache; /** * 查询应收费用管理 * * @param id 应收费用管理ID * @return 应收费用管理 */ @DataSource(DataSourceType.SLAVE) @Override public ReceivableFeeManagement selectReceivableFeeManagementById(Integer id) { ReceivableFeeManagement receivableFeeManagement = receivableFeeManagementMapper.selectReceivableFeeManagementById(id); if (receivableFeeManagement != null) { // 查询对应的费用明细 ReceivableFeeDetail detail = new ReceivableFeeDetail(); detail.setReceivableFeeId(id); List detailList = receivableFeeDetailService.selectReceivableFeeDetailList(detail); receivableFeeManagement.setReceivableFeeDetailList(detailList); } return receivableFeeManagement; } /** * 查询应收费用管理 记录数 * * @param receivableFeeManagement 应收费用管理 * @return 应收费用管理集合 */ @DataSource(DataSourceType.SLAVE) @Override public int selectReceivableFeeManagementCount(ReceivableFeeManagement receivableFeeManagement) { return receivableFeeManagementMapper.selectReceivableFeeManagementCount(receivableFeeManagement); } /** * 查询应收费用管理列表 * * @param receivableFeeManagement 应收费用管理 * @return 应收费用管理 */ @DataSource(DataSourceType.SLAVE) @Override public List selectReceivableFeeManagementList(ReceivableFeeManagement receivableFeeManagement) { return receivableFeeManagementMapper.selectReceivableFeeManagementList(receivableFeeManagement); } /** * 查询应收费用管理列表 异步 导出 * * @param receivableFeeManagement 应收费用管理 * @param exportKey 导出功能的唯一标识 * @return 应收费用管理集合 */ @DataSource(DataSourceType.SLAVE) @Async @Override public void export(ReceivableFeeManagement receivableFeeManagement,String exportKey) { super.export(ReceivableFeeManagement.class,exportKey,"receivableFeeManagementData",(pageNum)->{ PageUtils.startPage(pageNum, Constants.EXPORT_PATE_SIZE); return selectReceivableFeeManagementList(receivableFeeManagement); }); } /** * 新增应收费用管理 * * @param receivableFeeManagement 应收费用管理 * @return 结果 */ @Override public int insertReceivableFeeManagement(ReceivableFeeManagement receivableFeeManagement) { receivableFeeManagement.setCreateTime(DateUtils.getNowDate()); String noByKey = systemDataNoService.getNoByKey(SystemDataNoEnum.YS); receivableFeeManagement.setSystemNo(noByKey); // 计算应收金额字符串描述 if (receivableFeeManagement.getReceivableFeeDetailList() != null && !receivableFeeManagement.getReceivableFeeDetailList().isEmpty()) { String receivableAmountStr = calculateReceivableAmountStr(receivableFeeManagement.getReceivableFeeDetailList()); receivableFeeManagement.setReceivableAmountStr(receivableAmountStr); } receivableFeeManagement.setCreateBy(SecurityUtils.getUsername()); // 保存主表信息 int result = receivableFeeManagementMapper.insertReceivableFeeManagement(receivableFeeManagement); // 获取主表ID Integer receivableFeeId = receivableFeeManagement.getId(); // 批量保存明细列表 if (receivableFeeManagement.getReceivableFeeDetailList() != null && !receivableFeeManagement.getReceivableFeeDetailList().isEmpty()) { // 设置每个明细的应收费用管理ID receivableFeeManagement.getReceivableFeeDetailList().forEach(detail -> { detail.setReceivableFeeId(receivableFeeId); detail.setCreateTime(DateUtils.getNowDate()); // 设置创建时间 }); // 调用批量插入方法 receivableFeeDetailService.insertReceivableFeeDetailBatch(receivableFeeManagement.getReceivableFeeDetailList()); } // 记录操作日志 if (result > 0) { ReceivableFeeManagementLog log = new ReceivableFeeManagementLog(); log.setReceivableFeeId(receivableFeeId); log.setOperator(SecurityUtils.getUsername()); log.setOperationTime(DateUtils.getNowDate()); log.setOperationDesc("新增应收费用管理记录,系统编号:" + receivableFeeManagement.getSystemNo()); log.setCreateTime(DateUtils.getNowDate()); logService.insertReceivableFeeManagementLog(log); } return result; } /** * 修改应收费用管理 * * @param receivableFeeManagement 应收费用管理 * @return 结果 */ @Override public int updateReceivableFeeManagement(ReceivableFeeManagement receivableFeeManagement) { receivableFeeManagement.setUpdateTime(DateUtils.getNowDate()); // 计算应收金额字符串描述 if (receivableFeeManagement.getReceivableFeeDetailList() != null && !receivableFeeManagement.getReceivableFeeDetailList().isEmpty()) { String receivableAmountStr = calculateReceivableAmountStr(receivableFeeManagement.getReceivableFeeDetailList()); receivableFeeManagement.setReceivableAmountStr(receivableAmountStr); } // 1. 更新主表信息 int result = receivableFeeManagementMapper.updateReceivableFeeManagement(receivableFeeManagement); // 2. 获取主表ID Integer receivableFeeId = receivableFeeManagement.getId(); // 3. 删除该应收费用下的所有现有明细 receivableFeeDetailService.deleteReceivableFeeDetailByReceivableFeeId(receivableFeeId); // 4. 批量保存新的明细列表 if (receivableFeeManagement.getReceivableFeeDetailList() != null && !receivableFeeManagement.getReceivableFeeDetailList().isEmpty()) { // 设置每个明细的应收费用管理ID receivableFeeManagement.getReceivableFeeDetailList().forEach(detail -> { detail.setReceivableFeeId(receivableFeeId); detail.setCreateTime(DateUtils.getNowDate()); // 设置更新时间 }); // 调用批量插入方法 receivableFeeDetailService.insertReceivableFeeDetailBatch(receivableFeeManagement.getReceivableFeeDetailList()); } // 记录操作日志 if (result > 0) { ReceivableFeeManagementLog log = new ReceivableFeeManagementLog(); log.setReceivableFeeId(receivableFeeId); log.setOperator(SecurityUtils.getUsername()); log.setOperationTime(DateUtils.getNowDate()); log.setOperationDesc("修改应收费用管理记录,系统编号:" + receivableFeeManagement.getSystemNo()); log.setCreateTime(DateUtils.getNowDate()); logService.insertReceivableFeeManagementLog(log); } return result; } /** * 作废应收费用管理记录 * * @param id 应收费用管理ID * @return 结果 */ @Override public int voidReceivableFeeManagement(Integer id) { // 查询费用管理记录 ReceivableFeeManagement feeManagement = receivableFeeManagementMapper.selectReceivableFeeManagementById(id); if (feeManagement == null) { throw new ServiceException("费用管理记录不存在"); } // 判断状态是否为0(待生成账单),只有状态为0才能作废 if (!"0".equals(feeManagement.getStatus())) { throw new ServiceException("只有状态为待生成账单的记录才能作废"); } // 设置状态为作废(假设用"2"表示作废状态) feeManagement.setStatus("2"); feeManagement.setUpdateTime(DateUtils.getNowDate()); // 更新记录 int result = receivableFeeManagementMapper.updateReceivableFeeManagement(feeManagement); // 记录操作日志 if (result > 0) { ReceivableFeeManagementLog log = new ReceivableFeeManagementLog(); log.setReceivableFeeId(id); log.setOperator(SecurityUtils.getUsername()); log.setOperationTime(DateUtils.getNowDate()); log.setOperationDesc("作废应收费用管理记录,系统编号:" + feeManagement.getSystemNo()); log.setCreateTime(DateUtils.getNowDate()); logService.insertReceivableFeeManagementLog(log); } return result; } /** * 新增应收费用管理[批量] * * @param receivableFeeManagements 应收费用管理 * @return 结果 */ @Override public int insertReceivableFeeManagementBatch(List receivableFeeManagements) { int rows = receivableFeeManagementMapper.insertReceivableFeeManagementBatch(receivableFeeManagements); return rows; } /** * 修改应收费用管理[批量] * * @param receivableFeeManagements 应收费用管理 * @return 结果 */ @Override public int updateReceivableFeeManagementBatch(List receivableFeeManagements){ return receivableFeeManagementMapper.updateReceivableFeeManagementBatch(receivableFeeManagements); } /** * 删除应收费用管理对象 * * @param ids 需要删除的数据ID * @return 结果 */ @Override public int deleteReceivableFeeManagementByIds(String ids) { return deleteReceivableFeeManagementByIds(Convert.toIntArray(ids)); } /** * 删除应收费用管理对象 * * * @param ids 需要删除的数据ID * @return 结果 */ @Override public int deleteReceivableFeeManagementByIds(Integer[] ids) { return receivableFeeManagementMapper.deleteReceivableFeeManagementByIds(ids); } /** * 删除应收费用管理信息 * * @param id 应收费用管理ID * @return 结果 */ @Override public int deleteReceivableFeeManagementById(Integer id) { return receivableFeeManagementMapper.deleteReceivableFeeManagementById(id); } /** * 根据应收费用ID数组查询统计信息和明细 * * @param ids 应收费用ID数组 * @return 包含统计信息和明细的结果 */ @DataSource(DataSourceType.SLAVE) @Override public ReceivableFeeStatisticsVo getReceivableFeeStatistics(Integer[] ids) { // 查询应收费用主表记录 List receivableFeeList = receivableFeeManagementMapper.selectReceivableFeeManagementByIds(ids); // 检查所有记录是否属于同一个客户 if (!receivableFeeList.isEmpty()) { Integer firstCustomerId = receivableFeeList.get(0).getCustomerId(); boolean allSameCustomer = receivableFeeList.stream() .allMatch(item -> Objects.equals(item.getCustomerId(), firstCustomerId)); if (!allSameCustomer) { throw new ServiceException("所选记录包含不同客户的数据,无法进行统计"); } } // 计算单据数量 int documentCount = receivableFeeList.size(); SysConfig sysConfig = sysConfigMapper.selectConfig(new SysConfig() {{ setConfigKey("sys.hk.rmb.rate"); }}); // 计算总应收金额(按币种分别计算) BigDecimal totalAmountRmb = BigDecimal.ZERO; BigDecimal totalAmountHkd = BigDecimal.ZERO; // 获取所有应收费用明细,按币种汇总 if (!receivableFeeList.isEmpty()) { // 获取所有应收费用ID Integer[] feeIds = receivableFeeList.stream() .map(ReceivableFeeManagement::getId) .toArray(Integer[]::new); // 查询所有明细记录 List allDetails = receivableFeeDetailService.selectReceivableFeeDetailByReceivableFeeIds(feeIds); // 按币种汇总金额 for (ReceivableFeeDetail detail : allDetails) { if (detail.getBillingAmount() != null && detail.getCurrency() != null) { if ("RMB".equals(detail.getCurrency())) { totalAmountRmb = totalAmountRmb.add(detail.getBillingAmount()); } else if ("HKD".equals(detail.getCurrency())) { totalAmountHkd = totalAmountHkd.add(detail.getBillingAmount()); } } } } BigDecimal exchangeRate = new BigDecimal(sysConfig.getConfigValue()); // 计算人民币总金额(人民币金额 + 港币换算成人民币) BigDecimal totalAmountRmbWithConversion = totalAmountRmb.add( totalAmountHkd.multiply(exchangeRate).setScale(2, RoundingMode.HALF_UP) ); // 计算港币总金额(港币金额 + 人民币换算成港币) BigDecimal totalAmountHkdWithConversion = totalAmountHkd.add( totalAmountRmb.divide(exchangeRate, 2, RoundingMode.HALF_UP) ); // 组装返回结果 ReceivableFeeStatisticsVo result = new ReceivableFeeStatisticsVo(); result.setDocumentCount(documentCount); result.setRate(exchangeRate); result.setTotalReceivableAmount(totalAmountRmbWithConversion); // 默认使用人民币总金额 result.setTotalAmountRmb(totalAmountRmbWithConversion); result.setTotalAmountHkd(totalAmountHkdWithConversion); result.setIds(ids); return result; } /** * 根据统计数据创建应收账单 * * @param billCreateVo 包含统计数据和账单类型的请求对象 * @return 创建的应收账单ID */ @Override public Integer createReceivableBill(ReceivableBillCreateVo billCreateVo) { // 1. 准备数据 ReceivableFeeStatisticsVo statisticsVo = billCreateVo.getStatisticsData(); // 检查费用管理表的状态,只有状态为0才能创建账单 Integer[] feeIds = statisticsVo.getIds(); if (feeIds != null && feeIds.length > 0) { for (Integer feeId : feeIds) { ReceivableFeeManagement feeManagement = receivableFeeManagementMapper.selectReceivableFeeManagementById(feeId); if (feeManagement != null && !"0".equals(feeManagement.getStatus())) { throw new ServiceException("费用记录ID为" + feeId + "的状态不是待生成账单,无法创建账单"); } } } Integer billType = billCreateVo.getBillType(); // 2. 创建应收账单主记录 ReceivableBillManagement billManagement = new ReceivableBillManagement(); billManagement.setDocumentCount(statisticsVo.getDocumentCount()); billManagement.setExchangeRate(statisticsVo.getRate()); billManagement.setStatus("0"); // 默认草稿状态 billManagement.setCreateTime(DateUtils.getNowDate()); billManagement.setBillName(billCreateVo.getBillName()); billManagement.setCustomerName(billCreateVo.getCustomerName()); billManagement.setCreateBy(SecurityUtils.getUsername()); billManagement.setIsInternalSettlement(billCreateVo.getIsInternalSettlement()); billManagement.setInternalSettlementUnit(billCreateVo.getInternalSettlementUnit()); // 3. 根据账单类型设置币种和总金额 if (billType == 0) { // 人民币账单 billManagement.setCurrency("RMB"); billManagement.setTotalAmount(statisticsVo.getTotalAmountRmb()); } else if (billType == 1) { // 港币账单 billManagement.setCurrency("HKD"); billManagement.setTotalAmount(statisticsVo.getTotalAmountHkd()); } else { throw new IllegalArgumentException("无效的账单类型:" + billType); } billManagement.setPendingAmount(billManagement.getTotalAmount()); String noByKey = systemDataNoService.getNoByKey(SystemDataNoEnum.YSZD); billManagement.setSystemNo(noByKey); // 4. 保存主账单记录 int i = receivableBillManagementService.insertReceivableBillManagement(billManagement); // 5. 更新应收费用主表的关联账单编号 if (statisticsVo.getIds() != null && statisticsVo.getIds().length > 0) { // 获取生成的账单系统编号 String billSystemNo = billManagement.getSystemNo(); // 批量更新应收费用主表的关联账单编号 for (Integer feeId : statisticsVo.getIds()) { ReceivableFeeManagement feeManagement = new ReceivableFeeManagement(); feeManagement.setId(feeId); feeManagement.setRelatedBillNo(billSystemNo); feeManagement.setStatus("1"); receivableFeeManagementMapper.updateReceivableFeeManagement(feeManagement); // 记录操作日志 ReceivableFeeManagementLog log = new ReceivableFeeManagementLog(); log.setReceivableFeeId(feeId); log.setOperator(SecurityUtils.getUsername()); log.setOperationTime(DateUtils.getNowDate()); log.setOperationDesc("生成应收账单,账单编号:" + billSystemNo); log.setCreateTime(DateUtils.getNowDate()); logService.insertReceivableFeeManagementLog(log); } // 调用批量更新方法 } return i; } /** * 根据关联账单编号批量更新应收费用管理记录 * 清除关联账单编号并将状态改为0(待生成账单) * * @param relatedBillNo 关联账单编号 * @return 结果 */ @Override public int updateReceivableFeeManagementByRelatedBillNo(String relatedBillNo) { return receivableFeeManagementMapper.updateReceivableFeeManagementByRelatedBillNo(relatedBillNo); } /** * 计算应收金额字符串描述 * 根据明细列表按币种汇总金额,格式如:"200港币100人民币" * * @param detailList 应收费用明细列表 * @return 应收金额字符串描述 */ private String calculateReceivableAmountStr(List detailList) { if (detailList == null || detailList.isEmpty()) { return ""; } // 按币种汇总金额 Map currencyAmountMap = new HashMap<>(); for (ReceivableFeeDetail detail : detailList) { String currency = detail.getCurrency(); BigDecimal billingAmount = detail.getActualAmount(); if (currency != null && billingAmount != null) { currencyAmountMap.merge(currency, billingAmount, BigDecimal::add); } } // 构建字符串描述 StringBuilder sb = new StringBuilder(); for (Map.Entry entry : currencyAmountMap.entrySet()) { if (sb.length() > 0) { sb.append(" "); } sb.append(entry.getValue().stripTrailingZeros().toPlainString()); // 根据币种显示对应的货币名称 String currency = entry.getKey(); if ("RMB".equals(currency)) { sb.append("人民币"); } else if ("HKD".equals(currency)) { sb.append("港币"); } else if ("USD".equals(currency)) { sb.append("美元"); } else { sb.append(currency); } } return sb.toString(); } /** * 导入应收费用管理数据(包含明细数据) * * @param receivableFeeList 应收费用管理数据列表(包含明细数据) * @param operName 操作用户 * @return 结果 */ @Override @Transactional(rollbackFor = Exception.class) public String importReceivableFee(List receivableFeeList, String operName) { if (receivableFeeList == null || receivableFeeList.isEmpty()) { throw new ServiceException("导入应收费用数据不能为空!"); } int successNum = 0; int failureNum = 0; StringBuilder successMsg = new StringBuilder(); StringBuilder failureMsg = new StringBuilder(); // 获取当前日期 Date now = DateUtils.getNowDate(); for (ReceivableFeeManagement receivableFee : receivableFeeList) { try { // 自动生成系统编号(和新增功能一样) String noByKey = systemDataNoService.getNoByKey(SystemDataNoEnum.YS); receivableFee.setSystemNo(noByKey); // 设置创建时间和创建人 receivableFee.setCreateTime(now); receivableFee.setCreateBy(operName); // 计算应收金额字符串描述 if (receivableFee.getReceivableFeeDetailList() != null && !receivableFee.getReceivableFeeDetailList().isEmpty()) { String receivableAmountStr = calculateReceivableAmountStr(receivableFee.getReceivableFeeDetailList()); receivableFee.setReceivableAmountStr(receivableAmountStr); } // 插入主表数据 receivableFeeManagementMapper.insertReceivableFeeManagement(receivableFee); // 处理明细数据(如果有) if (receivableFee.getReceivableFeeDetailList() != null && !receivableFee.getReceivableFeeDetailList().isEmpty()) { for (ReceivableFeeDetail detail : receivableFee.getReceivableFeeDetailList()) { detail.setReceivableFeeId(receivableFee.getId()); detail.setCreateBy(operName); detail.setCreateTime(now); receivableFeeDetailService.insertReceivableFeeDetail(detail); } } successNum++; successMsg.append("
" + successNum + ".应收费用 " + receivableFee.getSystemNo() + " 导入成功"); } catch (Exception e) { failureNum++; String msg = "
" + failureNum + ".应收费用 " + receivableFee.getSystemNo() + " 导入失败:"; failureMsg.append(msg + e.getMessage()); logger.error(msg, e); } } if (failureNum > 0) { failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); throw new ServiceException(failureMsg.toString()); } else { successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); } return successMsg.toString(); } /** * 下载导入模板(包含Sheet1主表和Sheet2明细表) * * @param exportKey 导出功能的唯一标识 */ @DataSource(DataSourceType.SLAVE) @Async @Override public void importTemplate(String exportKey) { String fileName = ExcelUtil.encodeFileName("应收费用导入模板"); // 设置当前任务为"下载中"状态 DownloadExportUtil.deleteDownloadFile(redisCache, exportKey, ExprotStatus.XZZ.getStatus()); try { // 创建多Sheet导入模板 createMultiSheetImportTemplate(exportKey,fileName); // 设置下载完成状态 DownloadExportUtil.setDownloadFile(redisCache, exportKey, fileName); logger.info("导入模板导出完成: {}, file: {}", exportKey, fileName); } catch (Exception e) { logger.error("导入模板导出失败: {}, error: {}", exportKey, e.getMessage(), e); DownloadExportUtil.deleteDownloadFile(redisCache, exportKey, ExprotStatus.XZYC.getStatus()); // 设置失败状态 throw e; } } /** * 创建多Sheet导入模板 * 包含Sheet1:应收费用主表模板 * 包含Sheet2:应收费用明细表模板 * * @param exportKey 导出功能的唯一标识 * @param fileName */ private void createMultiSheetImportTemplate(String exportKey, String fileName) { try { // 创建新的工作簿,包含两个Sheet SXSSFWorkbook workbook = new SXSSFWorkbook(1000); // 创建主表Sheet Sheet mainSheet = workbook.createSheet("应收费用主表"); createMainSheetTemplateWithExcelUtil(mainSheet); // 创建明细表Sheet Sheet detailSheet = workbook.createSheet("应收费用明细"); createDetailSheetTemplateWithExcelUtil(detailSheet); // 保存工作簿到文件 try (OutputStream out = Files.newOutputStream(Paths.get(getAbsoluteFile(fileName)))) { workbook.write(out); } workbook.close(); } catch (Exception e) { logger.error("创建多Sheet导入模板失败: {}", e.getMessage(), e); throw new UtilException("导入模板生成失败!"); } } /** * 使用ExcelUtil创建主表Sheet模板 * * @param sheet Sheet对象 */ private void createMainSheetTemplateWithExcelUtil(Sheet sheet) { try { // 使用ExcelUtil创建主表模板 ExcelUtil mainSheetUtil = new ExcelUtil<>(ReceivableFeeManagement.class); // 初始化ExcelUtil mainSheetUtil.initialize("应收费用主表", "应收费用主表导入模板(请勿修改序号列)", Excel.Type.EXPORT); // 通过反射获取workbook字段 Field workbookField = ExcelUtil.class.getDeclaredField("workbook"); workbookField.setAccessible(true); SXSSFWorkbook excelUtilWorkbook = (SXSSFWorkbook) workbookField.get(mainSheetUtil); // 获取ExcelUtil生成的Sheet Sheet generatedSheet = excelUtilWorkbook.getSheetAt(0); // 复制标题行到目标Sheet copyRow(generatedSheet.getRow(0), sheet.createRow(0)); // 复制表头行到目标Sheet copyRow(generatedSheet.getRow(1), sheet.createRow(1)); // 添加说明行 Row instructionRow = sheet.createRow(2); Cell instructionCell = instructionRow.createCell(0); instructionCell.setCellValue("说明:序号用于关联主表和明细表,请确保主表和明细表中的序号一致"); // 设置列宽 for (int i = 0; i < generatedSheet.getRow(1).getLastCellNum(); i++) { sheet.setColumnWidth(i, generatedSheet.getColumnWidth(i)); } } catch (Exception e) { logger.error("使用ExcelUtil创建主表模板失败: {}", e.getMessage(), e); throw new UtilException("主表模板生成失败!"); } } /** * 使用ExcelUtil创建明细表Sheet模板 * * @param sheet Sheet对象 */ private void createDetailSheetTemplateWithExcelUtil(Sheet sheet) { try { // 使用ExcelUtil创建明细表模板 ExcelUtil detailSheetUtil = new ExcelUtil<>(ReceivableFeeDetail.class); // 初始化ExcelUtil detailSheetUtil.initialize("应收费用明细", "应收费用明细表导入模板(序号与主表对应)", Excel.Type.EXPORT); // 通过反射获取workbook字段 Field workbookField = ExcelUtil.class.getDeclaredField("workbook"); workbookField.setAccessible(true); SXSSFWorkbook excelUtilWorkbook = (SXSSFWorkbook) workbookField.get(detailSheetUtil); // 获取ExcelUtil生成的Sheet Sheet generatedSheet = excelUtilWorkbook.getSheetAt(0); // 复制标题行到目标Sheet copyRow(generatedSheet.getRow(0), sheet.createRow(0)); // 复制表头行到目标Sheet copyRow(generatedSheet.getRow(1), sheet.createRow(1)); // 添加说明行 Row instructionRow = sheet.createRow(2); Cell instructionCell = instructionRow.createCell(0); instructionCell.setCellValue("说明:序号必须与主表中的序号一致,用于关联主表和明细表数据"); // 设置列宽 for (int i = 0; i < generatedSheet.getRow(1).getLastCellNum(); i++) { sheet.setColumnWidth(i, generatedSheet.getColumnWidth(i)); } } catch (Exception e) { logger.error("使用ExcelUtil创建明细表模板失败: {}", e.getMessage(), e); throw new UtilException("明细表模板生成失败!"); } } /** * 复制行内容 * * @param sourceRow 源行 * @param targetRow 目标行 */ private void copyRow(Row sourceRow, Row targetRow) { if (sourceRow == null) return; targetRow.setHeight(sourceRow.getHeight()); for (int i = 0; i < sourceRow.getLastCellNum(); i++) { Cell sourceCell = sourceRow.getCell(i); if (sourceCell != null) { Cell targetCell = targetRow.createCell(i); copyCell(sourceCell, targetCell); } } } /** * 复制单元格内容和样式 * * @param sourceCell 源单元格 * @param targetCell 目标单元格 */ private void copyCell(Cell sourceCell, Cell targetCell) { // 复制单元格样式 targetCell.setCellStyle(sourceCell.getCellStyle()); // 复制单元格值 switch (sourceCell.getCellType()) { case STRING: targetCell.setCellValue(sourceCell.getStringCellValue()); break; case NUMERIC: targetCell.setCellValue(sourceCell.getNumericCellValue()); break; case BOOLEAN: targetCell.setCellValue(sourceCell.getBooleanCellValue()); break; case FORMULA: targetCell.setCellFormula(sourceCell.getCellFormula()); break; default: targetCell.setCellValue(sourceCell.getStringCellValue()); } } /** * 获取文件的绝对路径 * * @param fileName 文件名 * @return 绝对路径 */ private String getAbsoluteFile(String fileName) { String downloadPath = RuoYiConfig.getDownloadPath(); File desc = new File(downloadPath + File.separator + fileName); if (!desc.exists()) { if (!desc.getParentFile().exists()) { desc.getParentFile().mkdirs(); } } return desc.getAbsolutePath(); } }