|
@@ -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;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|