Sfoglia il codice sorgente

feat(api): add /api/health/foods/by-family endpoint and health report trigger for food index

Xiaogang Liao 2 mesi fa
parent
commit
e6b9cfdb43

+ 95 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/HealthReportController.java

@@ -10,6 +10,8 @@ import com.etotem.cfc.dto.ParsedReportPayload;
 import com.etotem.cfc.dto.ParsedReportResult;
 import java.math.BigDecimal;
 import com.etotem.cfc.entity.Food;
+import com.etotem.cfc.entity.FamilyMember;
+import com.etotem.cfc.entity.FoodRecommendIndex;
 import com.etotem.cfc.entity.HealthDiseaseRisk;
 import com.etotem.cfc.entity.HealthGutFlora;
 import com.etotem.cfc.entity.HealthIndicator;
@@ -17,8 +19,10 @@ import com.etotem.cfc.entity.HealthReport;
 import com.etotem.cfc.entity.HealthReportDraft;
 import com.etotem.cfc.entity.NutritionDeficiencyRecord;
 import com.etotem.cfc.entity.NutritionIndicatorMapping;
+import com.etotem.cfc.mapper.FamilyMemberMapper;
 import com.etotem.cfc.service.FamilyMemberNutritionProfileService;
 import com.etotem.cfc.service.DimensionScoreService;
+import com.etotem.cfc.service.FoodRecommendService;
 import com.etotem.cfc.service.FoodService;
 import com.etotem.cfc.service.HealthAnalysisService;
 import com.etotem.cfc.service.HealthReportDraftService;
@@ -26,6 +30,7 @@ import com.etotem.cfc.service.HealthReportService;
 import com.etotem.cfc.service.NutritionDeficiencyService;
 import com.etotem.cfc.service.PdfParseService;
 import com.etotem.cfc.service.TongueDiagnosisService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -41,9 +46,11 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
 
 /**
@@ -85,6 +92,12 @@ public class HealthReportController {
     @Resource
     private TongueDiagnosisService tongueDiagnosisService;
 
+    @Resource
+    private FoodRecommendService foodRecommendService;
+
+    @Resource
+    private FamilyMemberMapper familyMemberMapper;
+
     /**
      * 创建健康报告(含指标明细)
      */
@@ -305,6 +318,12 @@ public class HealthReportController {
                 } catch (Exception e) {
                     log.warn("刷新7维健康评分失败: {}", e.getMessage());
                 }
+                try {
+                    foodRecommendService.recalculateForUser(matchedMemberId);
+                    log.info("已刷新成员{}的食材推荐指数", matchedMemberId);
+                } catch (Exception e) {
+                    log.warn("刷新食材推荐指数失败: {}", e.getMessage());
+                }
             }
 
             healthReportDraftService.markConfirmed(draft.getId(), created.getId());
@@ -460,6 +479,12 @@ public class HealthReportController {
                 } catch (Exception e) {
                     log.warn("刷新7维健康评分失败: {}", e.getMessage());
                 }
+                try {
+                    foodRecommendService.recalculateForUser(subjectId);
+                    log.info("已刷新成员{}的食材推荐指数", subjectId);
+                } catch (Exception e) {
+                    log.warn("刷新食材推荐指数失败: {}", e.getMessage());
+                }
             } else if (draft.getFamilyId() != null && payload.getSummary() != null
                     && payload.getSummary().getPersonName() != null) {
                 Long matchedId = healthReportService.matchFamilyMemberByName(
@@ -471,6 +496,12 @@ public class HealthReportController {
                     } catch (Exception e) {
                         log.warn("刷新7维健康评分失败: {}", e.getMessage());
                     }
+                    try {
+                        foodRecommendService.recalculateForUser(matchedId);
+                        log.info("已刷新成员{}的食材推荐指数", matchedId);
+                    } catch (Exception e) {
+                        log.warn("刷新食材推荐指数失败: {}", e.getMessage());
+                    }
                     subjectId = matchedId;
                 }
             }
@@ -743,6 +774,70 @@ public class HealthReportController {
         return Result.success("报告已归档");
     }
 
+    @Operation(summary = "获取家庭成员食材推荐(含完整营养数据)")
+    @PostMapping("/foods/by-family")
+    public Result<Map<String, Object>> getFoodsByFamily(@RequestBody Map<String, Object> params) {
+        Long familyId = params.get("familyId") instanceof Number
+                ? ((Number) params.get("familyId")).longValue()
+                : Long.parseLong(params.get("familyId").toString());
+
+        Map<Long, List<FoodRecommendIndex>> byMember = foodRecommendService.getByFamily(familyId);
+
+        Set<Long> foodIds = new HashSet<>();
+        Map<Long, String> memberNames = new LinkedHashMap<>();
+        for (Map.Entry<Long, List<FoodRecommendIndex>> entry : byMember.entrySet()) {
+            for (FoodRecommendIndex idx : entry.getValue()) {
+                foodIds.add(idx.getFoodId());
+            }
+        }
+
+        List<FamilyMember> members = familyMemberMapper.selectList(
+                new LambdaQueryWrapper<FamilyMember>().eq(FamilyMember::getFamilyId, familyId));
+        for (FamilyMember m : members) {
+            if (m.getUserId() != null) {
+                memberNames.put(m.getUserId(), m.getNickname() != null ? m.getNickname() : "");
+            }
+        }
+
+        List<Map<String, Object>> totalList = new ArrayList<>();
+        for (Long foodId : foodIds) {
+            Food food = foodService.getById(foodId);
+            if (food != null) {
+                Map<String, Object> item = new LinkedHashMap<>();
+                item.put("id", food.getId());
+                item.put("name", food.getName());
+                item.put("category", food.getCategory());
+                item.put("calories", food.getCalories());
+                item.put("protein", food.getProtein());
+                item.put("carbs", food.getCarbs());
+                item.put("fat", food.getFat());
+                item.put("fiber", food.getFiber());
+                item.put("energyKj", food.getEnergyKj());
+                item.put("starch", food.getStarch());
+                item.put("cholesterol", food.getCholesterol());
+                for (Map.Entry<Long, List<FoodRecommendIndex>> entry : byMember.entrySet()) {
+                    for (FoodRecommendIndex idx : entry.getValue()) {
+                        if (foodId.equals(idx.getFoodId())) {
+                            item.put("recommendIndex", idx.getIndexScore());
+                            break;
+                        }
+                    }
+                    if (item.containsKey("recommendIndex")) break;
+                }
+                if (!item.containsKey("recommendIndex")) {
+                    item.put("recommendIndex", null);
+                }
+                totalList.add(item);
+            }
+        }
+
+        Map<String, Object> result = new LinkedHashMap<>();
+        result.put("total", totalList);
+        result.put("byMember", byMember);
+        result.put("memberNames", memberNames);
+        return Result.success(result);
+    }
+
     private ParsedReportPayload.Payload convertToPayload(ParsedReportResult parsed) {
         ParsedReportPayload.Payload payload = new ParsedReportPayload.Payload();