|
@@ -2,12 +2,14 @@ package com.qizhen.healsphere.facade;
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.qizhen.healsphere.common.util.BeanUtil;
|
|
|
+import com.qizhen.healsphere.common.util.ProvinceConverter;
|
|
|
import com.qizhen.healsphere.repository.mapper.EpifluMapper;
|
|
|
import com.qizhen.healsphere.repository.mapper.EpifluQueryMapper;
|
|
|
import com.qizhen.healsphere.repository.mapper.entity.Isolate;
|
|
|
import com.qizhen.healsphere.service.impl.IsolateServiceImpl;
|
|
|
import com.qizhen.healsphere.web.dto.*;
|
|
|
import com.qizhen.healsphere.web.param.*;
|
|
|
+import com.qizhen.healsphere.web.vo.ChinaInputVO;
|
|
|
import com.qizhen.healsphere.web.vo.InputVO;
|
|
|
import org.apache.poi.util.StringUtil;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@@ -54,8 +56,8 @@ public class IsolateFacade extends IsolateServiceImpl {
|
|
|
.map(Epiflu::getSubtype)
|
|
|
.noneMatch(st -> Objects.equals(st, inputVO.getSubtype()));
|
|
|
|
|
|
- if(flag){
|
|
|
- return getIsolateDTOList(inputVO);
|
|
|
+ if (flag) {
|
|
|
+ return getIsolateDTOList(inputVO);
|
|
|
}
|
|
|
resultList.add(isolateDTO);
|
|
|
} else {
|
|
@@ -132,7 +134,7 @@ public class IsolateFacade extends IsolateServiceImpl {
|
|
|
isolateDTO.setSubtype(subtype);
|
|
|
isolateDTO.setCumulative(getCumulativeList(subtype));
|
|
|
isolateDTO.setAnalyse(analyse);
|
|
|
- isolateDTO.setGeoInfoList(getGeoInfoList(inputVO,subtype));
|
|
|
+ isolateDTO.setGeoInfoList(getGeoInfoList(inputVO, subtype));
|
|
|
resultList.add(isolateDTO);
|
|
|
}
|
|
|
return resultList;
|
|
@@ -162,7 +164,7 @@ public class IsolateFacade extends IsolateServiceImpl {
|
|
|
return cumulative;
|
|
|
}
|
|
|
|
|
|
- public List<GeoInfo> getGeoInfoList(InputVO inputVO,String input) {
|
|
|
+ public List<GeoInfo> getGeoInfoList(InputVO inputVO, String input) {
|
|
|
|
|
|
List<String> continentList = StringUtil.isBlank(inputVO.getContinent())
|
|
|
? Arrays.asList("Asia", "Europe", "Africa", "North America", "South America", "Oceania")
|
|
@@ -209,40 +211,213 @@ public class IsolateFacade extends IsolateServiceImpl {
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* 获取中国的病毒分布情况
|
|
|
*
|
|
|
- * @param inputVO
|
|
|
+ * @param chinaInputVO
|
|
|
* @return List<GraphInfo>
|
|
|
*/
|
|
|
- public List<IsolateDTO> getChinaIsolate(InputVO inputVO) {
|
|
|
- List<IsolateDTO> resultList = new ArrayList<>();
|
|
|
- if (StringUtil.isNotBlank(inputVO.getContinent())) {
|
|
|
- List<Epiflu> subtypeContinent = getSubtypeContinent(inputVO.getContinent());
|
|
|
- // 创建并填充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()));
|
|
|
+ public List<ChinaIsolateDTO> getChinaIsolate(ChinaInputVO chinaInputVO) {
|
|
|
+ List<ChinaIsolateDTO> resultList = new ArrayList<>();
|
|
|
+ List<ChinaEpifluDTO> chinaEpiflu = epifluMapper.findChinaEpiflu(chinaInputVO);
|
|
|
|
|
|
- if(flag){
|
|
|
- return getIsolateDTOList(inputVO);
|
|
|
+ if (chinaEpiflu == null) {
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (ChinaEpifluDTO chinaEpifluDTO : chinaEpiflu) {
|
|
|
+ ChinaIsolateDTO chinaIsolateDTO = new ChinaIsolateDTO();
|
|
|
+ BeanUtil.copyProperties(chinaEpifluDTO, chinaIsolateDTO);
|
|
|
+ chinaIsolateDTO.setEpifluentName("甲流");
|
|
|
+
|
|
|
+
|
|
|
+ // 定义日期格式
|
|
|
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
+ String subtype = chinaEpifluDTO.getSubtype();
|
|
|
+ QueryWrapper<Epiflu> wrapper = new QueryWrapper<>();
|
|
|
+ wrapper.eq("subtype", subtype).eq("is_china", 1)
|
|
|
+ .orderByAsc("subtype", "collection_date");
|
|
|
+ List<Epiflu> epiflus = epifluMapper.selectList(wrapper);
|
|
|
+
|
|
|
+ if (epiflus.isEmpty()) {
|
|
|
+ continue; // 跳过无数据的subtype
|
|
|
}
|
|
|
- resultList.add(isolateDTO);
|
|
|
- } else {
|
|
|
- return getIsolateDTOList(inputVO);
|
|
|
+
|
|
|
+ // 处理首个隔离信息
|
|
|
+ Epiflu firstEpiflu = epiflus.get(0);
|
|
|
+// String firstLocation = firstEpiflu.getChinaCity() != null ? firstEpiflu.getChinaCity() : "未知地区";
|
|
|
+ String firstLocation = ProvinceConverter.toChinese(firstEpiflu.getChinaCity());
|
|
|
+ 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 chinaCity = epiflus.get(i).getChinaCity();
|
|
|
+ String chinaCity = ProvinceConverter.toChinese(epiflus.get(i).getChinaCity());
|
|
|
+ if (chinaCity != null) {
|
|
|
+// String lastSegment = getLastSegment(location);
|
|
|
+ propagationLocations.add(chinaCity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String propagation = propagationLocations.isEmpty() ? "无" : String.join(",", propagationLocations);
|
|
|
+ // 构建分析文本
|
|
|
+ String analyse = String.format("%s首次爆发在%s的%s,之后在%s传播。",
|
|
|
+ subtype, formattedDate, firstLocation, propagation);
|
|
|
+
|
|
|
+ chinaIsolateDTO.setAnalyse(analyse); //插入说明
|
|
|
+
|
|
|
+ chinaIsolateDTO.setCumulativeMap(getChinaCumulativeList(chinaInputVO, chinaEpifluDTO));//获取各个时间段的数量
|
|
|
+
|
|
|
+ chinaIsolateDTO.setGeoInfoList(chinaGeoInfoList(chinaInputVO, chinaEpifluDTO));//获取中国省份坐标及相关进化分支参数
|
|
|
+
|
|
|
+ resultList.add(chinaIsolateDTO);
|
|
|
}
|
|
|
|
|
|
return resultList;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ public List<GeoInfo> chinaGeoInfoList(ChinaInputVO chinaInputVO, ChinaEpifluDTO chinaEpifluDTO) {
|
|
|
+ // 处理 clade 参数
|
|
|
+ String cladeStr = chinaEpifluDTO.getClade();
|
|
|
+ Set<String> cladeSet = Optional.ofNullable(cladeStr)
|
|
|
+ .filter(s -> !s.trim().isEmpty())
|
|
|
+ .map(s -> Arrays.stream(s.split(","))
|
|
|
+ .map(String::trim)
|
|
|
+ .filter(part -> !part.isEmpty())
|
|
|
+ .collect(Collectors.toSet()))
|
|
|
+ .orElse(Collections.emptySet());
|
|
|
+
|
|
|
+ // 构建查询条件
|
|
|
+ QueryWrapper<Epiflu> epifluWrapper = new QueryWrapper<Epiflu>()
|
|
|
+ .eq("is_china", 1)
|
|
|
+ .eq("subtype", chinaEpifluDTO.getSubtype());
|
|
|
+ if (!cladeSet.isEmpty()) {
|
|
|
+ epifluWrapper.in("clade", cladeSet);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询并提取结果
|
|
|
+ List<String> provinceList = epifluMapper.selectList(epifluWrapper).stream()
|
|
|
+ .map(Epiflu::getChinaCity)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ List<String> continentList = StringUtil.isBlank(chinaInputVO.getProvince())
|
|
|
+ ? provinceList
|
|
|
+ : Collections.singletonList(chinaInputVO.getProvince().trim());
|
|
|
+
|
|
|
+ List<GeoInfo> geoInfoList = new ArrayList<>();
|
|
|
+
|
|
|
+ for (String continent : continentList) {
|
|
|
+ GeoInfo geoInfo = new GeoInfo();
|
|
|
+
|
|
|
+ // 1. 获取clade统计数据
|
|
|
+ List<CladeCountResult> cladeCountResult = epifluMapper.selectCladeCountByProvince(continent, chinaEpifluDTO.getSubtype());
|
|
|
+
|
|
|
+ // 2. 转换数据格式
|
|
|
+ List<GeoDataItem> dataItems = cladeCountResult.stream()
|
|
|
+ .map(result -> new GeoDataItem(result.getClade(), result.getCount()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 3. 设置中心坐标(注意这里传入的是Double数组)
|
|
|
+ ChinaProvinceCoordinates ChinaCoordinates = ChinaProvinceCoordinates.fromName(continent.toUpperCase().replace(" ", "_"));
|
|
|
+ geoInfo.setContinentName(continent);
|
|
|
+ geoInfo.setCenter(new Double[]{
|
|
|
+ Double.parseDouble(ChinaCoordinates.getLongitude()),
|
|
|
+ Double.parseDouble(ChinaCoordinates.getLatitude())
|
|
|
+ });
|
|
|
+
|
|
|
+ // 4. 设置数据
|
|
|
+ geoInfo.setData(dataItems);
|
|
|
+
|
|
|
+ geoInfoList.add(geoInfo);
|
|
|
+ }
|
|
|
+ return geoInfoList;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public Map<String, CumulativeDTO> getChinaCumulativeList(ChinaInputVO chinaInputVO, ChinaEpifluDTO chinaEpifluDTO) {
|
|
|
+ String cladeStr = chinaEpifluDTO.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(chinaInputVO.getStartDate()) && StringUtil.isNotBlank(chinaInputVO.getEndDate())) {
|
|
|
+ chinaCollectionDateDTO.setMINCollectionDate(chinaInputVO.getStartDate());
|
|
|
+ chinaCollectionDateDTO.setMAXCollectionDate(chinaInputVO.getEndDate());
|
|
|
+ chinaCollectionDateDTO.setCount(chinaEpifluDTO.getCount());
|
|
|
+ } else {
|
|
|
+ String subtype = chinaEpifluDTO.getSubtype();
|
|
|
+ chinaCollectionDateDTO = epifluMapper.findChinaCollectionDate(subtype);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 定义起始和结束日期
|
|
|
+ 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();
|
|
|
+ chinaInputVO.setStartDate(localDate.toString());
|
|
|
+ chinaInputVO.setSubtype(chinaEpifluDTO.getSubtype());
|
|
|
+ chinaInputVO.setClade(cladeList);
|
|
|
+ Integer count = epifluMapper.selectCountByChinaInput(chinaInputVO);
|
|
|
+ double percentage = (chinaCollectionDateDTO.getCount() == 0) ? 0.0 : (count * 100.0) / chinaCollectionDateDTO.getCount();
|
|
|
+ cumulativeDTO.setCount(count);
|
|
|
+ cumulativeDTO.setPercentage(percentage);
|
|
|
+ cumulativeMap.put(localDate.toString(), cumulativeDTO);
|
|
|
+ }
|
|
|
+ return cumulativeMap;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
public static String getLastSegment(String input) {
|
|
|
Pattern pattern = Pattern.compile(".*/([^/]+)/?");
|
|
|
Matcher matcher = pattern.matcher(input);
|
|
|
return matcher.find() ? matcher.group(1) : "";
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成固定间隔的日期列表(包含起始和结束日期)
|
|
|
+ *
|
|
|
+ * @param start 起始日期
|
|
|
+ * @param end 结束日期
|
|
|
+ * @param days 间隔天数
|
|
|
+ * @return 日期列表
|
|
|
+ */
|
|
|
+ public static List<LocalDate> generateDateIntervals(LocalDate start, LocalDate end, int days) {
|
|
|
+ List<LocalDate> dates = new ArrayList<>();
|
|
|
+
|
|
|
+ // 添加起始日期
|
|
|
+ dates.add(start);
|
|
|
+
|
|
|
+ // 计算并添加后续日期
|
|
|
+ LocalDate current = start;
|
|
|
+ while (true) {
|
|
|
+ current = current.plusDays(days);
|
|
|
+ if (current.isAfter(end)) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ dates.add(current);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保结束日期被包含(如果未被添加)
|
|
|
+ if (!dates.get(dates.size() - 1).equals(end)) {
|
|
|
+ dates.add(end);
|
|
|
+ }
|
|
|
+
|
|
|
+ return dates;
|
|
|
+ }
|
|
|
}
|