Преглед изворни кода

feat: 实现不动产一房产局址一表导出接口

weijianghai пре 10 месеци
родитељ
комит
a743aab3fa

+ 4 - 0
src/main/java/com/example/common/PageVo.java

@@ -54,4 +54,8 @@ public class PageVo<T> {
         this.currPage = (long) pageInfo.getPageNum();
         this.totalPage = (long) pageInfo.getPages();
     }
+
+    public PageVo(List<T> list) {
+        this.list = list;
+    }
 }

+ 13 - 9
src/main/java/com/example/config/ApiDocConfig.java

@@ -1,5 +1,6 @@
 package com.example.config;
 
+import com.example.utils.AESUtil;
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.info.Info;
 import io.swagger.v3.oas.models.parameters.Parameter;
@@ -19,14 +20,17 @@ public class ApiDocConfig {
 
     @Bean
     public OpenApiCustomiser openApiCustomiser() {
-        return openApi -> openApi.getPaths().values().forEach(pathItem -> pathItem.readOperations().forEach(operation -> {
-            Parameter headerParam = new Parameter()
-                    .required(true)
-                    .in("header")
-                    .name("token")
-                    .description("访问令牌")
-                    .example("zoQtYlmhk/add/mBUBZD5mFJB1IXEwaLRS97Uf9z9Hlqdh/UHio66b35GOo/eEziALCI90sLNBn3WM7k1/FVGgGiDUO84mJ2JUgw5zHx8fvcO/OxqUB83JYaeV6eJIWkvJpp");
-            operation.addParametersItem(headerParam);
-        }));
+        String token = AESUtil.getTestToken();
+        return openApi -> openApi.getPaths().values()
+                .forEach(pathItem -> pathItem.readOperations()
+                        .forEach(operation -> {
+                            Parameter headerParam = new Parameter()
+                                    .required(true)
+                                    .in("header")
+                                    .name("token")
+                                    .description("访问令牌")
+                                    .example(token);
+                            operation.addParametersItem(headerParam);
+                        }));
     }
 }

+ 9 - 0
src/main/java/com/example/config/web/MyDispatcherServlet.java

@@ -17,8 +17,17 @@ public class MyDispatcherServlet extends DispatcherServlet {
     public static final Set<String> UN_WRAPPER = Stream.of(
             "/house-car/house/dist/api/data-import/dataImport",
             "/house-car/house/dist/api/WzBuildManageDetails/ideListExport",
+            "/house-car/house/dist/api/WzBuildManageDetails/queryHouseDetailExport",
+            "/house-car/house/dist/api/WzBuildManageDetails/queryHouseYearExport",
+            "/house-car/house/dist/api/WzBuildManageDetails/buildingIdleStatExport",
             "/house-car/house/dist/api/wzHouseMaintenaCost/queryHighPriceExport",
             "/house-car/house/dist/api/wzHouseMaintenaCost/queryHighFrequencyExport",
+            "/house-car/house/dist/api/wzHouseMaintenaCost/queryDailyModifyExport",
+            "/house-car/house/dist/api/wzHouseMaintenaCost/buildingIdleRepairExport",
+            "/house-car/house/dist/api/wzHouseMaintenaCost/buildingRepairStatExport",
+            "/house-car/house/dist/api/wzHouseMaintenaCost/listBuildingRepairMonthExport",
+            "/house-car/house/dist/api/siteStat/siteStatExport",
+            "/house-car/house/dist/api/WzBuildmanageAvagearea/buildingOfficeAreaStatExport",
             "/house-car/house/dist/api/WzBuildManageDetails/excel",
             "/house-car/house/dist/api/WzHouseContractOut/excel",
             "/house-car/house/dist/api/WzHouseContrac/excel",

+ 9 - 2
src/main/java/com/example/controller/house/HouseSiteStatController.java

@@ -7,6 +7,7 @@ import com.example.service.house.HouseSiteStatService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -14,7 +15,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
 
-@Tag(name = "不动产一房产局址表")
+@Tag(name = "不动产一房产局址表")
 @Slf4j
 @RequestMapping("/house-car/house/dist/api/siteStat")
 @RestController
@@ -25,9 +26,15 @@ public class HouseSiteStatController {
         this.houseSiteStatService = houseSiteStatService;
     }
 
-    @Operation(summary = "查询一房产局址表")
+    @Operation(summary = "查询一房产局址表")
     @PostMapping("/getSiteStat")
     public Rsp<GetSiteStatVo> getSiteStat(@Valid @RequestBody GetSiteStatDto dto) {
         return houseSiteStatService.getSiteStat(dto);
     }
+
+    @Operation(summary = "一房产局址一表导出")
+    @GetMapping("/siteStatExport")
+    public void siteStatExport(@Valid GetSiteStatDto.GetSiteStatMapDTO dto) {
+        houseSiteStatService.siteStatExport(dto);
+    }
 }

+ 8 - 0
src/main/java/com/example/dao/house/HouseSiteStatDao.java

@@ -33,6 +33,7 @@ select * from house.site_month where year_month <= #{yearMonth} and site_id = #{
 select * from house.building_month
 where year_month = (select max(year_month) from house.building_month where year_month <= #{yearMonth})
 and site_id = #{siteId}
+order by building_area desc
 """)
     List<HouseBuildingPo> allBuildingBySiteIdAndYearMonth(@Param("yearMonth") Integer yearMonth,
                                                           @Param("siteId") String siteId);
@@ -97,6 +98,13 @@ order by month_no
                                                          @Param("endYearMonth") Integer endYearMonth,
                                                          @Param("siteId") String siteId);
 
+    /**
+     * 查询局址建筑面积闲置率变化
+     * @param startYearMonth 开始年月
+     * @param endYearMonth 结束年月
+     * @param siteId 局址id
+     * @return {@link HouseSiteBuildingAreaIdleDiffPo}
+     */
     @Select("""
 with
 t101 as (

+ 13 - 0
src/main/java/com/example/pojo/dto/GetSiteStatDto.java

@@ -3,9 +3,12 @@ package com.example.pojo.dto;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.springframework.util.StringUtils;
 
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
 
 @NoArgsConstructor
 @Data
@@ -14,6 +17,16 @@ public class GetSiteStatDto {
     @NotNull
     private GetSiteStatMapDTO map;
 
+    public GetSiteStatDto(GetSiteStatMapDTO dto) {
+        if (StringUtils.hasText(map.city)) {
+            map.city = URLDecoder.decode(map.city, StandardCharsets.UTF_8);
+        }
+        if (StringUtils.hasText(map.county)) {
+            map.county = URLDecoder.decode(map.county, StandardCharsets.UTF_8);
+        }
+        this.map = dto;
+    }
+
     @NoArgsConstructor
     @Data
     public static class GetSiteStatMapDTO {

+ 11 - 2
src/main/java/com/example/pojo/vo/GetSiteStatVo.java

@@ -2,13 +2,12 @@ package com.example.pojo.vo;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
-import lombok.NoArgsConstructor;
 
 import java.math.BigDecimal;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 
-@NoArgsConstructor
 @Data
 public class GetSiteStatVo {
     /**
@@ -106,4 +105,14 @@ public class GetSiteStatVo {
     private BigDecimal buildingAreaIdleRateNow;
     @Schema(description = "房屋面积闲置率-变化率")
     private BigDecimal buildingAreaIdleRateDiff;
+
+    public GetSiteStatVo() {
+        this.buildingList = Collections.singletonList(new GetSiteStatBuildingVo());
+        this.rentOutIncomeSsMonth = new LinkedHashMap<>();
+        this.rentOutArrearsSsMonth = new LinkedHashMap<>();
+        this.rentOutIncomeCxMonth = new LinkedHashMap<>();
+        this.rentOutArrearsCxMonth = new LinkedHashMap<>();
+        this.buildingRepairMonth = new LinkedHashMap<>();
+        this.propertyFeeMonth = new LinkedHashMap<>();
+    }
 }

+ 802 - 21
src/main/java/com/example/service/house/HouseSiteStatService.java

@@ -1,5 +1,6 @@
 package com.example.service.house;
 
+import cn.hutool.core.net.URLEncodeUtil;
 import com.example.common.Rsp;
 import com.example.dao.house.HouseSiteStatDao;
 import com.example.entity.house.HouseBuildingPo;
@@ -11,16 +12,38 @@ import com.example.pojo.dto.GetSiteStatDto;
 import com.example.pojo.vo.GetSiteStatBuildingVo;
 import com.example.pojo.vo.GetSiteStatVo;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.DataFormat;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.streaming.SXSSFSheet;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
 
+import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Stream;
 
 @Slf4j
 @Service
@@ -51,7 +74,7 @@ public class HouseSiteStatService {
         // 查询局址信息
         HouseSitePo houseSitePo = houseSiteStatDao.getHouseSiteBySiteIdAndYearMonth(endYearMonth, siteId);
         if (houseSitePo == null) {
-            return null;
+            return vo;
         }
         vo.setSiteNum(houseSitePo.getSiteNum());
         vo.setSiteName(houseSitePo.getSiteName());
@@ -67,28 +90,30 @@ public class HouseSiteStatService {
         BigDecimal buildingAreaRentSum = BigDecimal.ZERO;
         BigDecimal buildingAreaIdleSum = BigDecimal.ZERO;
         BigDecimal buildingAreaUnusableSum = BigDecimal.ZERO;
-        List<GetSiteStatBuildingVo> buildingList = new ArrayList<>();
-        vo.setBuildingList(buildingList);
-        for (HouseBuildingPo houseBuildingPo : houseBuildingPoList) {
-            buildingList.add(new GetSiteStatBuildingVo(houseBuildingPo));
-            // 计算局址建筑面积
-            if (houseBuildingPo.getBuildingArea() != null) {
-                buildingAreaSum = buildingAreaSum.add(houseBuildingPo.getBuildingArea());
-            }
-            if (houseBuildingPo.getBuildingAreaSelfUse() != null) {
-                buildingAreaSelfUseSum = buildingAreaSelfUseSum.add(houseBuildingPo.getBuildingAreaSelfUse());
-            }
-            if (houseBuildingPo.getBuildingAreaRent() != null) {
-                buildingAreaRentSum = buildingAreaRentSum.add(houseBuildingPo.getBuildingAreaRent());
-            }
-            if (houseBuildingPo.getBuildingAreaIdle() != null) {
-                buildingAreaIdleSum = buildingAreaIdleSum.add(houseBuildingPo.getBuildingAreaIdle());
-            }
-            if (houseBuildingPo.getBuildingAreaUnusable() != null) {
-                buildingAreaUnusableSum = buildingAreaUnusableSum.add(houseBuildingPo.getBuildingAreaUnusable());
+        if (!CollectionUtils.isEmpty(houseBuildingPoList)) {
+            List<GetSiteStatBuildingVo> buildingList = new ArrayList<>();
+            vo.setBuildingList(buildingList);
+            for (HouseBuildingPo houseBuildingPo : houseBuildingPoList) {
+                buildingList.add(new GetSiteStatBuildingVo(houseBuildingPo));
+                // 计算局址建筑面积
+                if (houseBuildingPo.getBuildingArea() != null) {
+                    buildingAreaSum = buildingAreaSum.add(houseBuildingPo.getBuildingArea());
+                }
+                if (houseBuildingPo.getBuildingAreaSelfUse() != null) {
+                    buildingAreaSelfUseSum = buildingAreaSelfUseSum.add(houseBuildingPo.getBuildingAreaSelfUse());
+                }
+                if (houseBuildingPo.getBuildingAreaRent() != null) {
+                    buildingAreaRentSum = buildingAreaRentSum.add(houseBuildingPo.getBuildingAreaRent());
+                }
+                if (houseBuildingPo.getBuildingAreaIdle() != null) {
+                    buildingAreaIdleSum = buildingAreaIdleSum.add(houseBuildingPo.getBuildingAreaIdle());
+                }
+                if (houseBuildingPo.getBuildingAreaUnusable() != null) {
+                    buildingAreaUnusableSum = buildingAreaUnusableSum.add(houseBuildingPo.getBuildingAreaUnusable());
+                }
             }
+            vo.setBuildingCount(buildingList.size());
         }
-        vo.setBuildingCount(buildingList.size());
         vo.setBuildingAreaSum(buildingAreaSum);
         vo.setBuildingAreaSelfUseSum(buildingAreaSelfUseSum);
         vo.setBuildingAreaRentSum(buildingAreaRentSum);
@@ -137,4 +162,760 @@ public class HouseSiteStatService {
         }
         return vo;
     }
+
+    public void siteStatExport(GetSiteStatDto.GetSiteStatMapDTO dto) {
+        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder
+                .getRequestAttributes();
+        if (servletRequestAttributes == null) {
+            return;
+        }
+        HttpServletResponse response = servletRequestAttributes.getResponse();
+        if (response == null) {
+            return;
+        }
+        String filename = "一房产局址一表"
+                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".xlsx";
+        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncodeUtil.encode(filename));
+        response.setContentType("application/octet-stream");
+        try (SXSSFWorkbook wb = new SXSSFWorkbook()) {
+            writeSiteStat(new GetSiteStatDto(dto), wb);
+            wb.write(response.getOutputStream());
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 写一房产局址一表文件
+     */
+    private void writeSiteStat(GetSiteStatDto dto, SXSSFWorkbook wb) {
+        GetSiteStatVo siteStatVo = getSiteStatVo(dto);
+        DataFormat dataFormat = wb.createDataFormat();
+        // 整数样式
+        CellStyle integerCellStyle = wb.createCellStyle();
+        integerCellStyle.setDataFormat(dataFormat.getFormat("#,##0"));
+        setBaseStyle(integerCellStyle);
+        // 数字样式居中对齐
+        CellStyle centerNumberCellStyle = wb.createCellStyle();
+        centerNumberCellStyle.setDataFormat(dataFormat.getFormat("#,##0.00"));
+        setBaseStyle(centerNumberCellStyle);
+        // 数字样式右对齐
+        CellStyle rightNumberCellStyle = wb.createCellStyle();
+        rightNumberCellStyle.cloneStyleFrom(centerNumberCellStyle);
+        rightNumberCellStyle.setAlignment(HorizontalAlignment.RIGHT);
+        // 默认样式
+        CellStyle baseCellStyle = wb.createCellStyle();
+        setBaseStyle(baseCellStyle);
+        Font titleFont1 = wb.createFont();
+        titleFont1.setFontHeightInPoints((short) 24);
+        titleFont1.setBold(true);
+        // 标题样式1
+        CellStyle titleCellStyle1 = wb.createCellStyle();
+        setBaseStyle(titleCellStyle1);
+        titleCellStyle1.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        titleCellStyle1.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);
+        titleCellStyle1.setFont(titleFont1);
+        Font titleFont2 = wb.createFont();
+        titleFont2.setFontHeightInPoints((short) 16);
+        titleFont2.setBold(true);
+        // 标题样式2
+        CellStyle titleCellStyle2 = wb.createCellStyle();
+        setBaseStyle(titleCellStyle2);
+        titleCellStyle2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        titleCellStyle2.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);
+        titleCellStyle2.setFont(titleFont2);
+        Font titleFont3 = wb.createFont();
+        titleFont3.setBold(true);
+        // 标题样式3
+        CellStyle titleCellStyle3 = wb.createCellStyle();
+        setBaseStyle(titleCellStyle3);
+        titleCellStyle3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        titleCellStyle3.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);
+        titleCellStyle3.setFont(titleFont3);
+        SXSSFSheet sheet = wb.createSheet();
+        AtomicInteger rowIndex = new AtomicInteger(0);
+        // 一房产局址一表标题
+        Row titleRow = sheet.createRow(rowIndex.getAndIncrement());
+        addMergedRegion(sheet, titleCellStyle1,
+                CellRangeAddress.valueOf("a" + rowIndex.get() + ":n" + rowIndex.get()));
+        Cell titleCell = titleRow.getCell(CellReference.convertColStringToIndex("a"));
+        titleCell.setCellValue("一房产局址一表");
+        // 基础信息第1行
+        Row baseInfoRow1 = sheet.createRow(rowIndex.getAndIncrement());
+        // 基础信息标题
+        addMergedRegion(sheet, titleCellStyle2,
+                CellRangeAddress.valueOf("a" + rowIndex.get() + ":a" + (rowIndex.get() + 2)));
+        Cell baseInfoTitleCell = baseInfoRow1.getCell(CellReference.convertColStringToIndex("a"));
+        baseInfoTitleCell.setCellValue("基础信息");
+        // 局址编码标题
+        Cell siteNumTitleCell = baseInfoRow1.createCell(CellReference.convertColStringToIndex("b"));
+        siteNumTitleCell.setCellValue("局址编码");
+        siteNumTitleCell.setCellStyle(titleCellStyle3);
+        // 局址编码
+        addMergedRegion(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("c" + rowIndex.get() + ":d" + rowIndex.get()));
+        Cell siteNumValueCell = baseInfoRow1.getCell(CellReference.convertColStringToIndex("c"));
+        if (siteStatVo.getSiteNum() != null) {
+            siteNumValueCell.setCellValue(siteStatVo.getSiteNum());
+        }
+        // 局址别名标题
+        Cell siteNameTitleCell = baseInfoRow1.createCell(CellReference.convertColStringToIndex("e"));
+        siteNameTitleCell.setCellValue("局址别名");
+        siteNameTitleCell.setCellStyle(titleCellStyle3);
+        // 局址别名
+        addMergedRegion(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("f" + rowIndex.get() + ":g" + rowIndex.get()));
+        Cell siteNameValueCell = baseInfoRow1.getCell(CellReference.convertColStringToIndex("f"));
+        if (siteStatVo.getSiteName() != null) {
+            siteNameValueCell.setCellValue(siteStatVo.getSiteName());
+        }
+        // 所属市区标题
+        Cell areaNameTitleCell = baseInfoRow1.createCell(CellReference.convertColStringToIndex("h"));
+        areaNameTitleCell.setCellValue("所属市区");
+        areaNameTitleCell.setCellStyle(titleCellStyle3);
+        // 所属市区
+        addMergedRegion(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("i" + rowIndex.get() + ":j" + rowIndex.get()));
+        Cell areaNameValueCell = baseInfoRow1.getCell(CellReference.convertColStringToIndex("i"));
+        if (siteStatVo.getAreaName() != null) {
+            areaNameValueCell.setCellValue(siteStatVo.getAreaName());
+        }
+        // 所属区县标题
+        Cell cityNameTitleCell = baseInfoRow1.createCell(CellReference.convertColStringToIndex("k"));
+        cityNameTitleCell.setCellValue("所属区县");
+        cityNameTitleCell.setCellStyle(titleCellStyle3);
+        // 所属区县
+        addMergedRegion(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("l" + rowIndex.get() + ":n" + rowIndex.get()));
+        Cell cityNameValueCell = baseInfoRow1.getCell(CellReference.convertColStringToIndex("l"));
+        if (siteStatVo.getCityName() != null) {
+            cityNameValueCell.setCellValue(siteStatVo.getCityName());
+        }
+        // 基础信息第2行
+        Row baseInfoRow2 = sheet.getRow(rowIndex.getAndIncrement());
+        // 局址地址标题
+        Cell addressTitleCell = baseInfoRow2.createCell(CellReference.convertColStringToIndex("b"));
+        addressTitleCell.setCellValue("局址地址");
+        addressTitleCell.setCellStyle(titleCellStyle3);
+        // 局址地址
+        addMergedRegion(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("c" + rowIndex.get() + ":g" + rowIndex.get()));
+        Cell addressValueCell = baseInfoRow2.getCell(CellReference.convertColStringToIndex("c"));
+        if (siteStatVo.getAddress() != null) {
+            addressValueCell.setCellValue(siteStatVo.getAddress());
+        }
+        // 所处地段标题
+        Cell areaSectorTitleCell = baseInfoRow2.createCell(CellReference.convertColStringToIndex("h"));
+        areaSectorTitleCell.setCellValue("所处地段");
+        areaSectorTitleCell.setCellStyle(titleCellStyle3);
+        // 所处地段
+        addMergedRegion(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("i" + rowIndex.get() + ":j" + rowIndex.get()));
+        Cell areaSectorValueCell = baseInfoRow2.getCell(CellReference.convertColStringToIndex("i"));
+        if (siteStatVo.getAreaSector() != null) {
+            areaSectorValueCell.setCellValue(siteStatVo.getAreaSector());
+        }
+        // 建筑数量标题
+        Cell buildingCountTitleCell = baseInfoRow2.createCell(CellReference.convertColStringToIndex("k"));
+        buildingCountTitleCell.setCellValue("建筑数量");
+        buildingCountTitleCell.setCellStyle(titleCellStyle3);
+        // 建筑数量
+        addMergedRegion(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("l" + rowIndex.get() + ":n" + rowIndex.get()));
+        Cell buildingCountValueCell = baseInfoRow2.getCell(CellReference.convertColStringToIndex("l"));
+        if (siteStatVo.getBuildingCount() != null) {
+            buildingCountValueCell.setCellValue(siteStatVo.getBuildingCount());
+        }
+        // 基础信息第3行
+        Row baseInfoRow3 = sheet.getRow(rowIndex.getAndIncrement());
+        // 建筑面积标题
+        Cell buildingAreaSumTitleCell = baseInfoRow3.createCell(CellReference.convertColStringToIndex("b"));
+        buildingAreaSumTitleCell.setCellValue("建筑面积");
+        buildingAreaSumTitleCell.setCellStyle(titleCellStyle3);
+        // 建筑面积
+        addMergedRegion(sheet, centerNumberCellStyle,
+                CellRangeAddress.valueOf("c" + rowIndex.get() + ":d" + rowIndex.get()));
+        Cell buildingAreaSumValueCell = baseInfoRow3.getCell(CellReference.convertColStringToIndex("c"));
+        if (siteStatVo.getBuildingAreaSum() != null) {
+            buildingAreaSumValueCell.setCellValue(siteStatVo.getBuildingAreaSum().doubleValue());
+        }
+        // 土地面积标题
+        Cell landAreaSumTitleCell = baseInfoRow3.createCell(CellReference.convertColStringToIndex("e"));
+        landAreaSumTitleCell.setCellValue("土地面积");
+        landAreaSumTitleCell.setCellStyle(titleCellStyle3);
+        // 土地面积
+        addMergedRegion(sheet, centerNumberCellStyle,
+                CellRangeAddress.valueOf("f" + rowIndex.get() + ":g" + rowIndex.get()));
+        Cell landAreaSumValueCell = baseInfoRow3.getCell(CellReference.convertColStringToIndex("f"));
+        if (siteStatVo.getLandAreaSum() != null) {
+            landAreaSumValueCell.setCellValue(siteStatVo.getLandAreaSum().doubleValue());
+        }
+        // 办公人数标题
+        Cell staffCountTitleCell = baseInfoRow3.createCell(CellReference.convertColStringToIndex("h"));
+        staffCountTitleCell.setCellValue("办公人数");
+        staffCountTitleCell.setCellStyle(titleCellStyle3);
+        // 办公人数
+        addMergedRegion(sheet, centerNumberCellStyle,
+                CellRangeAddress.valueOf("i" + rowIndex.get() + ":j" + rowIndex.get()));
+        Cell staffCountValueCell = baseInfoRow3.getCell(CellReference.convertColStringToIndex("i"));
+        if (siteStatVo.getStaffCount() != null) {
+            staffCountValueCell.setCellValue(siteStatVo.getStaffCount());
+        }
+        // 空单元格
+        batchSetCellStyle(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("k" + rowIndex.get() + ":n" + rowIndex.get()));
+        // 建筑信息第1行
+        Row buildingInfoRow1 = sheet.createRow(rowIndex.getAndIncrement());
+        List<GetSiteStatBuildingVo> buildingList = siteStatVo.getBuildingList();
+        int buildingRows = buildingList.size();
+        // 建筑信息标题
+        addMergedRegion(sheet, titleCellStyle2,
+                CellRangeAddress.valueOf("a" + rowIndex.get() + ":a" + (rowIndex.get() + buildingRows)));
+        Cell buildingInfoTitleCell = buildingInfoRow1.getCell(CellReference.convertColStringToIndex("a"));
+        buildingInfoTitleCell.setCellValue("建筑信息");
+        List<String> buildingInfoHeaders = Stream.of("资产编号", "建筑别名", "房龄开始日期", "投资主体", "楼层总数",
+                "建筑用途", "建筑面积", "自用面积", "出租面积", "闲置面积", "资产原值", "累计折旧", "").toList();
+        int buildingInfoHeadersSize = buildingInfoHeaders.size();
+        for (int i = 0; i < buildingInfoHeadersSize; i++) {
+            Cell cell = buildingInfoRow1.createCell(i + 1);
+            cell.setCellValue(buildingInfoHeaders.get(i));
+            cell.setCellStyle(titleCellStyle3);
+        }
+        for (GetSiteStatBuildingVo getSiteStatBuildingVo : buildingList) {
+            AtomicInteger columnIndex = new AtomicInteger(CellReference.convertColStringToIndex("b"));
+            Row row = sheet.getRow(rowIndex.getAndIncrement());
+            // 资产编号
+            Cell assetNumValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getAssetsNum() != null) {
+                assetNumValueCell.setCellValue(getSiteStatBuildingVo.getAssetsNum());
+            }
+            assetNumValueCell.setCellStyle(baseCellStyle);
+            // 建筑别名
+            Cell buildingNameValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getBuildingName() != null) {
+                buildingNameValueCell.setCellValue(getSiteStatBuildingVo.getBuildingName());
+            }
+            buildingNameValueCell.setCellStyle(baseCellStyle);
+            // 房龄开始日期
+            Cell houseYearBeganValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getHouseYearBegan() != null) {
+                houseYearBeganValueCell.setCellValue(getSiteStatBuildingVo.getHouseYearBegan());
+            }
+            houseYearBeganValueCell.setCellStyle(baseCellStyle);
+            // 投资主体
+            Cell investorValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getInvestor() != null) {
+                investorValueCell.setCellValue(getSiteStatBuildingVo.getInvestor());
+            }
+            investorValueCell.setCellStyle(baseCellStyle);
+            // 楼层总数
+            Cell totalFloorsValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getTotalFloors() != null) {
+                totalFloorsValueCell.setCellValue(getSiteStatBuildingVo.getTotalFloors());
+            }
+            totalFloorsValueCell.setCellStyle(baseCellStyle);
+            // 建筑用途
+            Cell buildingUseValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getBuildingUse() != null) {
+                buildingUseValueCell.setCellValue(getSiteStatBuildingVo.getBuildingUse());
+            }
+            buildingUseValueCell.setCellStyle(baseCellStyle);
+            // 建筑面积
+            Cell buildingAreaValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getBuildingArea() != null) {
+                buildingAreaValueCell.setCellValue(getSiteStatBuildingVo.getBuildingArea().doubleValue());
+            }
+            buildingAreaValueCell.setCellStyle(rightNumberCellStyle);
+            // 自用面积
+            Cell buildingAreaSelfUseValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getBuildingAreaSelfUse() != null) {
+                buildingAreaSelfUseValueCell.setCellValue(getSiteStatBuildingVo.getBuildingAreaSelfUse().doubleValue());
+            }
+            buildingAreaSelfUseValueCell.setCellStyle(rightNumberCellStyle);
+            // 出租面积
+            Cell buildingAreaRentValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getBuildingAreaRent() != null) {
+                buildingAreaRentValueCell.setCellValue(getSiteStatBuildingVo.getBuildingAreaRent().doubleValue());
+            }
+            buildingAreaRentValueCell.setCellStyle(rightNumberCellStyle);
+            // 闲置面积
+            Cell buildingAreaIdleValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getBuildingAreaIdle() != null) {
+                buildingAreaIdleValueCell.setCellValue(getSiteStatBuildingVo.getBuildingAreaIdle().doubleValue());
+            }
+            buildingAreaIdleValueCell.setCellStyle(rightNumberCellStyle);
+            // 资产原值
+            Cell initialAssetValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getInitialAssetValue() != null) {
+                initialAssetValueCell.setCellValue(getSiteStatBuildingVo.getInitialAssetValue().doubleValue());
+            }
+            initialAssetValueCell.setCellStyle(rightNumberCellStyle);
+            // 累计折旧
+            Cell accumulateDepreciationValueCell = row.createCell(columnIndex.getAndIncrement());
+            if (getSiteStatBuildingVo.getAccumulatedDepreciation() != null) {
+                accumulateDepreciationValueCell.setCellValue(getSiteStatBuildingVo.getAccumulatedDepreciation().doubleValue());
+            }
+            accumulateDepreciationValueCell.setCellStyle(rightNumberCellStyle);
+            // 空白单元格
+            Cell cell = row.createCell(columnIndex.getAndIncrement());
+            cell.setCellStyle(baseCellStyle);
+        }
+        // 出租信息第1行
+        Row rentInfoRow1 = sheet.createRow(rowIndex.getAndIncrement());
+        // 出租信息标题
+        addMergedRegion(sheet, titleCellStyle2,
+                CellRangeAddress.valueOf("a" + rowIndex.get() + ":a" + (rowIndex.get() + 7)));
+        Cell rentInfoTitleCell = rentInfoRow1.getCell(CellReference.convertColStringToIndex("a"));
+        rentInfoTitleCell.setCellValue("出租信息");
+        // 上市累计标题
+        Cell rentSsLjTitleCell = rentInfoRow1.createCell(CellReference.convertColStringToIndex("b"));
+        rentSsLjTitleCell.setCellValue("上市累计");
+        rentSsLjTitleCell.setCellStyle(titleCellStyle3);
+        // 对外出租收入标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("c" + rowIndex.get() + ":e" + rowIndex.get()));
+        Cell rentOutIncomeSsTitleCell = rentInfoRow1.getCell(CellReference.convertColStringToIndex("c"));
+        rentOutIncomeSsTitleCell.setCellValue("对外出租收入");
+        // 对外出租收入
+        Cell rentOutIncomeSsValueCell = rentInfoRow1.createCell(CellReference.convertColStringToIndex("f"));
+        if (siteStatVo.getRentOutIncomeSs() != null) {
+            rentOutIncomeSsValueCell.setCellValue(siteStatVo.getRentOutIncomeSs().doubleValue());
+        }
+        rentOutIncomeSsValueCell.setCellStyle(rightNumberCellStyle);
+        // 对外出租累计欠费标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("g" + rowIndex.get() + ":i" + rowIndex.get()));
+        Cell rentOutArrearsSsTitleCell = rentInfoRow1.getCell(CellReference.convertColStringToIndex("g"));
+        rentOutArrearsSsTitleCell.setCellValue("对外出租累计欠费");
+        // 对外出租累计欠费
+        Cell rentOutArrearsSsValueCell = rentInfoRow1.createCell(CellReference.convertColStringToIndex("j"));
+        if (siteStatVo.getRentOutArrearsSs() != null) {
+            rentOutArrearsSsValueCell.setCellValue(siteStatVo.getRentOutArrearsSs().doubleValue());
+        }
+        rentOutArrearsSsValueCell.setCellStyle(rightNumberCellStyle);
+        // 水电暖等杂费欠费标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("k" + rowIndex.get() + ":m" + rowIndex.get()));
+        Cell incidentalsArrearsSsTitleCell = rentInfoRow1.getCell(CellReference.convertColStringToIndex("k"));
+        incidentalsArrearsSsTitleCell.setCellValue("水电暖等杂费欠费");
+        // 水电暖等杂费欠费
+        Cell incidentalArrearsSsValueCell = rentInfoRow1.createCell(CellReference.convertColStringToIndex("n"));
+        if (siteStatVo.getIncidentalsArrearsSs() != null) {
+            incidentalArrearsSsValueCell.setCellValue(siteStatVo.getIncidentalsArrearsSs().doubleValue());
+        }
+        incidentalArrearsSsValueCell.setCellStyle(rightNumberCellStyle);
+        // 出租信息第2行
+        Row rentInfoRow2 = sheet.getRow(rowIndex.getAndIncrement());
+        // 存续累计标题
+        Cell rentCxLjTitleCell = rentInfoRow2.createCell(CellReference.convertColStringToIndex("b"));
+        rentCxLjTitleCell.setCellValue("存续累计");
+        rentCxLjTitleCell.setCellStyle(titleCellStyle3);
+        // 对外出租收入标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("c" + rowIndex.get() + ":e" + rowIndex.get()));
+        Cell rentOutIncomeCxTitleCell = rentInfoRow2.getCell(CellReference.convertColStringToIndex("c"));
+        rentOutIncomeCxTitleCell.setCellValue("对外出租收入");
+        // 对外出租收入
+        Cell rentOutIncomeCxValueCell = rentInfoRow2.createCell(CellReference.convertColStringToIndex("f"));
+        if (siteStatVo.getRentOutIncomeCx() != null) {
+            rentOutIncomeCxValueCell.setCellValue(siteStatVo.getRentOutIncomeCx().doubleValue());
+        }
+        rentOutIncomeCxValueCell.setCellStyle(rightNumberCellStyle);
+        // 对外出租累计欠费标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("g" + rowIndex.get() + ":i" + rowIndex.get()));
+        Cell rentOutArrearsCxTitleCell = rentInfoRow2.getCell(CellReference.convertColStringToIndex("g"));
+        rentOutArrearsCxTitleCell.setCellValue("对外出租累计欠费");
+        // 对外出租累计欠费
+        Cell rentOutArrearsCxValueCell = rentInfoRow2.createCell(CellReference.convertColStringToIndex("j"));
+        if (siteStatVo.getRentOutArrearsCx() != null) {
+            rentOutArrearsCxValueCell.setCellValue(siteStatVo.getRentOutArrearsCx().doubleValue());
+        }
+        rentOutArrearsCxValueCell.setCellStyle(rightNumberCellStyle);
+        // 水电暖等杂费欠费标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("k" + rowIndex.get() + ":m" + rowIndex.get()));
+        Cell incidentalsArrearsCxTitleCell = rentInfoRow2.getCell(CellReference.convertColStringToIndex("k"));
+        incidentalsArrearsCxTitleCell.setCellValue("水电暖等杂费欠费");
+        // 水电暖等杂费欠费
+        Cell incidentalArrearsCxValueCell = rentInfoRow2.createCell(CellReference.convertColStringToIndex("n"));
+        if (siteStatVo.getIncidentalsArrearsCx() != null) {
+            incidentalArrearsCxValueCell.setCellValue(siteStatVo.getIncidentalsArrearsCx().doubleValue());
+        }
+        incidentalArrearsCxValueCell.setCellStyle(rightNumberCellStyle);
+        // 出租信息第3行
+        Row rentInfoRow3 = sheet.getRow(rowIndex.getAndIncrement());
+        // 分月数据标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("b" + rowIndex.get() + ":b" + (rowIndex.get() + 1)));
+        Cell rentMonthTitleCell1 = rentInfoRow3.getCell(CellReference.convertColStringToIndex("b"));
+        rentMonthTitleCell1.setCellValue("分月数据");
+        // 12个月数据标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("c" + rowIndex.get() + ":n" + rowIndex.get()));
+        Cell rentMonthTitleCell2 = rentInfoRow3.getCell(CellReference.convertColStringToIndex("c"));
+        rentMonthTitleCell2.setCellValue("12个月数据");
+        // 出租信息第4行
+        Row rentInfoRow4 = sheet.getRow(rowIndex.getAndIncrement());
+        for (int i = 1; i <= 12; i++) {
+            Cell cell = rentInfoRow4.createCell(i + 1);
+            cell.setCellValue(i + "月");
+            cell.setCellStyle(titleCellStyle3);
+        }
+        // 出租信息第5行
+        Row rentInfoRow5 = sheet.getRow(rowIndex.getAndIncrement());
+        // 对外出租收入(上市)标题
+        Cell rentOutIncomeSsMonthTitleCell = rentInfoRow5.createCell(CellReference.convertColStringToIndex("b"));
+        rentOutIncomeSsMonthTitleCell.setCellValue("对外出租收入(上市)");
+        rentOutIncomeSsMonthTitleCell.setCellStyle(titleCellStyle3);
+        LinkedHashMap<String, BigDecimal> rentOutIncomeSsMonth = siteStatVo.getRentOutIncomeSsMonth();
+        for (int i = 1; i <= 12; i++) {
+            BigDecimal v = rentOutIncomeSsMonth.get(String.valueOf(i));
+            Cell cell = rentInfoRow5.createCell(i + 1);
+            if (v != null) {
+                cell.setCellValue(v.doubleValue());
+            }
+            cell.setCellStyle(rightNumberCellStyle);
+        }
+        // 出租信息第6行
+        Row rentInfoRow6 = sheet.getRow(rowIndex.getAndIncrement());
+        // 对外出租欠费(上市)标题
+        Cell rentOutArrearsSsMonthTitleCell = rentInfoRow6.createCell(CellReference.convertColStringToIndex("b"));
+        rentOutArrearsSsMonthTitleCell.setCellValue("对外出租欠费(上市)");
+        rentOutArrearsSsMonthTitleCell.setCellStyle(titleCellStyle3);
+        LinkedHashMap<String, BigDecimal> rentOutArrearsSsMonth = siteStatVo.getRentOutArrearsSsMonth();
+        for (int i = 1; i <= 12; i++) {
+            BigDecimal v = rentOutArrearsSsMonth.get(String.valueOf(i));
+            Cell cell = rentInfoRow6.createCell(i + 1);
+            if (v != null) {
+                cell.setCellValue(v.doubleValue());
+            }
+            cell.setCellStyle(rightNumberCellStyle);
+        }
+        // 出租信息第7行
+        Row rentInfoRow7 = sheet.getRow(rowIndex.getAndIncrement());
+        // 对外出租收入(存续)标题
+        Cell rentOutIncomeCxMonthTitleCell = rentInfoRow7.createCell(CellReference.convertColStringToIndex("b"));
+        rentOutIncomeCxMonthTitleCell.setCellValue("对外出租收入(存续)");
+        rentOutIncomeCxMonthTitleCell.setCellStyle(titleCellStyle3);
+        LinkedHashMap<String, BigDecimal> rentOutIncomeCxMonth = siteStatVo.getRentOutIncomeCxMonth();
+        for (int i = 1; i <= 12; i++) {
+            BigDecimal v = rentOutIncomeCxMonth.get(String.valueOf(i));
+            Cell cell = rentInfoRow7.createCell(i + 1);
+            if (v != null) {
+                cell.setCellValue(v.doubleValue());
+            }
+            cell.setCellStyle(rightNumberCellStyle);
+        }
+        // 出租信息第8行
+        Row rentInfoRow8 = sheet.getRow(rowIndex.getAndIncrement());
+        // 对外出租欠费(存续)标题
+        Cell rentOutArrearsCxMonthTitleCell = rentInfoRow8.createCell(CellReference.convertColStringToIndex("b"));
+        rentOutArrearsCxMonthTitleCell.setCellValue("对外出租欠费(存续)");
+        rentOutArrearsCxMonthTitleCell.setCellStyle(titleCellStyle3);
+        LinkedHashMap<String, BigDecimal> rentOutArrearsCxMonth = siteStatVo.getRentOutArrearsCxMonth();
+        for (int i = 1; i <= 12; i++) {
+            BigDecimal v = rentOutArrearsCxMonth.get(String.valueOf(i));
+            Cell cell = rentInfoRow8.createCell(i + 1);
+            if (v != null) {
+                cell.setCellValue(v.doubleValue());
+            }
+            cell.setCellStyle(rightNumberCellStyle);
+        }
+        // 费用信息第1行
+        Row feeInfoRow1 = sheet.createRow(rowIndex.getAndIncrement());
+        // 费用信息标题
+        addMergedRegion(sheet, titleCellStyle2,
+                CellRangeAddress.valueOf("a" + rowIndex.get() + ":a" + (rowIndex.get() + 5)));
+        Cell feeInfoTitleCell = feeInfoRow1.getCell(CellReference.convertColStringToIndex("a"));
+        feeInfoTitleCell.setCellValue("费用信息");
+        // 上市累计标题
+        Cell feeSsLjTitleCell = feeInfoRow1.createCell(CellReference.convertColStringToIndex("b"));
+        feeSsLjTitleCell.setCellValue("上市累计");
+        feeSsLjTitleCell.setCellStyle(titleCellStyle3);
+        // 房屋维修费标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("c" + rowIndex.get() + ":d" + rowIndex.get()));
+        Cell buildingRepairSsTitleCell = feeInfoRow1.getCell(CellReference.convertColStringToIndex("c"));
+        buildingRepairSsTitleCell.setCellValue("房屋维修费");
+        // 房屋维修费
+        Cell buildingRepairSsValueCell = feeInfoRow1.createCell(CellReference.convertColStringToIndex("e"));
+        if (siteStatVo.getBuildingRepairSs() != null) {
+            buildingRepairSsValueCell.setCellValue(siteStatVo.getBuildingRepairSs().doubleValue());
+        }
+        buildingRepairSsValueCell.setCellStyle(rightNumberCellStyle);
+        // 物业管理费标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("f" + rowIndex.get() + ":g" + rowIndex.get()));
+        Cell propertyFeeSsTitleCell = feeInfoRow1.getCell(CellReference.convertColStringToIndex("f"));
+        propertyFeeSsTitleCell.setCellValue("物业管理费");
+        // 物业管理费
+        Cell propertyFeeSsValueCell = feeInfoRow1.createCell(CellReference.convertColStringToIndex("h"));
+        if (siteStatVo.getPropertyFeeSs() != null) {
+            propertyFeeSsValueCell.setCellValue(siteStatVo.getPropertyFeeSs().doubleValue());
+        }
+        propertyFeeSsValueCell.setCellStyle(rightNumberCellStyle);
+        // 空单元格
+        batchSetCellStyle(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("i" + rowIndex.get() + ":n" + rowIndex.get()));
+        // 费用信息第2行
+        Row feeInfoRow2 = sheet.createRow(rowIndex.getAndIncrement());
+        // 存续累计标题
+        Cell feeCxLjTitleCell = feeInfoRow2.createCell(CellReference.convertColStringToIndex("b"));
+        feeCxLjTitleCell.setCellValue("存续累计");
+        feeCxLjTitleCell.setCellStyle(titleCellStyle3);
+        // 房屋维修费标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("c" + rowIndex.get() + ":d" + rowIndex.get()));
+        Cell buildingRepairCxTitleCell = feeInfoRow2.getCell(CellReference.convertColStringToIndex("c"));
+        buildingRepairCxTitleCell.setCellValue("房屋维修费");
+        // 房屋维修费
+        Cell buildingRepairCxValueCell = feeInfoRow2.createCell(CellReference.convertColStringToIndex("e"));
+        if (siteStatVo.getBuildingRepairCx() != null) {
+            buildingRepairCxValueCell.setCellValue(siteStatVo.getBuildingRepairCx().doubleValue());
+        }
+        buildingRepairCxValueCell.setCellStyle(rightNumberCellStyle);
+        // 物业管理费标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("f" + rowIndex.get() + ":g" + rowIndex.get()));
+        Cell propertyFeeCxTitleCell = feeInfoRow2.getCell(CellReference.convertColStringToIndex("f"));
+        propertyFeeCxTitleCell.setCellValue("物业管理费");
+        // 物业管理费
+        Cell propertyFeeCxValueCell = feeInfoRow2.createCell(CellReference.convertColStringToIndex("h"));
+        if (siteStatVo.getPropertyFeeCx() != null) {
+            propertyFeeCxValueCell.setCellValue(siteStatVo.getPropertyFeeCx().doubleValue());
+        }
+        propertyFeeCxValueCell.setCellStyle(rightNumberCellStyle);
+        // 空单元格
+        batchSetCellStyle(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("i" + rowIndex.get() + ":n" + rowIndex.get()));
+        // 费用信息第3行
+        Row feeInfoRow3 = sheet.getRow(rowIndex.getAndIncrement());
+        // 分月数据标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("b" + rowIndex.get() + ":b" + (rowIndex.get() + 1)));
+        Cell feeMonthTitleCell1 = feeInfoRow3.getCell(CellReference.convertColStringToIndex("b"));
+        feeMonthTitleCell1.setCellValue("分月数据");
+        // 12个月数据标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("c" + rowIndex.get() + ":n" + rowIndex.get()));
+        Cell feeMonthTitleCell2 = feeInfoRow3.getCell(CellReference.convertColStringToIndex("c"));
+        feeMonthTitleCell2.setCellValue("12个月数据");
+        // 费用信息第4行
+        Row feeInfoRow4 = sheet.getRow(rowIndex.getAndIncrement());
+        for (int i = 1; i <= 12; i++) {
+            Cell cell = feeInfoRow4.createCell(i + 1);
+            cell.setCellValue(i + "月");
+            cell.setCellStyle(titleCellStyle3);
+        }
+        // 费用信息第5行
+        Row feeInfoRow5 = sheet.getRow(rowIndex.getAndIncrement());
+        // 房屋维修费标题
+        Cell buildingRepairMonthTitleCell = feeInfoRow5.createCell(CellReference.convertColStringToIndex("b"));
+        buildingRepairMonthTitleCell.setCellValue("房屋维修费");
+        buildingRepairMonthTitleCell.setCellStyle(titleCellStyle3);
+        LinkedHashMap<String, BigDecimal> buildingRepairMonth = siteStatVo.getBuildingRepairMonth();
+        for (int i = 1; i <= 12; i++) {
+            BigDecimal v = buildingRepairMonth.get(String.valueOf(i));
+            Cell cell = feeInfoRow5.createCell(i + 1);
+            if (v != null) {
+                cell.setCellValue(v.doubleValue());
+            }
+            cell.setCellStyle(rightNumberCellStyle);
+        }
+        // 费用信息第6行
+        Row feeInfoRow6 = sheet.getRow(rowIndex.getAndIncrement());
+        // 物业管理费标题
+        Cell propertyFeeMonthTitleCell = feeInfoRow6.createCell(CellReference.convertColStringToIndex("b"));
+        propertyFeeMonthTitleCell.setCellValue("物业管理费");
+        propertyFeeMonthTitleCell.setCellStyle(titleCellStyle3);
+        LinkedHashMap<String, BigDecimal> propertyFeeMonth = siteStatVo.getPropertyFeeMonth();
+        for (int i = 1; i <= 12; i++) {
+            BigDecimal v = propertyFeeMonth.get(String.valueOf(i));
+            Cell cell = feeInfoRow6.createCell(i + 1);
+            if (v != null) {
+                cell.setCellValue(v.doubleValue());
+            }
+            cell.setCellStyle(rightNumberCellStyle);
+        }
+        // 评价信息第1行
+        Row evaluateInfoRow1 = sheet.createRow(rowIndex.getAndIncrement());
+        // 评价信息标题
+        addMergedRegion(sheet, titleCellStyle2,
+                CellRangeAddress.valueOf("a" + rowIndex.get() + ":a" + (rowIndex.get() + 2)));
+        Cell evaluateInfoTitleCell = evaluateInfoRow1.getCell(CellReference.convertColStringToIndex("a"));
+        evaluateInfoTitleCell.setCellValue("评价信息");
+        // 指标标题1
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("b" + rowIndex.get() + ":d" + rowIndex.get()));
+        Cell indicatorTitleCell1 = evaluateInfoRow1.getCell(CellReference.convertColStringToIndex("b"));
+        indicatorTitleCell1.setCellValue("指标");
+        List<String> indicatorHeaders = Stream.of("年初", "当期", "变化率").toList();
+        int indicatorHeadersSize = indicatorHeaders.size();
+        for (int i = 0; i < indicatorHeadersSize; i++) {
+            Cell cell = evaluateInfoRow1.createCell(i + 4);
+            cell.setCellValue(indicatorHeaders.get(i));
+            cell.setCellStyle(titleCellStyle3);
+        }
+        // 指标标题2
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("i" + rowIndex.get() + ":k" + rowIndex.get()));
+        Cell indicatorTitleCell2 = evaluateInfoRow1.getCell(CellReference.convertColStringToIndex("i"));
+        indicatorTitleCell2.setCellValue("指标");
+        for (int i = 0; i < indicatorHeadersSize; i++) {
+            Cell cell = evaluateInfoRow1.createCell(i + 11);
+            cell.setCellValue(indicatorHeaders.get(i));
+            cell.setCellStyle(titleCellStyle3);
+        }
+        // 空单元格
+        batchSetCellStyle(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("h" + rowIndex.get() + ":h" + (rowIndex.get() + 2)));
+        // 评价信息第2行
+        Row evaluateInfoRow2 = sheet.getRow(rowIndex.getAndIncrement());
+        // 自有房产人均办公面积标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("b" + rowIndex.get() + ":d" + rowIndex.get()));
+        Cell officeAreaAvgTitleCell = evaluateInfoRow2.getCell(CellReference.convertColStringToIndex("b"));
+        officeAreaAvgTitleCell.setCellValue("自有房产人均办公面积");
+        // 年初
+        Cell officeAreaAvgPastValueCell = evaluateInfoRow2.createCell(CellReference.convertColStringToIndex("e"));
+        if (siteStatVo.getOfficeAreaAvgPast() != null) {
+            officeAreaAvgPastValueCell.setCellValue(siteStatVo.getOfficeAreaAvgPast().doubleValue());
+        }
+        officeAreaAvgPastValueCell.setCellStyle(rightNumberCellStyle);
+        // 当期
+        Cell officeAreaAvgNowValueCell = evaluateInfoRow2.createCell(CellReference.convertColStringToIndex("f"));
+        if (siteStatVo.getOfficeAreaAvgNow() != null) {
+            officeAreaAvgNowValueCell.setCellValue(siteStatVo.getOfficeAreaAvgNow().doubleValue());
+        }
+        officeAreaAvgNowValueCell.setCellStyle(rightNumberCellStyle);
+        // 变化率
+        Cell officeAreaAvgDiffValueCell = evaluateInfoRow2.createCell(CellReference.convertColStringToIndex("g"));
+        if (siteStatVo.getOfficeAreaAvgDiff() != null) {
+            officeAreaAvgDiffValueCell.setCellValue(siteStatVo.getOfficeAreaAvgDiff().doubleValue());
+        }
+        officeAreaAvgDiffValueCell.setCellStyle(rightNumberCellStyle);
+        // 房屋面积闲置率标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("i" + rowIndex.get() + ":k" + rowIndex.get()));
+        Cell buildingAreaIdleRatePastTitleCell = evaluateInfoRow2.getCell(CellReference.convertColStringToIndex("i"));
+        buildingAreaIdleRatePastTitleCell.setCellValue("房屋面积闲置率");
+        // 年初
+        Cell buildingAreaIdleRatePastValueCell = evaluateInfoRow2.createCell(CellReference.convertColStringToIndex("l"));
+        if (siteStatVo.getBuildingAreaIdleRatePast() != null) {
+            buildingAreaIdleRatePastValueCell.setCellValue(siteStatVo.getBuildingAreaIdleRatePast().doubleValue());
+        }
+        buildingAreaIdleRatePastValueCell.setCellStyle(rightNumberCellStyle);
+        // 当期
+        Cell buildingAreaIdleRateNowValueCell = evaluateInfoRow2.createCell(CellReference.convertColStringToIndex("m"));
+        if (siteStatVo.getBuildingAreaIdleRateNow() != null) {
+            buildingAreaIdleRateNowValueCell.setCellValue(siteStatVo.getBuildingAreaIdleRateNow().doubleValue());
+        }
+        buildingAreaIdleRateNowValueCell.setCellStyle(rightNumberCellStyle);
+        // 变化率
+        Cell buildingAreaIdleRateDiffValueCell = evaluateInfoRow2.createCell(CellReference.convertColStringToIndex("n"));
+        if (siteStatVo.getBuildingAreaIdleRateDiff() != null) {
+            buildingAreaIdleRateDiffValueCell.setCellValue(siteStatVo.getBuildingAreaIdleRateDiff().doubleValue());
+        }
+        buildingAreaIdleRateDiffValueCell.setCellStyle(rightNumberCellStyle);
+        // 评价信息第3行
+        Row evaluateInfoRow3 = sheet.getRow(rowIndex.getAndIncrement());
+        // 对外出租平均单价标题
+        addMergedRegion(sheet, titleCellStyle3,
+                CellRangeAddress.valueOf("b" + rowIndex.get() + ":d" + rowIndex.get()));
+        Cell rentOutUnitPriceAvgTitleCell1 = evaluateInfoRow3.getCell(CellReference.convertColStringToIndex("b"));
+        rentOutUnitPriceAvgTitleCell1.setCellValue("对外出租平均单价");
+        // 年初
+        Cell rentOutUnitPriceAvgPastValueCell = evaluateInfoRow3.createCell(CellReference.convertColStringToIndex("e"));
+        if (siteStatVo.getRentOutUnitPriceAvgPast() != null) {
+            rentOutUnitPriceAvgPastValueCell.setCellValue(siteStatVo.getRentOutUnitPriceAvgPast().doubleValue());
+        }
+        rentOutUnitPriceAvgPastValueCell.setCellStyle(rightNumberCellStyle);
+        // 当期
+        Cell rentOutUnitPriceAvgNowValueCell = evaluateInfoRow3.createCell(CellReference.convertColStringToIndex("f"));
+        if (siteStatVo.getRentOutUnitPriceAvgNow() != null) {
+            rentOutUnitPriceAvgNowValueCell.setCellValue(siteStatVo.getRentOutUnitPriceAvgNow().doubleValue());
+        }
+        rentOutUnitPriceAvgNowValueCell.setCellStyle(rightNumberCellStyle);
+        // 变化率
+        Cell rentOutUnitPriceAvgDiffValueCell = evaluateInfoRow3.createCell(CellReference.convertColStringToIndex("g"));
+        if (siteStatVo.getRentOutUnitPriceAvgDiff() != null) {
+            rentOutUnitPriceAvgDiffValueCell.setCellValue(siteStatVo.getRentOutUnitPriceAvgDiff().doubleValue());
+        }
+        rentOutUnitPriceAvgDiffValueCell.setCellStyle(rightNumberCellStyle);
+        // 空单元格
+        batchSetCellStyle(sheet, baseCellStyle,
+                CellRangeAddress.valueOf("i" + rowIndex.get() + ":n" + rowIndex.get()));
+        // 设置列宽
+        for (int i = 0; i <= CellReference.convertColStringToIndex("n"); i++) {
+            sheet.setColumnWidth(i, 15 * 256);
+        }
+    }
+
+    /**
+     * 设置基本样式
+     *
+     * @param style 风格
+     */
+    private void setBaseStyle(CellStyle style) {
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setWrapText(true);
+        setBorder(style);
+    }
+
+    /**
+     * 设置边框样式
+     *
+     * @param style 风格
+     */
+    private void setBorder(CellStyle style) {
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setTopBorderColor(IndexedColors.BLACK.index);
+        style.setBottomBorderColor(IndexedColors.BLACK.index);
+        style.setLeftBorderColor(IndexedColors.BLACK.index);
+        style.setRightBorderColor(IndexedColors.BLACK.index);
+    }
+
+    /**
+     * 添加设置合并单元格样式
+     */
+    private void addMergedRegion(Sheet sheet, CellStyle style, CellRangeAddress range) {
+        sheet.addMergedRegion(range);
+        for (int rowNum = range.getFirstRow(); rowNum <= range.getLastRow(); rowNum++) {
+            Row row = sheet.getRow(rowNum);
+            if (row == null) {
+                row = sheet.createRow(rowNum);
+            }
+            for (int colNum = range.getFirstColumn(); colNum <= range.getLastColumn(); colNum++) {
+                Cell cell = row.getCell(colNum);
+                if (cell == null) {
+                    cell = row.createCell(colNum);
+                }
+                cell.setCellStyle(style);
+            }
+        }
+    }
+
+    /**
+     * 批量设置单元格样式
+     */
+    private void batchSetCellStyle(Sheet sheet, CellStyle style, CellRangeAddress range) {
+        for (int rowNum = range.getFirstRow(); rowNum <= range.getLastRow(); rowNum++) {
+            Row row = sheet.getRow(rowNum);
+            if (row == null) {
+                row = sheet.createRow(rowNum);
+            }
+            for (int colNum = range.getFirstColumn(); colNum <= range.getLastColumn(); colNum++) {
+                Cell cell = row.getCell(colNum);
+                if (cell == null) {
+                    cell = row.createCell(colNum);
+                }
+                cell.setCellStyle(style);
+            }
+        }
+    }
 }

+ 24 - 2
src/main/java/com/example/utils/AESUtil.java

@@ -69,8 +69,8 @@ public class AESUtil {
         return decrypt(str, KEY);
     }
 
-    public static void main(String[] args) throws Exception {
-// 参数
+    public static String getTestToken() {
+        // 参数
         HashMap<String, String> map = new HashMap<>();
         // 财务系统id, 固定值
         map.put("APP_ID", "FINANCE");
@@ -81,7 +81,29 @@ public class AESUtil {
         map.put("LOGIN_ID", "test");
         //请求的地址
         map.put("REQUEST_URL","");
+        map.put("EXPIRE_TIME","604800");
+        // 加密串
+        try {
+            return AESUtil.encrypt(new Gson().toJson(map), KEY);
+        } catch (Exception e) {
+            return "";
+        }
+    }
 
+
+    public static void main(String[] args) throws Exception {
+        // 参数
+        HashMap<String, String> map = new HashMap<>();
+        // 财务系统id, 固定值
+        map.put("APP_ID", "FINANCE");
+        // 时间戳
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        map.put("TIME_STAMP", sdf.format(new Date()));
+        // 当前登录账号
+        map.put("LOGIN_ID", "test");
+        //请求的地址
+        map.put("REQUEST_URL","");
+        map.put("EXPIRE_TIME","36000");
         // 加密串
         String encrypt = AESUtil.encrypt(new Gson().toJson(map), "2na$$PdV9AW8b#CS");
         // 返回

+ 2 - 2
src/test/java/com/example/MybatisPlusGeneratorTest.java

@@ -9,12 +9,12 @@ public class MybatisPlusGeneratorTest {
         FastAutoGenerator.create(
                 new DataSourceConfig.Builder("jdbc:postgresql://172.16.107.5:5432/financialdb",
                         "finance",
-                        "Finance@unicom23").schema("common"))
+                        "Finance@unicom23").schema("house"))
                 .globalConfig(builder -> {
                     builder.outputDir("z:/").disableOpenDir();
                 })
                 .strategyConfig(builder -> {
-                    builder.addInclude("request_log")
+                    builder.addInclude("building_repair_month")
                             .entityBuilder()
                             .disableSerialVersionUID()
                             .enableFileOverride()