Prechádzať zdrojové kódy

提交城市监测接口

ywf 1 mesiac pred
rodič
commit
b72091bd97

+ 48 - 0
onemap-modules/onemap-apply/src/main/java/com/onemap/apply/controller/yzt/UrbanMonitorController.java

@@ -0,0 +1,48 @@
+package com.onemap.apply.controller.yzt;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.onemap.common.core.web.domain.RequestResult;
+import com.onemap.apply.domain.yzt.UrbanMonitorVO;
+import com.onemap.apply.service.yzt.IUrbanMonitorService;
+
+@RestController
+@RequestMapping("/yzt/urbanMonitor")
+public class UrbanMonitorController {
+
+    @Autowired
+    private IUrbanMonitorService urbanMonitorService;
+
+    /**
+     * 获取城市监测数据
+     * 
+     * @param type buildUp_area(建成区面积) / building_area(建筑面积) / building_count(建筑数量)
+     * @param code 区域代码
+     */
+    @GetMapping("/getUrbanInfo")
+    public RequestResult getUrbanInfo(String type, String code) {
+        List<UrbanMonitorVO> list = urbanMonitorService.selectUrbanMonitorList(type, code);
+        return RequestResult.success(list);
+    }
+
+    /**
+     * 获取城市扩张图层配置
+     * 
+     * @param dimType 2d/3d
+     */
+    @GetMapping("/getUrbanExpansionInfo")
+    public RequestResult getUrbanExpansionInfo(String dimType) {
+        return RequestResult.success(urbanMonitorService.getUrbanExpansionConfig(dimType));
+    }
+
+    /**
+     * 获取所有城市监测数据(建成区面积、建筑面积、建筑数量)
+     */
+    @GetMapping("/getAllUrbanData")
+    public RequestResult getAllUrbanData() {
+        return RequestResult.success(urbanMonitorService.getAllUrbanMonitorData());
+    }
+}

+ 35 - 0
onemap-modules/onemap-apply/src/main/java/com/onemap/apply/domain/yzt/UrbanExpansionConfigVO.java

@@ -0,0 +1,35 @@
+package com.onemap.apply.domain.yzt;
+
+import lombok.Data;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 城市扩张配置响应VO
+ */
+@Data
+public class UrbanExpansionConfigVO {
+    /** 服务ID */
+    private String serviceId;
+    /** 年份列表 */
+    private List<Integer> years;
+    /** 边界图层: {"2009": {"layerName": "xxx", "data": 125.36}} */
+    private Map<String, LayerInfo> boundaryLayers;
+    /** 扩张图层: {"2009_2010": {"layerName": "xxx", "data": 7.22}} */
+    private Map<String, LayerInfo> expandLayers;
+
+    @Data
+    public static class LayerInfo {
+        private String layerName;
+        private BigDecimal data;
+
+        public LayerInfo() {
+        }
+
+        public LayerInfo(String layerName, BigDecimal data) {
+            this.layerName = layerName;
+            this.data = data;
+        }
+    }
+}

+ 25 - 0
onemap-modules/onemap-apply/src/main/java/com/onemap/apply/domain/yzt/UrbanExpansionLayerVO.java

@@ -0,0 +1,25 @@
+package com.onemap.apply.domain.yzt;
+
+import lombok.Data;
+import java.math.BigDecimal;
+
+/**
+ * 城市扩张图层配置VO
+ */
+@Data
+public class UrbanExpansionLayerVO {
+    /** 年份 */
+    private Integer year;
+    /** 图层类型: boundary-边界, expand-扩张 */
+    private String layerType;
+    /** 维度类型: 2d/3d */
+    private String dimType;
+    /** 图层名称 */
+    private String layerName;
+    /** 上一年份(扩张图层使用) */
+    private Integer prevYear;
+    /** 数据(面积或数量) */
+    private BigDecimal data;
+    /** 服务ID */
+    private String serviceId;
+}

+ 17 - 0
onemap-modules/onemap-apply/src/main/java/com/onemap/apply/domain/yzt/UrbanMonitorAllVO.java

@@ -0,0 +1,17 @@
+package com.onemap.apply.domain.yzt;
+
+import lombok.Data;
+import java.util.List;
+
+/**
+ * 城市监测数据聚合VO - 一次返回所有统计数据(按年份和区域分组)
+ */
+@Data
+public class UrbanMonitorAllVO {
+    /** 建成区面积统计 */
+    private List<UrbanMonitorYearVO> buildUpArea;
+    /** 建筑面积统计 */
+    private List<UrbanMonitorYearVO> buildingArea;
+    /** 建筑数量统计 */
+    private List<UrbanMonitorYearVO> buildingCount;
+}

+ 18 - 0
onemap-modules/onemap-apply/src/main/java/com/onemap/apply/domain/yzt/UrbanMonitorAreaVO.java

@@ -0,0 +1,18 @@
+package com.onemap.apply.domain.yzt;
+
+import lombok.Data;
+
+/**
+ * 区域监测数据VO(单个区的数据)
+ */
+@Data
+public class UrbanMonitorAreaVO {
+    /** 行政区划代码 */
+    private String code;
+    /** 行政区划名称 */
+    private String name;
+    /** 数据值(面积或数量) */
+    private double data;
+    /** 变化率 */
+    private double changeRate;
+}

+ 11 - 0
onemap-modules/onemap-apply/src/main/java/com/onemap/apply/domain/yzt/UrbanMonitorVO.java

@@ -0,0 +1,11 @@
+package com.onemap.apply.domain.yzt;
+
+import lombok.Data;
+
+@Data
+public class UrbanMonitorVO {
+
+    private double data;
+    private double changeRate;
+    private Integer year;
+}

+ 15 - 0
onemap-modules/onemap-apply/src/main/java/com/onemap/apply/domain/yzt/UrbanMonitorYearVO.java

@@ -0,0 +1,15 @@
+package com.onemap.apply.domain.yzt;
+
+import lombok.Data;
+import java.util.List;
+
+/**
+ * 年份监测数据VO(包含该年份下所有区域的数据)
+ */
+@Data
+public class UrbanMonitorYearVO {
+    /** 年份 */
+    private Integer year;
+    /** 各区域数据列表 */
+    private List<UrbanMonitorAreaVO> areas;
+}

+ 33 - 0
onemap-modules/onemap-apply/src/main/java/com/onemap/apply/mapper/yzt/UrbanMonitorMapper.java

@@ -0,0 +1,33 @@
+package com.onemap.apply.mapper.yzt;
+
+import com.onemap.apply.domain.yzt.UrbanMonitorVO;
+import com.onemap.apply.domain.yzt.UrbanExpansionLayerVO;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 城市监测Mapper接口
+ */
+public interface UrbanMonitorMapper {
+    /**
+     * 查询城市监测列表
+     * 
+     * @param type buildUp_area/building_area/building_count
+     * @param code 区域代码
+     */
+    public List<UrbanMonitorVO> selectUrbanMonitorList(@Param("type") String type, @Param("code") String code);
+
+    /**
+     * 查询城市扩张图层配置
+     * 
+     * @param dimType 维度类型: 2d/3d
+     */
+    public List<UrbanExpansionLayerVO> selectUrbanExpansionList(@Param("dimType") String dimType);
+
+    /**
+     * 按年份、区域、类型分组查询城市监测数据
+     * 返回 Map: year, code, type, total_area, count
+     */
+    public List<Map<String, Object>> selectUrbanMonitorGrouped();
+}

+ 296 - 0
onemap-modules/onemap-apply/src/main/java/com/onemap/apply/service/impl/yzt/UrbanMonitorServiceImpl.java

@@ -0,0 +1,296 @@
+package com.onemap.apply.service.impl.yzt;
+
+import java.util.List;
+import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.ArrayList;
+import java.util.stream.Collectors;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.onemap.apply.mapper.yzt.UrbanMonitorMapper;
+import com.onemap.apply.domain.yzt.UrbanMonitorVO;
+import com.onemap.apply.domain.yzt.UrbanMonitorAllVO;
+import com.onemap.apply.domain.yzt.UrbanMonitorYearVO;
+import com.onemap.apply.domain.yzt.UrbanMonitorAreaVO;
+import com.onemap.apply.domain.yzt.UrbanExpansionLayerVO;
+import com.onemap.apply.domain.yzt.UrbanExpansionConfigVO;
+import com.onemap.apply.service.yzt.IUrbanMonitorService;
+
+/**
+ * 城市监测Service业务层处理
+ */
+@Service
+public class UrbanMonitorServiceImpl implements IUrbanMonitorService {
+    @Autowired
+    private UrbanMonitorMapper urbanMonitorMapper;
+
+    // 区域代码和名称映射
+    private static final Map<String, String> AREA_NAME_MAP = new LinkedHashMap<>();
+    static {
+        AREA_NAME_MAP.put("460200", "三亚市");
+        AREA_NAME_MAP.put("460202", "海棠区");
+        AREA_NAME_MAP.put("460203", "吉阳区");
+        AREA_NAME_MAP.put("460204", "天涯区");
+        AREA_NAME_MAP.put("460205", "崖州区");
+    }
+
+    /**
+     * 查询城市监测列表
+     * 
+     * @param type buildUp_area/building_area/building_count
+     * @param code 区域代码
+     */
+    public List<UrbanMonitorVO> selectUrbanMonitorList(String type, String code) {
+        // 如果行政码是6位,且后两位为00,则查询全市(设为null不进行过滤)
+        if (code != null && code.length() == 6 && code.endsWith("00")) {
+            code = null;
+        }
+        List<UrbanMonitorVO> list = urbanMonitorMapper.selectUrbanMonitorList(type, code);
+        return calculateChangeRate(list);
+    }
+
+    /**
+     * 获取所有城市监测数据(建成区面积、建筑面积、建筑数量)
+     * 按年份分组,每年包含各区域数据
+     */
+    @Override
+    public UrbanMonitorAllVO getAllUrbanMonitorData() {
+        // 1. 查询原始数据(按 year, code, type 分组)
+        List<Map<String, Object>> rawData = urbanMonitorMapper.selectUrbanMonitorGrouped();
+
+        // 2. 按 type 拆分数据
+        // type=1: 建成区, type=0: 建筑
+        Map<Integer, Map<String, Double>> buildUpAreaMap = new LinkedHashMap<>(); // year -> code -> total_area
+        Map<Integer, Map<String, Double>> buildingAreaMap = new LinkedHashMap<>(); // year -> code -> total_area
+        Map<Integer, Map<String, Long>> buildingCountMap = new LinkedHashMap<>(); // year -> code -> count
+
+        for (Map<String, Object> row : rawData) {
+            Integer year = ((Number) row.get("year")).intValue();
+            String code = (String) row.get("code");
+            Integer type = ((Number) row.get("type")).intValue();
+            Double totalArea = row.get("total_area") != null ? ((Number) row.get("total_area")).doubleValue() : 0.0;
+            Long count = row.get("count") != null ? ((Number) row.get("count")).longValue() : 0L;
+
+            if (type == 1) {
+                // 建成区面积
+                buildUpAreaMap.computeIfAbsent(year, k -> new LinkedHashMap<>()).merge(code, totalArea, Double::sum);
+            } else {
+                // 建筑面积和数量
+                buildingAreaMap.computeIfAbsent(year, k -> new LinkedHashMap<>()).merge(code, totalArea, Double::sum);
+                buildingCountMap.computeIfAbsent(year, k -> new LinkedHashMap<>()).merge(code, count, Long::sum);
+            }
+        }
+
+        // 3. 计算三亚市(汇总所有区)
+        addCitySummary(buildUpAreaMap);
+        addCitySummary(buildingAreaMap);
+        addCitySummaryLong(buildingCountMap);
+
+        // 4. 组装返回数据
+        UrbanMonitorAllVO result = new UrbanMonitorAllVO();
+        result.setBuildUpArea(buildYearData(buildUpAreaMap, "area"));
+        result.setBuildingArea(buildYearData(buildingAreaMap, "area"));
+        result.setBuildingCount(buildYearDataLong(buildingCountMap));
+
+        return result;
+    }
+
+    /**
+     * 计算三亚市汇总数据(Double类型)
+     */
+    private void addCitySummary(Map<Integer, Map<String, Double>> dataMap) {
+        for (Map.Entry<Integer, Map<String, Double>> entry : dataMap.entrySet()) {
+            Map<String, Double> codeMap = entry.getValue();
+            double cityTotal = codeMap.values().stream().mapToDouble(Double::doubleValue).sum();
+            // 放在第一位
+            Map<String, Double> newMap = new LinkedHashMap<>();
+            newMap.put("460200", cityTotal);
+            newMap.putAll(codeMap);
+            entry.setValue(newMap);
+        }
+    }
+
+    /**
+     * 计算三亚市汇总数据(Long类型)
+     */
+    private void addCitySummaryLong(Map<Integer, Map<String, Long>> dataMap) {
+        for (Map.Entry<Integer, Map<String, Long>> entry : dataMap.entrySet()) {
+            Map<String, Long> codeMap = entry.getValue();
+            long cityTotal = codeMap.values().stream().mapToLong(Long::longValue).sum();
+            Map<String, Long> newMap = new LinkedHashMap<>();
+            newMap.put("460200", cityTotal);
+            newMap.putAll(codeMap);
+            entry.setValue(newMap);
+        }
+    }
+
+    /**
+     * 构建年份数据(Double类型)
+     */
+    private List<UrbanMonitorYearVO> buildYearData(Map<Integer, Map<String, Double>> dataMap, String dataType) {
+        List<UrbanMonitorYearVO> yearList = new ArrayList<>();
+        // 用于计算变化率:code -> 上一年数据
+        Map<String, Double> prevDataMap = new LinkedHashMap<>();
+
+        for (Map.Entry<Integer, Map<String, Double>> entry : dataMap.entrySet()) {
+            Integer year = entry.getKey();
+            Map<String, Double> codeMap = entry.getValue();
+
+            UrbanMonitorYearVO yearVO = new UrbanMonitorYearVO();
+            yearVO.setYear(year);
+            List<UrbanMonitorAreaVO> areas = new ArrayList<>();
+
+            for (Map.Entry<String, Double> codeEntry : codeMap.entrySet()) {
+                String code = codeEntry.getKey();
+                Double data = codeEntry.getValue();
+
+                UrbanMonitorAreaVO areaVO = new UrbanMonitorAreaVO();
+                areaVO.setCode(code);
+                areaVO.setName(AREA_NAME_MAP.getOrDefault(code, code));
+                areaVO.setData(data);
+
+                // 计算变化率
+                Double prevData = prevDataMap.get(code);
+                if (prevData == null || prevData == 0) {
+                    areaVO.setChangeRate(0);
+                } else {
+                    double rate = (data - prevData) / prevData * 100;
+                    areaVO.setChangeRate(Math.round(rate * 100.0) / 100.0);
+                }
+                prevDataMap.put(code, data);
+
+                areas.add(areaVO);
+            }
+
+            yearVO.setAreas(areas);
+            yearList.add(yearVO);
+        }
+
+        return yearList;
+    }
+
+    /**
+     * 构建年份数据(Long类型)
+     */
+    private List<UrbanMonitorYearVO> buildYearDataLong(Map<Integer, Map<String, Long>> dataMap) {
+        List<UrbanMonitorYearVO> yearList = new ArrayList<>();
+        Map<String, Long> prevDataMap = new LinkedHashMap<>();
+
+        for (Map.Entry<Integer, Map<String, Long>> entry : dataMap.entrySet()) {
+            Integer year = entry.getKey();
+            Map<String, Long> codeMap = entry.getValue();
+
+            UrbanMonitorYearVO yearVO = new UrbanMonitorYearVO();
+            yearVO.setYear(year);
+            List<UrbanMonitorAreaVO> areas = new ArrayList<>();
+
+            for (Map.Entry<String, Long> codeEntry : codeMap.entrySet()) {
+                String code = codeEntry.getKey();
+                Long data = codeEntry.getValue();
+
+                UrbanMonitorAreaVO areaVO = new UrbanMonitorAreaVO();
+                areaVO.setCode(code);
+                areaVO.setName(AREA_NAME_MAP.getOrDefault(code, code));
+                areaVO.setData(data.doubleValue());
+
+                Long prevData = prevDataMap.get(code);
+                if (prevData == null || prevData == 0) {
+                    areaVO.setChangeRate(0);
+                } else {
+                    double rate = (data - prevData) / (double) prevData * 100;
+                    areaVO.setChangeRate(Math.round(rate * 100.0) / 100.0);
+                }
+                prevDataMap.put(code, data);
+
+                areas.add(areaVO);
+            }
+
+            yearVO.setAreas(areas);
+            yearList.add(yearVO);
+        }
+
+        return yearList;
+    }
+
+    /**
+     * 获取城市扩张图层配置
+     * 
+     * @param dimType 维度类型: 2d/3d
+     */
+    @Override
+    public UrbanExpansionConfigVO getUrbanExpansionConfig(String dimType) {
+        // 默认为 2d
+        if (dimType == null || dimType.isEmpty()) {
+            dimType = "2d";
+        }
+
+        List<UrbanExpansionLayerVO> list = urbanMonitorMapper.selectUrbanExpansionList(dimType);
+
+        UrbanExpansionConfigVO config = new UrbanExpansionConfigVO();
+        List<Integer> years = new ArrayList<>();
+        Map<String, UrbanExpansionConfigVO.LayerInfo> boundaryLayers = new LinkedHashMap<>();
+        Map<String, UrbanExpansionConfigVO.LayerInfo> expandLayers = new LinkedHashMap<>();
+
+        if (list != null && !list.isEmpty()) {
+            config.setServiceId(list.get(0).getServiceId());
+            // 提取年份并去重排序
+            years = list.stream()
+                    .map(UrbanExpansionLayerVO::getYear)
+                    .distinct()
+                    .sorted()
+                    .collect(Collectors.toList());
+
+            for (UrbanExpansionLayerVO item : list) {
+                UrbanExpansionConfigVO.LayerInfo info = new UrbanExpansionConfigVO.LayerInfo(item.getLayerName(),
+                        item.getData());
+
+                if ("boundary".equals(item.getLayerType())) {
+                    // key is year string
+                    boundaryLayers.put(String.valueOf(item.getYear()), info);
+                } else if ("expand".equals(item.getLayerType())) {
+                    // key is prevYear_year
+                    if (item.getPrevYear() != null) {
+                        String key = item.getPrevYear() + "_" + item.getYear();
+                        expandLayers.put(key, info);
+                    }
+                }
+            }
+        }
+
+        config.setYears(years);
+        config.setBoundaryLayers(boundaryLayers);
+        config.setExpandLayers(expandLayers);
+
+        return config;
+    }
+
+    /**
+     * 计算变化率
+     */
+    private List<UrbanMonitorVO> calculateChangeRate(List<UrbanMonitorVO> list) {
+        if (list == null || list.isEmpty()) {
+            return list;
+        }
+
+        for (int i = 0; i < list.size(); i++) {
+            UrbanMonitorVO current = list.get(i);
+            if (i == 0) {
+                current.setChangeRate(0);
+                continue;
+            }
+
+            UrbanMonitorVO prev = list.get(i - 1);
+            double prevData = prev.getData();
+
+            if (prevData == 0) {
+                current.setChangeRate(0);
+            } else {
+                double rate = (current.getData() - prevData) / prevData * 100;
+                rate = Math.round(rate * 100.0) / 100.0;
+                current.setChangeRate(rate);
+            }
+        }
+
+        return list;
+    }
+}

+ 31 - 0
onemap-modules/onemap-apply/src/main/java/com/onemap/apply/service/yzt/IUrbanMonitorService.java

@@ -0,0 +1,31 @@
+package com.onemap.apply.service.yzt;
+
+import java.util.List;
+import com.onemap.apply.domain.yzt.UrbanMonitorVO;
+import com.onemap.apply.domain.yzt.UrbanMonitorAllVO;
+import com.onemap.apply.domain.yzt.UrbanExpansionConfigVO;
+
+/**
+ * 城市监测Service接口
+ */
+public interface IUrbanMonitorService {
+    /**
+     * 查询城市监测列表
+     * 
+     * @param type buildUp_area/building_area/building_count
+     * @param code 区域代码
+     */
+    public List<UrbanMonitorVO> selectUrbanMonitorList(String type, String code);
+
+    /**
+     * 获取所有城市监测数据(建成区面积、建筑面积、建筑数量)
+     */
+    public UrbanMonitorAllVO getAllUrbanMonitorData();
+
+    /**
+     * 获取城市扩张图层配置
+     * 
+     * @param dimType 维度类型: 2d/3d
+     */
+    public UrbanExpansionConfigVO getUrbanExpansionConfig(String dimType);
+}

+ 88 - 0
onemap-modules/onemap-apply/src/main/resources/mapper/postgresql/yzt/UrbanMonitorMapper.xml

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.onemap.apply.mapper.yzt.UrbanMonitorMapper">
+    
+    <resultMap type="com.onemap.apply.domain.yzt.UrbanMonitorVO" id="UrbanMonitorResult">
+        <result property="year"    column="year"    />
+        <result property="data"    column="data"    />
+    </resultMap>
+
+    <!-- 
+        查询城市监测列表
+        type: buildUp_area(建成区面积) / building_area(建筑面积) / building_count(建筑数量)
+        数据库 jc_urban: type=0 建筑信息, type=1 建成区
+    -->
+    <select id="selectUrbanMonitorList" resultMap="UrbanMonitorResult">
+        SELECT 
+            "year",
+            <choose>
+                <when test="type == 'building_count'">
+                    COUNT(*) as data
+                </when>
+                <otherwise>
+                    SUM(area) as data
+                </otherwise>
+            </choose>
+        FROM "vector"."jc_urban"
+        WHERE 1=1
+        <choose>
+            <when test="type == 'buildUp_area'">
+                AND type = 1
+            </when>
+            <otherwise>
+                AND type = 0
+            </otherwise>
+        </choose>
+        <if test="code != null and code != ''">
+            AND trim(code) = trim(#{code})
+        </if>
+        GROUP BY "year"
+        ORDER BY "year" ASC
+    </select>
+
+    
+    <resultMap type="com.onemap.apply.domain.yzt.UrbanExpansionLayerVO" id="UrbanExpansionLayerResult">
+        <result property="year"       column="year"       />
+        <result property="layerType"  column="layer_type" />
+        <result property="dimType"    column="dim_type"   />
+        <result property="layerName"  column="layer_name" />
+        <result property="prevYear"   column="prev_year"  />
+        <result property="data"       column="data"       />
+        <result property="serviceId"  column="service_id" />
+    </resultMap>
+
+    <select id="selectUrbanExpansionList" resultMap="UrbanExpansionLayerResult">
+        SELECT 
+            year, layer_type, dim_type, layer_name, prev_year, data, service_id
+        FROM "vector"."jc_urban_expansion"
+        WHERE status = 1 
+        <if test="dimType != null and dimType != ''">
+            AND dim_type = #{dimType}
+        </if>
+        ORDER BY sort_order ASC, year ASC
+    </select>
+
+    <resultMap type="com.onemap.apply.domain.yzt.UrbanMonitorAreaVO" id="UrbanMonitorAreaResult">
+        <result property="code"    column="code"    />
+        <result property="data"    column="data"    />
+    </resultMap>
+
+    <!-- 
+        按年份、区域、类型分组查询城市监测数据
+        返回: year, code, type, total_area, count
+        Service层根据type拆分数据
+    -->
+    <select id="selectUrbanMonitorGrouped" resultType="map">
+        SELECT 
+            "year",
+            trim(code) as code,
+            type,
+            SUM(area) as total_area,
+            COUNT(*) as count
+        FROM "vector"."jc_urban"
+        GROUP BY "year", code, type
+        ORDER BY "year" ASC, code ASC
+    </select>
+</mapper>