Browse Source

国际病毒接口上传

wangsy 2 months ago
parent
commit
5e5fa30104

+ 90 - 96
src/main/java/com/qizhen/healsphere/facade/IsolateFacade.java

@@ -46,126 +46,119 @@ public class IsolateFacade extends IsolateServiceImpl {
      */
     public List<IsolateDTO> getIsolate(InputVO inputVO) {
         List<IsolateDTO> resultList = new ArrayList<>();
-        if (StringUtil.isNotBlank(inputVO.getContinent())) {
-            List<Epiflu> subtypeContinent = getSubtypeContinent(inputVO.getContinent());
+        List<EpifluDTO> subtypeContinent = epifluMapper.getSubtypeContinent(inputVO);
+
+        boolean flag = StringUtil.isBlank(inputVO.getSubtype())
+                || subtypeContinent.stream()
+                .map(EpifluDTO::getSubtype)
+                .noneMatch(st -> Objects.equals(st, inputVO.getSubtype()));
+
+        if (flag) {
+            for (EpifluDTO epifluDTO : subtypeContinent) {
+                resultList.add(getIsolateDTOList(inputVO, epifluDTO));
+            }
+        } else {
             // 创建并填充DTO
             IsolateDTO isolateDTO = new IsolateDTO();
             isolateDTO.setEpifluentName("甲流");
-            boolean flag = StringUtil.isBlank(inputVO.getSubtype())
-                    || subtypeContinent.stream()
-                    .map(Epiflu::getSubtype)
-                    .noneMatch(st -> Objects.equals(st, inputVO.getSubtype()));
-
-            if (flag) {
-                return getIsolateDTOList(inputVO);
-            }
             resultList.add(isolateDTO);
-        } else {
-            return getIsolateDTOList(inputVO);
         }
 
         return resultList;
     }
 
-    public List<IsolateDTO> getIsolateDTOList(InputVO inputVO) {
-        List<GraphInfo> graphInfoList = this.selectGraphInfo(inputVO);
-
-        // 收集所有唯一的subtype
-        List<String> subtypes = graphInfoList.stream()
-                .map(GraphInfo::getSubtype)
-                .filter(Objects::nonNull)
-                .distinct()
-                .collect(Collectors.toList());
-
-        if (subtypes.isEmpty()) {
-            return Collections.emptyList(); // 根据实际需求返回适当值
-        }
-
-        // 批量查询所有相关的Isolate记录,按subtype和日期排序
-        List<Isolate> allIsolates = getBaseMapper().selectList(
-                new QueryWrapper<Isolate>()
-                        .in("subtype", subtypes)
-                        .orderByAsc("subtype", "collection_date")
-        );
+    public IsolateDTO getIsolateDTOList(InputVO inputVO, EpifluDTO epifluDTO) {
 
-        // 按subtype分组,优化数据处理
-        Map<String, List<Isolate>> isolatesBySubtype = allIsolates.stream()
-                .collect(Collectors.groupingBy(Isolate::getSubtype));
+        IsolateDTO isolateDTO = new IsolateDTO();
 
-        List<IsolateDTO> resultList = new ArrayList<>();
         // 定义日期格式
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        String subtype = epifluDTO.getSubtype();
+        QueryWrapper<Epiflu> wrapper = new QueryWrapper<>();
+        wrapper.eq("subtype", subtype)
+                .orderByAsc("subtype", "collection_date");
+        List<Epiflu> epiflus = epifluMapper.selectList(wrapper);
 
-        for (GraphInfo graphInfo : graphInfoList) {
-            String subtype = graphInfo.getSubtype();
-            List<Isolate> isolateList = isolatesBySubtype.getOrDefault(subtype, Collections.emptyList());
-
-            if (isolateList.isEmpty()) {
-                continue; // 跳过无数据的subtype
+        if (epiflus.isEmpty()) {
+            return isolateDTO;
+        }
+        BeanUtil.copyProperties(epifluDTO, isolateDTO);
+        isolateDTO.setEpifluentName("甲流");
+        // 处理首个隔离信息
+        Epiflu firstEpiflu = epiflus.get(0);
+        String firstLocation = firstEpiflu.getLocation() != null ? firstEpiflu.getLocation() : "未知地区";
+        Date firstDate = firstEpiflu.getCollectionDate();
+        // 格式化日期(处理空值)
+        String formattedDate = (firstDate != null) ? dateFormat.format(firstDate) : "未知日期";
+
+        // 收集传播地点(排除首个)
+        Set<String> propagationLocations = new LinkedHashSet<>();
+        for (int i = 1; i < epiflus.size(); i++) {
+            String location = epiflus.get(i).getLocation();
+            if (location != null) {
+                String lastSegment = getLastSegment(location);
+                propagationLocations.add(lastSegment);
             }
+        }
 
-            // 处理首个隔离信息
-            Isolate firstIsolate = isolateList.get(0);
-            String firstLocation = firstIsolate.getLocation() != null ? firstIsolate.getLocation() : "未知地区";
-            Date firstDate = firstIsolate.getCollectionDate();
-            // 格式化日期(处理空值)
-            String formattedDate = (firstDate != null) ? dateFormat.format(firstDate) : "未知日期";
+        String propagation = propagationLocations.isEmpty() ? "无" : String.join(",", propagationLocations);
+        // 构建分析文本
+        String analyse = String.format("%s首次爆发在%s的%s,之后在%s传播。",
+                subtype, formattedDate, firstLocation, propagation);
 
-            // 收集传播地点(排除首个)
-            Set<String> propagationLocations = new LinkedHashSet<>();
-            for (int i = 1; i < isolateList.size(); i++) {
-                String location = isolateList.get(i).getLocation();
-                if (location != null) {
-                    String lastSegment = getLastSegment(location);
-                    propagationLocations.add(lastSegment);
-                }
-            }
+        // 创建并填充DTO
+        isolateDTO.setEpifluentName("甲流");
+        isolateDTO.setCumulativeMap(getCumulativeList(inputVO, epifluDTO));
+        isolateDTO.setAnalyse(analyse);
+        isolateDTO.setGeoInfoList(getGeoInfoList(inputVO, epifluDTO));
 
-            String propagation = propagationLocations.isEmpty() ? "无" : String.join(",", propagationLocations);
+        return isolateDTO;
 
-            // 构建分析文本
-            String analyse = String.format("%s首次爆发日期:%s在%s爆发,之后在%s传播。",
-                    subtype, formattedDate, firstLocation, propagation);
+    }
 
-            // 创建并填充DTO
-            IsolateDTO isolateDTO = new IsolateDTO();
-            BeanUtil.copyProperties(graphInfo, isolateDTO);
-            isolateDTO.setEpifluentName("甲流");
-            isolateDTO.setSubtype(subtype);
-            isolateDTO.setCumulative(getCumulativeList(subtype));
-            isolateDTO.setAnalyse(analyse);
-            isolateDTO.setGeoInfoList(getGeoInfoList(inputVO, subtype));
-            resultList.add(isolateDTO);
+    public Map<String, CumulativeDTO> getCumulativeList(InputVO inputVO, EpifluDTO epifluDTO) {
+        String cladeStr = epifluDTO.getClade();
+        List<String> cladeList = Optional.ofNullable(cladeStr)
+                .filter(s -> !s.trim().isEmpty())
+                .map(s -> Arrays.stream(s.split(","))
+                        .map(String::trim)          // 去除前后空格
+                        .filter(part -> !part.isEmpty()) // 过滤空字符串
+                        .collect(Collectors.toList())    // 改为收集为 List
+                )
+                .orElse(Collections.emptyList());        // 默认返回空 List
+        Map<String, CumulativeDTO> cumulativeMap = new HashMap<>();
+
+        ChinaCollectionDateDTO chinaCollectionDateDTO = new ChinaCollectionDateDTO();
+        if (StringUtil.isNotBlank(inputVO.getStartDate()) && StringUtil.isNotBlank(inputVO.getEndDate())) {
+            chinaCollectionDateDTO.setMINCollectionDate(inputVO.getStartDate());
+            chinaCollectionDateDTO.setMAXCollectionDate(inputVO.getEndDate());
+            chinaCollectionDateDTO.setCount(epifluDTO.getCount());
+        } else {
+            String subtype = epifluDTO.getSubtype();
+            chinaCollectionDateDTO = epifluMapper.findCollectionDate(subtype);
         }
-        return resultList;
-    }
 
-    public Map<String, Integer> getCumulativeList(String subtype) {
-        Date maxCollectionDate = epifluMapper.findMaxCollectionDateBySubtype(subtype);
-        // 更安全的日期转换方式
-        LocalDate startDate = maxCollectionDate.toInstant()
-                .atZone(ZoneId.of("UTC"))  // 明确指定时区为UTC
-                .toLocalDate()
-                .withDayOfYear(1);
-        LocalDate endDate = startDate.plusMonths(12).minusDays(1);
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-
-        Map<String, Integer> cumulative = new TreeMap<>(); // 使用 TreeMap 保持键的有序性
-        for (int i = 0; i < 12; i++) {
-            LocalDate monthStartDate = startDate.plusMonths(i);
-            LocalDate monthEndDate = monthStartDate.plusMonths(1).minusDays(1);
-            String monthKey = monthStartDate.format(formatter);
-            //如果要把逻辑改成每个月占比,把下面的 startDate改成monthStartDate
-            int countInMonth = epifluMapper.selectCountBySubtypeAndDateRange(subtype, startDate, monthEndDate);
-            int countInYear = epifluMapper.selectCountBySubtypeAndDateRange(subtype, startDate, endDate);
-            int percentage = (int) countInMonth / countInYear * 100;
-            cumulative.put(monthKey, (int) (Math.ceil(percentage * 10.0) / 10.0));
+        // 定义起始和结束日期
+        LocalDate startDate = LocalDate.parse(chinaCollectionDateDTO.getMINCollectionDate());
+        LocalDate endDate = LocalDate.parse(chinaCollectionDateDTO.getMAXCollectionDate());
+        // 生成日期列表
+        List<LocalDate> dateList = generateDateIntervals(startDate, endDate, 30);
+
+        for (LocalDate localDate : dateList) {
+            CumulativeDTO cumulativeDTO = new CumulativeDTO();
+            inputVO.setStartDate(localDate.toString());
+            inputVO.setSubtype(epifluDTO.getSubtype());
+            inputVO.setClade(cladeList);
+            Integer count = epifluMapper.selectCountByInput(inputVO);
+            double percentage = (chinaCollectionDateDTO.getCount() == 0) ? 0.0 : (count * 100.0) / chinaCollectionDateDTO.getCount();
+            cumulativeDTO.setCount(count);
+            cumulativeDTO.setPercentage(percentage);
+            cumulativeMap.put(localDate.toString(), cumulativeDTO);
         }
-        return cumulative;
+        return cumulativeMap;
     }
 
-    public List<GeoInfo> getGeoInfoList(InputVO inputVO, String input) {
-
+    public List<GeoInfo> getGeoInfoList(InputVO inputVO, EpifluDTO epifluDTO) {
         List<String> continentList = StringUtil.isBlank(inputVO.getContinent())
                 ? Arrays.asList("Asia", "Europe", "Africa", "North America", "South America", "Oceania")
                 : Collections.singletonList(inputVO.getContinent().trim());
@@ -176,7 +169,7 @@ public class IsolateFacade extends IsolateServiceImpl {
             GeoInfo geoInfo = new GeoInfo();
 
             // 1. 获取clade统计数据
-            List<CladeCountResult> cladeCountResult = epifluMapper.selectCladeCountByContinent(continent, input);
+            List<CladeCountResult> cladeCountResult = epifluMapper.selectCladeCountByProvince(continent, epifluDTO.getSubtype());
 
             // 2. 转换数据格式
             List<GeoDataItem> dataItems = cladeCountResult.stream()
@@ -197,6 +190,7 @@ public class IsolateFacade extends IsolateServiceImpl {
             geoInfoList.add(geoInfo);
         }
         return geoInfoList;
+
     }
 
 

+ 70 - 38
src/main/java/com/qizhen/healsphere/repository/mapper/EpifluMapper.java

@@ -1,13 +1,11 @@
 package com.qizhen.healsphere.repository.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.qizhen.healsphere.web.dto.ChinaCollectionDateDTO;
-import com.qizhen.healsphere.web.dto.ChinaEpifluDTO;
-import com.qizhen.healsphere.web.dto.ChinaIsolateDTO;
-import com.qizhen.healsphere.web.dto.IsolateDTO;
+import com.qizhen.healsphere.web.dto.*;
 import com.qizhen.healsphere.web.param.CladeCountResult;
 import com.qizhen.healsphere.web.param.Epiflu;
 import com.qizhen.healsphere.web.vo.ChinaInputVO;
+import com.qizhen.healsphere.web.vo.InputVO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -78,38 +76,36 @@ public interface EpifluMapper extends BaseMapper<Epiflu> {
     Integer selectCount(@Param("subtype") String subtype, @Param("is_china") Integer is_china, @Param("startDate") LocalDate startDate);
 
 
-//    @Select("<script>" +
-//            "SELECT " +
-//            "subtype, " +
-//            "china_city, " +
-//            "STRING_AGG(DISTINCT clade::text, ',') AS clade, " +
-//            "COUNT(1) AS count " +
-//            "FROM epiflu " +
-//            "<where> " +
-//            "1=1 " +
-//            "AND is_china = 1 " +
-//            "<if test=\"chinaInputVO.chinaCity != null and chinaInputVO.chinaCity != ''\"> " +
-//            "AND china_city = #{chinaInputVO.chinaCity} " +
-//            "</if> " +
-//            "<if test=\"chinaInputVO.clade != null and chinaInputVO.hasValidClade()\"> " +
-//            "AND clade in " +
-//            "<foreach collection=\"chinaInputVO.clade\" item=\"item\" open=\"(\" close=\")\" separator=\",\"> " +
-//            "#{item}" +
-//            "</foreach>" +
-//            "</if> " +
-//            "<if test=\"chinaInputVO.subtype != null and chinaInputVO.subtype != ''\"> " +
-//            "AND subtype = #{chinaInputVO.subtype} " +
-//            "</if> " +
-//            "<if test=\"chinaInputVO.startDate != null and chinaInputVO.startDate != ''\"> " +
-//            "AND collection_date >= #{chinaInputVO.startDate}::date " +
-//            "</if> " +
-//            "<if test=\"chinaInputVO.endDate != null and chinaInputVO.startDate != ''\"> " +
-//            "AND collection_date &lt;= #{chinaInputVO.endDate}::date " +
-//            "</if> " +
-//            "</where> " +
-//            "GROUP BY subtype, china_city;" +
-//            "</script>")
-//    List<ChinaIsolateDTO> findChinaIsolate(@Param("chinaInputVO") ChinaInputVO chinaInputVO);
+@Select("<script>" +
+            "SELECT " +
+            "subtype, " +
+            "STRING_AGG(DISTINCT clade::text, ',') AS clade, " +
+            "COUNT(1) AS count " +
+            "FROM epiflu " +
+            "<where> " +
+            "1=1 " +
+            "<if test=\"inputVO.continent != null and inputVO.continent != ''\"> " +
+            "AND continent_location = #{inputVO.continent} " +
+            "</if> " +
+            "<if test=\"inputVO.clade != null and inputVO.hasValidClade()\"> " +
+            "AND clade in " +
+            "<foreach collection=\"inputVO.clade\" item=\"item\" open=\"(\" close=\")\" separator=\",\"> " +
+            "#{item}" +
+            "</foreach>" +
+            "</if> " +
+            "<if test=\"inputVO.subtype != null and inputVO.subtype != ''\"> " +
+            "AND subtype = #{inputVO.subtype} " +
+            "</if> " +
+            "<if test=\"inputVO.startDate != null and inputVO.startDate != ''\"> " +
+            "AND collection_date >= #{inputVO.startDate}::date " +
+            "</if> " +
+            "<if test=\"inputVO.endDate != null and inputVO.startDate != ''\"> " +
+            "AND collection_date &lt;= #{inputVO.endDate}::date " +
+            "</if> " +
+            "</where> " +
+            "GROUP BY subtype;" +
+            "</script>")
+    List<EpifluDTO> getSubtypeContinent(@Param("inputVO") InputVO inputVO);
 
     @Select("<script>" +
             "SELECT " +
@@ -135,7 +131,7 @@ public interface EpifluMapper extends BaseMapper<Epiflu> {
             "<if test=\"chinaInputVO.startDate != null and chinaInputVO.startDate != ''\"> " +
             "AND collection_date >= #{chinaInputVO.startDate}::date " +
             "</if> " +
-            "<if test=\"chinaInputVO.endDate != null and chinaInputVO.startDate != ''\"> " +
+            "<if test=\"chinaInputVO.endDate != null and chinaInputVO.endDate != ''\"> " +
             "AND collection_date &lt;= #{chinaInputVO.endDate}::date " +
             "</if> " +
             "</where> " +
@@ -151,7 +147,7 @@ public interface EpifluMapper extends BaseMapper<Epiflu> {
      */
     @Select("SELECT clade, COUNT(*) AS count " +
             "FROM public.epiflu " +
-            "WHERE china_city = #{continent} " +
+            "WHERE continent_location = #{continent} " +
             "AND subtype = #{subtype} " +
             "GROUP BY clade " +
             "ORDER BY count DESC")
@@ -183,8 +179,44 @@ public interface EpifluMapper extends BaseMapper<Epiflu> {
             "<if test=\"chinaInputVO.startDate != null and chinaInputVO.startDate != ''\"> " +
             "AND collection_date >= #{chinaInputVO.startDate}::date " +
             "</if> " +
+            "<if test=\"chinaInputVO.endDate != null and chinaInputVO.endDate != ''\"> " +
+            "AND collection_date &lt;= #{chinaInputVO.endDate}::date " +
+            "</if> " +
             "</where>;"+
             "</script>")
     Integer selectCountByChinaInput(@Param("chinaInputVO") ChinaInputVO chinaInputVO);
 
+
+    @Select("SELECT COUNT(1), MAX(collection_date) AS MAXCollectionDate,MIN(collection_date) AS MINCollectionDate " +
+            "FROM epiflu WHERE subtype = #{subtype}")
+    ChinaCollectionDateDTO findCollectionDate(@Param("subtype") String subtype);
+
+    @Select("<script>" +
+            "SELECT " +
+            "COUNT(1) AS count " +
+            "FROM epiflu " +
+            "<where> " +
+            "AND 1 = 1 " +
+            "<if test=\"iputVO.continent != null and iputVO.continent != ''\"> " +
+            "AND continent_location = #{iputVO.continent} " +
+            "</if> " +
+            "<if test=\"iputVO.clade != null and iputVO.hasValidClade()\"> " +
+            "AND clade in " +
+            "<foreach collection=\"iputVO.clade\" item=\"item\" open=\"(\" close=\")\" separator=\",\"> " +
+            "#{item}" +
+            "</foreach>" +
+            "</if> " +
+            "<if test=\"iputVO.subtype != null and iputVO.subtype != ''\"> " +
+            "AND subtype = #{iputVO.subtype} " +
+            "</if> " +
+            "<if test=\"iputVO.startDate != null and iputVO.startDate != ''\"> " +
+            "AND collection_date >= #{iputVO.startDate}::date " +
+            "</if> " +
+            "<if test=\"iputVO.endDate != null and iputVO.endDate != ''\"> " +
+            "AND collection_date &lt;= #{iputVO.endDate}::date " +
+            "</if> " +
+            "</where>;"+
+            "</script>")
+    Integer selectCountByInput(@Param("iputVO") InputVO iputVO);
+
 }

+ 26 - 26
src/main/java/com/qizhen/healsphere/service/impl/ZYApiServiceImpl.java

@@ -254,32 +254,32 @@ public Map<String, Object> getInEachContinentMap(String subtype) {
         graphInfo.setCount(epifluQueryMapper.getCountByQuery(inputVO));
 
         // 获取 startDate 和 endDate
-        Date startDate = inputVO.getStartDate();
-        Date endDate = inputVO.getEndDate();
-
-        if (startDate != null && endDate != null) {
-            LocalDate startLocalDate = startDate.toInstant()
-                    .atZone(ZoneId.systemDefault())
-                    .toLocalDate();
-            LocalDate endLocalDate = endDate.toInstant()
-                    .atZone(ZoneId.systemDefault())
-                    .toLocalDate();
-            Map<String, Integer> dailyCounts = new TreeMap<>();
-            // 遍历 startDate 到 endDate 的每一天
-            for (LocalDate date = startLocalDate; !date.isAfter(endLocalDate); date = date.plusDays(1)) {
-                // 遍历 constellation 列表
-                int totalCount = 0;
-//                for (String constellation : inputVO.getConstellation()) {
-//                    Integer count = epifluMapper.selectDayCount(inputVO.getSubtype(), constellation, date);
-//                    if (count != null) {
-//                        totalCount += count;
-//                    }
-//                }
-                dailyCounts.put(date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), totalCount);
-            }
-            // 设置累积数据
-            graphInfo.setCumulative(dailyCounts);
-        }
+//        Date startDate = inputVO.getStartDate();
+//        Date endDate = inputVO.getEndDate();
+//
+//        if (startDate != null && endDate != null) {
+//            LocalDate startLocalDate = startDate.toInstant()
+//                    .atZone(ZoneId.systemDefault())
+//                    .toLocalDate();
+//            LocalDate endLocalDate = endDate.toInstant()
+//                    .atZone(ZoneId.systemDefault())
+//                    .toLocalDate();
+//            Map<String, Integer> dailyCounts = new TreeMap<>();
+//            // 遍历 startDate 到 endDate 的每一天
+//            for (LocalDate date = startLocalDate; !date.isAfter(endLocalDate); date = date.plusDays(1)) {
+//                // 遍历 constellation 列表
+//                int totalCount = 0;
+////                for (String constellation : inputVO.getConstellation()) {
+////                    Integer count = epifluMapper.selectDayCount(inputVO.getSubtype(), constellation, date);
+////                    if (count != null) {
+////                        totalCount += count;
+////                    }
+////                }
+//                dailyCounts.put(date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), totalCount);
+//            }
+//            // 设置累积数据
+//            graphInfo.setCumulative(dailyCounts);
+//        }
         //TODO 总结分析
 
         // 设置地理信息

+ 17 - 0
src/main/java/com/qizhen/healsphere/web/dto/EpifluDTO.java

@@ -0,0 +1,17 @@
+package com.qizhen.healsphere.web.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Description:
+ * @author: dsYun
+ * @time: 2025/4/24 11:02
+ */
+@Getter
+@Setter
+public class EpifluDTO {
+    private String clade;
+    private String subtype;
+    private int count;
+}

+ 2 - 1
src/main/java/com/qizhen/healsphere/web/dto/IsolateDTO.java

@@ -19,7 +19,8 @@ public class IsolateDTO {
     private String clade;
     private String subtype;
     private int count;
-    private Map<String, Integer> cumulative;
+    private Map<String, CumulativeDTO> cumulativeMap;
+//    private Map<String, Integer> cumulative;
     //private Map<String, Object> inEachContinent;
     private String analyse;
     private List<GeoInfo> geoInfoList;

+ 1 - 0
src/main/java/com/qizhen/healsphere/web/param/Epiflu.java

@@ -11,5 +11,6 @@ public class Epiflu {
     private String clade;
     private String isolateId;
     private String isChina;
+    private String continentLocation;
     private String chinaCity;
 }

+ 14 - 2
src/main/java/com/qizhen/healsphere/web/vo/InputVO.java

@@ -11,7 +11,19 @@ public class InputVO {
     private List<String> clade; // clade
     private String subtype;
     private Integer isChina = 0; // 0: 全球 1: 中国
-    private Date startDate;
-    private Date endDate;
+    private String startDate;
+    private String endDate;
     private String continent; //大洲
+
+    public boolean hasValidClade() {
+        if (clade == null || clade.isEmpty()) {
+            return false;
+        }
+        for (String item : clade) {
+            if (item != null && !item.trim().isEmpty()) {
+                return true; // 存在有效元素
+            }
+        }
+        return false; // 所有元素为空或空字符串
+    }
 }