jialh
1 天以前 dd6687b118561100e1677e88a9c2f5842a54c531
service-fee/src/main/java/com/java110/fee/cmd/fee/ReportFeePropertyCmd.java
@@ -27,17 +27,14 @@
import com.java110.utils.util.DateUtil;
import com.java110.vo.FeeQueryParams;
import com.java110.vo.ResultVo;
import com.sun.org.apache.regexp.internal.RE;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Java110Cmd(serviceCode = "fee.reportPropertyFeeCmd")
public class ReportFeePropertyCmd extends Cmd {
@@ -93,32 +90,42 @@
        reportQueryRecord.setOperator("白单流水物业表");
        List<ReportQueryRecord> reportQueryRecords = reportFeeInnerServiceSMOImpl.queryReport(BeanConvertUtil.beanCovertMap(reportQueryRecord));
        if (reqJson.containsKey("roomNum")){
        if (reqJson.containsKey("roomNum") && !(reqJson.get("roomNum").equals(""))) {
            RoomDto roomDto = new RoomDto();
            roomDto.setRoomNum(reqJson.getString("roomNum"));
            String[] roomTitle = reqJson.getString("roomNum").split("-");
            roomDto.setFloorNum(roomTitle[0]);
            roomDto.setUnitNum(roomTitle[1]);
            roomDto.setRoomNum(roomTitle[2]);
            roomDto.setCommunityId(reqJson.getString("communityId"));
            List<RoomDto> roomDtos = roomInnerServiceSMOImpl.queryRooms(roomDto);//获取房屋
            OwnerDto ownerDto = new OwnerDto();
            ownerDto.setCommunityId(reqJson.getString("communityId"));
            ownerDto.setRoomId(reqJson.getString("roomNum"));
            ownerDto.setRoomId(roomDtos.get(0).getRoomId());
            List<OwnerDto> ownerDtos = ownerInnerServiceSMOImpl.queryOwners(ownerDto);//获取业主
            roomDto.setOwnerName(ownerDtos.get(0).getName());
            ReportExcelDto reportExcelDto = new ReportExcelDto();
            reportExcelDto.setOwner(ownerDtos.get(0));
            reportExcelDto.setRoomDto(roomDtos.get(0));
            FeeDetailDto feeDetailDto = new FeeDetailDto();
            List<Map> rooms = roomInnerServiceSMOImpl.queryRoomsAsReport(roomDto);
            String[][] strings = new String[rooms.size() + 1][];
            setHeader(strings[0]);
            List<Map> onceOwner = roomInnerServiceSMOImpl.queryRoomsAsReport(roomDto);
            ResultVo resultVo = new ResultVo(strings);
            reportExcelDto.setPropertyFeeList(backFeeList("3333",rooms.get(0).get("room_id")));
            reportExcelDto.setCarFeeList(backFeeList("6666",rooms.get(0).get("room_id")));
            reportExcelDto.setOtherFeeList(backFeeList("7777",rooms.get(0).get("room_id")));
            ResultVo resultVo = new ResultVo(reportExcelDto);
            ResponseEntity<String> responseEntity = new ResponseEntity<String>(resultVo.toString(), HttpStatus.OK);
            context.setResponseEntity(responseEntity);
            return;
        }
        else if(reportQueryRecords.size()>0 && !reqJson.containsKey("reload")){
        else if(reportQueryRecords.size()>0 && !reqJson.containsKey("reload") && !reqJson.containsKey("floorId")){
            ResultVo resultVo = new ResultVo(JSONObject.parse(reportQueryRecords.get(reportQueryRecords.size()-1).getReportContent()));
            ResponseEntity<String> responseEntity = new ResponseEntity<String>(resultVo.toString(), HttpStatus.OK);
@@ -130,20 +137,58 @@
            int row = Integer.parseInt(reqJson.containsKey("row")?reqJson.getString("row"):"10");
            int page = Integer.parseInt(reqJson.containsKey("page")?reqJson.getString("page"):"1");
            startYear = 2016;
            endYear = 2025;
            endYear = DateUtil.getYear();
            Object[][] test = new Object[row][];
            RoomDto roomDto = new RoomDto();
            roomDto.setCommunityId(reqJson.getString("communityId"));
            roomDto.setRow(row);
            roomDto.setPage(page);
            int count = roomInnerServiceSMOImpl.queryRoomsCount(roomDto);
            roomDto.setPage(page * row - row);
            roomDto.setFloorNum(reqJson.containsKey("floorId")&&!(reqJson.getString("floorId").equals(""))?reqJson.getString("floorId"):null);
            roomDto.setOwnerName(reqJson.containsKey("ownerName")&&reqJson.getString("ownerName").equals("")?null:reqJson.getString("ownerName"));
            List<Map> rooms = roomInnerServiceSMOImpl.queryRoomsAsReport(roomDto);
            if (rooms.size() == 0) {
                ResultVo resultVo = new ResultVo("未查询到数据");
                resultVo.setTotal(0);
                resultVo.setRecords(0);
                ResponseEntity<String> responseEntity = new ResponseEntity<String>(resultVo.toString(), HttpStatus.NOT_FOUND);
                context.setResponseEntity(responseEntity);
                return;
            }
            int count = roomInnerServiceSMOImpl.queryRoomsCount(roomDto);
            FeeConfigDto feeConfigDto = new FeeConfigDto();
            feeConfigDto.setCommunityId(reqJson.getString("communityId"));
            feeConfigDto.setFeeTypeCds(new String[]{"630000001","630000002"});
            feeConfigDto.setRow(2);
            feeConfigDto.setPage(1);
            List<FeeConfigDto> feeConfigDtos = feeConfigInnerServiceSMOImpl.queryFeeConfigs(feeConfigDto);
            if(reqJson.containsKey("feeTypeCd") && !(reqJson.get("feeTypeCd").equals(""))){
                feeConfigDto.setFeeTypeCd(reqJson.getString("feeTypeCd"));
            }else{
                feeConfigDto.setFeeTypeCds(new String[]{"630000001"});
            }
            if(reqJson.containsKey("importFee") && !(reqJson.get("importFee").equals(""))){
                feeConfigDto.setFeeNameEq(reqJson.getString("importFee"));
            }else{
                feeConfigDto.setFeeTypeCds(new String[]{"630000001"});
            }
            List<FeeConfigDto> originalDtos = feeConfigInnerServiceSMOImpl.queryFeeConfigs(feeConfigDto);
// 2. 流式处理:排序 → 去重(按单价) → 取前2条
            List<FeeConfigDto> top2DistinctPriceDtos = originalDtos.stream()
                    // 第一步:按业务规则排序(示例:先按单价升序,相同单价按startTime降序(保留最新记录))
                    .sorted(
                            // 单价排序:null值放最后,非null按自然顺序(如BigDecimal升序)
                            Comparator.comparing(FeeConfigDto::getSquarePrice, Comparator.nullsLast(Comparator.naturalOrder()))
                                    // 相同单价时,按startTime降序(确保保留“最新”的那条)
                                    .thenComparing(FeeConfigDto::getStartTime, Comparator.nullsLast(Comparator.reverseOrder()))
                    )
                    // 第二步:按单价分组(自动去重,每组对应一个唯一单价)
                    .collect(Collectors.groupingBy(
                            dto -> (dto.getSquarePrice() == null) ? new Object() : dto.getSquarePrice(), // 处理null的分组键
                            Collectors.toList() // 每组内是排序后的记录(已确保最优)
                    ))
                    // 第三步:提取每组的第一条(即该单价的“最优记录”),再取前2条
                    .values().stream()
                    .map(group -> group.get(0))
                    .collect(Collectors.toList());
            List<FeeConfigDto> feeConfigDtos = top2DistinctPriceDtos;
            int arrLength = 11 + (2 * feeConfigDtos.size()) + 8 + ((endYear - startYear + 1) * 3 + 10) - 9;
            ReportExcelDto[] header = new ReportExcelDto[arrLength];
            List<List<ReportExcelDto>> lists = headerDoing(feeConfigDtos, startYear, endYear, arrLength);
@@ -161,38 +206,39 @@
                strings[7] = rooms.get(i - 1).get("room_area").toString();
                strings[8] = rooms.get(i - 1).get("name").toString();
                for (int j = 1; j <= feeConfigDtos.size(); j++) {
                    strings[8 + j] = feeConfigDtos.get(j - 1).getSquarePrice();
                    strings[8 + j] = doublequ2(Double.parseDouble(feeConfigDtos.get(j - 1).getSquarePrice()))+"";
                }
                strings[8 + feeConfigDtos.size() + 1] = "";
                for (int j = 1; j <= feeConfigDtos.size(); j++) {
                    strings[8 + feeConfigDtos.size() + 1 + j] = (doublequ2(Double.parseDouble(feeConfigDtos.get(j - 1).getSquarePrice()) * Double.parseDouble(String.valueOf((BigDecimal) rooms.get(i - 1).get("room_area")))))+"";
                }
                strings[8 + (2 * feeConfigDtos.size()) + 2] = (doublequ2(Double.parseDouble(feeConfigDtos.get(feeConfigDtos.size() - 1).getSquarePrice()) * Double.parseDouble(String.valueOf((BigDecimal) rooms.get(i - 1).get("room_area")))))+"";
                strings[8 + (2 * feeConfigDtos.size()) + 2] = doublequ2(Double.parseDouble(strings[8 + (2 * feeConfigDtos.size()) + 2]) * 12)+"";
                HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
                objectObjectHashMap.put("payObjId", map.get("room_id"));
                List<Map> fee = reportFeeInnerServiceSMOImpl.onceRoomFee(objectObjectHashMap);
                double allMoney = 0;
                double allPayMoney = 0;
                int monthCount = 0;
                int noPayMoney = 0;
                int year1 = 0;
                int year2 = 0;
                double noPayMoney = 0;
                double year1 = 0;
                double year2 = 0;
                double discountMoney = 0;
                String noPayDate = "";
                currentYear = DateUtil.getYear();
                for (Map map1 : fee){
                    if(map1.containsKey("统计维度") && !(map1.get("统计维度").toString().contains("总计"))){
                        allMoney += ((BigDecimal) map1.get("应收金额")).doubleValue();
                        allPayMoney += ((BigDecimal) map1.get("实收金额")).doubleValue();
                        monthCount += ((BigDecimal)map1.get("未收月数")).intValue();
                        noPayMoney += ((BigDecimal)map1.get("未收金额")).intValue();
                        allMoney = doublequ2(((BigDecimal) map1.get("应收金额")).doubleValue()+allMoney);
                        allPayMoney = doublequ2(((BigDecimal) map1.get("实收金额")).doubleValue()+allPayMoney);
                        monthCount = ((BigDecimal)map1.get("未收月数")).intValue()+monthCount;
                        noPayMoney = doublequ2(((BigDecimal)map1.get("未收金额")).intValue()+noPayMoney);
                        noPayDate = noPayDate + map1.get("未收区间");
                        discountMoney += ((BigDecimal)map1.get("折扣金额")).doubleValue();
                        discountMoney = doublequ2(((BigDecimal)map1.get("折扣金额")).doubleValue()+discountMoney);
                        if(map1.get("统计维度").equals("2026")){
                            year1 += ((BigDecimal) map1.get("应收金额")).doubleValue();
                            year1 = doublequ2(((BigDecimal) map1.get("应收金额")).doubleValue() + year1);
                        }
                        if(map1.get("统计维度").equals("2027")){
                            year2 += ((BigDecimal) map1.get("应收金额")).doubleValue();
                            year2 = doublequ2(((BigDecimal) map1.get("应收金额")).doubleValue() + year2);
                        }
                    }
@@ -246,6 +292,192 @@
        }
    }
    public Object[][] doCmd2(JSONObject reqJson) throws CmdException, ParseException {
        int startYear = 2020;
        CommunityDto communityDto = new CommunityDto();
        communityDto.setCommunityId(reqJson.getString("communityId"));
        List<CommunityDto> communityDtos = communityInnerServiceSMOImpl.queryCommunitys(communityDto);
        FeeQueryParams feeQueryParams = new FeeQueryParams();
        feeQueryParams.setCommunityId(reqJson.getString("communityId"));
        feeQueryParams.setStartYear(startYear);
        int currentYear = java.time.Year.now().getValue();
        feeQueryParams.setEndYear(currentYear + 2);
        if(reqJson.containsKey("endYear") && !reqJson.get("endYear").equals("") && reqJson.get("endYear") != null) {
            currentYear=Integer.parseInt(reqJson.get("endYear")+"");
            feeQueryParams.setEndYear(Integer.parseInt(reqJson.get("endYear")+"")+2);
        }
        int endYear = feeQueryParams.getEndYear();
        int doYear = endYear - startYear;
        ReportQueryRecord reportQueryRecord = new ReportQueryRecord();
        reportQueryRecord.setCommunityId(reqJson.getString("communityId"));
        reportQueryRecord.setQueryStatus("0");
        reportQueryRecord.setEndYear(currentYear+"");
        reportQueryRecord.setOperator("白单流水物业表");
        List<ReportQueryRecord> reportQueryRecords = reportFeeInnerServiceSMOImpl.queryReport(BeanConvertUtil.beanCovertMap(reportQueryRecord));
            int row = Integer.parseInt(reqJson.containsKey("row")?reqJson.getString("row"):"10");
            int page = Integer.parseInt(reqJson.containsKey("page")?reqJson.getString("page"):"1");
            startYear = 2016;
            endYear = DateUtil.getYear();
            Object[][] test = new Object[row][];
            RoomDto roomDto = new RoomDto();
            roomDto.setCommunityId(reqJson.getString("communityId"));
            roomDto.setRow(row);
            roomDto.setPage(page * row - row);
            roomDto.setFloorNum(reqJson.containsKey("floorId")&&!(reqJson.getString("floorId").equals(""))?reqJson.getString("floorId"):null);
            roomDto.setOwnerName(reqJson.containsKey("ownerName")&&reqJson.getString("ownerName").equals("")?null:reqJson.getString("ownerName"));
            List<Map> rooms = roomInnerServiceSMOImpl.queryRoomsAsReport(roomDto);
            int count = roomInnerServiceSMOImpl.queryRoomsCount(roomDto);
            FeeConfigDto feeConfigDto = new FeeConfigDto();
            feeConfigDto.setCommunityId(reqJson.getString("communityId"));
            if(reqJson.containsKey("feeTypeCd") && !(reqJson.get("feeTypeCd").equals(""))){
                feeConfigDto.setFeeTypeCd(reqJson.getString("feeTypeCd"));
            }else{
                feeConfigDto.setFeeTypeCds(new String[]{"630000001"});
            }
            if(reqJson.containsKey("importFee") && !(reqJson.get("importFee").equals(""))){
                feeConfigDto.setFeeNameEq(reqJson.getString("importFee"));
            }else{
                feeConfigDto.setFeeTypeCds(new String[]{"630000001"});
            }
            List<FeeConfigDto> originalDtos = feeConfigInnerServiceSMOImpl.queryFeeConfigs(feeConfigDto);
// 2. 流式处理:排序 → 去重(按单价) → 取前2条
            List<FeeConfigDto> top2DistinctPriceDtos = originalDtos.stream()
                    // 第一步:按业务规则排序(示例:先按单价升序,相同单价按startTime降序(保留最新记录))
                    .sorted(
                            // 单价排序:null值放最后,非null按自然顺序(如BigDecimal升序)
                            Comparator.comparing(FeeConfigDto::getSquarePrice, Comparator.nullsLast(Comparator.naturalOrder()))
                                    // 相同单价时,按startTime降序(确保保留“最新”的那条)
                                    .thenComparing(FeeConfigDto::getStartTime, Comparator.nullsLast(Comparator.reverseOrder()))
                    )
                    // 第二步:按单价分组(自动去重,每组对应一个唯一单价)
                    .collect(Collectors.groupingBy(
                            dto -> (dto.getSquarePrice() == null) ? new Object() : dto.getSquarePrice(), // 处理null的分组键
                            Collectors.toList() // 每组内是排序后的记录(已确保最优)
                    ))
                    // 第三步:提取每组的第一条(即该单价的“最优记录”),再取前2条
                    .values().stream()
                    .map(group -> group.get(0))
                    .collect(Collectors.toList());
            List<FeeConfigDto> feeConfigDtos = top2DistinctPriceDtos;
            int arrLength = 11 + (2 * feeConfigDtos.size()) + 8 + ((endYear - startYear + 1) * 3 + 10) - 9;
            ReportExcelDto[] header = new ReportExcelDto[arrLength];
            List<List<ReportExcelDto>> lists = headerDoing(feeConfigDtos, startYear, endYear, arrLength);
            test[0] = header;
            for (int i = 1; i <= rooms.size(); i++) {
                Map map = rooms.get(i - 1);
                String[] strings = new String[arrLength];
                strings[0] = String.valueOf(row * (page - 1) + i);
                strings[1] = String.valueOf(rooms.get(i - 1).get("property_type"));
                strings[2] = rooms.get(i - 1).get("floor_num").toString();
                strings[3] = rooms.get(i - 1).get("unit_num").toString();
                strings[4] = rooms.get(i - 1).get("room_num").toString();
                strings[5] = strings[3] + "-" +  strings[4];
                strings[6] = rooms.get(i - 1).get("property_address").toString();
                strings[7] = rooms.get(i - 1).get("room_area").toString();
                strings[8] = rooms.get(i - 1).get("name").toString();
                for (int j = 1; j <= feeConfigDtos.size(); j++) {
                    strings[8 + j] = doublequ2(Double.parseDouble(feeConfigDtos.get(j - 1).getSquarePrice()))+"";
                }
                strings[8 + feeConfigDtos.size() + 1] = "";
                for (int j = 1; j <= feeConfigDtos.size(); j++) {
                    strings[8 + feeConfigDtos.size() + 1 + j] = (doublequ2(Double.parseDouble(feeConfigDtos.get(j - 1).getSquarePrice()) * Double.parseDouble(String.valueOf((BigDecimal) rooms.get(i - 1).get("room_area")))))+"";
                }
                strings[8 + (2 * feeConfigDtos.size()) + 2] = (doublequ2(Double.parseDouble(feeConfigDtos.get(feeConfigDtos.size() - 1).getSquarePrice()) * Double.parseDouble(String.valueOf((BigDecimal) rooms.get(i - 1).get("room_area")))))+"";
                strings[8 + (2 * feeConfigDtos.size()) + 2] = doublequ2(Double.parseDouble(strings[8 + (2 * feeConfigDtos.size()) + 2]) * 12)+"";
                HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
                objectObjectHashMap.put("payObjId", map.get("room_id"));
                List<Map> fee = reportFeeInnerServiceSMOImpl.onceRoomFee(objectObjectHashMap);
                double allMoney = 0;
                double allPayMoney = 0;
                int monthCount = 0;
                double noPayMoney = 0;
                double year1 = 0;
                double year2 = 0;
                double discountMoney = 0;
                String noPayDate = "";
                currentYear = DateUtil.getYear();
                for (Map map1 : fee){
                    if(map1.containsKey("统计维度") && !(map1.get("统计维度").toString().contains("总计"))){
                        allMoney = doublequ2(((BigDecimal) map1.get("应收金额")).doubleValue()+allMoney);
                        allPayMoney = doublequ2(((BigDecimal) map1.get("实收金额")).doubleValue()+allPayMoney);
                        monthCount = ((BigDecimal)map1.get("未收月数")).intValue()+monthCount;
                        noPayMoney = doublequ2(((BigDecimal)map1.get("未收金额")).intValue()+noPayMoney);
                        noPayDate = noPayDate + map1.get("未收区间");
                        discountMoney = doublequ2(((BigDecimal)map1.get("折扣金额")).doubleValue()+discountMoney);
                        if(map1.get("统计维度").equals("2026")){
                            year1 = doublequ2(((BigDecimal) map1.get("应收金额")).doubleValue() + year1);
                        }
                        if(map1.get("统计维度").equals("2027")){
                            year2 = doublequ2(((BigDecimal) map1.get("应收金额")).doubleValue() + year2);
                        }
                    }
                }
                for (int x = endYear ; x >= startYear ; x --){
                    strings[8 + (2 * feeConfigDtos.size()) + 10 + (3 * (endYear - x)) + 1] = "0";
                    strings[8 + (2 * feeConfigDtos.size()) + 10 + (3 * (endYear - x)) + 2] = "";
                    strings[8 + (2 * feeConfigDtos.size()) + 10 + (3 * (endYear - x)) + 3] = "";
                    for (Map map1 : fee){
                        if(map1.get("统计维度").equals((endYear - x + startYear)+"年")) {
                            strings[8 + (2 * feeConfigDtos.size()) + 10 + (3 * (endYear - x)) + 1] = Integer.parseInt(strings[8 + (2 * feeConfigDtos.size()) + 10 + (3 * (endYear - x)) + 1]) + ((BigDecimal) map1.get("已收月数")).intValue() + "";
                            if(map1.containsKey("已收区间")){
                                strings[8 + (2 * feeConfigDtos.size()) + 10 + (3 * (endYear - x)) + 2] = strings[8 + (2 * feeConfigDtos.size()) + 10 + (3 * (endYear - x)) + 2] + "  " + map1.get("已收区间");
                            }
                            if(map1.containsKey("未收区间")){
                                strings[8 + (2 * feeConfigDtos.size()) + 10 + (3 * (endYear - x)) + 3] = strings[8 + (2 * feeConfigDtos.size()) + 10 + (3 * (endYear - x)) + 3] + "  " + map1.get("未收区间");
                            }
                        }
                    }
                }
                strings[8 + (2 * feeConfigDtos.size()) + 3] = allMoney+"";
                strings[8 + (2 * feeConfigDtos.size()) + 4] = allPayMoney+"";
                strings[8 + (2 * feeConfigDtos.size()) + 5] = "";
                strings[8 + (2 * feeConfigDtos.size()) + 6] = year1+"";//2026
                strings[8 + (2 * feeConfigDtos.size()) + 7] = year2+"";//2027
                strings[8 + (2 * feeConfigDtos.size()) + 8] = monthCount+"";
                strings[8 + (2 * feeConfigDtos.size()) + 9] = noPayMoney+"";
                strings[8 + (2 * feeConfigDtos.size()) + 10] = "";//22
                strings[8 + (2 * feeConfigDtos.size()) + 11] = "";//23历年待收
                strings[8 + (2 * feeConfigDtos.size()) + 10 + (3 * (endYear - startYear)) + 3 + 1] = discountMoney+"";
                test[i - 1] = strings;
            }
            return test;
    }
    private String[][] backFeeList(String number, Object roomId) {
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("payObjId", roomId);
        objectObjectHashMap.put("feeTypeCd",number);
        List<Map> fee = reportFeeInnerServiceSMOImpl.onceRoomFee(objectObjectHashMap);
        String[][] strings = new String[fee.size()][17];
        for (int i = 0 ; i < fee.size(); i++) {
            Map map = fee.get(i);
            strings[i][0] = (String) map.get("统计维度");
            strings[i][1] = ((BigDecimal) map.get("应收月数")).toString();
            strings[i][2] = doublequ2(((BigDecimal) map.get("应收金额")).doubleValue())+"";
//                strings[i][3] = (String) map.get("折扣金额");
            strings[i][4] = doublequ2(((BigDecimal) map.get("折扣金额")).doubleValue())+"";
//                strings[i][5] = (String) map.get("折扣金额");
//                strings[i][6] = (String) map.get("折扣金额");
//                strings[i][7] = (String) map.get("折扣金额");//申请人
//                strings[i][8] = (String) map.get("折扣金额");//审批人
//                strings[i][9] = (String) map.get("折扣金额");//发起日期
            strings[i][10] = Double.parseDouble(strings[i][2]) - Double.parseDouble(strings[i][4])+"";
            strings[i][11] = ((BigDecimal) map.get("已收月数")).toString();
            strings[i][12] = doublequ2(((BigDecimal) map.get("实收金额")).doubleValue())+"";
            strings[i][13] = (String) map.get("已收区间");
            strings[i][14] = ((BigDecimal) map.get("未收月数")).toString();
            strings[i][15] = doublequ2(((BigDecimal) map.get("未收金额")).doubleValue())+"";
            strings[i][16] = (String) map.get("未收区间");
        }
        return strings;
    }
    private void setHeader(String[] header) {
        header[0] = "年份";
        header[1] = "应缴月数";
@@ -285,7 +517,7 @@
// 2. 第一个feeRow循环:原未显式改col,沿用前一个1(按原逻辑保持col=1)
        for (int i = 0; i < feeRow; i++) {
            header.add(createHeaderRow(feeConfigDtos.get(0).getFeeName(), 1, 3));
            header.add(createHeaderRow(feeConfigDtos.get(i).getFeeName(), 1, 3));
        }
// 3. 设备运作费:原未改col,沿用前一个1
@@ -293,7 +525,7 @@
// 4. 第二个feeRow循环:原未显式改col,沿用前一个1(按原逻辑保持col=1)
        for (int i = 0; i < feeRow; i++) {
            header.add(createHeaderRow(feeConfigDtos.get(0).getFeeName(), 1, 3));
            header.add(createHeaderRow(feeConfigDtos.get(i).getFeeName(), 1, 3));
        }
// 5. 年应收款:原显式setCol(1),保持col=1