|
@@ -25,12 +25,15 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
import javax.annotation.Resource;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.Collections;
|
|
import java.util.Collections;
|
|
|
import java.util.Comparator;
|
|
import java.util.Comparator;
|
|
|
import java.util.Date;
|
|
import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
|
|
+import java.util.HashSet;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
|
+import java.util.Set;
|
|
|
import com.etotem.cfc.util.SortUtil;
|
|
import com.etotem.cfc.util.SortUtil;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -362,6 +365,60 @@ public class HealthReportService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取身体维度异常指标(身体页面"指标告警"专供)
|
|
|
|
|
+ * 返回:疾病风险(非低风险) + 主要营养评估异常 + 氨基酸评估异常
|
|
|
|
|
+ * 正常指标不显示,减少信息噪音
|
|
|
|
|
+ */
|
|
|
|
|
+ public Map<String, Object> getBodyAbnormalIndicators(Long memberId) {
|
|
|
|
|
+ HealthReport latest = getLatestReport(memberId);
|
|
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
|
|
+ result.put("diseaseRisks", Collections.emptyList());
|
|
|
|
|
+ result.put("nutritionAbnormal", Collections.emptyList());
|
|
|
|
|
+ result.put("aminoAcidAbnormal", Collections.emptyList());
|
|
|
|
|
+ result.put("hasReport", latest != null);
|
|
|
|
|
+ if (latest == null) return result;
|
|
|
|
|
+
|
|
|
|
|
+ // 疾病风险:排除低风险
|
|
|
|
|
+ List<HealthDiseaseRisk> allRisks = getDiseaseRisksByReportId(latest.getId());
|
|
|
|
|
+ List<Map<String, Object>> abnormalRisks = new ArrayList<>();
|
|
|
|
|
+ for (HealthDiseaseRisk r : allRisks) {
|
|
|
|
|
+ if (r.getRiskLevel() != null && !"低风险".equals(r.getRiskLevel())) {
|
|
|
|
|
+ Map<String, Object> item = new HashMap<>();
|
|
|
|
|
+ item.put("name", r.getDiseaseName());
|
|
|
|
|
+ item.put("value", r.getRiskValue());
|
|
|
|
|
+ item.put("level", r.getRiskLevel());
|
|
|
|
|
+ abnormalRisks.add(item);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ result.put("diseaseRisks", abnormalRisks);
|
|
|
|
|
+
|
|
|
|
|
+ // 主要营养评估 + 氨基酸评估:只保留异常状态
|
|
|
|
|
+ List<HealthIndicator> allIndicators = getReportIndicators(latest.getId());
|
|
|
|
|
+ List<Map<String, Object>> nutritionAbnormal = new ArrayList<>();
|
|
|
|
|
+ List<Map<String, Object>> aminoAcidAbnormal = new ArrayList<>();
|
|
|
|
|
+ for (HealthIndicator ind : allIndicators) {
|
|
|
|
|
+ String category = ind.getCategory();
|
|
|
|
|
+ String status = ind.getStatus();
|
|
|
|
|
+ if (status == null || "正常".equals(status) || "normal".equalsIgnoreCase(status)
|
|
|
|
|
+ || "低风险".equals(status)) continue;
|
|
|
|
|
+ Map<String, Object> item = new HashMap<>();
|
|
|
|
|
+ item.put("name", ind.getIndicatorName());
|
|
|
|
|
+ item.put("value", ind.getIndicatorValue());
|
|
|
|
|
+ item.put("unit", ind.getUnit());
|
|
|
|
|
+ item.put("status", status);
|
|
|
|
|
+ item.put("refRange", ind.getRefRange());
|
|
|
|
|
+ if ("主要营养评估".equals(category)) {
|
|
|
|
|
+ nutritionAbnormal.add(item);
|
|
|
|
|
+ } else if ("氨基酸评估".equals(category)) {
|
|
|
|
|
+ aminoAcidAbnormal.add(item);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ result.put("nutritionAbnormal", nutritionAbnormal);
|
|
|
|
|
+ result.put("aminoAcidAbnormal", aminoAcidAbnormal);
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 获取报告完整详情(含指标明细 + 菌群数据 + 疾病风险评估)
|
|
* 获取报告完整详情(含指标明细 + 菌群数据 + 疾病风险评估)
|
|
|
*/
|
|
*/
|
|
@@ -790,6 +847,81 @@ public class HealthReportService {
|
|
|
return healthIndicatorMapper.selectList(indicatorWrapper);
|
|
return healthIndicatorMapper.selectList(indicatorWrapper);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 情绪相关指标关键词(知识库"神经递质及激素"分类中与情绪状态直接相关的指标)
|
|
|
|
|
+ * 体现"心生身"概念:情绪状态通过神经递质反映在身体上
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final Set<String> EMOTION_INDICATOR_KEYWORDS = new HashSet<>(Arrays.asList(
|
|
|
|
|
+ "血清素", "5-HT", "多巴胺", "GABA", "γ-氨基丁酸", "色氨酸", "褪黑素", "皮质醇"
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 认知相关指标关键词(与学习记忆、智力、注意力相关的肠脑轴指标)
|
|
|
|
|
+ * 含谷氨酸(学习记忆)、多巴胺(专注力,用户确认)、色氨酸(褪黑素前体→睡眠→记忆力)
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final Set<String> COGNITION_INDICATOR_KEYWORDS = new HashSet<>(Arrays.asList(
|
|
|
|
|
+ "谷氨酸", "Glutamate", "乙酰胆碱", "多巴胺", "色氨酸", "丁酸", "丙酸", "乙酸", "组胺", "短链脂肪酸"
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据关键词过滤指标列表
|
|
|
|
|
+ */
|
|
|
|
|
+ private List<HealthIndicator> filterIndicatorsByKeywords(List<HealthIndicator> indicators, Set<String> keywords) {
|
|
|
|
|
+ if (indicators == null || indicators.isEmpty()) return Collections.emptyList();
|
|
|
|
|
+ List<HealthIndicator> result = new ArrayList<>();
|
|
|
|
|
+ for (HealthIndicator ind : indicators) {
|
|
|
|
|
+ if (ind.getIndicatorName() == null) continue;
|
|
|
|
|
+ String name = ind.getIndicatorName();
|
|
|
|
|
+ for (String kw : keywords) {
|
|
|
|
|
+ if (name.contains(kw)) {
|
|
|
|
|
+ result.add(ind);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取与情绪状态相关的菌群报告指标(心页面"情绪与肠胃")
|
|
|
|
|
+ * 体现"心生身":从菌群报告提取与情绪调节直接相关的神经递质指标
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param childId the child's ID
|
|
|
|
|
+ * @return list of emotion-related HealthIndicator
|
|
|
|
|
+ */
|
|
|
|
|
+ public List<HealthIndicator> getEmotionIndicators(Long childId) {
|
|
|
|
|
+ List<HealthIndicator> all = getMindRelatedIndicators(childId);
|
|
|
|
|
+ return filterIndicatorsByKeywords(all, EMOTION_INDICATOR_KEYWORDS);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取与认知/智力相关的菌群报告指标(智页面"肠胃与认知")
|
|
|
|
|
+ * 体现"肠脑轴":肠道菌群代谢产物影响认知功能
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param childId the child's ID
|
|
|
|
|
+ * @return list of cognition-related HealthIndicator
|
|
|
|
|
+ */
|
|
|
|
|
+ public List<HealthIndicator> getCognitionIndicators(Long childId) {
|
|
|
|
|
+ // Get latest gut flora report for this child
|
|
|
|
|
+ LambdaQueryWrapper<HealthReport> reportWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ reportWrapper.eq(HealthReport::getUserId, childId);
|
|
|
|
|
+ reportWrapper.eq(HealthReport::getReportType, "gut_flora");
|
|
|
|
|
+ reportWrapper.orderByDesc(HealthReport::getCreatedAt);
|
|
|
|
|
+ reportWrapper.last("LIMIT 1");
|
|
|
|
|
+ SortUtil.applySort(reportWrapper);
|
|
|
|
|
+ HealthReport report = healthReportMapper.selectOne(reportWrapper);
|
|
|
|
|
+ if (report == null) {
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+ LambdaQueryWrapper<HealthIndicator> indicatorWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ indicatorWrapper.eq(HealthIndicator::getReportId, report.getId());
|
|
|
|
|
+ indicatorWrapper.in(HealthIndicator::getCategory, "神经递质与激素", "短链脂肪酸");
|
|
|
|
|
+ indicatorWrapper.orderByAsc(HealthIndicator::getSortOrder);
|
|
|
|
|
+ SortUtil.applySort(indicatorWrapper);
|
|
|
|
|
+ List<HealthIndicator> all = healthIndicatorMapper.selectList(indicatorWrapper);
|
|
|
|
|
+ return filterIndicatorsByKeywords(all, COGNITION_INDICATOR_KEYWORDS);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Get gut-emotion insight summary based on neurotransmitter and SCFA indicators.
|
|
* Get gut-emotion insight summary based on neurotransmitter and SCFA indicators.
|
|
|
*
|
|
*
|
|
@@ -797,7 +929,7 @@ public class HealthReportService {
|
|
|
* @return map with summary text and indicator highlights
|
|
* @return map with summary text and indicator highlights
|
|
|
*/
|
|
*/
|
|
|
public Map<String, Object> getGutEmotionInsight(Long childId) {
|
|
public Map<String, Object> getGutEmotionInsight(Long childId) {
|
|
|
- List<HealthIndicator> indicators = getMindRelatedIndicators(childId);
|
|
|
|
|
|
|
+ List<HealthIndicator> indicators = getEmotionIndicators(childId);
|
|
|
if (indicators.isEmpty()) {
|
|
if (indicators.isEmpty()) {
|
|
|
Map<String, Object> empty = new HashMap<>();
|
|
Map<String, Object> empty = new HashMap<>();
|
|
|
empty.put("summary", "暂无菌群报告数据");
|
|
empty.put("summary", "暂无菌群报告数据");
|