未结算报表zip导出

This commit is contained in:
hongchao 2025-12-10 17:04:39 +08:00
parent e298c589cf
commit 88d1c12a64
2 changed files with 347 additions and 360 deletions

View File

@ -1,7 +1,9 @@
package com.bonus.material.basic.domain.report;
import com.bonus.material.settlement.domain.SltAgreementInfo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.web.bind.annotation.RequestBody;
import java.math.BigDecimal;
import java.util.List;
@ -11,6 +13,8 @@ public class DownloadRequest {
private String zipName;
private List<ItemInfo> items;
private List<SltAgreementInfo> list;
private String taskId;
@Data

View File

@ -3,10 +3,15 @@ package com.bonus.material.settlement.controller;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
@ -21,13 +26,17 @@ import com.bonus.common.biz.config.PoiOutPage;
import com.bonus.common.biz.constant.GlobalConstants;
import com.bonus.common.biz.utils.RequestContext;
import com.bonus.common.biz.utils.StringHelper;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.ServletUtils;
import com.bonus.common.log.enums.OperaType;
import com.bonus.common.log.enums.OperatorType;
import com.bonus.material.basic.domain.BmProject;
import com.bonus.material.basic.domain.dto.DownloadProgress;
import com.bonus.material.basic.domain.report.DownloadRequest;
import com.bonus.material.common.annotation.PreventRepeatSubmit;
import com.bonus.material.common.domain.dto.SelectDto;
import com.bonus.material.common.utils.DocxUtil;
import com.bonus.material.part.domain.PartLeaseInfo;
import com.bonus.material.settlement.domain.*;
import com.bonus.material.settlement.domain.dto.ExportProgressManager;
@ -42,12 +51,18 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.bonus.common.log.annotation.SysLog;
@ -60,6 +75,7 @@ import com.bonus.common.core.utils.poi.ExcelUtil;
import com.bonus.common.core.web.page.TableDataInfo;
import java.util.ArrayList;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@ -93,6 +109,7 @@ public class SltAgreementInfoController extends BaseController {
@Autowired
private ExportProgressManager exportProgressManager;
private static final Map<String, DownloadProgress> downloadProgressMap = new ConcurrentHashMap<>();
/**
* 查询结算信息列表
*/
@ -2028,236 +2045,6 @@ public class SltAgreementInfoController extends BaseController {
}
// /**
// * 一键批量导出未结算报表zip
// */
// @ApiOperation(value = "一键批量导出未结算报表")
// @PreventRepeatSubmit
// @SysLog(title = "结算信息", businessType = OperaType.EXPORT, logType = 1,module = "结算管理->一键批量导出未结算报表")
// @PostMapping("/exportUnsettled")
// public void exportUnsettled(HttpServletResponse response, @RequestBody List<SltAgreementInfo> list) throws Exception {
// // 创建临时文件夹
// String tempDir = System.getProperty("java.io.tmpdir") + File.separator + UUID.randomUUID();
// new File(tempDir).mkdirs();
//
// try {
// for(SltAgreementInfo info : list){
// if(info.getAgreementId() == null){
// continue;
// }
// //根据协议id获取结算单位和结算工程
// SltAgreementInfo agreementInfo = sltAgreementInfoMapper.getUnitAndProjectByAgreementId(info.getAgreementId());
// // 生成文件名
// String fileName = "";
// String unitName = "";
// String projectName = "";
// // 清理非法字符Windows文件名不允许: \ / : * ? " < > |
// unitName = cleanFileName(agreementInfo.getUnitName());
// projectName = cleanFileName(agreementInfo.getProjectName());
// String agreementCode = cleanFileName(agreementInfo.getAgreementCode());
//
// // 构建安全的文件名限制总长度不超过150字符
// String rawFileName = agreementCode + "-" + unitName + "-" + projectName + "_结算单.xls";
// fileName = rawFileName.length() > 150 ?
// rawFileName.substring(0, 150) + ".xls" : rawFileName;
//
// //租赁费用明细
// BigDecimal totalCostLease = BigDecimal.valueOf(0.00);
// List<SltAgreementInfo> leaseList = new ArrayList<>();
// leaseList = sltAgreementInfoMapper.getLeaseList(info);
//
// for (SltAgreementInfo bean : leaseList) {
// if (null == bean.getLeasePrice()) {
// bean.setLeasePrice(BigDecimal.valueOf(0.00));
// }
// if (null == bean.getNum()) {
// bean.setNum(BigDecimal.valueOf(0L));
// }
// if (null == bean.getLeaseDays()) {
// bean.setLeaseDay(0L);
// }
// BigDecimal leasePrice = bean.getLeasePrice();
// BigDecimal num = bean.getNum();
// BigDecimal leaseDays = new BigDecimal(bean.getLeaseDays());
// BigDecimal costs = leasePrice.multiply(num).multiply(leaseDays);
// if(costs!=null){
// totalCostLease = totalCostLease.add(costs);
// }
// bean.setCosts(costs);
// }
// List<SltLeaseInfo> lease = Convert.toList(SltLeaseInfo.class, leaseList);
//
// //丢失费用明细
// BigDecimal totalCostLose = BigDecimal.valueOf(0.00);
// List<SltAgreementInfo> loseList = new ArrayList<>();
//
// loseList = sltAgreementInfoMapper.getLoseList(info);
//
// for (SltAgreementInfo bean : loseList) {
// if (null == bean.getBuyPrice()) {
// bean.setBuyPrice(BigDecimal.valueOf(0.00));
// }
// if (null == bean.getNum()) {
// bean.setNum(BigDecimal.valueOf(0L));
// }
// BigDecimal buyPrice = bean.getBuyPrice();
// BigDecimal num = bean.getNum();
// // 原价 x 数量
// BigDecimal costs = buyPrice.multiply(num);
// if(costs!=null){
// totalCostLose = totalCostLose.add(costs);
// }
// //计算租赁费用
// bean.setCosts(costs);
// }
// List<SltLeaseInfo> lose = Convert.toList(SltLeaseInfo.class, loseList);
//
// //维修费用明细
// BigDecimal totalCostRepair = BigDecimal.valueOf(0.00);
// List<SltAgreementInfo> repairList = new ArrayList<>();
//
//
// List<TmTask> taskRepairList = taskMapper.getTaskIdList(info);
// List<TmTask> taskRepairList2 = new ArrayList<>();
// taskRepairList2 = checkTeamAgreementInfo(info);
// if (null != taskRepairList && !taskRepairList.isEmpty()) {
// if (null != taskRepairList2 && !taskRepairList2.isEmpty()) {
// taskRepairList.addAll(taskRepairList2);
// }
// repairList = sltAgreementInfoMapper.getRepairDetailsList(info, taskRepairList);
// }
//
// for (SltAgreementInfo bean : repairList) {
// if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
// totalCostRepair = totalCostRepair.add(bean.getCosts());
// }
// }
// List<SltLeaseInfo> repair = Convert.toList(SltLeaseInfo.class, repairList);
//
// //报废费用明细
// BigDecimal totalCostScrap = BigDecimal.valueOf(0.00);
// List<SltAgreementInfo> scrapList = new ArrayList<>();
//
// List<TmTask> taskScrapList = taskMapper.getTaskIdList(info);
//
// List<TmTask> taskScrapList2 = new ArrayList<>();
// taskScrapList2 = checkTeamAgreementInfo(info);
//
// if (null != taskScrapList && !taskScrapList.isEmpty()) {
//
// if (null != taskScrapList2 && !taskScrapList2.isEmpty()) {
// taskScrapList.addAll(taskScrapList2);
// }
// scrapList = sltAgreementInfoMapper.getScrapDetailsList(info, taskScrapList);
// }
//
//
// for (SltAgreementInfo bean : scrapList) {
// if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
// totalCostScrap = totalCostScrap.add(bean.getCosts());
// }
// }
// List<SltLeaseInfo> scrap = Convert.toList(SltLeaseInfo.class, scrapList);
//
// //减免费用明细
// BigDecimal totalCostReduction = BigDecimal.valueOf(0.00);
// List<SltAgreementReduce> reductionList = new ArrayList<>();
//
// if (info.getAgreementId() != null){
// SltAgreementReduce bean =new SltAgreementReduce();
// bean.setAgreementId(info.getAgreementId());
// reductionList = sltAgreementRecudceMapper.getReductionList(bean);
// }
//
// for (SltAgreementReduce reduction : reductionList) {
// if(reduction.getLeaseMoney()!=null){
// totalCostReduction = totalCostReduction.add(reduction.getLeaseMoney());
// }
// }
// List<SltLeaseInfo> reduction = Convert.toList(SltLeaseInfo.class, reductionList);
//
//
// List<Map<String, Object>> resultsLease = new ArrayList<>();
// List<Map<String, Object>> resultsLose = new ArrayList<>();
// List<Map<String, Object>> resultsRepair = new ArrayList<>();
// List<Map<String, Object>> resultsScrap = new ArrayList<>();
// List<Map<String, Object>> resultsReduction = new ArrayList<>();
// if (lease!= null) {
// for (SltLeaseInfo bean : lease) {
// Map<String, Object> maps = outReceiveDetailsBeanToMap(bean, 1, 1);
// resultsLease.add(maps);
// }
// }
// if (lose!= null) {
// for (SltLeaseInfo bean : lose) {
// Map<String, Object> maps = outReceiveDetailsBeanToMap(bean, 2, 1);
// resultsLose.add(maps);
// }
// }
// if (repair!= null) {
// for (SltLeaseInfo bean : repair) {
// Map<String, Object> maps = outReceiveDetailsBeanToMap(bean, 3, 1);
// resultsRepair.add(maps);
// }
// }
// if (scrap!= null) {
// for (SltLeaseInfo bean : scrap) {
// Map<String, Object> maps = outReceiveDetailsBeanToMap(bean, 4, 1);
// resultsScrap.add(maps);
// }
// }
// if (reduction!= null) {
// for (SltLeaseInfo bean : reduction) {
// Map<String, Object> maps = outReceiveDetailsBeanToMap(bean, 5, 1);
// resultsReduction.add(maps);
// }
// }
//
// List<String> headersLease = receiveDetailsHeader(1,1);
// List<String> headersLose = receiveDetailsHeader(2,1);
// List<String> headersRepair = receiveDetailsHeader(3,1);
// List<String> headersScrap = receiveDetailsHeader(4,1);
// List<String> headersReduction = receiveDetailsHeader(5,1);
//
//// fileName = agreementInfo.getAgreementCode() + "-" + unitName + "-" + projectName+ "_结算单.xls" ;
// // 导出单个Excel文件
// String filePath = tempDir + File.separator + fileName;
// try (FileOutputStream fos = new FileOutputStream(filePath)) {
// HSSFWorkbook workbook = PoiOutPage.excelForcheckAll(resultsLease,resultsLose,resultsRepair,resultsScrap,resultsReduction, headersLease,headersLose,headersRepair,headersScrap,headersReduction, "结算明细",projectName,unitName,totalCostLease,totalCostLose,totalCostRepair,totalCostScrap,totalCostReduction);
// workbook.write(fos);
// }
//
// }
// // 创建压缩包
// String zipFileName = "结算单_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".zip";
// response.setContentType("application/zip");
// response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(zipFileName, "UTF-8"));
//
// try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
// File[] files = new File(tempDir).listFiles();
// if (files != null) {
// for (File file : files) {
// zipOut.putNextEntry(new ZipEntry(file.getName()));
// try (FileInputStream fis = new FileInputStream(file)) {
// byte[] buffer = new byte[1024];
// int len;
// while ((len = fis.read(buffer)) > 0) {
// zipOut.write(buffer, 0, len);
// }
// }
// zipOut.closeEntry();
// }
// }
// }
// } catch (Exception e) {
// log.error("一键批量导出未结算报表失败", e);
// } finally {
// // 删除临时文件
// FileUtils.deleteDirectory(new File(tempDir));
// }
// }
/************************************************************************/
/**
* 一键批量导出未结算报表zip
*/
@ -2265,120 +2052,12 @@ public class SltAgreementInfoController extends BaseController {
@PreventRepeatSubmit
@SysLog(title = "结算信息", businessType = OperaType.EXPORT, logType = 1,module = "结算管理->一键批量导出未结算报表")
@PostMapping("/exportUnsettled")
public ResponseEntity<Map<String, String>> exportUnsettled(HttpServletResponse response, @RequestBody List<SltAgreementInfo> list) throws Exception {
// 生成任务ID
String taskId = UUID.randomUUID().toString();
// 初始化进度
exportProgressManager.initProgress(taskId, list.size());
// 异步执行导出任务
CompletableFuture.runAsync(() -> {
try {
executeExport(taskId, list);
} catch (Exception e) {
log.error("导出任务执行失败, taskId: {}", taskId, e);
exportProgressManager.errorProgress(taskId, "导出失败: " + e.getMessage());
}
});
// 立即返回任务ID
Map<String, String> result = new HashMap<>();
result.put("taskId", taskId);
result.put("message", "导出任务已开始请通过taskId查询进度");
result.put("total", String.valueOf(list.size()));
return ResponseEntity.ok(result);
}
@ApiOperation(value = "查询导出进度")
@PostMapping("/exZipProgress")
public ResponseEntity<ExportProgressManager.ExportProgress> getExportProgress(@RequestBody SltAgreementInfo info) {
String taskId = info.getTaskId();
ExportProgressManager.ExportProgress progress = exportProgressManager.getProgress(taskId);
if (progress == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(progress);
}
@ApiOperation(value = "下载导出文件")
@PostMapping("/dlExProgress")
public void downloadExportFile(@RequestBody SltAgreementInfo info, HttpServletResponse response) {
try {
ExportProgressManager.ExportProgress progress = exportProgressManager.getProgress(info.getTaskId());
if (progress == null || !"completed".equals(progress.getStatus())) {
response.setStatus(HttpStatus.NOT_FOUND.value());
response.getWriter().write("文件不存在或导出未完成");
return;
}
File file = new File(progress.getFileUrl());
if (!file.exists()) {
response.setStatus(HttpStatus.NOT_FOUND.value());
response.getWriter().write("文件不存在");
return;
}
String fileName = "结算单_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".zip";
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
try (FileInputStream fis = new FileInputStream(file);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) > 0) {
os.write(buffer, 0, len);
}
}
} catch (Exception e) {
log.error("下载文件失败, taskId: {}", info.getTaskId(), e);
try {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
response.getWriter().write("下载失败: " + e.getMessage());
} catch (IOException ex) {
log.error("写入响应失败", ex);
}
}
}
@ApiOperation(value = "清理导出任务")
@DeleteMapping("/cleanExport/{taskId}")
public ResponseEntity<Map<String, String>> cleanExportTask(@PathVariable String taskId) {
try {
ExportProgressManager.ExportProgress progress = exportProgressManager.getProgress(taskId);
if (progress != null && progress.getFileUrl() != null) {
File file = new File(progress.getFileUrl());
if (file.exists()) {
file.delete();
}
}
exportProgressManager.removeProgress(taskId);
Map<String, String> result = new HashMap<>();
result.put("message", "任务清理成功");
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("清理任务失败, taskId: {}", taskId, e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
/**
* 执行导出任务的核心方法
*/
private void executeExport(String taskId, List<SltAgreementInfo> list) throws Exception {
String tempDir = System.getProperty("java.io.tmpdir") + File.separator + "export_" + taskId;
String zipFilePath = System.getProperty("java.io.tmpdir") + File.separator + "export_" + taskId + ".zip";
public void exportUnsettled(HttpServletResponse response, @RequestBody List<SltAgreementInfo> list) throws Exception {
// 创建临时文件夹
String tempDir = System.getProperty("java.io.tmpdir") + File.separator + UUID.randomUUID();
new File(tempDir).mkdirs();
try {
int processed = 0;
for(SltAgreementInfo info : list){
if(info.getAgreementId() == null){
continue;
@ -2565,33 +2244,315 @@ public class SltAgreementInfoController extends BaseController {
workbook.write(fos);
}
processed++;
exportProgressManager.updateProgress(taskId, 1);
// 每处理完一个文件短暂休息以避免资源过度占用
Thread.sleep(100);
}
// 创建压缩包
createZipFile(tempDir, zipFilePath);
String zipFileName = "结算单_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".zip";
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(zipFileName, "UTF-8"));
// 标记任务完成
exportProgressManager.completeProgress(taskId, zipFilePath);
} catch (Exception e) {
exportProgressManager.errorProgress(taskId, "导出过程发生错误: " + e.getMessage());
throw e;
} finally {
// 清理临时文件夹但保留zip文件
try {
FileUtils.deleteDirectory(new File(tempDir));
} catch (IOException e) {
log.warn("清理临时文件夹失败: {}", e.getMessage());
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
File[] files = new File(tempDir).listFiles();
if (files != null) {
for (File file : files) {
zipOut.putNextEntry(new ZipEntry(file.getName()));
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) > 0) {
zipOut.write(buffer, 0, len);
}
}
zipOut.closeEntry();
}
}
}
} catch (Exception e) {
log.error("一键批量导出未结算报表失败", e);
} finally {
// 删除临时文件
FileUtils.deleteDirectory(new File(tempDir));
}
}
@ApiOperation(value = "下载导出文件")
@PostMapping("/dlExProgress")
public void downloadExportFile(@RequestBody DownloadRequest request,HttpServletResponse response) throws IOException {
String taskId = request.getTaskId() != null ? request.getTaskId() : UUID.randomUUID().toString();
String zipName = request.getZipName() != null ? request.getZipName() : "未结算批量明细导出_" + LocalDate.now();
// 初始化进度
DownloadProgress progress = new DownloadProgress();
progress.setTotalFiles(request.getList().size());
progress.setStatus("processing");
progress.setStartTime(System.currentTimeMillis());
downloadProgressMap.put(taskId, progress);
try {
String encoded = java.net.URLEncoder.encode(zipName + ".zip", "UTF-8");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encoded);
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
// 设置流式传输相关头部
response.setHeader("Transfer-Encoding", "chunked");
response.setHeader("X-Content-Type-Options", "nosniff");
// 使用低压缩级别提高速度
try (ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(response.getOutputStream())) {
zipOut.setLevel(Deflater.BEST_SPEED);
zipOut.setEncoding("UTF-8");
zipOut.setUseZip64(Zip64Mode.AsNeeded);
AtomicInteger fileCount = new AtomicInteger(0);
for(SltAgreementInfo info : request.getList()){
if(info.getAgreementId() == null){
continue;
}
// 更新进度
progress.setCurrentFileName("正在生成: " + info.getAgreementCode());
progress.setCurrentFile(fileCount.incrementAndGet());
progress.setPercentage((int)((fileCount.get() * 100.0) / progress.getTotalFiles()));
updateProgress(taskId, progress);
//根据协议id获取结算单位和结算工程
SltAgreementInfo agreementInfo = sltAgreementInfoMapper.getUnitAndProjectByAgreementId(info.getAgreementId());
// 生成文件名
String fileName = "";
String unitName = "";
String projectName = "";
// 清理非法字符Windows文件名不允许: \ / : * ? " < > |
unitName = cleanFileName(agreementInfo.getUnitName());
projectName = cleanFileName(agreementInfo.getProjectName());
String agreementCode = cleanFileName(agreementInfo.getAgreementCode());
// 构建安全的文件名限制总长度不超过150字符
String rawFileName = agreementCode + "-" + unitName + "-" + projectName + "_结算单.xls";
fileName = rawFileName.length() > 150 ?
rawFileName.substring(0, 150) + ".xls" : rawFileName;
//租赁费用明细
BigDecimal totalCostLease = BigDecimal.valueOf(0.00);
List<SltAgreementInfo> leaseList = new ArrayList<>();
leaseList = sltAgreementInfoMapper.getLeaseList(info);
for (SltAgreementInfo bean : leaseList) {
if (null == bean.getLeasePrice()) {
bean.setLeasePrice(BigDecimal.valueOf(0.00));
}
if (null == bean.getNum()) {
bean.setNum(BigDecimal.valueOf(0L));
}
if (null == bean.getLeaseDays()) {
bean.setLeaseDay(0L);
}
BigDecimal leasePrice = bean.getLeasePrice();
BigDecimal num = bean.getNum();
BigDecimal leaseDays = new BigDecimal(bean.getLeaseDays());
BigDecimal costs = leasePrice.multiply(num).multiply(leaseDays);
if(costs!=null){
totalCostLease = totalCostLease.add(costs);
}
bean.setCosts(costs);
}
List<SltLeaseInfo> lease = Convert.toList(SltLeaseInfo.class, leaseList);
//丢失费用明细
BigDecimal totalCostLose = BigDecimal.valueOf(0.00);
List<SltAgreementInfo> loseList = new ArrayList<>();
loseList = sltAgreementInfoMapper.getLoseList(info);
for (SltAgreementInfo bean : loseList) {
if (null == bean.getBuyPrice()) {
bean.setBuyPrice(BigDecimal.valueOf(0.00));
}
if (null == bean.getNum()) {
bean.setNum(BigDecimal.valueOf(0L));
}
BigDecimal buyPrice = bean.getBuyPrice();
BigDecimal num = bean.getNum();
// 原价 x 数量
BigDecimal costs = buyPrice.multiply(num);
if(costs!=null){
totalCostLose = totalCostLose.add(costs);
}
//计算租赁费用
bean.setCosts(costs);
}
List<SltLeaseInfo> lose = Convert.toList(SltLeaseInfo.class, loseList);
//维修费用明细
BigDecimal totalCostRepair = BigDecimal.valueOf(0.00);
List<SltAgreementInfo> repairList = new ArrayList<>();
List<TmTask> taskRepairList = taskMapper.getTaskIdList(info);
List<TmTask> taskRepairList2 = new ArrayList<>();
taskRepairList2 = checkTeamAgreementInfo(info);
if (null != taskRepairList && !taskRepairList.isEmpty()) {
if (null != taskRepairList2 && !taskRepairList2.isEmpty()) {
taskRepairList.addAll(taskRepairList2);
}
repairList = sltAgreementInfoMapper.getRepairDetailsList(info, taskRepairList);
}
for (SltAgreementInfo bean : repairList) {
if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
totalCostRepair = totalCostRepair.add(bean.getCosts());
}
}
List<SltLeaseInfo> repair = Convert.toList(SltLeaseInfo.class, repairList);
//报废费用明细
BigDecimal totalCostScrap = BigDecimal.valueOf(0.00);
List<SltAgreementInfo> scrapList = new ArrayList<>();
List<TmTask> taskScrapList = taskMapper.getTaskIdList(info);
List<TmTask> taskScrapList2 = new ArrayList<>();
taskScrapList2 = checkTeamAgreementInfo(info);
if (null != taskScrapList && !taskScrapList.isEmpty()) {
if (null != taskScrapList2 && !taskScrapList2.isEmpty()) {
taskScrapList.addAll(taskScrapList2);
}
scrapList = sltAgreementInfoMapper.getScrapDetailsList(info, taskScrapList);
}
for (SltAgreementInfo bean : scrapList) {
if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
totalCostScrap = totalCostScrap.add(bean.getCosts());
}
}
List<SltLeaseInfo> scrap = Convert.toList(SltLeaseInfo.class, scrapList);
//减免费用明细
BigDecimal totalCostReduction = BigDecimal.valueOf(0.00);
List<SltAgreementReduce> reductionList = new ArrayList<>();
if (info.getAgreementId() != null){
SltAgreementReduce bean =new SltAgreementReduce();
bean.setAgreementId(info.getAgreementId());
reductionList = sltAgreementRecudceMapper.getReductionList(bean);
}
for (SltAgreementReduce reduction : reductionList) {
if(reduction.getLeaseMoney()!=null){
totalCostReduction = totalCostReduction.add(reduction.getLeaseMoney());
}
}
List<SltLeaseInfo> reduction = Convert.toList(SltLeaseInfo.class, reductionList);
List<Map<String, Object>> resultsLease = new ArrayList<>();
List<Map<String, Object>> resultsLose = new ArrayList<>();
List<Map<String, Object>> resultsRepair = new ArrayList<>();
List<Map<String, Object>> resultsScrap = new ArrayList<>();
List<Map<String, Object>> resultsReduction = new ArrayList<>();
if (lease!= null) {
for (SltLeaseInfo bean : lease) {
Map<String, Object> maps = outReceiveDetailsBeanToMap(bean, 1, 1);
resultsLease.add(maps);
}
}
if (lose!= null) {
for (SltLeaseInfo bean : lose) {
Map<String, Object> maps = outReceiveDetailsBeanToMap(bean, 2, 1);
resultsLose.add(maps);
}
}
if (repair!= null) {
for (SltLeaseInfo bean : repair) {
Map<String, Object> maps = outReceiveDetailsBeanToMap(bean, 3, 1);
resultsRepair.add(maps);
}
}
if (scrap!= null) {
for (SltLeaseInfo bean : scrap) {
Map<String, Object> maps = outReceiveDetailsBeanToMap(bean, 4, 1);
resultsScrap.add(maps);
}
}
if (reduction!= null) {
for (SltLeaseInfo bean : reduction) {
Map<String, Object> maps = outReceiveDetailsBeanToMap(bean, 5, 1);
resultsReduction.add(maps);
}
}
List<String> headersLease = receiveDetailsHeader(1,1);
List<String> headersLose = receiveDetailsHeader(2,1);
List<String> headersRepair = receiveDetailsHeader(3,1);
List<String> headersScrap = receiveDetailsHeader(4,1);
List<String> headersReduction = receiveDetailsHeader(5,1);
// fileName = agreementInfo.getAgreementCode() + "-" + unitName + "-" + projectName+ "_结算单.xls" ;
// 导出单个Excel文件
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
// 生成Excel工作簿
HSSFWorkbook workbook = PoiOutPage.excelForcheckAll(
resultsLease, resultsLose, resultsRepair, resultsScrap, resultsReduction,
headersLease, headersLose, headersRepair, headersScrap, headersReduction,
"结算明细", projectName, unitName,
totalCostLease, totalCostLose, totalCostRepair, totalCostScrap, totalCostReduction);
workbook.write(baos);
workbook.close();
// 将Excel字节流直接添加到ZIP
addToZipStream(zipOut, fileName, baos.toByteArray());
// 定期刷新缓冲区
if (fileCount.get() % 5 == 0) {
zipOut.flush();
response.flushBuffer();
}
}
}
// 更新进度为完成
progress.setStatus("completed");
progress.setPercentage(100);
progress.setEndTime(System.currentTimeMillis());
progress.setCurrentFileName("下载完成");
updateProgress(taskId, progress);
zipOut.finish();
} catch (IOException e) {
progress.setStatus("error");
progress.setErrorMessage(e.getMessage());
updateProgress(taskId, progress);
throw e;
}
} finally {
// 清理进度信息延迟清理以便前端可以获取最终状态
new Timer().schedule(new TimerTask() {
@Override
public void run() {
downloadProgressMap.remove(taskId);
}
}, 300000); // 5分钟后清理
}
}
/**
* 创建压缩包
*/
@ -2617,9 +2578,31 @@ public class SltAgreementInfoController extends BaseController {
private void addToZipStream(ZipArchiveOutputStream zipOut, String path, byte[] bytes) throws IOException {
if (bytes == null || bytes.length == 0) return;
ZipArchiveEntry entry = new ZipArchiveEntry(path);
entry.setSize(bytes.length);
zipOut.putArchiveEntry(entry);
try (ByteArrayInputStream in = new ByteArrayInputStream(bytes)) {
IOUtils.copy(in, zipOut);
}
zipOut.closeArchiveEntry();
zipOut.flush();
}
/**
* 更新进度信息
*/
private void updateProgress(String taskId, DownloadProgress progress) {
if (taskId != null && progress != null) {
downloadProgressMap.put(taskId, progress);
}
}