diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/customizeExcel/CustomizeExcelController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/customizeExcel/CustomizeExcelController.java index 9d973860..8eafff9f 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/customizeExcel/CustomizeExcelController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/customizeExcel/CustomizeExcelController.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.module.member.controller.admin.customizeExcel; +import cn.hutool.core.date.DateUtil; import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.member.controller.admin.customizeExcel.vo.OrderExcelVO; import cn.iocoder.yudao.module.member.service.customizeExcel.CustomizeExcelService; +import cn.iocoder.yudao.module.member.util.CustomMergeStrategy; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.converters.longconverter.LongStringConverter; @@ -12,6 +14,9 @@ import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -23,9 +28,11 @@ import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.Stream; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @@ -42,47 +49,98 @@ public class CustomizeExcelController { @GetMapping("/orderExcel") @Operation(summary = "导出订单详情") @OperateLog(type = EXPORT) - public void exportBusinessExcel(String startTime,String endTime, + public void exportBusinessExcel(String startTime,String endTime,Long carteenId, HttpServletResponse response) throws IOException { - List orderExcelVOS = excelService.exportOrderExcel(startTime, endTime); + List orderExcelVOS = excelService.exportOrderExcel(startTime, endTime,carteenId); // 导出 Excel ExcelUtils.write(response, "订单详情统计.xls", "数据", OrderExcelVO.class, orderExcelVOS); - - } + @GetMapping("/orderExcel1") + @Operation(summary = "导出订单详情") + @OperateLog(type = EXPORT) + public void exportBusinessExcel1(String startTime,String endTime,Long carteenId, + HttpServletResponse response) throws IOException { + List orderExcelVOS = excelService.exportOrderExcel(startTime, endTime,carteenId); + exporOrderDate(orderExcelVOS,response); + } /** * 根据时间导出多个sheet 页 - * @param list + * @param + * @param data1 * @param response * @throws IOException */ - public void exporOrderDate(List list,HttpServletResponse response) throws IOException { - Map> collect = list.stream().collect(Collectors.groupingBy(OrderExcelVO::getDayTime)); + public void exporOrderDate(List data1,HttpServletResponse response) throws IOException { + data1.forEach(f-> + { + f.setDayTime(f.getDayTime().substring(0,10)); + if(f.getNickname()==null ){ + f.setNickname("null"); + } + if(f.getMobile()==null){ + f.setMobile("null"); + } + }); + Map> collect = data1.stream().collect(Collectors.groupingBy(OrderExcelVO::getDayTime)); // 按key(时间)排序,将数据按时间顺序放入列表 List>> sortedEntries = collect.entrySet() .stream() .sorted(Map.Entry.comparingByKey()) // 按时间排序 .collect(Collectors.toList()); - // 创建输出流 - try (OutputStream outputStream = response.getOutputStream(); - ExcelWriter excelWriter = EasyExcel.write(outputStream).build()) { - int sheetIndex = 0; - // 逐个创建Sheet,并写入每个时间段的数据 + long l = System.currentTimeMillis(); + // 设置文件名和响应内容类型 + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("订单详情统计.xlsx", StandardCharsets.UTF_8.name())); + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + try (SXSSFWorkbook workbook = new SXSSFWorkbook(); OutputStream outputStream = response.getOutputStream()) { for (Map.Entry> entry : sortedEntries) { - WriteSheet writeSheet = EasyExcel.writerSheet(sheetIndex, "数据 " + entry.getKey()) // 使用时间作为sheet名 - .head(OrderExcelVO.class) - .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自动列宽策略 - .build(); - // 写入数据到当前Sheet - excelWriter.write(entry.getValue(), writeSheet); - sheetIndex++; + // 创建一个Sheet + Sheet sheet = workbook.createSheet("数据"+entry.getKey()); + // 处理数据和写入逻辑 + createHeader(sheet, workbook); // 创建表头 + int rowNum = 1; + // 写入数据 + for (OrderExcelVO order : data1) { + Row row = sheet.createRow(rowNum++); + row.createCell(0).setCellValue(order.getDayTime()); + row.createCell(1).setCellValue(order.getNickname()); + row.createCell(2).setCellValue(order.getMobile()); + row.createCell(3).setCellValue(order.getTimeSlot()); + row.createCell(4).setCellValue(order.getTotalMoney().toString()); + row.createCell(5).setCellValue(order.getDishesName()); + row.createCell(5).setCellValue(order.getUnitPrice()==null?"0.00":order.getUnitPrice().toString()); + row.createCell(7).setCellValue(order.getWeight()); + row.createCell(8).setCellValue(order.getPrice().toString()); + } + List data = entry.getValue(); + List> collect1 = Stream.of(data.stream().map(OrderExcelVO::getNickname).collect(Collectors.toList()), data.stream().map(OrderExcelVO::getMobile).collect(Collectors.toList()), data.stream().map(f -> f.getTotalMoney().toString()).collect(Collectors.toList())).collect(Collectors.toList()); + Map map = new HashMap<>(); + map.put(1, 0); // 第三列合并 + map.put(2, 1); // 第三列合并 + map.put(3, 2); // 第三列合并 + map.put(4, 2); // 第四列合并 + CustomMergeStrategy customMergeStrategy = new CustomMergeStrategy(collect1, map); + customMergeStrategy.merge(sheet,4); + // 将数据写入输出流 } - // 下载EXCEL,返回给前段stream流 - excelWriter.finish(); + workbook.write(outputStream); outputStream.flush(); + System.out.println( System.currentTimeMillis()-l); } } + // 创建表头 + private void createHeader(Sheet sheet, SXSSFWorkbook workbook) { + Row header = sheet.createRow(0); + header.createCell(0).setCellValue("日期"); + header.createCell(1).setCellValue("用户名"); + header.createCell(2).setCellValue("手机"); + header.createCell(3).setCellValue("总价"); + header.createCell(4).setCellValue("时间段"); + header.createCell(5).setCellValue("菜名"); + header.createCell(6).setCellValue("单价(元/50g)"); + header.createCell(7).setCellValue("重量(g)"); + header.createCell(8).setCellValue("价格(元)"); + } } \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/business/vo/BusinessDataVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/business/vo/BusinessDataVO.java index f74def83..d05c1ba0 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/business/vo/BusinessDataVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/business/vo/BusinessDataVO.java @@ -9,7 +9,7 @@ import java.util.List; @Data public class BusinessDataVO { - private BusinessRespVO old; + private BusinessRespVO now; private List businessList; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/customizeExcel/CustomizeExcelMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/customizeExcel/CustomizeExcelMapper.java index d892a369..7f1eefbb 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/customizeExcel/CustomizeExcelMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/customizeExcel/CustomizeExcelMapper.java @@ -11,5 +11,5 @@ import java.util.List; public interface CustomizeExcelMapper { - List selectOrder(@Param("startTime")String startTime, @Param("endTime")String endTime); + List selectOrder(@Param("startTime")String startTime, @Param("endTime")String endTime, @Param("carteenId")Long carteenId); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/business/BusinessServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/business/BusinessServiceImpl.java index 6e7019b8..d17a3870 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/business/BusinessServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/business/BusinessServiceImpl.java @@ -166,6 +166,9 @@ public class BusinessServiceImpl implements BusinessService { @Override public BusinessDataVO getDay(String time,Long carteenId) { + Integer nowDay = MemberTimeUtils.getDay(time); + time = MemberTimeUtils.getYearMonth(time); + BusinessDataVO businessDataVO = new BusinessDataVO(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -210,17 +213,14 @@ public class BusinessServiceImpl implements BusinessService { if(CollectionUtil.isNotEmpty(previousList)){ BeanUtil.copyProperties(previousList.get(0), old); }else { - old.setTurnover(BigDecimal.ZERO).setOrderSum(0).setReduce(BigDecimal.ZERO).setWeigh(BigDecimal.ZERO) - .setBreakfast(BigDecimal.ZERO).setLunch(BigDecimal.ZERO).setDinner(BigDecimal.ZERO); + old = getInitBusinessRespVO(); } // 循环遍历该月的每一天 for (int day = 1; day <= daysInMonth; day++) { BusinessRespVO bean = new BusinessRespVO(); if(map.get(day) == null){ - bean.setTurnover(BigDecimal.ZERO).setOrderSum(0).setReduce(BigDecimal.ZERO).setWeigh(BigDecimal.ZERO) - .setBreakfast(BigDecimal.ZERO).setLunch(BigDecimal.ZERO).setDinner(BigDecimal.ZERO) - .setTime(String.valueOf(day)); + bean = getInitBusinessRespVO().setTime(String.valueOf(day)); }else { bean = BeanUtils.toBean(map.get(day), BusinessRespVO.class); bean.setTime(String.valueOf(day)); @@ -234,7 +234,7 @@ public class BusinessServiceImpl implements BusinessService { monthData.put(day,bean); } - + businessDataVO.setNow(monthData.get(nowDay)); businessDataVO.setBusinessList(new ArrayList<>(monthData.values())); return businessDataVO; } @@ -254,10 +254,7 @@ public class BusinessServiceImpl implements BusinessService { int totalWeeksOfMonth = MemberTimeUtils.getTotalWeeksOfMonth(time); for (int i = 1; i <= totalWeeksOfMonth; i++) { - BusinessRespVO bean = new BusinessRespVO(); - bean.setTurnover(BigDecimal.ZERO).setOrderSum(0).setReduce(BigDecimal.ZERO).setWeigh(BigDecimal.ZERO) - .setBreakfast(BigDecimal.ZERO).setLunch(BigDecimal.ZERO).setDinner(BigDecimal.ZERO) - .setTime(String.valueOf(i)); + BusinessRespVO bean = getInitBusinessRespVO().setTime(String.valueOf(i)); map.put(i,bean); } @@ -281,6 +278,7 @@ public class BusinessServiceImpl implements BusinessService { @Override public BusinessDataVO getMonth(String time,Long carteenId) { + time = MemberTimeUtils.getYearMonth(time); BusinessDataVO businessDataVO = new BusinessDataVO(); @@ -295,10 +293,8 @@ public class BusinessServiceImpl implements BusinessService { Map map = new HashMap<>(); //时间处理 for (int i = 1; i <= 12; i++) { - BusinessRespVO bean = new BusinessRespVO(); - bean.setTurnover(BigDecimal.ZERO).setOrderSum(0).setReduce(BigDecimal.ZERO).setWeigh(BigDecimal.ZERO) - .setBreakfast(BigDecimal.ZERO).setLunch(BigDecimal.ZERO).setDinner(BigDecimal.ZERO) - .setTime(String.valueOf(i)); + BusinessRespVO bean = getInitBusinessRespVO(); + bean.setTime(String.valueOf(i)); map.put(i,bean); } //数据统计 @@ -319,9 +315,7 @@ public class BusinessServiceImpl implements BusinessService { previousWrapper.orderByAsc(BusinessDO::getCreateTime); previousWrapper.apply("DATE_FORMAT(create_time, '%Y-%m') = {0}", previousYear+"-12"); List previousList = businessMapper.selectList(previousWrapper); - BusinessRespVO previousVO = new BusinessRespVO(); - previousVO.setTurnover(BigDecimal.ZERO).setOrderSum(0).setReduce(BigDecimal.ZERO).setWeigh(BigDecimal.ZERO) - .setBreakfast(BigDecimal.ZERO).setLunch(BigDecimal.ZERO).setDinner(BigDecimal.ZERO); + BusinessRespVO previousVO = getInitBusinessRespVO(); for (BusinessDO businessDO : previousList) { handleBusiness(businessDO,previousVO); } @@ -334,6 +328,8 @@ public class BusinessServiceImpl implements BusinessService { } } + int month = MemberTimeUtils.getMonthFromYearMonthString(time); + businessDataVO.setNow(map.get(month)); businessDataVO.setBusinessList(new ArrayList<>(map.values())); return businessDataVO; @@ -346,7 +342,9 @@ public class BusinessServiceImpl implements BusinessService { //订单数 businessRespVO.setOrderSum(businessRespVO.getOrderSum()+businessDO.getOrderSum()); //均单价 - businessRespVO.setPriceAvg(businessDO.getTurnover().divide(new BigDecimal(businessDO.getOrderSum()), 2, RoundingMode.HALF_UP)); + if(businessRespVO.getOrderSum()!=0){ + businessRespVO.setPriceAvg(businessRespVO.getTurnover().divide(new BigDecimal(businessRespVO.getOrderSum().toString()), 2, RoundingMode.HALF_UP)); + } //减免金额 businessRespVO.setReduce(businessRespVO.getReduce().add(businessDO.getReduce())); //重量 @@ -367,4 +365,11 @@ public class BusinessServiceImpl implements BusinessService { today.setPriceAvgCompare(today.getPriceAvg().subtract(last.getPriceAvg())); } + BusinessRespVO getInitBusinessRespVO() { + BusinessRespVO previousVO = new BusinessRespVO(); + previousVO.setTurnover(BigDecimal.ZERO).setOrderSum(0).setReduce(BigDecimal.ZERO).setWeigh(BigDecimal.ZERO) + .setBreakfast(BigDecimal.ZERO).setLunch(BigDecimal.ZERO).setDinner(BigDecimal.ZERO).setPriceAvg(BigDecimal.ZERO); + return previousVO; + } + } \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/customizeExcel/CustomizeExcelService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/customizeExcel/CustomizeExcelService.java index d0627bfc..f6171ff6 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/customizeExcel/CustomizeExcelService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/customizeExcel/CustomizeExcelService.java @@ -10,5 +10,5 @@ import java.util.List; public interface CustomizeExcelService { - List exportOrderExcel(String startTime,String endTime); + List exportOrderExcel(String startTime,String endTime,Long carteenId); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/customizeExcel/CustomizeExcelServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/customizeExcel/CustomizeExcelServiceImpl.java index 53fed431..6a9544ba 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/customizeExcel/CustomizeExcelServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/customizeExcel/CustomizeExcelServiceImpl.java @@ -17,7 +17,7 @@ public class CustomizeExcelServiceImpl implements CustomizeExcelService { @Override - public List exportOrderExcel(String startTime, String endTime) { - return customizeExcelMapper.selectOrder(startTime,endTime); + public List exportOrderExcel(String startTime, String endTime,Long carteenId) { + return customizeExcelMapper.selectOrder(startTime,endTime,carteenId); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/util/CustomMergeStrategy.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/util/CustomMergeStrategy.java new file mode 100644 index 00000000..d7d325f6 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/util/CustomMergeStrategy.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.member.util; + +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.springframework.util.ObjectUtils; + +import java.util.*; + +public class CustomMergeStrategy { + + /** + * 分组,每几行合并一次 + */ + private final List> mergeColDataGroupCountList; + + /** + * 目标合并列index + */ + private final Map targetColumnIndex; + /** + * 需要开始合并单元格的首行index + */ + private Integer rowIndex; + //存放合并的 + private Map> aaa=new HashMap<>(); + + /** + * mergeColDataList为待合并目标列的值 + */ + public CustomMergeStrategy(List> mergeColDataList, Map targetColumnIndex) { + this.mergeColDataGroupCountList = getGroupCountList(mergeColDataList); + this.targetColumnIndex = targetColumnIndex; + } + + public void merge(Sheet sheet,int i) { + rowIndex = 1; // 假设从第二行开始合并,第一行为表头 + // 遍历所有行 + Iterator rowIterator = sheet.rowIterator(); + while (rowIterator.hasNext()) { + Row row = rowIterator.next(); + int i1=0; + Iterator cellIterator = row.cellIterator(); + while (cellIterator.hasNext()) { + if(i1>i){ + return; + } + Cell cell = cellIterator.next(); + if (null == rowIndex) { + rowIndex = cell.getRowIndex(); + } + // 仅从首行以及目标列的单元格开始合并,忽略其他 + if (targetColumnIndex.get(cell.getColumnIndex())!=null) { + //找到对应的需要合并的列 + mergeGroupColumn(sheet, targetColumnIndex.get(cell.getColumnIndex()),cell.getColumnIndex()); + } + i1++; + } + } + } + + private void mergeGroupColumn(Sheet sheet, Integer index,Integer i) { + int rowCount = rowIndex; + for (Integer count : mergeColDataGroupCountList.get(index)) { + if (count == 1) { + rowCount += count; + continue; + } + // 合并单元格 + CellRangeAddress cellRangeAddress = new CellRangeAddress(rowCount, rowCount + count - 1, + i, i); + sheet.addMergedRegion(cellRangeAddress); + + rowCount += count; + } + } + + /** + * 该方法将目标列根据值是否相同连续可合并,存储可合并的行数 + */ + private List> getGroupCountList(List> exportDataList) { + if (ObjectUtils.isEmpty(exportDataList)) { + return new ArrayList<>(); + } + List> groupCountListList = new ArrayList<>(); + for (List dataList : exportDataList) { + List groupCountList = new ArrayList<>(); + int count = 1; + for (int i = 1; i < dataList.size(); i++) { + if (dataList.get(i).equals(dataList.get(i - 1))) { + count++; + } else { + groupCountList.add(count); + count = 1; + } + } + // 处理完最后一条后 + groupCountList.add(count); + groupCountListList.add(groupCountList); + } + return groupCountListList; + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/util/MemberTimeUtils.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/util/MemberTimeUtils.java index 484d771b..5c502e10 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/util/MemberTimeUtils.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/util/MemberTimeUtils.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.member.util; import java.time.LocalDate; import java.time.YearMonth; +import java.time.format.DateTimeFormatter; import java.time.temporal.WeekFields; import java.util.Locale; @@ -41,4 +42,25 @@ public class MemberTimeUtils { // 返回年份 return yearMonth.getYear(); } + + public static int getMonthFromYearMonthString(String yearMonthString) { + // 使用YearMonth类解析字符串 + YearMonth yearMonth = YearMonth.parse(yearMonthString); + + // 返回年份 + return yearMonth.getMonth().getValue(); + } + + public static String getYearMonth(String time) { + // 解析成 LocalDate + LocalDate date = LocalDate.parse(time); + // 获取年份和月份,并格式化为 yyyy-MM 格式 + return date.format(DateTimeFormatter.ofPattern("yyyy-MM")); + } + + public static Integer getDay(String time) { + LocalDate date = LocalDate.parse(time); + return date.getDayOfMonth(); + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/resources/mapper/customizeExcel/CustomizeExcelMapper.xml b/yudao-module-member/yudao-module-member-biz/src/main/resources/mapper/customizeExcel/CustomizeExcelMapper.xml index 9577c687..c8e76e9d 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/resources/mapper/customizeExcel/CustomizeExcelMapper.xml +++ b/yudao-module-member/yudao-module-member-biz/src/main/resources/mapper/customizeExcel/CustomizeExcelMapper.xml @@ -27,7 +27,7 @@ from member_order_detail md left join member_dish_order mo on md.order_id = mo.id left join member_user mu on mu.id = mo.user_id - where DATE_FORMAT(md.create_time, '%Y%m%d') between #{startTime} and #{endTime} + where DATE_FORMAT(md.create_time, '%Y%m%d') between #{startTime} and #{endTime} and mo.store_id = #{carteenId} order by mo.user_id,order_id