From 4ad74a1dc93d67d9bcb8198f5243f09097fe080e Mon Sep 17 00:00:00 2001 From: "huojin\\hj" <982011> Date: Tue, 15 Jul 2025 10:24:09 +0800 Subject: [PATCH] =?UTF-8?q?fastExcel=E5=AF=BC=E5=87=BA=E5=AE=B9=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 + .../basicdata/rest/StockController.java | 10 +- .../basicdata/service/StockService.java | 21 ++- .../service/impl/StockServiceImpl.java | 72 +++++++-- .../youchain/basicdata/vo/StockExcelVO.java | 22 +++ .../com/youchain/utils/FastExcelUtil.java | 145 ++++++++++++++++++ .../main/resources/config/application-dev.yml | 2 +- .../src/main/resources/config/application.yml | 12 +- 8 files changed, 263 insertions(+), 27 deletions(-) create mode 100644 youchain-system/src/main/java/com/youchain/basicdata/vo/StockExcelVO.java create mode 100644 youchain-system/src/main/java/com/youchain/utils/FastExcelUtil.java diff --git a/pom.xml b/pom.xml index 11d9233..706b742 100644 --- a/pom.xml +++ b/pom.xml @@ -199,6 +199,12 @@ 6.11 + + + cn.idev.excel + fastexcel + 1.2.0 + diff --git a/youchain-system/src/main/java/com/youchain/basicdata/rest/StockController.java b/youchain-system/src/main/java/com/youchain/basicdata/rest/StockController.java index d494024..1b7b2fe 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/rest/StockController.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/rest/StockController.java @@ -22,6 +22,7 @@ import com.youchain.annotation.Log; import com.youchain.basicdata.domain.Stock; import com.youchain.basicdata.service.StockService; import com.youchain.basicdata.service.dto.StockQueryCriteria; +import com.youchain.basicdata.vo.StockExcelVO; import com.youchain.config.FileProperties; import com.youchain.exception.handler.ApiResult; import com.youchain.modules.system.domain.Dept; @@ -61,12 +62,19 @@ public class StockController { @Log("导出数据") @ApiOperation("导出数据") - @GetMapping(value = "/download") + @GetMapping(value = "/download2") @PreAuthorize("@el.check('stock:list')") public void exportStock(HttpServletResponse response, StockQueryCriteria criteria) throws IOException { stockService.download(stockService.queryAll(criteria), response); } + @Log("导出 @author 卓大") + @ApiOperation("导出数据") + @GetMapping("/download") + public void exportStocks(HttpServletResponse response,StockQueryCriteria criteria){ + stockService.exportStocks(criteria, response); + } + @Log("容器导入") @ApiOperation("容器导入") @PostMapping(value = "/importStock") diff --git a/youchain-system/src/main/java/com/youchain/basicdata/service/StockService.java b/youchain-system/src/main/java/com/youchain/basicdata/service/StockService.java index de182e1..4cc4686 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/service/StockService.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/service/StockService.java @@ -21,6 +21,7 @@ import com.youchain.basicdata.domain.Point; import com.youchain.basicdata.domain.Stock; import com.youchain.basicdata.service.dto.StockDto; import com.youchain.basicdata.service.dto.StockQueryCriteria; +import com.youchain.basicdata.vo.StockExcelVO; import com.youchain.businessdata.domain.Pick; import org.springframework.data.domain.Pageable; import org.springframework.web.multipart.MultipartFile; @@ -137,9 +138,9 @@ public interface StockService { * 查询指定库区可用的空车 * * @param areaName 库区 - * @param status 状态 + * @param status 状态 */ - List findByFreeOrUsedStock(String areaName,String status); + List findByFreeOrUsedStock(String areaName, String status); /** * 根据点位编号查询容器 @@ -162,5 +163,21 @@ public interface StockService { */ String stockMsg(String msg); + /** + * 游标分页 + * + * @param lastId 每页的最后一个id + * @param pageSize 每页数量 + * @param criteria 查询参数 + * @return List + */ + List listByStocks(Long lastId, int pageSize, StockQueryCriteria criteria); + + /** + * 导出 + * @param criteria 查询参数 + * @param response 请求 + */ + void exportStocks(StockQueryCriteria criteria,HttpServletResponse response); } diff --git a/youchain-system/src/main/java/com/youchain/basicdata/service/impl/StockServiceImpl.java b/youchain-system/src/main/java/com/youchain/basicdata/service/impl/StockServiceImpl.java index 8903b38..e032b7f 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/service/impl/StockServiceImpl.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/service/impl/StockServiceImpl.java @@ -15,25 +15,16 @@ */ package com.youchain.basicdata.service.impl; -import cn.hutool.core.date.DateUtil; +import com.youchain.basicdata.vo.StockExcelVO; +import org.apache.commons.lang3.StringUtils; import cn.hutool.poi.excel.ExcelReader; import cn.hutool.poi.excel.ExcelUtil; -import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; -import com.youchain.RequestData.TransTask; -import com.youchain.appupdate.ReturnJson.ReturnTaskVo; -import com.youchain.basicdata.domain.Area; -import com.youchain.basicdata.domain.Item; + import com.youchain.basicdata.domain.Point; import com.youchain.basicdata.domain.Stock; -import com.youchain.basicdata.repository.AreaRepository; import com.youchain.basicdata.repository.PointRepository; -import com.youchain.basicdata.service.ItemService; -import com.youchain.basicdata.vo.BarCodeVo; -import com.youchain.businessdata.domain.*; -import com.youchain.businessdata.repository.*; -import com.youchain.businessdata.service.*; -import com.youchain.businessdata.service.dto.TaskDto; + import com.youchain.config.FileProperties; import com.youchain.exception.BadRequestException; import com.youchain.modules.mnt.websocket.MsgType; @@ -55,12 +46,10 @@ import org.springframework.data.domain.Pageable; import org.springframework.web.multipart.MultipartFile; import java.io.File; -import java.sql.Timestamp; import java.util.*; import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; import javax.servlet.http.HttpServletResponse; @@ -78,6 +67,7 @@ public class StockServiceImpl implements StockService { private final StockRepository stockRepository; private final PointRepository pointRepository; private final StockMapper stockMapper; + private final EntityManager entityMapper; private final FileProperties properties; @@ -244,6 +234,54 @@ public class StockServiceImpl implements StockService { return "error"; } + @Override + public List listByStocks(Long lastId, int pageSize, StockQueryCriteria criteria) { + // 构建基础 HQL 查询语句 + String hql = "SELECT s FROM Stock s WHERE 1=1 "; + if (StringUtils.isNotEmpty(criteria.getCode())) { + hql += " AND s.code ='" + criteria.getCode() + "' "; + } + + // 添加游标条件:只获取比当前游标大的 id 的记录 + if (lastId != null) { + hql += " AND s.id > " + lastId; + } + + // 按照 id 排序,确保结果集顺序一致 + hql += " ORDER BY s.id ASC"; + + // 创建查询对象 + TypedQuery query = entityMapper.createQuery(hql, Stock.class); + + // 设置分页大小 + query.setMaxResults(pageSize); + + + return query.getResultList(); + } + + @Override + public void exportStocks(StockQueryCriteria criteria, HttpServletResponse response) { + try { + FastExcelUtil.batchExportExcel( + response, + "容器信息.xlsx", + "容器", + StockExcelVO.class, + (lastId, pageSize) -> this.listByStocks(lastId, pageSize, criteria), + stock -> StockExcelVO.builder() + .code(stock.getCode()) + .type(stock.getStockType()) + .build(), + Stock::getId, + 2000 + ); + } catch (IOException e) { + throw new BadRequestException("文件导出失败,请重试!"); + } + + } + /** * 验证容器是否存在 diff --git a/youchain-system/src/main/java/com/youchain/basicdata/vo/StockExcelVO.java b/youchain-system/src/main/java/com/youchain/basicdata/vo/StockExcelVO.java new file mode 100644 index 0000000..bc1bb48 --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/basicdata/vo/StockExcelVO.java @@ -0,0 +1,22 @@ +package com.youchain.basicdata.vo; + +import cn.idev.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.write.style.ColumnWidth; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ColumnWidth(20) +public class StockExcelVO { + @ExcelProperty("代码") + private String code; + + @ExcelProperty("类型") + private String type; + +} diff --git a/youchain-system/src/main/java/com/youchain/utils/FastExcelUtil.java b/youchain-system/src/main/java/com/youchain/utils/FastExcelUtil.java new file mode 100644 index 0000000..7d641bd --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/utils/FastExcelUtil.java @@ -0,0 +1,145 @@ +package com.youchain.utils; + +import cn.idev.excel.ExcelWriter; +import cn.idev.excel.FastExcel; +import cn.idev.excel.write.metadata.WriteSheet; +import cn.idev.excel.write.metadata.style.WriteCellStyle; +import cn.idev.excel.write.metadata.style.WriteFont; +import cn.idev.excel.write.style.HorizontalCellStyleStrategy; + +import com.youchain.exception.BadRequestException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.MediaTypeFactory; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Collection; + +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.ToLongFunction; +import java.util.stream.Collectors; + +import static cn.hutool.core.util.CharsetUtil.UTF_8; + + +/** + * excel 工具类 + */ +@Slf4j +public class FastExcelUtil { + + /** + * 设置下载文件消息头 + * + * @param response 响应 + * @param fileName 文件名 + * @param fileSize 文件大小 + */ + public static void setDownloadFileHeader(HttpServletResponse response, String fileName, Long fileSize) { + response.setCharacterEncoding(UTF_8); + if (fileSize != null) { + response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileSize)); + } + + if (StringUtils.isNotEmpty(fileName)) { + response.setHeader(HttpHeaders.CONTENT_TYPE, MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM) + ";charset=utf-8"); + try { + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, UTF_8).replaceAll("\\+", "%20")); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + response.setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION); + } + } + + /** + * 获取样式 + * + * @return horizontalCellStyleStrategy + */ + public static HorizontalCellStyleStrategy getHorizontalCellStyleStrategy() { + + WriteCellStyle headWriteCellStyle = new WriteCellStyle(); + headWriteCellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex()); + + WriteFont headWriteFont = new WriteFont(); + headWriteFont.setFontName("宋体"); + headWriteFont.setColor(IndexedColors.WHITE.getIndex()); + headWriteCellStyle.setWriteFont(headWriteFont); + + WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); + contentWriteCellStyle.setFillForegroundColor(IndexedColors.BLACK.getIndex()); + + return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); + } + + /** + * 通用单sheet导出 + */ + public static void exportExcel(HttpServletResponse response, String fileName, String sheetName, Class head, Collection data) throws IOException { + // 设置下载消息头 + setDownloadFileHeader(response, fileName, null); + //样式 + HorizontalCellStyleStrategy horizontalCellStyleStrategy = getHorizontalCellStyleStrategy(); + // 下载 + FastExcel.write(response.getOutputStream(), head) + .autoCloseStream(Boolean.FALSE) + .sheet(sheetName) + .registerWriteHandler(horizontalCellStyleStrategy) + .doWrite(data); + } + + /** + * 大数据导出 + * @param response 响应 + * @param fileName 文件名 + * @param sheetName sheet名称 + * @param head 头 + * @param pageQueryFunction 查询方法 + * @param convertFunction 转换方法 + * @param idExtractor id提取方法 + * @param pageSize 每页大小 + * @param 泛型 + * @param 泛型 + * @throws IOException 抛出IO异常 + */ + public static void batchExportExcel(HttpServletResponse response, String fileName, String sheetName, Class head, BiFunction> pageQueryFunction, Function convertFunction, ToLongFunction idExtractor, int pageSize) throws IOException { + long startTime = System.currentTimeMillis(); + // 设置下载消息头 + setDownloadFileHeader(response, fileName, null); + HorizontalCellStyleStrategy horizontalCellStyleStrategy = getHorizontalCellStyleStrategy(); + try (ExcelWriter excelWriter = FastExcel.write(response.getOutputStream(), head).registerWriteHandler(horizontalCellStyleStrategy).build()) { + WriteSheet writeSheet = FastExcel.writerSheet(sheetName).build(); + long lastId = 0;//最后一个id + while (true) { + List batch = pageQueryFunction.apply(lastId, pageSize); + if (batch.isEmpty()) { + break; + } + + List excelData = batch.stream() + .map(convertFunction) + .collect(Collectors.toList()); + excelWriter.write(excelData, writeSheet); + + lastId = batch.stream() + .mapToLong(idExtractor) + .max() + .orElse(lastId); + } + excelWriter.finish(); + log.info(" 耗时: {}ms", System.currentTimeMillis() - startTime); + } catch (Exception e) { + throw new BadRequestException("导出失败"); + } + } +} diff --git a/youchain-system/src/main/resources/config/application-dev.yml b/youchain-system/src/main/resources/config/application-dev.yml index 5fe3b40..02f875a 100644 --- a/youchain-system/src/main/resources/config/application-dev.yml +++ b/youchain-system/src/main/resources/config/application-dev.yml @@ -4,7 +4,7 @@ spring: druid: db-type: com.alibaba.druid.pool.DruidDataSource driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy - url: jdbc:log4jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:53306}/${DB_NAME:byd_wms}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&rewriteBatchedStatements=true + url: jdbc:log4jdbc:mysql://${DB_HOST:47.103.100.52}:${DB_PORT:53306}/${DB_NAME:byd_wms}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&rewriteBatchedStatements=true username: ${DB_USER:root} password: ${DB_PWD:Youchain@56} # 初始连接数 diff --git a/youchain-system/src/main/resources/config/application.yml b/youchain-system/src/main/resources/config/application.yml index b1ffe53..65ebfa4 100644 --- a/youchain-system/src/main/resources/config/application.yml +++ b/youchain-system/src/main/resources/config/application.yml @@ -6,8 +6,8 @@ spring: freemarker: check-template-location: false profiles: - active: prod - #active: dev + #active: prod + active: dev jackson: time-zone: GMT+8 data: @@ -36,11 +36,11 @@ spring: redis: #数据库索引 database: ${REDIS_DB:2} - host: ${REDIS_HOST:192.168.100.102} - password: ${REDIS_PWD:123456} + #host: ${REDIS_HOST:192.168.100.102} + #password: ${REDIS_PWD:123456} - #host: ${REDIS_HOST:localhost} - #password: ${REDIS_PWD:} + host: ${REDIS_HOST:localhost} + password: ${REDIS_PWD:} port: ${REDIS_PORT:6379} #连接超时时间 timeout: 5000