1
0
chenendian 3 долоо хоног өмнө
parent
commit
415d8027c8

+ 23 - 1
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/controller/cadastre/ParcelAnalysisController.java

@@ -1,7 +1,8 @@
 package com.siwei.apply.controller.cadastre;
 
+import com.siwei.apply.domain.cadastre.LandSupplyReportDTO;
 import com.siwei.apply.domain.cadastre.ParcelStatisticsRes;
-
+import com.siwei.apply.domain.cadastre.ZdqlReportVO;
 import com.siwei.apply.domain.cadastre.Zdjbxx;
 import com.siwei.apply.service.cadastre.IParcelService;
 import com.siwei.common.core.domain.R;
@@ -75,6 +76,24 @@ public class ParcelAnalysisController extends BaseController {
 
 
 
+    /**
+     * 宗地分析报表-宗地权利报表
+     * 按地籍子区统计各权利类型(已登记/未登记/合计)面积(单位:亩)
+     *
+     * @return ZdqlReportVO 含列头定义、各地籍子区数据行、合计行
+     */
+    @GetMapping("/report/zdql")
+    public R<ZdqlReportVO> getZdqlReport() {
+        try {
+            ZdqlReportVO res = parcelService.getZdqlReport();
+            return R.ok(res);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return R.fail(e.getMessage());
+        }
+    }
+
+
 
 
 
@@ -96,4 +115,7 @@ public class ParcelAnalysisController extends BaseController {
 
 
 
+
+
+
 }

+ 76 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/domain/cadastre/ZdqlReportVO.java

@@ -0,0 +1,76 @@
+package com.siwei.apply.domain.cadastre;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 宗地权利统计报表响应对象
+ * <p>
+ * 报表维度说明:
+ *   - 行:地籍子区(每个乡/镇/街道一行) + 合计行
+ *   - 列:5种权利类型,每种含(合计、已登记、未登记)3个小列,共15列
+ *     权利类型:
+ *       10 - 宅基地使用权和房屋使用权
+ *       11 - 集体建设用地使用权和房屋使用权
+ *       12 - 国有建设用地使用权和房屋使用权(国有建设用地使用权 & 房屋所有权)
+ *       40 - 林权
+ *       20 - 土地承包经营权
+ * </p>
+ */
+@Data
+public class ZdqlReportVO {
+
+    /**
+     * 合计行(全量不分子区统计)
+     */
+    private RowData total;
+
+    /**
+     * 各地籍子区数据行列表
+     */
+    private List<RowData> rows;
+
+    // -------------------------------------------------------
+    //  内部类:单行数据(一个地籍子区或合计)
+    // -------------------------------------------------------
+
+    /**
+     * 报表数据行
+     */
+    @Data
+    public static class RowData {
+        /** 地籍子区代码(合计行为 null) */
+        private String djzqdm;
+        /** 地籍子区名称(合计行为"合计") */
+        private String djzqmc;
+        /**
+         * 按权利类型分组的统计单元列表,顺序与 columns 对应
+         */
+        private List<QllxStatCell> cells;
+    }
+
+    // -------------------------------------------------------
+    //  内部类:单个权利类型的统计单元(合计/已登记/未登记)
+    // -------------------------------------------------------
+
+    /**
+     * 单权利类型统计单元(一个三格小组:合计、已登记、未登记)
+     * <p>
+     * 注意:qllxName 已融合在此处,前端无需额外处理 columns 数组
+     * </p>
+     */
+    @Data
+    public static class QllxStatCell {
+        /** 权利类型代码,与 QllxColumn.qllxCode 对应 */
+        private String qllxCode;
+        /** 权利类型名称(从 columns 融合至此,便于前端直接使用) */
+        private String qllxName;
+        /** 合计面积(亩),已登记 + 未登记 */
+        private Double totalArea;
+        /** 已登记面积(亩),djzt=1 */
+        private Double registeredArea;
+        /** 未登记面积(亩),djzt=2 或 djzt=3 */
+        private Double unregisteredArea;
+    }
+}

+ 7 - 3
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/enums/DecisionType.java

@@ -11,16 +11,20 @@ public enum DecisionType {
      * extraFields:查询业务表时需要额外返回的字段名列表(动态拼接到 SELECT 中)
      * 字段名需与业务表列名完全一致
      */
+    DECISION_TYPE_1("1", "现状数据", "vector.zdjbxx", "zddm", "zdjbxx", "zddm", "qlrsjsyrlxm","zdszx"),
+    DECISION_TYPE_2("2", "城镇开发边界", "vector.zdjbxx", "zddm", "zdjbxx", "zddm", "qlrsjsyrlxm","zdszx"),
+    DECISION_TYPE_3("3", "规划数据", "vector.zdjbxx", "zddm", "zdjbxx", "zddm", "qlrsjsyrlxm","zdszx"),
     DECISION_TYPE_4("4", "所有权宗地", "vector.zdjbxx", "zddm", "zdjbxx", "zddm", "qlrsjsyrlxm","zdszx"),
     DECISION_TYPE_5("5", "使用权宗地", "vector.zdjbxx", "zddm", "zdjbxx", "zddm", "qlrsjsyrlxm","zdszx"),
     DECISION_TYPE_6("6", "供地数据", "vector.gj_gd_data", "gid", "gj_gd_data", "gid","srr", "nf"),
     DECISION_TYPE_7("7", "报批数据", "vector.gj_bp_data", "gid", "gj_bp_data", "gid", "xmmc","xmlx"),
-
     DECISION_TYPE_6_1("6", "土地供应数据", "public.c_one_code_tdgy", "node_id", "c_one_code_tdgy", "node_id","srf","hbcrht_date"),
-    DECISION_TYPE_7_1("7", "用地报批数据", "public.c_one_code_ydbp", "node_id", "c_one_code_ydbp", "node_id", "project_name","tdyt");
-
+    DECISION_TYPE_7_1("7", "用地报批数据", "public.c_one_code_ydbp", "node_id", "c_one_code_ydbp", "node_id", "project_name","tdyt"),
 //    DECISION_TYPE_6_2("6", "供地数据", "c_one_code_tdgy", "node_id", "供地数据2", "project_name","project_code"),
 //    DECISION_TYPE_7_2("7", "报批数据", "c_one_code_ydbp", "node_id", "报批数据2", "node_id", "project_name","project_code");
+    DECISION_TYPE_8("8", "永久基本农田", "vector.zdjbxx", "zddm", "zdjbxx", "zddm", "qlrsjsyrlxm","zdszx"),
+    DECISION_TYPE_9("9", "生态保护红线", "vector.zdjbxx", "zddm", "zdjbxx", "zddm", "qlrsjsyrlxm","zdszx");
+
 
     private final String name;
     private final String code;

+ 16 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/mapper/cadastre/ZdjbxxMapper.java

@@ -59,4 +59,20 @@ public interface ZdjbxxMapper {
      */
     List<Map<String, Object>> getDjzqWithDjqList();
 
+    /**
+     * 查询宗地按权利类型和登记状态统计
+     * @return
+     */
+    List<Map<String, Object>> getStatisticsByQllx();
+
+    /**
+     * 按地籍子区 + 权利类型 + 登记状态统计宗地面积(用于宗地权利报表)
+     * <p>
+     * 返回字段:djzqdm, djzqmc, qllx, djzt, area_mu
+     * </p>
+     * @param qllxCodes 要统计的权利类型代码列表(逗号分隔的字符串,如 '10','11','12','40','20')
+     * @return 统计结果列表
+     */
+    List<Map<String, Object>> getZdqlReportData(@Param("qllxCodes") List<String> qllxCodes);
+
 }

+ 3 - 16
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/service/cadastre/IParcelService.java

@@ -1,20 +1,12 @@
 package com.siwei.apply.service.cadastre;
 
-
-import com.siwei.apply.domain.GongdiJihua;
-import com.siwei.apply.domain.LandType;
-import com.siwei.apply.domain.cadastre.LandSupplyReportDTO;
 import com.siwei.apply.domain.cadastre.ParcelStatisticsRes;
 import com.siwei.apply.domain.cadastre.Zdjbxx;
-import com.siwei.apply.domain.res.SupplyYearStatisticsRes;
-import com.siwei.apply.domain.res.TrendStatisticsRes;
-import com.siwei.apply.domain.vo.LandSupplyProjectVO;
-import com.siwei.apply.domain.vo.LandSupplyReportVO;
+import com.siwei.apply.domain.cadastre.ZdqlReportVO;
 
 import java.util.List;
 import java.util.Map;
 
-
 public interface IParcelService {
 
     List<Map<String, Object>> djzqList();
@@ -23,12 +15,7 @@ public interface IParcelService {
 
     List<Zdjbxx> zdList(String djzqdm);
 
-
-    LandSupplyReportDTO getTdgyReport(String startTime,String endTime); //  supplyService.getTdgyReport(startTime,endTime);
-
-    TrendStatisticsRes trendStatistics(String landType);
-
-    LandSupplyReportVO getTdgyPurposeReport(String startYear, String endYear);
-
+    ZdqlReportVO getZdqlReport();
 
 }
+

+ 129 - 384
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/service/cadastre/impl/ParcelServiceImpl.java

@@ -1,17 +1,11 @@
 package com.siwei.apply.service.cadastre.impl;
 
-import com.siwei.apply.domain.GongdiJihua;
 import com.siwei.apply.domain.LandType;
-import com.siwei.apply.domain.cadastre.LandSupplyReportDTO;
 import com.siwei.apply.domain.cadastre.ParcelStatisticsRes;
 import com.siwei.apply.domain.cadastre.Zdjbxx;
-import com.siwei.apply.domain.res.*;
-import com.siwei.apply.domain.vo.GongdiJihuaFilterVo;
-import com.siwei.apply.domain.vo.LandSupplyReportVO;
-import com.siwei.apply.enums.LandUseTypeEnum;
-import com.siwei.apply.mapper.GongdiJihuaMapper;
+import com.siwei.apply.domain.cadastre.ZdqlReportVO;
+
 import com.siwei.apply.mapper.LandTypeMapper;
-import com.siwei.apply.mapper.TdgyMapper;
 import com.siwei.apply.mapper.cadastre.ZdjbxxMapper;
 import com.siwei.apply.service.cadastre.IParcelService;
 import com.siwei.common.core.exception.ServiceException;
@@ -31,11 +25,6 @@ public class ParcelServiceImpl implements IParcelService {
     @Autowired
     private ZdjbxxMapper zdjbxxMapper;
 
-    @Autowired
-    private GongdiJihuaMapper gongdiJihuaMapper;
-
-    @Autowired
-    private TdgyMapper dgyMapper;
 
     @Autowired
     private LandTypeMapper landTypeMapper;
@@ -209,7 +198,6 @@ public class ParcelServiceImpl implements IParcelService {
 
 
 
-
     private ParcelStatisticsRes.QllxSuoyouquanDTO getQllxSuoyouquanDTO(Map.Entry<String, List<Zdjbxx>> entry) {
         ParcelStatisticsRes.QllxSuoyouquanDTO qllxSuoyouquanDTO = new ParcelStatisticsRes.QllxSuoyouquanDTO();
         qllxSuoyouquanDTO.setQllxsyqmc(entry.getKey());
@@ -295,395 +283,152 @@ public class ParcelServiceImpl implements IParcelService {
     }
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
     /**
+     * 生成宗地权利报表
+     * <p>
+     * 报表结构:
+     *   - 行:地籍子区(djzq)各一行 + 末尾合计行
+     *   - 列:5种权利类型,每种包含(合计、已登记、未登记)3个统计值,共15列
+     *     权利类型代码(qllx字段,字典A6):
+     *       10 - 宅基地使用权和房屋使用权
+     *       11 - 集体建设用地使用权和房屋使用权
+     *       12 - 国有建设用地使用权和房屋使用权
+     *       40 - 林权
+     *       20 - 土地承包经营权
+     *   - 面积单位:亩(根据 mjdw 字段自动换算)
+     *   - 登记状态:djzt=1 已登记,djzt=2/3 未登记
+     * </p>
      *
-     * @param landType
-     * @return
+     * @return ZdqlReportVO
      */
     @Override
-    public TrendStatisticsRes trendStatistics(String landType) {
-
-        List<TdgyStatisticsRes> completeList = dgyMapper.getListByYear(null, landType, null, null);
-
-        TrendStatisticsRes res = new TrendStatisticsRes();
-        List<Map<String, Object>> areaTrendStatisticsList = new ArrayList<>();
-        List<Map<String, Object>> supplyModeStatisticsList = new ArrayList<>();
-
-        if (CollectionUtils.isNotEmpty(completeList)) {
-            Map<Integer, Double> areaByYear = new LinkedHashMap<>();
-            Map<Integer, Map<String, Double>> modeAreaByYear = new LinkedHashMap<>();
-
-            for (TdgyStatisticsRes item : completeList) {
-                if (item.getGysj() != null) {
-                    int year = item.getGysj().getYear() + 1900;
-                    double area = item.getMjMu() != null ? item.getMjMu().doubleValue() : 0.0;
-                    String gyfs = item.getGyfs();
-
-                    areaByYear.merge(year, area, Double::sum);
-
-                    Map<String, Double> yearModeMap = modeAreaByYear.computeIfAbsent(year, k -> new HashMap<>());
-                    if ("划拨".equals(gyfs)) {
-                        yearModeMap.merge("allocate", area, Double::sum);
-                    } else if ("出让".equals(gyfs)) {
-                        yearModeMap.merge("transfer", area, Double::sum);
-                    } else {
-                        yearModeMap.merge("other", area, Double::sum);
-                    }
-                }
+    public ZdqlReportVO getZdqlReport() {
+        // ---------------------------------------------------
+        // 1. 定义报表关注的权利类型列(顺序即为展示顺序)
+        // ---------------------------------------------------
+        // qllx 字段对应字典 A6
+        LinkedHashMap<String, String> qllxDefMap = new LinkedHashMap<>();
+        qllxDefMap.put("3", "宅基地使用权和房屋使用权");
+        qllxDefMap.put("5", "集体建设用地使用权和房屋使用权");
+        qllxDefMap.put("6", "国有建设用地使用权和房屋使用权");
+        qllxDefMap.put("40", "林权");
+        qllxDefMap.put("20", "土地承包经营权");
+
+        List<String> qllxCodes = new ArrayList<>(qllxDefMap.keySet());
+
+        // ---------------------------------------------------
+        // 2. 查询原始聚合数据(地籍子区 × 权利类型 × 登记状态)
+        // ---------------------------------------------------
+        List<Map<String, Object>> rawData = zdjbxxMapper.getZdqlReportData(qllxCodes);
+
+        // ---------------------------------------------------
+        // 3. 按地籍子区聚合:Map<djzqdm, Map<qllx, double[2]>>
+        //    double[0] = 已登记面积,double[1] = 未登记面积
+        //    djzqmc 同步记录
+        // ---------------------------------------------------
+        LinkedHashMap<String, Map<String, double[]>> zqDataMap = new LinkedHashMap<>();
+        Map<String, String> djzqmcMap = new LinkedHashMap<>();
+
+        for (Map<String, Object> row : rawData) {
+            String djzqdm = (String) row.get("djzqdm");
+            String djzqmc = (String) row.get("djzqmc");
+            String qllx   = (String) row.get("qllx");
+            String djzt   = (String) row.get("djzt");
+            double areaMu = row.get("area_mu") != null ? ((Number) row.get("area_mu")).doubleValue() : 0.0;
+
+            if (StringUtils.isBlank(djzqdm) || StringUtils.isBlank(qllx)) {
+                continue;
             }
 
-            areaByYear.forEach((year, area) -> {
-                Map<String, Object> map = new LinkedHashMap<>();
-                map.put("year", year);
-                map.put("area", area);
-                areaTrendStatisticsList.add(map);
-            });
-
-            modeAreaByYear.forEach((year, modeAreas) -> {
-                Map<String, Object> map = new LinkedHashMap<>();
-                map.put("year", year);
-                map.put("transferArea", modeAreas.getOrDefault("transfer", 0.0));
-                map.put("allocateArea", modeAreas.getOrDefault("allocate", 0.0));
-                map.put("otherArea", modeAreas.getOrDefault("other", 0.0));
-                supplyModeStatisticsList.add(map);
-            });
-        }
-        res.setAreaTrendStatisticsList(areaTrendStatisticsList);
-        res.setSupplyModeStatisticsList(supplyModeStatisticsList);
-        return res;
-    }
-
+            djzqmcMap.putIfAbsent(djzqdm, djzqmc != null ? djzqmc : "");
+            zqDataMap.computeIfAbsent(djzqdm, k -> new LinkedHashMap<>())
+                     .computeIfAbsent(qllx, k -> new double[]{0.0, 0.0});
 
-    @Override
-    public LandSupplyReportDTO getTdgyReport(String startTime, String endTime) {
-        LandSupplyReportDTO report = new LandSupplyReportDTO();
-        report.setTitle("土地供应进度分析报表");
-        report.setStatTimeRange(startTime + " 至 " + endTime);
-
-        // 获取时间范围内的完成数据
-        List<TdgyStatisticsRes> completeList = dgyMapper.getListByYear(null, null, startTime, endTime);
-
-        // 获取时间范围内的计划数据
-        Map<String, Object> planSummary = gongdiJihuaMapper.getPlanSummaryByTimeRange(startTime, endTime);
-        List<Map<String, Object>> planStatsByLandType = gongdiJihuaMapper.getPlanStatsByLandType(startTime, endTime);
-
-        // 获取所有一级分类
-        List<LandType> landTypeList = landTypeMapper.selectFirstLevel();
-        Map<String, String> codeToFirstName = landTypeList.stream()
-                .collect(Collectors.toMap(LandType::getCode, LandType::getName, (v1, v2) -> v1));
-
-        // 按一级分类名称汇总统计数据的 Map
-        Map<String, LandSupplyReportDTO.DetailDTO> detailMap = new HashMap<>();
-
-        // 1. 统计计划数据并按一级分类归类
-        for (Map<String, Object> landTypeStat : planStatsByLandType) {
-            String category = (String) landTypeStat.get("category");
-            String parentName = "其他";
-            
-            // 通过枚举查找对应的一级分类名称
-            for (LandUseTypeEnum type : LandUseTypeEnum.values()) {
-                if (type.getName().equals(category)) {
-                    parentName = type.getParentName();
-                    break;
-                }
+            double[] areaArr = zqDataMap.get(djzqdm).get(qllx);
+            if ("1".equals(djzt)) {
+                areaArr[0] += areaMu;  // 已登记
+            } else if ("2".equals(djzt) || "3".equals(djzt)) {
+                areaArr[1] += areaMu;  // 未登记
             }
-
-            LandSupplyReportDTO.DetailDTO detail = detailMap.computeIfAbsent(parentName, k -> {
-                LandSupplyReportDTO.DetailDTO d = new LandSupplyReportDTO.DetailDTO();
-                d.setCategory(k);
-                d.setPlan(new LandSupplyReportDTO.PlanDTO());
-                d.getPlan().setArea(0.0);
-                d.getPlan().setCount(0);
-                d.getPlan().setTransfer(0);
-                d.getPlan().setAllocation(0);
-                d.getPlan().setOther(0);
-                d.setCompleted(new LandSupplyReportDTO.CompletedDTO());
-                d.getCompleted().setArea(0.0);
-                d.getCompleted().setCount(0);
-                d.getCompleted().setTransfer(0);
-                d.getCompleted().setAllocation(0);
-                d.getCompleted().setOther(0);
-                return d;
-            });
-
-            LandSupplyReportDTO.PlanDTO plan = detail.getPlan();
-            plan.setArea(plan.getArea() + toDouble(landTypeStat.get("planmu")));
-            plan.setCount(plan.getCount() + toInteger(landTypeStat.get("plancount")));
-            plan.setTransfer(plan.getTransfer() + toInteger(landTypeStat.get("plantransfer")));
-            plan.setAllocation(plan.getAllocation() + toInteger(landTypeStat.get("planallocation")));
-            plan.setOther(plan.getOther() + toInteger(landTypeStat.get("planother")));
         }
 
-        // 2. 统计完成数据并按一级分类归类
-        if (CollectionUtils.isNotEmpty(completeList)) {
-            for (TdgyStatisticsRes item : completeList) {
-                String tdyt = item.getTdyt();
-                String parentName = "其他";
-                if (tdyt != null && tdyt.length() >= 2) {
-                    String firstLevelCode = tdyt.substring(0, 2);
-                    parentName = codeToFirstName.getOrDefault(firstLevelCode, "其他");
-                }
-
-                LandSupplyReportDTO.DetailDTO detail = detailMap.computeIfAbsent(parentName, k -> {
-                    LandSupplyReportDTO.DetailDTO d = new LandSupplyReportDTO.DetailDTO();
-                    d.setCategory(k);
-                    d.setPlan(new LandSupplyReportDTO.PlanDTO());
-                    d.getPlan().setArea(0.0);
-                    d.getPlan().setCount(0);
-                    d.getPlan().setTransfer(0);
-                    d.getPlan().setAllocation(0);
-                    d.getPlan().setOther(0);
-                    d.setCompleted(new LandSupplyReportDTO.CompletedDTO());
-                    d.getCompleted().setArea(0.0);
-                    d.getCompleted().setCount(0);
-                    d.getCompleted().setTransfer(0);
-                    d.getCompleted().setAllocation(0);
-                    d.getCompleted().setOther(0);
-                    return d;
-                });
-
-                LandSupplyReportDTO.CompletedDTO completed = detail.getCompleted();
-                double area = item.getMjMu() != null ? item.getMjMu().doubleValue() : 0.0;
-                completed.setArea(completed.getArea() + area);
-                completed.setCount(completed.getCount() + 1);
-                
-                String gyfs = item.getGyfs();
-                if ("出让".equals(gyfs)) {
-                    int transfer = completed.getTransfer()+1;
-                    completed.setTransfer(transfer);
-                } else if ("划拨".equals(gyfs)) {
-                    int allocation = completed.getAllocation()+1;
-                    completed.setAllocation(allocation);
-                } else {
-                    int other = completed.getOther()+1;
-                    completed.setOther(other);
-                }
+        // ---------------------------------------------------
+        // 4. 构建数据行列表
+        // ---------------------------------------------------
+        List<ZdqlReportVO.RowData> rows = new ArrayList<>();
+
+        // 合计行的累加器 Map<qllx, double[2]>
+        Map<String, double[]> totalAccMap = new LinkedHashMap<>();
+        qllxCodes.forEach(code -> totalAccMap.put(code, new double[]{0.0, 0.0}));
+
+        for (Map.Entry<String, Map<String, double[]>> zqEntry : zqDataMap.entrySet()) {
+            String djzqdm = zqEntry.getKey();
+            Map<String, double[]> qllxAreaMap = zqEntry.getValue();
+
+            ZdqlReportVO.RowData rowData = new ZdqlReportVO.RowData();
+            rowData.setDjzqdm(djzqdm);
+            rowData.setDjzqmc(djzqmcMap.getOrDefault(djzqdm, ""));
+
+            List<ZdqlReportVO.QllxStatCell> cells = new ArrayList<>();
+            for (String code : qllxCodes) {
+                double[] areaArr = qllxAreaMap.getOrDefault(code, new double[]{0.0, 0.0});
+                double registered   = areaArr[0];
+                double unregistered = areaArr[1];
+                double total        = registered + unregistered;
+
+                ZdqlReportVO.QllxStatCell cell = new ZdqlReportVO.QllxStatCell();
+                cell.setQllxCode(code);
+                cell.setQllxName(qllxDefMap.get(code)); // 融合 qllxName 到 cell 中
+                cell.setTotalArea(roundArea(total));
+                cell.setRegisteredArea(roundArea(registered));
+                cell.setUnregisteredArea(roundArea(unregistered));
+                cells.add(cell);
+
+                // 累计到合计行
+                totalAccMap.get(code)[0] += registered;
+                totalAccMap.get(code)[1] += unregistered;
             }
+            rowData.setCells(cells);
+            rows.add(rowData);
         }
 
-
-        // 3. 构建 Summary
-        LandSupplyReportDTO.SummaryDTO summary = new LandSupplyReportDTO.SummaryDTO();
-        LandSupplyReportDTO.TotalDTO total = buildTotalDTO(planSummary);
-        
-        // 重新计算 Total 的 Completed 部分,因为之前 buildTotalDTO 填充的是 0
-        if (CollectionUtils.isNotEmpty(completeList)) {
-            double totalArea = completeList.stream().filter(g -> g.getMjMu() != null).mapToDouble(g -> g.getMjMu().doubleValue()).sum();
-            long totalTransfer = completeList.stream().filter(g -> "出让".equals(g.getGyfs())).count();
-            long totalAllocation = completeList.stream().filter(g -> "划拨".equals(g.getGyfs()) ).count();
-            long totalOther =  completeList.size() - totalTransfer - totalAllocation;
-            total.setCompleted(buildCompletedDTO(totalArea, completeList.size(), (int) totalTransfer,  (int) totalAllocation,  (int) totalOther));
-            double planArea = total.getPlan().getArea();
-            if (planArea > 0) {
-                total.setSupplyRate(String.format("%.2f%%", (totalArea / planArea) * 100));
-            } else {
-                total.setSupplyRate("0%");
-            }
-        }
-        
-        summary.setTotal(total);
-        report.setSummary(summary);
-
-        // 4. 构建 Details 列表并计算供应率
-        List<LandSupplyReportDTO.DetailDTO> details = new ArrayList<>(detailMap.values());
-        for (LandSupplyReportDTO.DetailDTO detail : details) {
-            double planArea = detail.getPlan().getArea();
-            double completedArea = detail.getCompleted().getArea();
-            if (planArea > 0) {
-                detail.setSupplyRate(String.format("%.2f%%", (completedArea / planArea) * 100));
-            } else {
-                detail.setSupplyRate("0%");
-            }
-        }
-        
-        // 按计划面积排序
-        details.sort((d1, d2) -> d2.getPlan().getArea().compareTo(d1.getPlan().getArea()));
-        report.setDetails(details);
-
-        return report;
-    }
-
-
-
-    @Override
-    public LandSupplyReportVO getTdgyPurposeReport(String startYear, String endYear){
-        //List<TdgyStatisticsRes> completeList = dgyMapper.getListByYear(null, null, startYear, endYear);
-        //todo 这里需要修改
-        SupplyYearStatisticsRes res = new SupplyYearStatisticsRes();
-        GongdiJihuaFilterVo filterVo = new GongdiJihuaFilterVo();
-        filterVo.setPageSize(100000);
-        List<GongdiJihua> completeList = gongdiJihuaMapper.getList(filterVo);
-
-        if (CollectionUtils.isEmpty(completeList)) {
-            return new LandSupplyReportVO();
+        // ---------------------------------------------------
+        // 5. 构建合计行
+        // ---------------------------------------------------
+        ZdqlReportVO.RowData totalRow = new ZdqlReportVO.RowData();
+        totalRow.setDjzqdm(null);
+        totalRow.setDjzqmc("合计");
+        List<ZdqlReportVO.QllxStatCell> totalCells = new ArrayList<>();
+        for (String code : qllxCodes) {
+            double[] areaArr    = totalAccMap.get(code);
+            double registered   = areaArr[0];
+            double unregistered = areaArr[1];
+            ZdqlReportVO.QllxStatCell cell = new ZdqlReportVO.QllxStatCell();
+            cell.setQllxCode(code);
+            cell.setQllxName(qllxDefMap.get(code)); // 融合 qllxName 到 cell 中
+            cell.setTotalArea(roundArea(registered + unregistered));
+            cell.setRegisteredArea(roundArea(registered));
+            cell.setUnregisteredArea(roundArea(unregistered));
+            totalCells.add(cell);
         }
-
-        LandSupplyReportVO report = new LandSupplyReportVO();
-        
-        // 1. 获取一级分类映射
-        List<LandType> landTypeList = landTypeMapper.selectFirstLevel();
-        Map<String, String> codeToFirstName = landTypeList.stream()
-                .collect(Collectors.toMap(LandType::getCode, LandType::getName, (v1, v2) -> v1));
-
-        // 2. 统计年份并排序
-        Set<Integer> yearSet = new TreeSet<>();
-        for (GongdiJihua item : completeList) {
-            if (item.getGysj() != null) {
-                yearSet.add(item.getGysj().getYear() + 1900);
-            }
-        }
-        report.setYears(new ArrayList<>(yearSet));
-
-        // 3. 按一级分类、供应方式、年份进行汇总统计
-        // Map<一级分类名称, Map<供应方式, Map<年份, 面积汇总>>>
-        Map<String, Map<String, Map<String, Double>>> stats = new HashMap<>();
-
-        for (GongdiJihua item : completeList) {
-            if (item.getGysj() == null || item.getTdyt() == null || item.getTdyt().length() < 2) continue;
-            String firstLevelCode  = LandUseTypeEnum.getCodeByName(item.getTdyt());
-            //todo 这里需要修改
-            //String firstLevelCode = item.getTdyt().substring(0, 2);
-            String parentName = codeToFirstName.getOrDefault(firstLevelCode, "其他");
-            String year = String.valueOf(item.getGysj().getYear() + 1900);
-            String gyfs = "划拨".equals(item.getGyfs()) ? "划拨" : ("出让".equals(item.getGyfs()) ? "出让" : "其他");
-            double area = item.getMjMu() != null ? item.getMjMu().doubleValue() : 0.0;
-
-            stats.computeIfAbsent(parentName, k -> new HashMap<>())
-                 .computeIfAbsent(gyfs, k -> new HashMap<>())
-                 .merge(year, area, Double::sum);
-        }
-
-        // 4. 构建返回对象数据
-        List<LandSupplyReportVO.LandTypeData> dataList = new ArrayList<>();
-        
-        for (LandType lt : landTypeList) {
-            String parentName = lt.getName();
-            Map<String, Map<String, Double>> modeMap = stats.get(parentName);
-            if (modeMap == null) continue;
-
-            LandSupplyReportVO.LandTypeData landTypeData = new LandSupplyReportVO.LandTypeData();
-            landTypeData.setLandType(parentName);
-
-            // 划拨数据
-            landTypeData.setAllocation(buildCategoryData(modeMap.get("划拨"), report.getYears()));
-            // 出让数据
-            landTypeData.setTransfer(buildCategoryData(modeMap.get("出让"), report.getYears()));
-            
-            // 总计数据
-            LandSupplyReportVO.CategoryData totalData = new LandSupplyReportVO.CategoryData();
-            Map<String, Double> totalYearData = new LinkedHashMap<>();
-            double grandTotal = 0.0;
-            for (Integer y : report.getYears()) {
-                String yearStr = String.valueOf(y);
-                double areaSum = 0.0;
-                if (modeMap.get("划拨") != null) areaSum += modeMap.get("划拨").getOrDefault(yearStr, 0.0);
-                if (modeMap.get("出让") != null) areaSum += modeMap.get("出让").getOrDefault(yearStr, 0.0);
-                if (modeMap.get("其他") != null) areaSum += modeMap.get("其他").getOrDefault(yearStr, 0.0);
-                
-                totalYearData.put(yearStr, areaSum);
-                grandTotal += areaSum;
-            }
-            totalData.setTotal(grandTotal);
-            totalData.setYearData(totalYearData);
-            landTypeData.setTotal(totalData);
-
-            dataList.add(landTypeData);
-        }
-        report.setData(dataList);
-
+        totalRow.setCells(totalCells);
+
+        // ---------------------------------------------------
+        // 6. 组装返回结果
+        // ---------------------------------------------------
+        ZdqlReportVO report = new ZdqlReportVO();
+        report.setRows(rows);
+        report.setTotal(totalRow);
         return report;
     }
 
-    private LandSupplyReportVO.CategoryData buildCategoryData(Map<String, Double> yearCounts, List<Integer> years) {
-        LandSupplyReportVO.CategoryData data = new LandSupplyReportVO.CategoryData();
-        Map<String, Double> yearData = new LinkedHashMap<>();
-        double total = 0.0;
-        for (Integer y : years) {
-            String yearStr = String.valueOf(y);
-            double areaSum = yearCounts != null ? yearCounts.getOrDefault(yearStr, 0.0) : 0.0;
-            yearData.put(yearStr, areaSum);
-            total += areaSum;
-        }
-        data.setTotal(total);
-        data.setYearData(yearData);
-        return data;
-    }
-
-
-
-    private LandSupplyReportDTO.TotalDTO buildTotalDTO(Map<String, Object> summary) {
-        LandSupplyReportDTO.TotalDTO total = new LandSupplyReportDTO.TotalDTO();
-        total.setSupplyRate("0%");
-
-        LandSupplyReportDTO.PlanDTO plan = new LandSupplyReportDTO.PlanDTO();
-        plan.setArea(toDouble(summary.get("planmu")));
-        plan.setCount(toInteger(summary.get("plancount")));
-        plan.setTransfer(toInteger(summary.get("plantransfer")));
-        plan.setAllocation(toInteger(summary.get("planallocation")));
-        plan.setOther(toInteger(summary.get("planother")));
-        total.setPlan(plan);
-
-        LandSupplyReportDTO.CompletedDTO completed = new LandSupplyReportDTO.CompletedDTO();
-        completed.setArea(0.0);
-        completed.setCount(0);
-        completed.setTransfer(0);
-        completed.setAllocation(0);
-        completed.setOther(0);
-        total.setCompleted(completed);
-
-        return total;
-    }
-
-
-
-    private LandSupplyReportDTO.CompletedDTO buildCompletedDTO(Double area, Integer count, Integer transfer, Integer allocation, Integer other) {
-        LandSupplyReportDTO.CompletedDTO completed = new LandSupplyReportDTO.CompletedDTO();
-        completed.setArea(area);
-        completed.setCount(count);
-        completed.setTransfer(transfer);
-        completed.setAllocation(allocation);
-        completed.setOther(other);
-        return completed;
+    /**
+     * 面积保留两位小数(四舍五入)
+     */
+    private double roundArea(double value) {
+        return Math.round(value * 100.0) / 100.0;
     }
 
-    private String convertCategory(String category) {
-        if (category == null || category.equals("未知")) {
-            return "其他";
-        }
-        return category;
-    }
 
-    private Double toDouble(Object value) {
-        if (value == null) {
-            return 0.0;
-        }
-        if (value instanceof Number) {
-            return ((Number) value).doubleValue();
-        }
-        return 0.0;
-    }
 
-    private Integer toInteger(Object value) {
-        if (value == null) {
-            return 0;
-        }
-        if (value instanceof Number) {
-            return ((Number) value).intValue();
-        }
-        return 0;
-    }
 }

+ 59 - 0
siwei-modules/siwei-apply/src/main/resources/mapper/cadastre/ZdjbxxMapper.xml

@@ -252,4 +252,63 @@
         WHERE djq.djqdm IS NOT NULL
     </select>
 
+    <select id="getStatisticsByQllx" resultType="Map">
+        SELECT
+            COALESCE(NULLIF(TRIM(qllx), ''), '其他') AS qllx,
+            djzt,
+            SUM(
+                CASE
+                    WHEN mjdw = '1' THEN zdmj / 666.6666667
+                    WHEN mjdw = '2' THEN zdmj
+                    WHEN mjdw = '3' THEN zdmj * 15
+                    WHEN mjdw = '4' THEN zdmj * 1500
+                    ELSE COALESCE(zdmj, 0)
+                END
+            ) AS area_mu
+        FROM vector.zdjbxx
+        WHERE qllx IS NOT NULL
+        GROUP BY COALESCE(NULLIF(TRIM(qllx), ''), '其他'), djzt
+        ORDER BY COALESCE(NULLIF(TRIM(qllx), ''), '其他')
+    </select>
+
+    <!--
+        宗地权利报表数据查询
+        按 地籍子区(djzq) × 权利类型(qllx) × 登记状态(djzt) 三维度聚合面积
+        - 通过 zddm 前12位关联 djzq.djzqdm
+        - 面积统一换算为亩(mu)
+        - 只统计指定权利类型代码范围内的记录
+        返回字段:djzqdm, djzqmc, qllx, djzt, area_mu
+    -->
+    <select id="getZdqlReportData" resultType="Map">
+        SELECT
+            dq.djzqdm,
+            dq.djzqmc,
+            zd.qllx,
+            zd.djzt,
+            SUM(
+                CASE
+                    WHEN zd.mjdw = '1' THEN zd.zdmj / 666.6666667
+                    WHEN zd.mjdw = '2' THEN zd.zdmj
+                    WHEN zd.mjdw = '3' THEN zd.zdmj * 15
+                    WHEN zd.mjdw = '4' THEN zd.zdmj * 1500
+                    ELSE COALESCE(zd.zdmj, 0)
+                END
+            ) AS area_mu
+        FROM vector.zdjbxx zd
+        INNER JOIN vector.djzq dq
+            ON LEFT(zd.zddm, 12) = dq.djzqdm
+        WHERE zd.qllx IS NOT NULL
+          AND zd.zdmj IS NOT NULL
+          AND (zd.valid_flag IS NULL OR zd.valid_flag = 0)
+          AND (dq.valid_flag IS NULL OR dq.valid_flag = 0)
+        <if test="qllxCodes != null and qllxCodes.size() > 0">
+            AND zd.qllx IN
+            <foreach collection="qllxCodes" item="code" open="(" separator="," close=")">
+                #{code}
+            </foreach>
+        </if>
+        GROUP BY dq.djzqdm, dq.djzqmc, zd.qllx, zd.djzt
+        ORDER BY dq.djzqdm, zd.qllx, zd.djzt
+    </select>
+
 </mapper>