Commit 02dfba2e156c728ec4d994548e1feb4710f60039

Authored by wangqian
2 parents 291db743 510cf6f8

Merge remote-tracking branch 'origin/dev' into dev

urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/gis/GisRoadController.java
1 1 package com.zteits.urbanops.module.garden.controller.admin.gis;
2 2  
  3 +import cn.idev.excel.FastExcelFactory;
  4 +import cn.idev.excel.write.merge.OnceAbsoluteMergeStrategy;
3 5 import com.zteits.urbanops.framework.common.pojo.PageParam;
  6 +import com.zteits.urbanops.framework.excel.core.handler.ColumnWidthMatchStyleStrategy;
  7 +import com.zteits.urbanops.framework.excel.core.handler.SelectSheetWriteHandler;
4 8 import org.slf4j.Logger;
5 9 import org.slf4j.LoggerFactory;
6 10 import org.springframework.web.bind.annotation.*;
... ... @@ -14,9 +18,12 @@ import io.swagger.v3.oas.annotations.Operation;
14 18 import jakarta.validation.*;
15 19 import jakarta.servlet.http.*;
16 20 import java.io.IOException;
  21 +import java.net.URLEncoder;
  22 +import java.nio.charset.StandardCharsets;
17 23 import java.time.LocalDate;
18 24 import java.time.format.DateTimeFormatter;
19 25 import java.util.*;
  26 +import java.util.stream.Collectors;
20 27  
21 28 import com.zteits.urbanops.framework.common.pojo.PageResult;
22 29 import com.zteits.urbanops.framework.common.pojo.CommonResult;
... ... @@ -63,40 +70,120 @@ public class GisRoadController {
63 70 }
64 71  
65 72 @GetMapping("/export-excel")
66   - @Operation(summary = "导出 GIS 道路 Excel")
  73 + @Operation(summary = "导出 GIS 道路 Excel(同道路多绿地合并单元格)")
67 74 @PreAuthorize("@ss.hasPermission('garden:gis-road:export')")
68 75 @ApiAccessLog(operateType = EXPORT)
69 76 public void exportGisRoadExcel(@Valid GisRoadPageReqVO pageReqVO,
70 77 HttpServletResponse response) throws IOException {
71 78 pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
72 79 List<GisRoadRespVO> list = gisRoadService.getGisRoadPage(pageReqVO).getList();
  80 +
  81 + // 分离:已关联 vs 未关联(未关联的不参与合并)
  82 + List<GisRoadRespVO> relatedList = list.stream()
  83 + .filter(vo -> vo.getGisIsRelated() != null && vo.getGisIsRelated() == 1)
  84 + .sorted(Comparator.comparing(GisRoadRespVO::getRoadName, Comparator.nullsLast(String::compareTo)))
  85 + .collect(Collectors.toList());
  86 + List<GisRoadRespVO> unrelatedList = list.stream()
  87 + .filter(vo -> vo.getGisIsRelated() == null || vo.getGisIsRelated() != 1)
  88 + .collect(Collectors.toList());
  89 +
  90 + // 已关联的按 roadName 分组
  91 + Map<String, List<GisRoadRespVO>> grouped = relatedList.stream()
  92 + .collect(Collectors.groupingBy(
  93 + vo -> vo.getRoadName() != null ? vo.getRoadName() : "",
  94 + LinkedHashMap::new, Collectors.toList()));
  95 +
73 96 List<GisRoadExportVO> exportList = new ArrayList<>();
74   - for (GisRoadRespVO vo : list) {
75   - GisRoadExportVO exportVO = new GisRoadExportVO();
76   - exportVO.setGisPlotName(vo.getGisPlotName());
77   - exportVO.setRoadName(vo.getRoadName());
78   - exportVO.setGisPlotArea(vo.getGisPlotArea());
79   - exportVO.setTotalArea(vo.getTotalArea());
80   - exportVO.setGisIsRelatedStr(vo.getGisIsRelated() != null && vo.getGisIsRelated() == 1 ? "已关联" : "未关联");
81   - exportVO.setGisDiffArea(vo.getGisDiffArea());
82   - exportVO.setCompanyName(vo.getCompanyName());
83   - exportVO.setDeptName(vo.getDeptName());
84   - // 位置信息:起点描述 ~ 终点描述
85   - String positionInfo = "";
86   - if (vo.getStartingRemark() != null) {
87   - positionInfo += vo.getStartingRemark();
  97 + List<OnceAbsoluteMergeStrategy> mergeStrategies = new ArrayList<>();
  98 + int rowIdx = 1;
  99 +
  100 + // ===== 处理已关联的(合并) =====
  101 + for (List<GisRoadRespVO> group : grouped.values()) {
  102 + int startRow = rowIdx;
  103 + float sumArea = 0f;
  104 + String roadName = group.get(0).getRoadName();
  105 + Float totalArea = group.get(0).getTotalArea();
  106 + String companyName = group.get(0).getCompanyName();
  107 + String deptName = group.get(0).getDeptName();
  108 +
  109 + String posInfo = "";
  110 + if (group.get(0).getStartingRemark() != null) posInfo += group.get(0).getStartingRemark();
  111 + if (group.get(0).getEndRemark() != null) {
  112 + if (!posInfo.isEmpty()) posInfo += " ~ ";
  113 + posInfo += group.get(0).getEndRemark();
  114 + }
  115 +
  116 + for (GisRoadRespVO vo : group) {
  117 + GisRoadExportVO ev = new GisRoadExportVO();
  118 + ev.setGisPlotName(vo.getGisPlotName());
  119 + ev.setRoadName(roadName);
  120 + ev.setGisPlotArea(vo.getGisPlotArea());
  121 + if (vo.getGisPlotArea() != null) sumArea += vo.getGisPlotArea();
  122 + ev.setTotalArea(totalArea);
  123 + ev.setGisIsRelatedStr("已关联");
  124 + ev.setCompanyName(companyName);
  125 + ev.setDeptName(deptName);
  126 + ev.setPositionInfo(posInfo.isEmpty() ? null : posInfo);
  127 + exportList.add(ev);
  128 + rowIdx++;
  129 + }
  130 +
  131 + int endRow = rowIdx - 1;
  132 + float diff = sumArea - (totalArea != null ? totalArea : 0f);
  133 + if (group.size() > 1) {
  134 + exportList.get(startRow - 1).setMergedGisPlotArea(sumArea);
  135 + exportList.get(startRow - 1).setGisDiffArea(diff);
  136 + mergeStrategies.add(new OnceAbsoluteMergeStrategy(startRow, endRow, 1, 1));
  137 + mergeStrategies.add(new OnceAbsoluteMergeStrategy(startRow, endRow, 3, 3));
  138 + mergeStrategies.add(new OnceAbsoluteMergeStrategy(startRow, endRow, 4, 4));
  139 + mergeStrategies.add(new OnceAbsoluteMergeStrategy(startRow, endRow, 5, 5));
  140 + mergeStrategies.add(new OnceAbsoluteMergeStrategy(startRow, endRow, 6, 6));
  141 + mergeStrategies.add(new OnceAbsoluteMergeStrategy(startRow, endRow, 7, 7));
  142 + mergeStrategies.add(new OnceAbsoluteMergeStrategy(startRow, endRow, 8, 8));
  143 + mergeStrategies.add(new OnceAbsoluteMergeStrategy(startRow, endRow, 9, 9));
88 144 }
  145 + exportList.get(startRow - 1).setMergedGisPlotArea(sumArea);
  146 + exportList.get(startRow - 1).setGisDiffArea(diff);
  147 + }
  148 +
  149 + // ===== 处理未关联的(不合并,各自独立行) =====
  150 + for (GisRoadRespVO vo : unrelatedList) {
  151 + GisRoadExportVO ev = new GisRoadExportVO();
  152 + ev.setGisPlotName(vo.getGisPlotName());
  153 + ev.setRoadName(vo.getRoadName());
  154 + ev.setGisPlotArea(vo.getGisPlotArea());
  155 + ev.setMergedGisPlotArea(vo.getGisPlotArea());
  156 + ev.setTotalArea(vo.getTotalArea());
  157 + ev.setGisIsRelatedStr("未关联");
  158 + ev.setGisDiffArea(vo.getGisDiffArea());
  159 + ev.setCompanyName(vo.getCompanyName());
  160 + ev.setDeptName(vo.getDeptName());
  161 + String posInfo = "";
  162 + if (vo.getStartingRemark() != null) posInfo += vo.getStartingRemark();
89 163 if (vo.getEndRemark() != null) {
90   - if (!positionInfo.isEmpty()) {
91   - positionInfo += " ~ ";
92   - }
93   - positionInfo += vo.getEndRemark();
  164 + if (!posInfo.isEmpty()) posInfo += " ~ ";
  165 + posInfo += vo.getEndRemark();
94 166 }
95   - exportVO.setPositionInfo(positionInfo.isEmpty() ? null : positionInfo);
96   - exportList.add(exportVO);
  167 + ev.setPositionInfo(posInfo.isEmpty() ? null : posInfo);
  168 + exportList.add(ev);
  169 + rowIdx++;
  170 + }
  171 +
  172 + // 使用 FastExcelFactory 写 Excel,逐个注册 merge 策略
  173 + String filename = "十谱绿地核对" + LocalDate.now()
  174 + .format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".xls";
  175 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  176 + response.setCharacterEncoding("utf-8");
  177 + response.setHeader("Content-disposition",
  178 + "attachment;filename*=utf-8''" + URLEncoder.encode(filename, StandardCharsets.UTF_8));
  179 +
  180 + var builder = FastExcelFactory.write(response.getOutputStream(), GisRoadExportVO.class)
  181 + .registerWriteHandler(new ColumnWidthMatchStyleStrategy())
  182 + .registerWriteHandler(new SelectSheetWriteHandler(GisRoadExportVO.class));
  183 + for (OnceAbsoluteMergeStrategy ms : mergeStrategies) {
  184 + builder.registerWriteHandler(ms);
97 185 }
98   - String filename = "十谱绿地核对" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".xls";
99   - ExcelUtils.write(response, filename, "数据", GisRoadExportVO.class, exportList);
  186 + builder.sheet("数据").doWrite(exportList);
100 187 }
101 188  
102 189 @PostMapping("/associate")
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/gis/vo/GisRoadExportVO.java
... ... @@ -25,6 +25,11 @@ public class GisRoadExportVO {
25 25 @JsonSerialize(using = TwoDecimalFloatSerializer.class)
26 26 private Float gisPlotArea;
27 27  
  28 + @Schema(description = "十谱绿地合并面积")
  29 + @ExcelProperty("十谱绿地合并面积(㎡)")
  30 + @JsonSerialize(using = TwoDecimalFloatSerializer.class)
  31 + private Float mergedGisPlotArea;
  32 +
28 33 @Schema(description = "道路面积")
29 34 @ExcelProperty("道路面积(㎡)")
30 35 @JsonSerialize(using = TwoDecimalFloatSerializer.class)
... ...