# 食材推荐均衡化设计 ## 目标 改进饮食推荐首页的"今日菜篮"食材推荐,从单纯按菌属推荐分排序 → 综合考虑菌属推荐、营养均衡、烹饪便捷性、能量控制,选出 10-12 个食材。 ## 设计 ### 一、综合评分维度 每份食材计算 4 个维度的子分数(均归一化到 0-100),加权合成综合分: | 维度 | 权重 | 计算方式 | |------|:----:|----------| | 菌属推荐分 | 40% | 知识库方向(推荐/避免/中性)+ 推荐指数修正 | | 营养密度分 | 25% | 基于类别的维生素/矿物质基础分 + 宏量营养素质量分 | | 烹饪便捷分 | 20% | 类别映射(快手=90,中等=60,耗时=35)| | 能量效率分 | 15% | 营养密度/能量比值,能量低且营养高者分高 | **菌属推荐分**: - 方向为 recommend → 基础 85 分,叠加推荐指数归一化修正(±10) - 方向为 avoid → 基础 15 分 - 方向为 mixed/无 → 基础 50 分 **营养密度分**(基于类别启发式): - 蔬菜/水果 → 基础 85(维生素A/C/K丰富) - 水产品 → 基础 80(omega-3, VD, 碘, 硒) - 豆类及豆制品 → 基础 75(叶酸, 铁, 镁) - 蛋类 → 基础 70(胆碱, VD, B12) - 肉类 → 基础 65(铁, B12, 锌) - 乳制品 → 基础 60(钙, VD) - 主食 → 基础 45(碳水为主,微量营养素相对低) - 干果 → 基础 55(矿物质丰富但热量高) - 快餐 → 基础 20(加工食品,营养密度低) - 汤 → 基础 35 叠加宏量营养素质量修正(±15): - 高蛋白/高纤维 → 正向 - 高脂肪/高胆固醇 → 负向 **烹饪便捷分**: - 快手(蔬菜、蛋类、水果、汤)→ 90 分 - 中等(豆类、乳制品、干果、主食)→ 60 分 - 耗时(水产品、肉类)→ 35 分 **能量效率分**: - energy_efficiency = 营养密度分 / max(能量KJ/1000, 0.5) - 归一化到 0-100,能量低且营养高的食材分高 ### 二、组合优化策略(贪心算法) 1. 计算所有食材的综合分 2. 按类别分组 3. 优先选:有菌属推荐标记的食材(bonus +10 分) 4. 贪心填充:每次选当前未选且综合分最高的食材,但优先确保类别覆盖 5. 类别配额约束: - 蔬菜: 2-3 个 - 水果: 1-2 个 - 水产品: 1-2 个 - 肉类: 1-2 个 - 蛋类: 1 个 - 豆类: 1-2 个 - 主食: 1-2 个 - 其他类别: 0-1 个 6. 总目标: 10-12 个,覆盖 5-6 个类别 7. 换一批: 综合分加入种子扰动(±5分随机偏移),重新排序选择 ### 三、新增数据结构 **IngredientRecommendation** 新增字段: ```java private Integer caloriesPer100g; // 千卡/100g private Integer cookingLevel; // 1=快手, 2=中等, 3=耗时 private Integer nutritionScore; // 营养密度分 private Integer cookingScore; // 烹饪便捷分 private String balanceReason; // 推荐理由(如"高蛋白·快手") ``` ### 四、不涉及变更 - 前端 API 调用方式不变(仍调 `/api/diet/ingredients/suggest` 和 `/recommend`) - 前端 `refreshIngredients()` 方法不变,seed 机制保留 - 数据库表结构不变 - 现有 `foods` 表无 vitamin/mineral 字段,评分完全在内存中计算 ### 五、文件变更清单 | 文件 | 变更类型 | 说明 | |------|---------|------| | `dto/IngredientRecommendation.java` | 修改 | 新增 4 个字段 | | `service/BeijingNutritionService.java` | 修改 | `generateIngredientList()` 重构为均衡化选择 | | `service/DietIngredientService.java` | 修改 | `refreshIngredients()` 传递 seed 给新算法 |