JiangPengLi 4 months ago
parent
commit
320b0f4cdb

+ 2 - 1
projects-service/src/main/java/com/rtrh/projects/modules/projects/mapper/SubInfoMapper.xml

@@ -385,7 +385,8 @@
         SELECT sub_info.subject_id as subjectId,
                sub_info.sub_name as subName,
                sub_info.amt_total as amtTotal,
-               sub_info.indus_kind as indusKind
+               sub_info.indus_kind as indusKind,
+               sub_info.status as status
                from sub_info
         WHERE sub_info.logic_delete_flag = 0
             <if test="status != null and status != ''">

+ 16 - 32
projects-service/src/main/java/com/rtrh/projects/modules/projects/service/impl/SubInfoQueryServiceImpl.java

@@ -278,52 +278,36 @@ public class SubInfoQueryServiceImpl implements SubInfoQueryService {
             num = list.stream().filter(e -> queryVO.getStatus().equals(e.getStatus())).count();
         }
         // abc类统计
-        Map<String, Long> abc = list.stream()
-                .peek(e -> {
-                    if (StringUtils.isBlank(e.getAbc())) {
-                        e.setAbc(" ");
-                    }
-                })
-                .filter(e -> StringUtils.isNotBlank(e.getAbc()))
-                .collect(Collectors.groupingBy(SubInfoGxj::getAbc, Collectors.counting()));
+        Map<String, Long> abc = list.stream().collect(Collectors.groupingBy(e -> StringUtils.defaultIfBlank(e.getAbc(), "."), Collectors.counting()));
         // 建设地点统计
         List<TSystable> jsddDict = tSysTableService.getByKind(SysTableKind.JSDD);
-        Map<String, Long> subject = list.stream()
-                .filter(e -> StringUtils.isNotBlank(e.getSubjectId()))
-                .collect(Collectors.groupingBy(SubInfoGxj::getSubjectId, Collectors.counting()));
+        Map<String, String> jsddNameMap = jsddDict.stream().collect(Collectors.toMap(TSystable::getCode, TSystable::getTitle));
+        Map<String, Long> subject = list.stream().collect(Collectors.groupingBy(e -> StringUtils.defaultIfBlank(e.getSubjectId(), "."), Collectors.counting()));
         List<StatisticsVO.KvNum> jsddList = new ArrayList<>();
         subject.forEach((k, v) -> {
-            jsddDict.stream()
-                    .filter(d -> d.getCode().equals(k))
-                    .findFirst()
-                    .ifPresent(d -> {
-                        jsddList.add(new StatisticsVO.KvNum()
-                                .setCode(d.getCode())
-                                .setName(d.getTitle())
-                                .setNum(v));
-                    });
+            jsddList.add(new StatisticsVO.KvNum()
+                    .setCode(k)
+                    .setName(jsddNameMap.getOrDefault(k, ""))
+                    .setNum(v));
         });
         // 行业统计
         List<TSystable> hyflDict = tSysTableService.getByKind(SysTableKind.HYFL);
-        Map<String, Long> indusKind = list.stream().filter(e -> StringUtils.isNotBlank(e.getIndusKind())).collect(Collectors.groupingBy(SubInfoGxj::getIndusKind, Collectors.counting()));
+        Map<String, String> hyflNameMap = hyflDict.stream().collect(Collectors.toMap(TSystable::getCode, TSystable::getTitle));
+        Map<String, Long> indusKind = list.stream()
+                .collect(Collectors.groupingBy(e -> StringUtils.defaultIfBlank(e.getIndusKind(), "."), Collectors.counting()));
         List<StatisticsVO.KvNum> hyflList = new ArrayList<>();
         indusKind.forEach((k, v) -> {
-            hyflDict.stream().filter(d -> d.getId().equals(k))
-                    .findFirst()
-                    .ifPresent(d -> {
-                        hyflList.add(new StatisticsVO.KvNum()
-                                .setCode(d.getId())
-                                .setName(d.getTitle())
-                                .setNum(v));
-                    });
+            hyflList.add(new StatisticsVO.KvNum()
+                    .setCode(k)
+                    .setName(hyflNameMap.getOrDefault(k, ""))
+                    .setNum(v));
         });
         return new StatisticsVO()
-                .setCbNum(num)
                 .setNum(num)
                 .setANum(abc.getOrDefault("A", 0L))
                 .setBNum(abc.getOrDefault("B", 0L))
-                .setCNum(abc.getOrDefault("C", 0L))
-                .setNum(abc.getOrDefault(" ", 0L))
+                .setCNum(abc.getOrDefault("C", 0L) + abc.getOrDefault("c", 0L))
+                .setNNum(abc.getOrDefault(".", 0L))
                 .setJsddData(jsddList)
                 .setHyflData(hyflList);
     }

+ 2 - 0
projects-service/src/main/java/com/rtrh/projects/modules/projects/vo/SubInfoTotalExcel.java

@@ -15,4 +15,6 @@ public class SubInfoTotalExcel {
 
     private String induskind;   //行业id
 
+    private String status;   //项目状态
+
 }

+ 2 - 0
projects-service/src/main/java/com/rtrh/projects/modules/projects/vo/export/SubInfoCbVO.java

@@ -7,6 +7,8 @@ import java.math.BigDecimal;
 
 @Data
 public class SubInfoCbVO {
+    @Excel(name = "序号")
+    private String index;
 
     @Excel(name = "项目名称",width = 20.0)
     private String subName;

+ 2 - 0
projects-service/src/main/java/com/rtrh/projects/modules/projects/vo/export/SubInfoTcVO.java

@@ -9,6 +9,8 @@ import java.util.Date;
 
 @Data
 public class SubInfoTcVO {
+    @Excel(name = "序号")
+    private String index;
 
     @Excel(name = "项目名称",width = 20.0)
     private String subName;

+ 2 - 0
projects-service/src/main/java/com/rtrh/projects/modules/projects/vo/export/SubInfoXjVO.java

@@ -9,6 +9,8 @@ import java.util.Date;
 
 @Data
 public class SubInfoXjVO {
+    @Excel(name = "序号")
+    private String index;
 
     @Excel(name = "项目名称",width = 20.0)
     private String subName;

+ 3 - 0
projects-service/src/main/java/com/rtrh/projects/modules/projects/vo/export/SubInfoZjVO.java

@@ -9,6 +9,9 @@ import java.util.Date;
 
 @Data
 public class SubInfoZjVO {
+    @Excel(name = "序号")
+    private String index;
+
     @Excel(name = "项目名称",width = 20.0)
     private String subName;
 

+ 2 - 0
projects-service/src/main/java/com/rtrh/projects/modules/projects/vo/export/SubInfoZkVO.java

@@ -9,6 +9,8 @@ import java.util.Date;
 
 @Data
 public class SubInfoZkVO {
+    @Excel(name = "序号")
+    private String index;
 
     @Excel(name = "项目名称",width = 20.0)
     private String subName;

+ 454 - 100
projects/src/main/java/com/rtrh/projects/web/controller/subject/SubInfoExportController.java

@@ -13,6 +13,7 @@ import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
 
 import cn.afterturn.easypoi.excel.ExcelExportUtil;
+import cn.afterturn.easypoi.handler.inter.IExcelExportServer;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.io.IoUtil;
@@ -42,6 +43,7 @@ import com.rtrh.projects.modules.utils.QualificationsDeclareCellWriteHandler;
 import com.rtrh.projects.outapi.result.JsonResult;
 import com.rtrh.projects.web.util.SheetData;
 import com.rtrh.projects.web.util.SheetHead;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.xssf.streaming.SXSSFSheet;
@@ -799,31 +801,264 @@ public class SubInfoExportController extends BaseController {
             }
         }
     }
+    // 将数字转换为中文数字的方法
+    public static String toChineseNumber(int num) {
+        String[] chineseDigits = {"", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
+        String[] chineseUnits = {"", "十", "百", "千"};
+
+        StringBuilder result = new StringBuilder();
+        int unitPosition = 0;
+
+        while (num > 0) {
+            int digit = num % 10;
+            if (digit != 0) {
+                result.insert(0, chineseDigits[digit] + chineseUnits[unitPosition]);
+            } else if (result.length() > 0 && result.charAt(0) != '零') {
+                result.insert(0, "零");
+            }
+            num /= 10;
+            unitPosition++;
+        }
+
+        // 处理特殊情况,比如 "一十" -> "十"
+        if (result.length() > 1 && result.charAt(0) == '一' && result.charAt(1) == '十') {
+            result.deleteCharAt(0);
+        }
 
+        return result.toString();
+    }
     /**
-     * 导出明细
+     * 4库/总库 导出明细
      *
      * @param response
      */
     @PostMapping("/exportDetailExcel")
     public void exportDetailExcel(HttpServletResponse response, @RequestBody SubInfoQueryTzVO queryVO) {
         List<SubInfoGxj> list = subInfoQueryService.queryAll(getCurUser().getLoginUser(), queryVO);
+        // 行业字典
+        Map<String, String> hyDictMap = subInduService.queryParentAll().stream().collect(Collectors.toMap(SubIndu::getCode, SubIndu::getTitle));
+        // 按行业分组
+        Map<String, List<SubInfoGxj>> groupMap = list.stream()
+                .collect(Collectors.groupingBy(e -> StringUtils.defaultIfBlank(e.getIndusKind(), "未知行业")));
         Workbook workbook;
         if (SubInfoStatusEnum.CB.getCode().equals(queryVO.getStatus())) {
-            workbook = exportExcel(list, SubInfoCbVO.class, "“四个一批”工业项目表(储备项目库)", "储备项目库");
-        } else if (SubInfoStatusEnum.XJ.getCode().equals(queryVO.getStatus())) {
-            workbook = exportExcel(list, SubInfoXjVO.class, "“四个一批”工业项目表(新建项目库)", "新建项目库");
-        } else if (SubInfoStatusEnum.ZJ.getCode().equals(queryVO.getStatus())) {
-            workbook = exportExcel(list, SubInfoZjVO.class, "“四个一批”工业项目表(在建项目库)", "在建项目库");
-        } else if (SubInfoStatusEnum.TC.getCode().equals(queryVO.getStatus())) {
-            workbook = exportExcel(list, SubInfoTcVO.class, "“四个一批”工业项目表(投产项目库)", "投产项目库");
-        } else {
-            workbook = exportExcel(list, SubInfoZkVO.class, "“四个一批”工业项目表(项目总库)", "项目总库");
+            List<SubInfoCbVO> exportList = new ArrayList<>();
+            // 合计行
+            SubInfoCbVO hjCount = new SubInfoCbVO();
+            hjCount.setIndex(String.format("合计(%s个)",list.size()));
+            exportList.add(hjCount);
+
+            int index = 1;
+            List<Integer> allSize = new ArrayList<>();
+            for (Map.Entry<String, List<SubInfoGxj>> entry : groupMap.entrySet()){
+                String key = entry.getKey();
+                List<SubInfoGxj> value = entry.getValue();
+                List<SubInfoCbVO> hyList = new ArrayList<>();
+                // 行业合计行
+                SubInfoCbVO hyCount = new SubInfoCbVO();
+                hyCount.setIndex(String.format("%s、%s( %s个 )",toChineseNumber(index), hyDictMap.getOrDefault(key, key), value.size()));
+                // 每条数据行
+                hyList.add(hyCount);
+                for (int i = 0; i < value.size(); i++) {
+                    SubInfoGxj subInfoGxj = value.get(i);
+                    SubInfoCbVO vo = new SubInfoCbVO();
+                    BeanUtils.copyProperties(subInfoGxj,vo);
+                    vo.setIndex(i + 1 + "");
+                    hyList.add(vo);
+                }
+                // 添加前计算合并行
+                allSize.add(exportList.size() + 2);
+                exportList.addAll(hyList);
+                index++;
+            }
+            ExportParams exportParams = getExportParams();
+            exportParams.setTitle("“四个一批”工业项目表(储备项目库)");
+            exportParams.setSheetName("储备项目库");
+            workbook = ExcelExportUtil.exportExcel(exportParams, SubInfoCbVO.class, exportList);
+            extracted(response, list, workbook, allSize);
+        }else if (SubInfoStatusEnum.XJ.getCode().equals(queryVO.getStatus())){
+            List<SubInfoXjVO> exportList = new ArrayList<>();
+            // 合计行
+            SubInfoXjVO hjCount = new SubInfoXjVO();
+            hjCount.setIndex(String.format("合计(%s个)",list.size()));
+            exportList.add(hjCount);
+
+            int index = 1;
+            List<Integer> allSize = new ArrayList<>();
+            for (Map.Entry<String, List<SubInfoGxj>> entry : groupMap.entrySet()){
+                String key = entry.getKey();
+                List<SubInfoGxj> value = entry.getValue();
+                List<SubInfoXjVO> hyList = new ArrayList<>();
+                // 行业合计行
+                SubInfoXjVO hyCount = new SubInfoXjVO();
+                hyCount.setIndex(String.format("%s、%s( %s个 )",toChineseNumber(index), hyDictMap.getOrDefault(key, key), value.size()));
+                // 每条数据行
+                hyList.add(hyCount);
+                for (int i = 0; i < value.size(); i++) {
+                    SubInfoGxj subInfoGxj = value.get(i);
+                    SubInfoXjVO vo = new SubInfoXjVO();
+                    BeanUtils.copyProperties(subInfoGxj,vo);
+                    vo.setIndex(i + 1 + "");
+                    hyList.add(vo);
+                }
+                // 添加前计算合并行
+                allSize.add(exportList.size() + 2);
+                exportList.addAll(hyList);
+                index++;
+            }
+            ExportParams exportParams = getExportParams();
+            exportParams.setTitle("“四个一批”工业项目表(新建项目库)");
+            exportParams.setSheetName("新建项目库");
+            workbook = ExcelExportUtil.exportExcel(exportParams, SubInfoXjVO.class, exportList);
+            extracted(response, list, workbook, allSize);
+        }else if (SubInfoStatusEnum.ZJ.getCode().equals(queryVO.getStatus())){
+            List<SubInfoZjVO> exportList = new ArrayList<>();
+            // 合计行
+            SubInfoZjVO hjCount = new SubInfoZjVO();
+            hjCount.setIndex(String.format("合计(%s个)",list.size()));
+            exportList.add(hjCount);
+
+            int index = 1;
+            List<Integer> allSize = new ArrayList<>();
+            for (Map.Entry<String, List<SubInfoGxj>> entry : groupMap.entrySet()){
+                String key = entry.getKey();
+                List<SubInfoGxj> value = entry.getValue();
+                List<SubInfoZjVO> hyList = new ArrayList<>();
+                // 行业合计行
+                SubInfoZjVO hyCount = new SubInfoZjVO();
+                hyCount.setIndex(String.format("%s、%s( %s个 )",toChineseNumber(index), hyDictMap.getOrDefault(key, key), value.size()));
+                // 每条数据行
+                hyList.add(hyCount);
+                for (int i = 0; i < value.size(); i++) {
+                    SubInfoGxj subInfoGxj = value.get(i);
+                    SubInfoZjVO vo = new SubInfoZjVO();
+                    BeanUtils.copyProperties(subInfoGxj,vo);
+                    vo.setIndex(i + 1 + "");
+                    hyList.add(vo);
+                }
+                // 添加前计算合并行
+                allSize.add(exportList.size() + 2);
+                exportList.addAll(hyList);
+                index++;
+            }
+            ExportParams exportParams = getExportParams();
+            exportParams.setTitle("“四个一批”工业项目表(在建项目库)");
+            exportParams.setSheetName("在建项目库");
+            workbook = ExcelExportUtil.exportExcel(exportParams, SubInfoZjVO.class, exportList);
+            extracted(response, list, workbook, allSize);
+        }else if(SubInfoStatusEnum.TC.getCode().equals(queryVO.getStatus())) {
+            List<SubInfoTcVO> exportList = new ArrayList<>();
+            // 合计行
+            SubInfoTcVO hjCount = new SubInfoTcVO();
+            hjCount.setIndex(String.format("合计(%s个)",list.size()));
+            exportList.add(hjCount);
+
+            int index = 1;
+            List<Integer> allSize = new ArrayList<>();
+            for (Map.Entry<String, List<SubInfoGxj>> entry : groupMap.entrySet()){
+                String key = entry.getKey();
+                List<SubInfoGxj> value = entry.getValue();
+                List<SubInfoTcVO> hyList = new ArrayList<>();
+                // 行业合计行
+                SubInfoTcVO hyCount = new SubInfoTcVO();
+                hyCount.setIndex(String.format("%s、%s( %s个 )",toChineseNumber(index), hyDictMap.getOrDefault(key, key), value.size()));
+                // 每条数据行
+                hyList.add(hyCount);
+                for (int i = 0; i < value.size(); i++) {
+                    SubInfoGxj subInfoGxj = value.get(i);
+                    SubInfoTcVO vo = new SubInfoTcVO();
+                    BeanUtils.copyProperties(subInfoGxj,vo);
+                    vo.setIndex(i + 1 + "");
+                    hyList.add(vo);
+                }
+                // 添加前计算合并行
+                allSize.add(exportList.size() + 2);
+                exportList.addAll(hyList);
+                index++;
+            }
+            ExportParams exportParams = getExportParams();
+            exportParams.setTitle("“四个一批”工业项目表(投产项目库)");
+            exportParams.setSheetName("投产项目库");
+            workbook = ExcelExportUtil.exportExcel(exportParams, SubInfoTcVO.class, exportList);
+            extracted(response, list, workbook, allSize);
+        }else {
+            List<SubInfoZkVO> exportList = new ArrayList<>();
+            // 合计行
+            SubInfoZkVO hjCount = new SubInfoZkVO();
+            hjCount.setIndex(String.format("合计(%s个)",list.size()));
+            exportList.add(hjCount);
+
+            int index = 1;
+            List<Integer> allSize = new ArrayList<>();
+            for (Map.Entry<String, List<SubInfoGxj>> entry : groupMap.entrySet()){
+                String key = entry.getKey();
+                List<SubInfoGxj> value = entry.getValue();
+                List<SubInfoZkVO> hyList = new ArrayList<>();
+                // 行业合计行
+                SubInfoZkVO hyCount = new SubInfoZkVO();
+                hyCount.setIndex(String.format("%s、%s( %s个 )",toChineseNumber(index), hyDictMap.getOrDefault(key, key), value.size()));
+                // 每条数据行
+                hyList.add(hyCount);
+                for (int i = 0; i < value.size(); i++) {
+                    SubInfoGxj subInfoGxj = value.get(i);
+                    SubInfoZkVO vo = new SubInfoZkVO();
+                    BeanUtils.copyProperties(subInfoGxj,vo);
+                    vo.setIndex(i + 1 + "");
+                    hyList.add(vo);
+                }
+                // 添加前计算合并行
+                allSize.add(exportList.size() + 2);
+                exportList.addAll(hyList);
+                index++;
+            }
+            ExportParams exportParams = getExportParams();
+            exportParams.setTitle("“四个一批”工业项目表(项目总库)");
+            exportParams.setSheetName("项目总库");
+            workbook = ExcelExportUtil.exportExcel(exportParams, SubInfoZkVO.class, exportList);
+            // workbook = ExcelExportUtil.exportBigExcel(exportParams, SubInfoZkVO.class, new IExcelExportServer() {
+            //     /**
+            //      * obj 就是下面的限制条件
+            //      * page 是页数,他是在分页进行文件转换,page每次+1
+            //      */
+            //     @Override
+            //     public List<Object> selectListForExcelExport(Object obj, int page) {
+            //         int pageSize = 100;
+            //         int fromIndex = (page - 1) * pageSize;
+            //         int toIndex = Math.min(fromIndex + pageSize, exportList.size());
+            //
+            //         // 如果 fromIndex 超过了列表大小,返回空列表
+            //         if (fromIndex >= exportList.size()) {
+            //             return null;
+            //         }
+            //         // 使用 subList 方法获取分页后的子列表
+            //         List<Object> list1 = new ArrayList<>();
+            //         List<SubInfoZkVO> zkVOList = exportList.subList(fromIndex, toIndex);
+            //         list1.addAll(zkVOList);
+            //         return list1;
+            //     }
+            // }, (exportList.size() / 10000) + 1);
+            extracted(response, list, workbook, allSize);
         }
+    }
+
+    private void extracted(HttpServletResponse response, List<SubInfoGxj> list, Workbook workbook, List<Integer> allSize) {
         response.setContentType("application/xlsx;charset=utf-8");
         response.setHeader("Content-Disposition", "attachment; filename=" + URLEncodeUtil.encode("项目明细表") + System.currentTimeMillis() + ".xlsx");
-        // workbook.getSheetAt(0).autoSizeColumn(2);
+        // 合并单元格
+        CellStyle nonCenterCellStyle = createNonCenterBoldCellStyle(workbook);
         Sheet sheet = workbook.getSheetAt(0);
+        allSize.add(2);
+        for (Integer row : allSize) {
+            sheet.addMergedRegion(new CellRangeAddress(row, row, 0, 3));
+            // 获取合并区域的左上角单元格并设置样式
+            Row mergedRow = sheet.getRow(row);
+            if (mergedRow != null) {
+                Cell cell = mergedRow.getCell(0);
+                if (cell != null) {
+                    cell.setCellStyle(nonCenterCellStyle);
+                }
+            }
+        }
         // 设置自适应行高,i为需要自适应行高的起始行号, 起始行号为3 但是因为下标从0开始3需要减一,因为表格是循环生成,需要一行一行设置自适应高度
         for (int i = 2; i <= list.size() + 1; i++) {
             sheet.getRow(i).setHeight((short) -1);
@@ -835,8 +1070,32 @@ public class SubInfoExportController extends BaseController {
         }
     }
 
-    private <T> Workbook exportExcel(List<SubInfoGxj> list, Class<T> clazz, String title, String sheetName) {
+    private ExportParams getExportParams() {
         ExportParams exportParams = new ExportParams();
+        exportParams.setType(ExcelType.XSSF);
+        return exportParams;
+    }
+
+    /**
+     * 创建非居中且加粗的单元格样式
+     */
+    private static CellStyle createNonCenterBoldCellStyle(Workbook workbook) {
+        // 创建字体对象并设置为加粗
+        Font font = workbook.createFont();
+        font.setBold(true);  // 设置字体为加粗
+        // 创建单元格样式
+        CellStyle cellStyle = workbook.createCellStyle();
+        // 设置字体
+        cellStyle.setFont(font);
+        // 设置水平对齐方式为左对齐(非居中)
+        cellStyle.setAlignment(HorizontalAlignment.LEFT);
+        // 设置垂直对齐方式为居中
+        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        return cellStyle;
+    }
+
+    private <T> Workbook exportExcel(List<SubInfoGxj> list, Class<T> clazz, String title, String sheetName) {
+        ExportParams exportParams = getExportParams();
         exportParams.setTitle(title);
         exportParams.setSheetName(sheetName);
         exportParams.setType(ExcelType.XSSF);
@@ -849,9 +1108,13 @@ public class SubInfoExportController extends BaseController {
                 .collect(Collectors.toList());
         return ExcelExportUtil.exportExcel(exportParams, clazz, voList);
     }
-
+    private ExcelExportEntity getExcelExportEntity(String name, Object key, int width) {
+        ExcelExportEntity excelExportEntity = new ExcelExportEntity(name, key, width);
+        excelExportEntity.setWidth(width);
+        return excelExportEntity;
+    }
     /**
-     * 4库导出
+     * 4库导出总表
      *
      * @param response
      * @param vo
@@ -863,93 +1126,55 @@ public class SubInfoExportController extends BaseController {
         List<TSystable> jsddDict = tSysTableService.getByKind(SysTableKind.JSDD);
         Map<String, String> jsddMap = jsddDict.stream().collect(Collectors.toMap(TSystable::getCode, TSystable::getTitle));
         Map<String, String> hyflMap = subInduService.queryParentAll().stream().collect(Collectors.toMap(SubIndu::getCode, SubIndu::getTitle));
-        // 处理数据
-        List<SubInfoTotalInfoVO> exportData = new ArrayList<>();
-        if (CollectionUtil.isNotEmpty(list)) {
-            // 1.按属地分
-            List<SubInfoTotalInfoVO> ddList = list.stream()
-                    .collect(Collectors.groupingBy(SubInfoTotalExcel::getSubjectId))
-                    .entrySet().stream()
-                    .map(entry -> new SubInfoTotalInfoVO(
-                            "按属地分",
-                            jsddMap.getOrDefault(entry.getKey(), entry.getKey()),
-                            entry.getValue().size(),
-                            entry.getValue().stream()
-                                    .map(SubInfoTotalExcel::getAmtTotal)
-                                    .reduce(BigDecimal.ZERO, BigDecimal::add)
-                                    .divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP)
-                    ))
-                    .collect(Collectors.toList());
-
-            // 2.按金额分 定义分组边界
-            Map<String, BigDecimal> groupBoundaries = new LinkedHashMap<>();
-            groupBoundaries.put("10亿元以下", new BigDecimal("100000"));
-            groupBoundaries.put("10-50亿元", new BigDecimal("500000"));
-            groupBoundaries.put("50-100亿元", new BigDecimal("1000000"));
-            List<SubInfoTotalInfoVO> amtList = list.stream()
-                    .collect(Collectors.groupingBy(transaction -> {
-                        for (Map.Entry<String, BigDecimal> entry : groupBoundaries.entrySet()) {
-                            if (transaction.getAmtTotal().compareTo(entry.getValue()) < 0) {
-                                return entry.getKey();
-                            }
-                        }
-                        return "100亿元以上"; // 超过最高范围的默认分组
-                    }))
-                    .entrySet().stream()
-                    .map(entry -> new SubInfoTotalInfoVO(
-                            "按金额分",
-                            entry.getKey(),
-                            entry.getValue().size(),
-                            entry.getValue().stream()
-                                    .map(SubInfoTotalExcel::getAmtTotal)
-                                    .reduce(BigDecimal.ZERO, BigDecimal::add)
-                                    .divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP)
-                    ))
-                    .collect(Collectors.toList());
-
-            // 3.按行业分
-            List<SubInfoTotalInfoVO> hyList = list.stream()
-                    .collect(Collectors.groupingBy(transaction ->{
-                        String code = transaction.getInduskind();
-                        // 确保code不为空且长度至少为2
-                        if (code == null || code.length() < 2) {
-                            return "未知行业";  // 默认未知行业
-                        }
-                        return code.substring(0, 2);
-                    }))
-                    .entrySet().stream()
-                    .map(entry -> new SubInfoTotalInfoVO(
-                            "按行业分",
-                            hyflMap.getOrDefault(entry.getKey(),entry.getKey()),
-                            entry.getValue().size(),
-                            entry.getValue().stream()
-                                    .map(SubInfoTotalExcel::getAmtTotal)
-                                    .reduce(BigDecimal.ZERO, BigDecimal::add)
-                                    .divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP)
-                            )
-                    )
-                    .collect(Collectors.toList());
-            exportData.addAll(ddList);
-            exportData.addAll(amtList);
-            exportData.addAll(hyList);
-            BigDecimal reduce = list.stream().map(SubInfoTotalExcel::getAmtTotal).reduce(BigDecimal.ZERO, BigDecimal::add);
-            exportData.add(new SubInfoTotalInfoVO("合计", "合计", list.size(), reduce.divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP)));
-            // 4.导出
-            ExportParams exportParams = new ExportParams();
-            exportParams.setTitle("项目库基本情况");
-            exportParams.setSheetName("项目库基本情况");
-            exportParams.setType(ExcelType.XSSF);
-            int mergeTotalStartRow = exportData.size() + 1;
-            Workbook workbook = ExcelExportUtil.exportExcel(exportParams, SubInfoTotalInfoVO.class, exportData);
+        // 0.项目总库导出总表
+        if (StringUtils.isBlank(vo.getStatus())){
+            // 0.1 按区域构建表头
+            List<String> subjectIds = list.stream().map(SubInfoTotalExcel::getSubjectId).distinct().collect(Collectors.toList());
+            // 创建主表头
+            List<ExcelExportEntity> entityList = new ArrayList<>();
+            // 添加表头
+            ExcelExportEntity lbEntity = new ExcelExportEntity("项目类别", "subjectName");
+            entityList.add(lbEntity);
+
+            ExcelExportEntity hj = new ExcelExportEntity("合计", "hj");
+            List<ExcelExportEntity> subHeadEntities = new ArrayList<>();
+            subHeadEntities.add(getExcelExportEntity("项目个数", "count", 12));
+            subHeadEntities.add(getExcelExportEntity("计划总投资(亿元)", "amt", 20));
+            hj.setList(subHeadEntities);
+            entityList.add(hj);
+
+            for (String subjectId : subjectIds) {
+                ExcelExportEntity jsdd = new ExcelExportEntity(jsddMap.get(subjectId), subjectId);
+                List<ExcelExportEntity> ddHead = new ArrayList<>();
+                ddHead.add(getExcelExportEntity("项目个数", "count", 12));
+                ddHead.add(getExcelExportEntity("计划总投资(亿元)", "amt", 20));
+                jsdd.setList(ddHead);
+                entityList.add(jsdd);
+            }
+            // 0.2 构建数据
+            Map<String, List<SubInfoTotalExcel>> statusGroup = list.stream().collect(Collectors.groupingBy(SubInfoTotalExcel::getStatus));
+            List<Map<String,Object>> dataList = new ArrayList<>();
+            // 0.2.1 储备项目
+            List<SubInfoTotalExcel> cb = statusGroup.get(SubInfoStatusEnum.CB.getCode());
+            List<SubInfoTotalExcel> xj = statusGroup.get(SubInfoStatusEnum.XJ.getCode());
+            List<SubInfoTotalExcel> zj = statusGroup.get(SubInfoStatusEnum.ZJ.getCode());
+            List<SubInfoTotalExcel> tc = statusGroup.get(SubInfoStatusEnum.TC.getCode());
+
+            fillRowData(subjectIds, dataList, cb, SubInfoStatusEnum.CB.getDesc() + "项目");
+            fillRowData(subjectIds, dataList, xj, SubInfoStatusEnum.XJ.getDesc() + "项目");
+            fillRowData(subjectIds, dataList, zj, SubInfoStatusEnum.ZJ.getDesc() + "项目");
+            fillRowData(subjectIds, dataList, tc, SubInfoStatusEnum.TC.getDesc() + "项目");
+            fillRowData(subjectIds, dataList, list, "合计");
+
+
+            // 3.导出
+            ExportParams exportParams = getExportParams();
+            exportParams.setTitle("哈密市“四个一批”工业项目库总体情况");
+            exportParams.setSheetName("项目库总体情况");
+
+            Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, dataList);
             response.setContentType("application/xlsx;charset=utf-8");
-            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncodeUtil.encode("项目明细表") + System.currentTimeMillis() + ".xlsx");
-            Sheet sheet = workbook.getSheetAt(0);
-            // 合并单元格
-            sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 1));
-            sheet.addMergedRegion(new CellRangeAddress(2, ddList.size() + 1, 0, 0));
-            sheet.addMergedRegion(new CellRangeAddress(ddList.size() + 2, ddList.size() + amtList.size() + 1, 0, 0));
-            sheet.addMergedRegion(new CellRangeAddress(ddList.size() + amtList.size() + 2, ddList.size() + amtList.size() + hyList.size() + 1, 0, 0));
-            sheet.addMergedRegion(new CellRangeAddress(mergeTotalStartRow, mergeTotalStartRow, 0, 1));
+            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncodeUtil.encode("项目库总体情况") + System.currentTimeMillis() + ".xlsx");
 
             try (OutputStream outputStream = response.getOutputStream()) {
                 workbook.write(outputStream);
@@ -957,10 +1182,139 @@ public class SubInfoExportController extends BaseController {
             } catch (IOException e) {
                 e.printStackTrace();
             }
+        }else {
+            // 处理数据
+            List<SubInfoTotalInfoVO> exportData = new ArrayList<>();
+            if (CollectionUtil.isNotEmpty(list)) {
+                // 1.按属地分
+                List<SubInfoTotalInfoVO> ddList = list.stream()
+                        .collect(Collectors.groupingBy(SubInfoTotalExcel::getSubjectId))
+                        .entrySet().stream()
+                        .map(entry -> new SubInfoTotalInfoVO(
+                                "按属地分",
+                                jsddMap.getOrDefault(entry.getKey(), entry.getKey()),
+                                entry.getValue().size(),
+                                entry.getValue().stream()
+                                        .map(SubInfoTotalExcel::getAmtTotal)
+                                        .reduce(BigDecimal.ZERO, BigDecimal::add)
+                                        .divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP)
+                        ))
+                        .collect(Collectors.toList());
+
+                // 2.按金额分 定义分组边界
+                Map<String, BigDecimal> groupBoundaries = new LinkedHashMap<>();
+                groupBoundaries.put("10亿元以下", new BigDecimal("100000"));
+                groupBoundaries.put("10-50亿元", new BigDecimal("500000"));
+                groupBoundaries.put("50-100亿元", new BigDecimal("1000000"));
+                List<SubInfoTotalInfoVO> amtList = list.stream()
+                        .collect(Collectors.groupingBy(transaction -> {
+                            for (Map.Entry<String, BigDecimal> entry : groupBoundaries.entrySet()) {
+                                if (transaction.getAmtTotal().compareTo(entry.getValue()) < 0) {
+                                    return entry.getKey();
+                                }
+                            }
+                            return "100亿元以上"; // 超过最高范围的默认分组
+                        }))
+                        .entrySet().stream()
+                        .map(entry -> new SubInfoTotalInfoVO(
+                                "按金额分",
+                                entry.getKey(),
+                                entry.getValue().size(),
+                                entry.getValue().stream()
+                                        .map(SubInfoTotalExcel::getAmtTotal)
+                                        .reduce(BigDecimal.ZERO, BigDecimal::add)
+                                        .divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP)
+                        ))
+                        .collect(Collectors.toList());
+
+                // 3.按行业分
+                List<SubInfoTotalInfoVO> hyList = list.stream()
+                        .collect(Collectors.groupingBy(transaction ->{
+                            String code = transaction.getInduskind();
+                            // 确保code不为空且长度至少为2
+                            if (code == null || code.length() < 2) {
+                                return "未知行业";  // 默认未知行业
+                            }
+                            return code.substring(0, 2);
+                        }))
+                        .entrySet().stream()
+                        .map(entry -> new SubInfoTotalInfoVO(
+                                        "按行业分",
+                                        hyflMap.getOrDefault(entry.getKey(),entry.getKey()),
+                                        entry.getValue().size(),
+                                        entry.getValue().stream()
+                                                .map(SubInfoTotalExcel::getAmtTotal)
+                                                .reduce(BigDecimal.ZERO, BigDecimal::add)
+                                                .divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP)
+                                )
+                        )
+                        .collect(Collectors.toList());
+                exportData.addAll(ddList);
+                exportData.addAll(amtList);
+                exportData.addAll(hyList);
+                BigDecimal reduce = list.stream().map(SubInfoTotalExcel::getAmtTotal).reduce(BigDecimal.ZERO, BigDecimal::add);
+                exportData.add(new SubInfoTotalInfoVO("合计", "合计", list.size(), reduce.divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP)));
+                // 4.导出
+                ExportParams exportParams = getExportParams();
+                exportParams.setTitle("项目库基本情况");
+                exportParams.setSheetName("项目库基本情况");
+                int mergeTotalStartRow = exportData.size() + 1;
+                Workbook workbook = ExcelExportUtil.exportExcel(exportParams, SubInfoTotalInfoVO.class, exportData);
+                response.setContentType("application/xlsx;charset=utf-8");
+                response.setHeader("Content-Disposition", "attachment; filename=" + URLEncodeUtil.encode("项目明细表") + System.currentTimeMillis() + ".xlsx");
+                Sheet sheet = workbook.getSheetAt(0);
+                // 合并单元格
+                sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 1));
+                sheet.addMergedRegion(new CellRangeAddress(2, ddList.size() + 1, 0, 0));
+                sheet.addMergedRegion(new CellRangeAddress(ddList.size() + 2, ddList.size() + amtList.size() + 1, 0, 0));
+                sheet.addMergedRegion(new CellRangeAddress(ddList.size() + amtList.size() + 2, ddList.size() + amtList.size() + hyList.size() + 1, 0, 0));
+                sheet.addMergedRegion(new CellRangeAddress(mergeTotalStartRow, mergeTotalStartRow, 0, 1));
+
+                try (OutputStream outputStream = response.getOutputStream()) {
+                    workbook.write(outputStream);
+                    workbook.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
         }
+    }
 
+    private void fillRowData(List<String> subjectIds, List<Map<String, Object>> dataList, List<SubInfoTotalExcel> cb,String name) {
+        Map<String, List<SubInfoTotalExcel>> collect = cb.stream().collect(Collectors.groupingBy(e -> StringUtils.defaultIfBlank(e.getSubjectId(), ".")));
+        Map<String, List<Object>> map = new LinkedHashMap<>();
+        collect.forEach((key, value) -> {
+            List<Object> list1 = new ArrayList<>();
+            Map<String,Object> columnMap = new LinkedHashMap<>();
+            columnMap.put("count", value.size());
+            columnMap.put("amt", value.stream().map(SubInfoTotalExcel::getAmtTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
+            list1.add(columnMap);
+            map.put(key, list1);
+        });
+
+        // 合计金额
+        BigDecimal cbAmtSum = cb.stream()
+                .map(SubInfoTotalExcel::getAmtTotal)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        Map<String, Object> rowMap = new LinkedHashMap<>();
+        rowMap.put("subjectName", name);
+
+        List<Object> list = new ArrayList<>();
+        Map<String, Object> hjMap = new LinkedHashMap<>();
+        hjMap.put("count", cb.size());
+        hjMap.put("amt", cbAmtSum);
+        list.add(hjMap);
+
+        rowMap.put("hj", list);
+
+        for (String subjectId : subjectIds) {
+            rowMap.put(subjectId, map.getOrDefault(subjectId, Collections.emptyList()));
+        }
+        dataList.add(rowMap);
     }
 
+
     /**
      * 导出重点项目明细表
      *

+ 5 - 2
projects/src/main/webapp/vmodules/subject/subInfo/tz/cb.jsp

@@ -201,7 +201,7 @@
         <div>
             <div class="layui-row">
                 <div style="display: flex;margin-bottom: 3px">
-                    <label class="juli" onclick="levelList('abcs','A类','A')">
+                    <label class="juli" onclick="levelList('abcs','A类','')">
                         储备项目总数
                         <span class="info-icon" title="A类项目:成熟类项目,可研或初设已编制并完成初审,达到项目等资金的进度">?</span>
                         <span class="lanse-first">{{beginRate.num}}</span>
@@ -221,7 +221,10 @@
                         <span class="info-icon" title="C类项目:意向类项目,还处于谋划论证阶段项目">?</span>
                         <span class="lanse-first">{{beginRate.cnum}}</span>
                     </label>
-
+                    <label class="juli" onclick="levelList('abcs','D类','.')">
+                        <span class="info-icon" title="ABC类未设置">?</span>
+                        <span class="lanse-first">{{beginRate.nnum}}</span>
+                    </label>
                 </div>
                 <div style="display: flex;margin-bottom: 3px">
                     <label class="juli"