Procházet zdrojové kódy

营养宣教 营养诊断

HuRongxin před 2 měsíci
rodič
revize
33e603bcad
18 změnil soubory, kde provedl 2479 přidání a 0 odebrání
  1. 115 0
      ruoyi-admin/src/main/java/org/dromara/web/controller/NutritionEducationController.java
  2. 117 0
      ruoyi-admin/src/main/java/org/dromara/web/controller/NutritionSettingController.java
  3. 80 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/NutritionEducation.java
  4. 310 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/NutritionSetting.java
  5. 78 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/bo/NutritionEducationBo.java
  6. 313 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/bo/NutritionSettingBo.java
  7. 51 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/bo/RecalculateBo.java
  8. 93 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/vo/NutritionEducationVo.java
  9. 366 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/vo/NutritionSettingVo.java
  10. 18 0
      ruoyi-admin/src/main/java/org/dromara/web/mapper/NutritionEducationMapper.java
  11. 18 0
      ruoyi-admin/src/main/java/org/dromara/web/mapper/NutritionSettingMapper.java
  12. 73 0
      ruoyi-admin/src/main/java/org/dromara/web/service/INutritionEducationService.java
  13. 74 0
      ruoyi-admin/src/main/java/org/dromara/web/service/INutritionSettingService.java
  14. 213 0
      ruoyi-admin/src/main/java/org/dromara/web/service/NutritionDataUtil.java
  15. 247 0
      ruoyi-admin/src/main/java/org/dromara/web/service/impl/NutritionEducationServiceImpl.java
  16. 299 0
      ruoyi-admin/src/main/java/org/dromara/web/service/impl/NutritionSettingServiceImpl.java
  17. 7 0
      ruoyi-admin/src/main/resources/mapper/parameter/NutritionEducationMapper.xml
  18. 7 0
      ruoyi-admin/src/main/resources/mapper/parameter/NutritionSettingMapper.xml

+ 115 - 0
ruoyi-admin/src/main/java/org/dromara/web/controller/NutritionEducationController.java

@@ -0,0 +1,115 @@
+package org.dromara.web.controller;
+
+import java.util.List;
+import java.util.Map;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.web.domain.bo.NutritionEducationBo;
+import org.dromara.web.domain.vo.NutritionEducationVo;
+import org.dromara.web.service.INutritionEducationService;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 营养宣教
+ *
+ * @author Lion Li
+ * @date 2025-07-18
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/patients/nutritionEducation")
+public class NutritionEducationController extends BaseController {
+
+    private final INutritionEducationService nutritionEducationService;
+
+    /**
+     * 查询营养宣教列表
+     */
+    @SaCheckPermission("patients:nutritionEducation:list")
+    @GetMapping("/list")
+    public TableDataInfo<NutritionEducationVo> list(NutritionEducationBo bo, PageQuery pageQuery) {
+        return nutritionEducationService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出营养宣教列表
+     */
+    @SaCheckPermission("patients:nutritionEducation:export")
+    @Log(title = "营养宣教", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(NutritionEducationBo bo, HttpServletResponse response) {
+        List<NutritionEducationVo> list = nutritionEducationService.queryList(bo);
+        ExcelUtil.exportExcel(list, "营养宣教", NutritionEducationVo.class, response);
+    }
+
+    /**
+     * 查询模板列表
+     */
+    @GetMapping("/queryTemplateList")
+    public Map<String, Object> queryTemplateList() {
+        return nutritionEducationService.queryTemplateList();
+    }
+
+    /**
+     * 获取营养宣教详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("patients:nutritionEducation:query")
+    @GetMapping("/{id}")
+    public R<NutritionEducationVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable Long id) {
+        return R.ok(nutritionEducationService.queryById(id));
+    }
+
+    /**
+     * 新增营养宣教
+     */
+    @SaCheckPermission("patients:nutritionEducation:add")
+    @Log(title = "营养宣教", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody NutritionEducationBo bo) {
+        return toAjax(nutritionEducationService.insertByBo(bo));
+    }
+
+    /**
+     * 修改营养宣教
+     */
+    @SaCheckPermission("patients:nutritionEducation:edit")
+    @Log(title = "营养宣教", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody NutritionEducationBo bo) {
+        return toAjax(nutritionEducationService.updateByBo(bo));
+    }
+
+    /**
+     * 删除营养宣教
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("patients:nutritionEducation:remove")
+    @Log(title = "营养宣教", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable Long[] ids) {
+        return toAjax(nutritionEducationService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 117 - 0
ruoyi-admin/src/main/java/org/dromara/web/controller/NutritionSettingController.java

@@ -0,0 +1,117 @@
+package org.dromara.web.controller;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.web.domain.bo.NutritionSettingBo;
+import org.dromara.web.domain.bo.RecalculateBo;
+import org.dromara.web.domain.vo.NutritionSettingVo;
+import org.dromara.web.service.INutritionSettingService;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 营养设定
+ *
+ * @author Lion Li
+ * @date 2025-07-21
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/patients/nutritionSetting")
+public class NutritionSettingController extends BaseController {
+
+    private final INutritionSettingService nutritionSettingService;
+
+    /**
+     * 查询营养设定列表
+     */
+    @SaCheckPermission("patients:nutritionSetting:list")
+    @GetMapping("/list")
+    public TableDataInfo<NutritionSettingVo> list(NutritionSettingBo bo, PageQuery pageQuery) {
+        return nutritionSettingService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出营养设定列表
+     */
+    @SaCheckPermission("patients:nutritionSetting:export")
+    @Log(title = "营养设定", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(NutritionSettingBo bo, HttpServletResponse response) {
+        List<NutritionSettingVo> list = nutritionSettingService.queryList(bo);
+        ExcelUtil.exportExcel(list, "营养设定", NutritionSettingVo.class, response);
+    }
+
+    /**
+     * 获取营养设定详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("patients:nutritionSetting:query")
+    @GetMapping("/{id}")
+    public R<NutritionSettingVo> getInfo(@NotNull(message = "主键不能为空")
+                                         @PathVariable Long id) {
+        return R.ok(nutritionSettingService.queryById(id));
+    }
+
+    /**
+     * 新增营养设定
+     */
+    @SaCheckPermission("patients:nutritionSetting:add")
+    @Log(title = "营养设定", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody NutritionSettingBo bo) {
+        return toAjax(nutritionSettingService.insertByBo(bo));
+    }
+
+    /**
+     * 修改营养设定
+     */
+    @SaCheckPermission("patients:nutritionSetting:edit")
+    @Log(title = "营养设定", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody NutritionSettingBo bo) {
+        return toAjax(nutritionSettingService.updateByBo(bo));
+    }
+
+    /**
+     * 删除营养设定
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("patients:nutritionSetting:remove")
+    @Log(title = "营养设定", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable Long[] ids) {
+        return toAjax(nutritionSettingService.deleteWithValidByIds(List.of(ids), true));
+    }
+
+    /**
+     * 计算
+     */
+    @PostMapping("/recalculate")
+    public Map<String, String> recalculate(@Validated(EditGroup.class) @RequestBody RecalculateBo bo) {
+        Integer age = Integer.valueOf(bo.getAge().substring(0,2));
+        return nutritionSettingService.calculateEnergyRequirements(bo.getGender(), age, bo.getHeight().doubleValue(), bo.getWeight().doubleValue(), bo.getActivity(), bo.getStressType());
+    }
+}

+ 80 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/NutritionEducation.java

@@ -0,0 +1,80 @@
+package org.dromara.web.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.util.Date;
+
+/**
+ * 营养宣教对象 nutrition_education
+ *
+ * @author Lion Li
+ * @date 2025-07-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("nutrition_education")
+public class NutritionEducation extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 患者id
+     */
+    private Long patientId;
+
+    /**
+     * 营养宣教标题
+     */
+    private String educationTitle;
+
+    /**
+     * 营养宣教模板id
+     */
+    private Long educationTemplateId;
+
+    /**
+     * 描述
+     */
+    private String description;
+
+    /**
+     * 正文
+     */
+    private String content;
+
+    /**
+     * 看诊类型
+     */
+    private String type;
+
+    /**
+     * 科室
+     */
+    private Long deptId;
+
+    /**
+     * 门诊号
+     */
+    private String outpatientNo;
+
+    /**
+     * 删除标志(0代表存在 1代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+
+
+
+}

+ 310 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/NutritionSetting.java

@@ -0,0 +1,310 @@
+package org.dromara.web.domain;
+
+import com.google.type.Decimal;
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.math.BigDecimal;
+
+/**
+ * 营养设定对象 nutrition_setting
+ *
+ * @author Lion Li
+ * @date 2025-07-21
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("nutrition_setting")
+public class NutritionSetting extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 所需热量
+     */
+    private BigDecimal caloriesKcalPerDay;
+
+    /**
+     * 所需热量
+     */
+    private BigDecimal caloriesKcalPerKgDay;
+
+    /**
+     * 所需热量
+     */
+    private BigDecimal caloriesKjPerDay;
+
+    /**
+     * 蛋白质热量占比
+     */
+    private BigDecimal proteinCaloriePercentage;
+
+    /**
+     * 脂肪热量占比
+     */
+    private BigDecimal fatCaloriePercentage;
+
+    /**
+     * 碳水化合物热量占比
+     */
+    private BigDecimal carbohydrateCaloriePercentage;
+
+    /**
+     * 所需蛋白质
+     */
+    private BigDecimal proteinGPerKgDay;
+
+    /**
+     * 所需蛋白质
+     */
+    private BigDecimal proteinGPerDay;
+
+    /**
+     * 所需脂肪
+     */
+    private BigDecimal fatGPerKgDay;
+
+    /**
+     * 所需脂肪
+     */
+    private BigDecimal fatGPerDay;
+
+    /**
+     * 所需碳水化合物
+     */
+    private BigDecimal carbohydrateGPerKgDay;
+
+    /**
+     * 所需碳水化合物
+     */
+    private BigDecimal carbohydrateGPerDay;
+
+    /**
+     * 钙
+     */
+    private BigDecimal calcium;
+
+    /**
+     * 钾
+     */
+    private BigDecimal potassium;
+
+    /**
+     * 钠
+     */
+    private BigDecimal sodium;
+
+    /**
+     * 镁
+     */
+    private BigDecimal magnesium;
+
+    /**
+     * 磷
+     */
+    private BigDecimal phosphorus;
+
+    /**
+     * 氯
+     */
+    private BigDecimal chloride;
+
+    /**
+     * 铁
+     */
+    private BigDecimal iron;
+
+    /**
+     * 硒
+     */
+    private BigDecimal selenium;
+
+    /**
+     * 锰
+     */
+    private BigDecimal manganese;
+
+    /**
+     * 氟
+     */
+    private BigDecimal fluoride;
+
+    /**
+     * 钼
+     */
+    private BigDecimal molybdenum;
+
+    /**
+     * 锌
+     */
+    private BigDecimal zinc;
+
+    /**
+     * 铜
+     */
+    private BigDecimal copper;
+
+    /**
+     * 碘
+     */
+    private BigDecimal iodine;
+
+    /**
+     * 铬
+     */
+    private BigDecimal chromium;
+
+    /**
+     * 维生素A
+     */
+    private BigDecimal vitaminA;
+
+    /**
+     * 维生素D
+     */
+    private BigDecimal vitaminD;
+
+    /**
+     * 维生素E
+     */
+    private BigDecimal vitaminE;
+
+    /**
+     * 维生素K
+     */
+    private BigDecimal vitaminK;
+
+    /**
+     * 维生素B1
+     */
+    private BigDecimal vitaminBOne;
+
+    /**
+     * 维生素B2
+     */
+    private BigDecimal vitaminBTwo;
+
+    /**
+     * 维生素B6
+     */
+    private BigDecimal vitaminBSix;
+
+    /**
+     * 维生素B12
+     */
+    private BigDecimal vitaminBTwelve;
+
+    /**
+     * 烟酸(尼克酸)
+     */
+    private BigDecimal niacin;
+
+    /**
+     * 维生素C
+     */
+    private BigDecimal vitaminC;
+
+    /**
+     * 叶酸
+     */
+    private BigDecimal folicAcid;
+
+    /**
+     * 胆碱
+     */
+    private BigDecimal choline;
+
+    /**
+     * 生物素
+     */
+    private BigDecimal biotin;
+
+    /**
+     * 泛酸
+     */
+    private BigDecimal pantothenicAcid;
+
+    /**
+     * 膳食纤维
+     */
+    private BigDecimal dietaryFiber;
+
+    /**
+     * 设定方式
+     */
+    private String settingType;
+
+    /**
+     * 患者id
+     */
+    private Long patientId;
+
+    /**
+     * 看诊类型
+     */
+    private String type;
+
+    /**
+     * 科室
+     */
+    private Long deptId;
+
+    /**
+     * 门诊号
+     */
+    private String outpatientNo;
+
+    /**
+     * 删除标志(0代表存在 1代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 身高
+     */
+    private BigDecimal height;
+
+
+    /**
+     * 体重
+     */
+    private BigDecimal weight;
+
+
+    /**
+     * 体力活动
+     */
+    private Integer activity;
+
+
+    /**
+     * 应激状态
+     */
+    private Integer stressType;
+
+
+    /**
+     * 上臀围
+     */
+    private BigDecimal highHip;
+
+    /**
+     * 下臀围
+     */
+    private BigDecimal lowHip;
+
+    /*烧伤面积*/
+    private BigDecimal burnArea;
+
+}

+ 78 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/bo/NutritionEducationBo.java

@@ -0,0 +1,78 @@
+package org.dromara.web.domain.bo;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import org.dromara.web.domain.NutritionEducation;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 营养宣教业务对象 nutrition_education
+ *
+ * @author Lion Li
+ * @date 2025-07-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = NutritionEducation.class, reverseConvertGenerate = false)
+public class NutritionEducationBo extends BaseEntity {
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = { EditGroup.class })
+    private Long id;
+
+    /**
+     * 患者id
+     */
+    @NotNull(message = "患者id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long patientId;
+
+    /**
+     * 营养宣教标题
+     */
+    private String educationTitle;
+
+    /**
+     * 营养宣教模板id
+     */
+    private Long educationTemplateId;
+
+    /**
+     * 描述
+     */
+    private String description;
+
+    /**
+     * 正文
+     */
+    private String content;
+
+    /**
+     * 看诊类型
+     */
+    private String type;
+
+    /**
+     * 科室
+     */
+    private Long deptId;
+
+    /**
+     * 门诊号
+     */
+    private String outpatientNo;
+
+    private List<Date> dateRange;
+
+    private String contentStr;
+
+
+}

+ 313 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/bo/NutritionSettingBo.java

@@ -0,0 +1,313 @@
+package org.dromara.web.domain.bo;
+
+import com.google.type.Decimal;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import org.dromara.web.domain.NutritionSetting;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 营养设定业务对象 nutrition_setting
+ *
+ * @author Lion Li
+ * @date 2025-07-21
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = NutritionSetting.class, reverseConvertGenerate = false)
+public class NutritionSettingBo extends BaseEntity {
+
+    /**
+     * 主键
+     */
+    @NotNull(message = "主键不能为空", groups = { EditGroup.class })
+    private Long id;
+
+    /**
+     * 所需热量
+     */
+    private BigDecimal caloriesKcalPerDay;
+
+    /**
+     * 所需热量
+     */
+    private BigDecimal caloriesKcalPerKgDay;
+
+    /**
+     * 所需热量
+     */
+    private BigDecimal caloriesKjPerDay;
+
+    /**
+     * 蛋白质热量占比
+     */
+    private BigDecimal proteinCaloriePercentage;
+
+    /**
+     * 脂肪热量占比
+     */
+    private BigDecimal fatCaloriePercentage;
+
+    /**
+     * 碳水化合物热量占比
+     */
+    private BigDecimal carbohydrateCaloriePercentage;
+
+    /**
+     * 所需蛋白质
+     */
+    private BigDecimal proteinGPerKgDay;
+
+    /**
+     * 所需蛋白质
+     */
+    private BigDecimal proteinGPerDay;
+
+    /**
+     * 所需脂肪
+     */
+    private BigDecimal fatGPerKgDay;
+
+    /**
+     * 所需脂肪
+     */
+    private BigDecimal fatGPerDay;
+
+    /**
+     * 所需碳水化合物
+     */
+    private BigDecimal carbohydrateGPerKgDay;
+
+    /**
+     * 所需碳水化合物
+     */
+    private BigDecimal carbohydrateGPerDay;
+
+    /**
+     * 钙
+     */
+    private BigDecimal calcium;
+
+    /**
+     * 钾
+     */
+    private BigDecimal potassium;
+
+    /**
+     * 钠
+     */
+    private BigDecimal sodium;
+
+    /**
+     * 镁
+     */
+    private BigDecimal magnesium;
+
+    /**
+     * 磷
+     */
+    private BigDecimal phosphorus;
+
+    /**
+     * 氯
+     */
+    private BigDecimal chloride;
+
+    /**
+     * 铁
+     */
+    private BigDecimal iron;
+
+    /**
+     * 硒
+     */
+    private BigDecimal selenium;
+
+    /**
+     * 锰
+     */
+    private BigDecimal manganese;
+
+    /**
+     * 氟
+     */
+    private BigDecimal fluoride;
+
+    /**
+     * 钼
+     */
+    private BigDecimal molybdenum;
+
+    /**
+     * 锌
+     */
+    private BigDecimal zinc;
+
+    /**
+     * 铜
+     */
+    private BigDecimal copper;
+
+    /**
+     * 碘
+     */
+    private BigDecimal iodine;
+
+    /**
+     * 铬
+     */
+    private BigDecimal chromium;
+
+    /**
+     * 维生素A
+     */
+    private BigDecimal vitaminA;
+
+    /**
+     * 维生素D
+     */
+    private BigDecimal vitaminD;
+
+    /**
+     * 维生素E
+     */
+    private BigDecimal vitaminE;
+
+    /**
+     * 维生素K
+     */
+    private BigDecimal vitaminK;
+
+    /**
+     * 维生素B1
+     */
+    private BigDecimal vitaminBOne;
+
+    /**
+     * 维生素B2
+     */
+    private BigDecimal vitaminBTwo;
+
+    /**
+     * 维生素B6
+     */
+    private BigDecimal vitaminBSix;
+
+    /**
+     * 维生素B12
+     */
+    private BigDecimal vitaminBTwelve;
+
+    /**
+     * 烟酸(尼克酸)
+     */
+    private BigDecimal niacin;
+
+    /**
+     * 维生素C
+     */
+    private BigDecimal vitaminC;
+
+    /**
+     * 叶酸
+     */
+    private BigDecimal folicAcid;
+
+    /**
+     * 胆碱
+     */
+    private BigDecimal choline;
+
+    /**
+     * 生物素
+     */
+    private BigDecimal biotin;
+
+    /**
+     * 泛酸
+     */
+    private BigDecimal pantothenicAcid;
+
+    /**
+     * 膳食纤维
+     */
+    private BigDecimal dietaryFiber;
+
+    /**
+     * 设定方式
+     */
+    private String settingType;
+
+    /**
+     * 患者id
+     */
+    private Long patientId;
+
+    /**
+     * 看诊类型
+     */
+    private String type;
+
+    /**
+     * 科室
+     */
+    private Long deptId;
+
+    /**
+     * 门诊号
+     */
+    private String outpatientNo;
+
+    /**
+     * 身高
+     */
+    private BigDecimal height;
+
+
+    /**
+     * 体重
+     */
+    private BigDecimal weight;
+
+
+    /**
+     * 体力活动
+     */
+    private Integer activity;
+
+
+    /**
+     * 应激状态
+     */
+    private Integer stressType;
+
+
+    /**
+     * 上臀围
+     */
+    private BigDecimal highHip;
+
+    /**
+     * 下臀围
+     */
+    private BigDecimal lowHip;
+
+    /*燃烧面积*/
+    private BigDecimal burnArea;
+
+    private String gender;
+
+    private String age;
+
+    private List<Date> dateRange;
+
+
+}

+ 51 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/bo/RecalculateBo.java

@@ -0,0 +1,51 @@
+package org.dromara.web.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class RecalculateBo implements Serializable {
+
+    /**
+     * 身高
+     */
+    private BigDecimal height;
+
+
+    /**
+     * 体重
+     */
+    private BigDecimal weight;
+
+
+    /**
+     * 体力活动
+     */
+    private Integer activity;
+
+
+    /**
+     * 应激状态
+     */
+    private Integer stressType;
+
+
+    /**
+     * 上臀围
+     */
+    private BigDecimal highHip;
+
+    /**
+     * 下臀围
+     */
+    private BigDecimal lowHip;
+
+    /*燃烧面积*/
+    private BigDecimal burnArea;
+
+    private String gender;
+
+    private String age;
+}

+ 93 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/vo/NutritionEducationVo.java

@@ -0,0 +1,93 @@
+package org.dromara.web.domain.vo;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import org.dromara.web.domain.NutritionEducation;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 营养宣教视图对象 nutrition_education
+ *
+ * @author Lion Li
+ * @date 2025-07-18
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = NutritionEducation.class)
+public class NutritionEducationVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Long id;
+
+    /**
+     * 患者id
+     */
+    @ExcelProperty(value = "患者id")
+    private Long patientId;
+
+    /**
+     * 营养宣教标题
+     */
+    @ExcelProperty(value = "营养宣教标题")
+    private String educationTitle;
+
+    /**
+     * 营养宣教模板id
+     */
+    @ExcelProperty(value = "营养宣教模板id")
+    private Long educationTemplateId;
+
+    /**
+     * 描述
+     */
+    @ExcelProperty(value = "描述")
+    private String description;
+
+    /**
+     * 正文
+     */
+    @ExcelProperty(value = "正文")
+    private String content;
+
+    /**
+     * 看诊类型
+     */
+    @ExcelProperty(value = "看诊类型")
+    private String type;
+
+    /**
+     * 科室
+     */
+    @ExcelProperty(value = "科室")
+    private Long deptId;
+
+    /**
+     * 门诊号
+     */
+    @ExcelProperty(value = "门诊号")
+    private String outpatientNo;
+
+    private Long createBy;
+
+    private Date createTime;
+
+    private String deptName;
+
+    private String createByUser;
+
+
+}

+ 366 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/vo/NutritionSettingVo.java

@@ -0,0 +1,366 @@
+package org.dromara.web.domain.vo;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import com.google.type.Decimal;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import org.dromara.web.domain.NutritionSetting;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+
+
+/**
+ * 营养设定视图对象 nutrition_setting
+ *
+ * @author Lion Li
+ * @date 2025-07-21
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = NutritionSetting.class)
+public class NutritionSettingVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @ExcelProperty(value = "主键")
+    private Long id;
+
+    /**
+     * 所需热量
+     */
+    @ExcelProperty(value = "所需热量")
+    private BigDecimal caloriesKcalPerDay;
+
+    /**
+     * 所需热量
+     */
+    @ExcelProperty(value = "所需热量")
+    private BigDecimal caloriesKcalPerKgDay;
+
+    /**
+     * 所需热量
+     */
+    @ExcelProperty(value = "所需热量")
+    private BigDecimal caloriesKjPerDay;
+
+    /**
+     * 蛋白质热量占比
+     */
+    @ExcelProperty(value = "蛋白质热量占比")
+    private BigDecimal proteinCaloriePercentage;
+
+    /**
+     * 脂肪热量占比
+     */
+    @ExcelProperty(value = "脂肪热量占比")
+    private BigDecimal fatCaloriePercentage;
+
+    /**
+     * 碳水化合物热量占比
+     */
+    @ExcelProperty(value = "碳水化合物热量占比")
+    private BigDecimal carbohydrateCaloriePercentage;
+
+    /**
+     * 所需蛋白质
+     */
+    @ExcelProperty(value = "所需蛋白质")
+    private BigDecimal proteinGPerKgDay;
+
+    /**
+     * 所需蛋白质
+     */
+    @ExcelProperty(value = "所需蛋白质")
+    private BigDecimal proteinGPerDay;
+
+    /**
+     * 所需脂肪
+     */
+    @ExcelProperty(value = "所需脂肪")
+    private BigDecimal fatGPerKgDay;
+
+    /**
+     * 所需脂肪
+     */
+    @ExcelProperty(value = "所需脂肪")
+    private BigDecimal fatGPerDay;
+
+    /**
+     * 所需碳水化合物
+     */
+    @ExcelProperty(value = "所需碳水化合物")
+    private BigDecimal carbohydrateGPerKgDay;
+
+    /**
+     * 所需碳水化合物
+     */
+    @ExcelProperty(value = "所需碳水化合物")
+    private BigDecimal carbohydrateGPerDay;
+
+    /**
+     * 钙
+     */
+    @ExcelProperty(value = "钙")
+    private BigDecimal calcium;
+
+    /**
+     * 钾
+     */
+    @ExcelProperty(value = "钾")
+    private BigDecimal potassium;
+
+    /**
+     * 钠
+     */
+    @ExcelProperty(value = "钠")
+    private BigDecimal sodium;
+
+    /**
+     * 镁
+     */
+    @ExcelProperty(value = "镁")
+    private BigDecimal magnesium;
+
+    /**
+     * 磷
+     */
+    @ExcelProperty(value = "磷")
+    private BigDecimal phosphorus;
+
+    /**
+     * 氯
+     */
+    @ExcelProperty(value = "氯")
+    private BigDecimal chloride;
+
+    /**
+     * 铁
+     */
+    @ExcelProperty(value = "铁")
+    private BigDecimal iron;
+
+    /**
+     * 硒
+     */
+    @ExcelProperty(value = "硒")
+    private BigDecimal selenium;
+
+    /**
+     * 锰
+     */
+    @ExcelProperty(value = "锰")
+    private BigDecimal manganese;
+
+    /**
+     * 氟
+     */
+    @ExcelProperty(value = "氟")
+    private BigDecimal fluoride;
+
+    /**
+     * 钼
+     */
+    @ExcelProperty(value = "钼")
+    private BigDecimal molybdenum;
+
+    /**
+     * 锌
+     */
+    @ExcelProperty(value = "锌")
+    private BigDecimal zinc;
+
+    /**
+     * 铜
+     */
+    @ExcelProperty(value = "铜")
+    private BigDecimal copper;
+
+    /**
+     * 碘
+     */
+    @ExcelProperty(value = "碘")
+    private BigDecimal iodine;
+
+    /**
+     * 铬
+     */
+    @ExcelProperty(value = "铬")
+    private BigDecimal chromium;
+
+    /**
+     * 维生素A
+     */
+    @ExcelProperty(value = "维生素A")
+    private BigDecimal vitaminA;
+
+    /**
+     * 维生素D
+     */
+    @ExcelProperty(value = "维生素D")
+    private BigDecimal vitaminD;
+
+    /**
+     * 维生素E
+     */
+    @ExcelProperty(value = "维生素E")
+    private BigDecimal vitaminE;
+
+    /**
+     * 维生素K
+     */
+    @ExcelProperty(value = "维生素K")
+    private BigDecimal vitaminK;
+
+    /**
+     * 维生素B1
+     */
+    @ExcelProperty(value = "维生素B1")
+    private BigDecimal vitaminBOne;
+
+    /**
+     * 维生素B2
+     */
+    @ExcelProperty(value = "维生素B2")
+    private BigDecimal vitaminBTwo;
+
+    /**
+     * 维生素B6
+     */
+    @ExcelProperty(value = "维生素B6")
+    private BigDecimal vitaminBSix;
+
+    /**
+     * 维生素B12
+     */
+    @ExcelProperty(value = "维生素B12")
+    private BigDecimal vitaminBTwelve;
+
+    /**
+     * 烟酸(尼克酸)
+     */
+    @ExcelProperty(value = "烟酸", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "尼=克酸")
+    private BigDecimal niacin;
+
+    /**
+     * 维生素C
+     */
+    @ExcelProperty(value = "维生素C")
+    private BigDecimal vitaminC;
+
+    /**
+     * 叶酸
+     */
+    @ExcelProperty(value = "叶酸")
+    private BigDecimal folicAcid;
+
+    /**
+     * 胆碱
+     */
+    @ExcelProperty(value = "胆碱")
+    private BigDecimal choline;
+
+    /**
+     * 生物素
+     */
+    @ExcelProperty(value = "生物素")
+    private BigDecimal biotin;
+
+    /**
+     * 泛酸
+     */
+    @ExcelProperty(value = "泛酸")
+    private BigDecimal pantothenicAcid;
+
+    /**
+     * 膳食纤维
+     */
+    @ExcelProperty(value = "膳食纤维")
+    private BigDecimal dietaryFiber;
+
+    /**
+     * 设定方式
+     */
+    @ExcelProperty(value = "设定方式")
+    private String settingType;
+
+    /**
+     * 患者id
+     */
+    @ExcelProperty(value = "患者id")
+    private Long patientId;
+
+    /**
+     * 看诊类型
+     */
+    @ExcelProperty(value = "看诊类型")
+    private String type;
+
+    /**
+     * 科室
+     */
+    @ExcelProperty(value = "科室")
+    private Long deptId;
+
+    /**
+     * 门诊号
+     */
+    @ExcelProperty(value = "门诊号")
+    private String outpatientNo;
+
+    /**
+     * 身高
+     */
+    private BigDecimal height;
+
+
+    /**
+     * 体重
+     */
+    private BigDecimal weight;
+
+
+    /**
+     * 体力活动
+     */
+    private Integer activity;
+
+
+    /**
+     * 应激状态
+     */
+    private Integer stressType;
+
+
+    /**
+     * 上臀围
+     */
+    private BigDecimal highHip;
+
+    /**
+     * 下臀围
+     */
+    private BigDecimal lowHip;
+
+    /*烧伤面积*/
+    private BigDecimal burnArea;
+
+    private Date createTime;
+
+    private Long createBy;
+
+    private String createByUser;
+
+
+}

+ 18 - 0
ruoyi-admin/src/main/java/org/dromara/web/mapper/NutritionEducationMapper.java

@@ -0,0 +1,18 @@
+package org.dromara.web.mapper;
+
+
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+import org.dromara.web.domain.NutritionEducation;
+import org.dromara.web.domain.vo.NutritionEducationVo;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 营养宣教Mapper接口
+ *
+ * @author Lion Li
+ * @date 2025-07-18
+ */
+@Repository
+public interface NutritionEducationMapper extends BaseMapperPlus<NutritionEducation, NutritionEducationVo> {
+
+}

+ 18 - 0
ruoyi-admin/src/main/java/org/dromara/web/mapper/NutritionSettingMapper.java

@@ -0,0 +1,18 @@
+package org.dromara.web.mapper;
+
+
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+import org.dromara.web.domain.NutritionSetting;
+import org.dromara.web.domain.vo.NutritionSettingVo;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 营养设定Mapper接口
+ *
+ * @author Lion Li
+ * @date 2025-07-21
+ */
+@Repository
+public interface NutritionSettingMapper extends BaseMapperPlus<NutritionSetting, NutritionSettingVo> {
+
+}

+ 73 - 0
ruoyi-admin/src/main/java/org/dromara/web/service/INutritionEducationService.java

@@ -0,0 +1,73 @@
+package org.dromara.web.service;
+
+
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.web.domain.bo.NutritionEducationBo;
+import org.dromara.web.domain.vo.NutritionEducationVo;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 营养宣教Service接口
+ *
+ * @author Lion Li
+ * @date 2025-07-18
+ */
+public interface INutritionEducationService {
+
+    /**
+     * 查询营养宣教
+     *
+     * @param id 主键
+     * @return 营养宣教
+     */
+    NutritionEducationVo queryById(Long id);
+
+    /**
+     * 分页查询营养宣教列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 营养宣教分页列表
+     */
+    TableDataInfo<NutritionEducationVo> queryPageList(NutritionEducationBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的营养宣教列表
+     *
+     * @param bo 查询条件
+     * @return 营养宣教列表
+     */
+    List<NutritionEducationVo> queryList(NutritionEducationBo bo);
+
+    /**
+     * 新增营养宣教
+     *
+     * @param bo 营养宣教
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(NutritionEducationBo bo);
+
+    /**
+     * 修改营养宣教
+     *
+     * @param bo 营养宣教
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(NutritionEducationBo bo);
+
+    /**
+     * 校验并批量删除营养宣教信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /*获取营养宣教模板*/
+    Map<String, Object> queryTemplateList();
+}

+ 74 - 0
ruoyi-admin/src/main/java/org/dromara/web/service/INutritionSettingService.java

@@ -0,0 +1,74 @@
+package org.dromara.web.service;
+
+
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.web.domain.bo.NutritionSettingBo;
+import org.dromara.web.domain.vo.NutritionSettingVo;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 营养设定Service接口
+ *
+ * @author Lion Li
+ * @date 2025-07-21
+ */
+public interface INutritionSettingService {
+
+    /**
+     * 查询营养设定
+     *
+     * @param id 主键
+     * @return 营养设定
+     */
+    NutritionSettingVo queryById(Long id);
+
+    /**
+     * 分页查询营养设定列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 营养设定分页列表
+     */
+    TableDataInfo<NutritionSettingVo> queryPageList(NutritionSettingBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的营养设定列表
+     *
+     * @param bo 查询条件
+     * @return 营养设定列表
+     */
+    List<NutritionSettingVo> queryList(NutritionSettingBo bo);
+
+    /**
+     * 新增营养设定
+     *
+     * @param bo 营养设定
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(NutritionSettingBo bo);
+
+    /**
+     * 修改营养设定
+     *
+     * @param bo 营养设定
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(NutritionSettingBo bo);
+
+    /**
+     * 校验并批量删除营养设定信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    Map<String, String> calculateEnergyRequirements(
+        String gender, int age, double height, double weight,
+        Integer activityLevel, Integer stressLevel);
+}

+ 213 - 0
ruoyi-admin/src/main/java/org/dromara/web/service/NutritionDataUtil.java

@@ -0,0 +1,213 @@
+package org.dromara.web.service;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 营养代谢基础值查询工具类
+ * 支持通过营养素名称、性别和年龄查询推荐值
+ */
+public class NutritionDataUtil {
+
+    // 营养素数据映射表
+    private static final Map<String, Map<String, String>> NUTRIENT_MAP = new HashMap<>();
+
+    // 年龄范围映射表
+    private static final Map<String, AgeRange> AGE_RANGE_MAP = new HashMap<>();
+
+    // 年龄范围类
+    private static class AgeRange {
+        final int min;
+        final int max;
+        final String groupName;
+
+        AgeRange(int min, int max, String groupName) {
+            this.min = min;
+            this.max = max;
+            this.groupName = groupName;
+        }
+
+        boolean contains(int age) {
+            return age >= min && age <= max;
+        }
+    }
+
+    static {
+        // 初始化年龄范围映射
+        initializeAgeRanges();
+        // 初始化营养素数据
+        initializeNutrientData();
+    }
+
+    // 初始化年龄范围
+    private static void initializeAgeRanges() {
+        AGE_RANGE_MAP.put("0-6月", new AgeRange(0, 0, "0-6月"));
+        AGE_RANGE_MAP.put("7-12月", new AgeRange(0, 1, "7-12月"));
+        AGE_RANGE_MAP.put("1-3岁", new AgeRange(1, 3, "1-3岁"));
+        AGE_RANGE_MAP.put("4-6岁", new AgeRange(4, 6, "4-6岁"));
+        AGE_RANGE_MAP.put("7-10岁", new AgeRange(7, 10, "7-10岁"));
+        AGE_RANGE_MAP.put("11-13岁", new AgeRange(11, 13, "11-13岁"));
+        AGE_RANGE_MAP.put("14-17岁", new AgeRange(14, 17, "14-17岁"));
+        AGE_RANGE_MAP.put("18-49岁", new AgeRange(18, 49, "18-49岁"));
+        AGE_RANGE_MAP.put("50-64岁", new AgeRange(50, 64, "50-64岁"));
+        AGE_RANGE_MAP.put("≥65岁", new AgeRange(65, Integer.MAX_VALUE, "≥65岁"));
+        AGE_RANGE_MAP.put("孕妇", new AgeRange(-1, -1, "孕妇(中期/晚期)"));
+        AGE_RANGE_MAP.put("乳母", new AgeRange(-1, -1, "乳母"));
+    }
+
+    // 初始化营养素数据
+    private static void initializeNutrientData() {
+        // 常量元素
+        addNutrientData("钙", "mg", "300 (AI)", "350 (AI)", "600", "800", "1000", "1200", "1000", "800", "1000", "1000", "1000/1200", "1000");
+        addNutrientData("磷", "mg", "160 (AI)", "280 (AI)", "400", "500", "600", "800", "700", "700", "700", "700", "700", "700");
+        addNutrientData("钾", "mg", "350 (AI)", "450 (AI)", "700", "900", "1300", "1800", "2000", "2000", "2000", "2000", "2000", "2000");
+        addNutrientData("钠", "mg", "170 (AI)", "350 (AI)", "700", "900", "1200", "1500", "1500", "1500", "1500", "1500", "1500", "1500");
+        addNutrientData("镁", "mg", "25 (AI)", "40 (AI)", "100", "120", "150", "200", "250", "330", "330", "330", "350", "350");
+        addNutrientData("氯", "mg", "270 (AI)", "540 (AI)", "1000", "1200", "1700", "2300", "2300", "2300", "2300", "2300", "2300", "2300");
+
+        // 微量元素
+        addNutrientData("铁", "mg", "0.3 (AI)", "10", "9", "10", "12", "男16/女20", "男15/女20", "男12/女20", "12", "12", "24", "13");
+        addNutrientData("锌", "mg", "1.5 (AI)", "3 (AI)", "4", "5", "7", "男10/女9", "男12.5/女7.5", "男12.5/女7.5", "男12.5/女7.5", "男12.5/女7.5", "10/12.5", "16.5");
+        addNutrientData("硒", "μg", "15 (AI)", "20 (AI)", "20", "25", "30", "40", "50", "60", "60", "60", "65", "75");
+        addNutrientData("铜", "mg", "0.2 (AI)", "0.3 (AI)", "0.8", "0.9", "1", "1.1", "1.1", "0.8", "0.8", "0.8", "1.3", "1.3");
+        addNutrientData("锰", "mg", "0.05 (AI)", "0.08 (AI)", "1.5", "2.5", "3.5", "4.5", "4.5", "4.5", "4.5", "4.5", "4.5", "4.5");
+        addNutrientData("碘", "μg", "85 (AI)", "115 (AI)", "90", "90", "120", "120", "120", "120", "120", "120", "230", "240");
+        addNutrientData("氟", "mg", "0.01 (AI)", "0.05 (AI)", "0.7", "1", "1.5", "2", "2.5", "3", "3", "3", "3", "3");
+        addNutrientData("铬", "μg", "5 (AI)", "10 (AI)", "15", "20", "25", "30", "30", "50", "50", "50", "50", "50");
+        addNutrientData("钼", "μg", "2 (AI)", "4 (AI)", "6", "8", "10", "12", "15", "30", "30", "30", "30", "30");
+
+        // 脂溶性维生素
+        addNutrientData("维生素A", "μg RE", "400 (AI)", "400 (AI)", "400", "500", "600", "700", "700", "800", "700", "700", "800/900", "1200");
+        addNutrientData("维生素D", "μg", "10 (AI)", "10 (AI)", "10", "10", "10", "10", "10", "10", "10", "10", "10", "10");
+        addNutrientData("维生素E", "mg α-TE", "3 (AI)", "4 (AI)", "6", "7", "9", "11", "14", "14", "14", "14", "14", "14");
+        addNutrientData("维生素K", "μg", "2 (AI)", "2.5 (AI)", "25", "30", "40", "50", "60", "80", "80", "80", "80", "80");
+
+        // 水溶性维生素
+        addNutrientData("维生素B1", "mg", "0.2 (AI)", "0.3 (AI)", "0.6", "0.8", "1", "男1.2/女1.0", "男1.3/女1.1", "男1.4/女1.2", "男1.4/女1.2", "男1.4/女1.2", "1.5/1.6", "1.6");
+        addNutrientData("维生素B2", "mg", "0.2 (AI)", "0.3 (AI)", "0.6", "0.8", "1", "男1.2/女1.0", "男1.3/女1.1", "男1.4/女1.2", "男1.4/女1.2", "男1.4/女1.2", "1.5/1.6", "1.7");
+        addNutrientData("维生素B6", "mg", "0.1 (AI)", "0.2 (AI)", "0.6", "0.8", "1", "男1.2/女1.0", "男1.4/女1.2", "男1.4/女1.2", "男1.4/女1.2", "男1.4/女1.2", "1.8", "2");
+        addNutrientData("维生素B12", "μg", "0.3 (AI)", "0.4 (AI)", "0.7", "1", "1.3", "1.6", "2", "2.4", "2.4", "2.4", "2.6", "2.8");
+        addNutrientData("烟酸", "mg NE", "2 (AI)", "3 (AI)", "6", "8", "11", "男14/女12", "男16/女14", "男18/女14", "男18/女14", "男18/女14", "18", "18");
+        addNutrientData("维生素C", "mg", "40 (AI)", "50 (AI)", "60", "70", "80", "90", "100", "100", "100", "100", "115/130", "150");
+        addNutrientData("叶酸", "μg DFE", "65 (AI)", "80 (AI)", "150", "200", "250", "300", "350", "400", "400", "400", "600", "500");
+        addNutrientData("胆碱", "mg", "125 (AI)", "150 (AI)", "175", "200", "250", "300", "350", "400", "400", "400", "450", "550");
+        addNutrientData("生物素", "μg", "5 (AI)", "6 (AI)", "8", "12", "15", "20", "25", "30", "30", "30", "30", "35");
+        addNutrientData("泛酸", "mg", "1.7 (AI)", "2.0 (AI)", "3", "4", "4", "5", "5", "5", "5", "5", "6", "7");
+
+        // 其他
+        addNutrientData("膳食纤维", "g", "-", "-", "13", "14", "15", "18", "20", "25", "25", "25", "25", "25");
+    }
+
+    // 添加营养素数据
+    private static void addNutrientData(String nutrient,  String... values) {
+        Map<String, String> dataMap = new HashMap<>();
+        String[] ageGroups = {
+            "0-6月", "7-12月", "1-3岁", "4-6岁", "7-10岁",
+            "11-13岁", "14-17岁", "18-49岁", "50-64岁", "≥65岁",
+            "孕妇(中期/晚期)", "乳母"
+        };
+
+        for (int i = 0; i < values.length && i < ageGroups.length; i++) {
+            dataMap.put(ageGroups[i], values[i] + (values[i].equals("-") ? "" : " " ));
+        }
+        NUTRIENT_MAP.put(nutrient, dataMap);
+    }
+
+    /**
+     * 根据整数年龄获取营养推荐值
+     *
+     * @param nutrient 营养素名称
+     * @param gender 性别 (男/女,当不需要区分性别时可传null)
+     * @param age 实际年龄 (整数)
+     * @return 对应的营养值 (带单位),未找到返回null
+     */
+    public static String getValueByAge(String nutrient, String gender, int age) {
+        String ageGroup = findAgeGroup(age);
+        return getValue(nutrient, gender, ageGroup);
+    }
+
+    /**
+     * 根据年龄组名称获取营养推荐值
+     *
+     * @param nutrient 营养素名称
+     * @param gender 性别 (男/女,当不需要区分性别时可传null)
+     * @param ageGroup 年龄组名称
+     * @return 对应的营养值 (带单位),未找到返回null
+     */
+    public static String getValue(String nutrient, String gender, String ageGroup) {
+        // 获取标准化的年龄组
+        String normalizedAgeGroup = normalizeAgeGroup(ageGroup);
+
+        // 获取营养素数据
+        Map<String, String> nutrientData = NUTRIENT_MAP.get(nutrient);
+        if (nutrientData == null) return null;
+
+        // 获取原始值
+        String rawValue = nutrientData.get(normalizedAgeGroup);
+        if (rawValue == null) return null;
+
+        // 处理带斜杠的值
+        if (rawValue.contains("/")) {
+            // 处理孕妇中期/晚期
+            if ("孕妇(中期/晚期)".equals(normalizedAgeGroup)) {
+                String[] parts = rawValue.split(" ")[0].split("/");
+                return parts.length > 1 ? parts[0] + " (中期)" + "/" + parts[1] + " (晚期)" : rawValue;
+            }
+
+            // 处理性别区分值
+            if (gender != null && rawValue.contains("男") && rawValue.contains("女")) {
+                return extractGenderSpecificValue(rawValue, gender);
+            }
+        }
+
+        return rawValue;
+    }
+
+    // 根据年龄查找对应的年龄组
+    private static String findAgeGroup(int age) {
+        // 特殊处理婴儿(0岁)
+        if (age == 0) return "0-6月";
+
+        for (Map.Entry<String, AgeRange> entry : AGE_RANGE_MAP.entrySet()) {
+            AgeRange range = entry.getValue();
+            if (range.contains(age)) {
+                return entry.getKey();
+            }
+        }
+        return "18-49岁"; // 默认值
+    }
+
+    // 标准化年龄组
+    private static String normalizeAgeGroup(String ageGroup) {
+        if (AGE_RANGE_MAP.containsKey(ageGroup)) {
+            return AGE_RANGE_MAP.get(ageGroup).groupName;
+        }
+        return ageGroup;
+    }
+
+    // 提取性别特定值
+    private static String extractGenderSpecificValue(String rawValue, String gender) {
+        // 分离值和单位
+        String[] parts = rawValue.split(" ");
+        String valuePart = parts[0];
+        String unit = parts.length > 1 ? " " + parts[1] : "";
+
+        Pattern pattern = Pattern.compile("男([^/]+)/女([^/]+)");
+        Matcher matcher = pattern.matcher(valuePart);
+
+        if (matcher.find()) {
+            String maleValue = matcher.group(1).trim();
+            String femaleValue = matcher.group(2).trim();
+            return ("男".equals(gender) ? maleValue : femaleValue) + unit;
+        }
+        return rawValue;
+    }
+
+    // 获取所有支持查询的营养素列表
+    public static String[] getAvailableNutrients() {
+        return NUTRIENT_MAP.keySet().toArray(new String[0]);
+    }
+
+}

+ 247 - 0
ruoyi-admin/src/main/java/org/dromara/web/service/impl/NutritionEducationServiceImpl.java

@@ -0,0 +1,247 @@
+package org.dromara.web.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.system.domain.SysDept;
+import org.dromara.system.domain.SysUser;
+import org.dromara.system.mapper.SysDeptMapper;
+import org.dromara.system.mapper.SysUserMapper;
+import org.dromara.web.domain.*;
+import org.dromara.web.domain.bo.NutritionEducationBo;
+import org.dromara.web.domain.vo.ConsultantResultTemplateVo;
+import org.dromara.web.domain.vo.NutritionEducationTemplateVo;
+import org.dromara.web.domain.vo.NutritionEducationVo;
+import org.dromara.web.mapper.NutritionEducationMapper;
+import org.dromara.web.mapper.NutritionEducationTemplateMapper;
+import org.dromara.web.service.INutritionEducationService;
+import org.springframework.stereotype.Service;
+
+
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 营养宣教Service业务层处理
+ *
+ * @author Lion Li
+ * @date 2025-07-18
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class NutritionEducationServiceImpl implements INutritionEducationService {
+
+    private final NutritionEducationMapper baseMapper;
+
+    private final SysDeptMapper deptMapper;
+
+    private final SysUserMapper userMapper;
+
+    private final NutritionEducationTemplateMapper templateMapper;
+
+    /**
+     * 查询营养宣教
+     *
+     * @param id 主键
+     * @return 营养宣教
+     */
+    @Override
+    public NutritionEducationVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询营养宣教列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 营养宣教分页列表
+     */
+    @Override
+    public TableDataInfo<NutritionEducationVo> queryPageList(NutritionEducationBo bo, PageQuery pageQuery) {
+        List<SysDept> deptList = deptMapper.selectList(Wrappers.lambdaQuery(SysDept.class).select(SysDept::getDeptId, SysDept::getDeptName));
+        Map<Long, String> deptMap = deptList.stream().collect(Collectors.toMap(k1 -> k1.getDeptId(), k2 -> String.valueOf(k2.getDeptName()), (k1, k2) -> k1));
+
+        List<SysUser> userList = userMapper.selectList(Wrappers.lambdaQuery(SysUser.class).select(SysUser::getUserId, SysUser::getUserName));
+        Map<Long, String> userMap = userList.stream().collect(Collectors.toMap(k1 -> k1.getUserId(), k2 -> String.valueOf(k2.getUserName()), (k1, k2) -> k1));
+
+        LambdaQueryWrapper<NutritionEducation> lqw = buildQueryWrapper(bo);
+        Page<NutritionEducationVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        List<NutritionEducationVo> records = result.getRecords();
+        if (CollUtil.isNotEmpty(records)) {
+            for (NutritionEducationVo record : records) {
+                record.setDeptName(deptMap.get(record.getDeptId()));
+                record.setCreateByUser(userMap.get(record.getCreateBy()));
+            }
+        }
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的营养宣教列表
+     *
+     * @param bo 查询条件
+     * @return 营养宣教列表
+     */
+    @Override
+    public List<NutritionEducationVo> queryList(NutritionEducationBo bo) {
+        LambdaQueryWrapper<NutritionEducation> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<NutritionEducation> buildQueryWrapper(NutritionEducationBo bo) {
+        Map<String, Object> params = bo.getParams();
+        List<Date> dateRange = bo.getDateRange();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        List<SysUser> userList = userMapper.selectList(Wrappers.lambdaQuery(SysUser.class).select(SysUser::getUserId, SysUser::getUserName));
+        Map<String, Long> userMap = userList.stream().collect(Collectors.toMap(k1 -> String.valueOf(k1.getUserName()), k2 -> k2.getUserId(), (k1, k2) -> k1));
+        LambdaQueryWrapper<NutritionEducation> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(NutritionEducation::getId);
+        lqw.eq(StringUtils.isNotBlank(bo.getType()), NutritionEducation::getType, bo.getType());
+        lqw.eq(bo.getPatientId() != null, NutritionEducation::getPatientId, bo.getPatientId());
+        lqw.eq(StringUtils.isNotBlank(bo.getOutpatientNo()), NutritionEducation::getOutpatientNo, bo.getOutpatientNo());
+
+        if (StringUtils.isNotBlank(bo.getSearchValue())) {
+            lqw.and(wrapper -> wrapper.like(NutritionEducation::getCreateBy, userMap.get(bo.getSearchValue())).or().like(NutritionEducation::getOutpatientNo, bo.getSearchValue()));
+        }
+        if (dateRange != null && dateRange.size() == 2) {
+            String startTime = sdf.format(dateRange.get(0)) + " 00:00:00";  // 开始时间
+            String endTime = sdf.format(dateRange.get(1)) + " 23:59:59";    // 结束时间
+            if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
+                lqw.between(NutritionEducation::getCreateTime, startTime, endTime);
+
+            }
+        }
+        return lqw;
+    }
+
+    /**
+     * 新增营养宣教
+     *
+     * @param bo 营养宣教
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(NutritionEducationBo bo) {
+        bo.setContent(URLDecoder.decode(new String(Base64.getDecoder().decode(bo.getContentStr()), StandardCharsets.UTF_8)));
+        NutritionEducation add = MapstructUtils.convert(bo, NutritionEducation.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改营养宣教
+     *
+     * @param bo 营养宣教
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(NutritionEducationBo bo) {
+        bo.setContent(URLDecoder.decode(new String(Base64.getDecoder().decode(bo.getContentStr()), StandardCharsets.UTF_8)));
+        NutritionEducation update = MapstructUtils.convert(bo, NutritionEducation.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(NutritionEducation entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除营养宣教信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+
+    @Override
+    public Map<String, Object> queryTemplateList() {
+        Map<String, Object> resultMap = new HashMap<>();
+
+        List<SysDept> deptList = deptMapper.selectList(Wrappers.lambdaQuery(SysDept.class).select(SysDept::getDeptId, SysDept::getDeptName));
+        Map<String, String> deptNameMap = deptList.stream().collect(Collectors.toMap(k1 -> String.valueOf(k1.getDeptId()), k2 -> String.valueOf(k2.getDeptName()), (k1, k2) -> k1));
+        List<Map<String, Object>> result = new ArrayList<>();
+
+        // 1. 处理 "基础/公共模板" 部分
+        Map<String, Object> publicTemplate = new HashMap<>();
+        publicTemplate.put("label", "基础/公共模板");
+
+
+        // 查询所有非个人的公共模板(deptId不为null的模板)
+        List<NutritionEducationTemplateVo> publicTemplates = templateMapper.selectVoList(new LambdaQueryWrapper<NutritionEducationTemplate>().isNotNull(NutritionEducationTemplate::getDeptId).orderByAsc(NutritionEducationTemplate::getDeptId)  // 按部门ID排序
+        );
+
+        // 使用LinkedHashMap保持插入顺序
+        Map<String, List<Map<String, Object>>> deptMap = new LinkedHashMap<>();
+
+        // 按部门名称分组模板
+        for (NutritionEducationTemplateVo template : publicTemplates) {
+            String deptName = deptNameMap.get(template.getDeptId()); // 部门名称如"骨伤科"
+            deptMap.computeIfAbsent(deptName, k -> new ArrayList<>()).add(createTemplateNode(template));
+        }
+
+        // 构建部门分类结构
+        List<Map<String, Object>> publicChildren = deptMap.entrySet().stream().map(entry -> {
+            Map<String, Object> deptNode = new HashMap<>();
+            deptNode.put("label", entry.getKey()); // 部门名称
+            deptNode.put("children", entry.getValue()); // 该部门下的模板列表
+            return deptNode;
+        }).collect(Collectors.toList());
+
+        publicTemplate.put("children", publicChildren);
+        result.add(publicTemplate);
+
+        // 2. 处理 "个人模板" 部分
+        Map<String, Object> personalTemplate = new HashMap<>();
+        personalTemplate.put("label", "个人模板");
+
+        // 查询个人模板(假设个人模板的deptId为null)
+        List<NutritionEducationTemplateVo> personalTemplates = templateMapper.selectVoList(new LambdaQueryWrapper<NutritionEducationTemplate>().isNull(NutritionEducationTemplate::getDeptId));
+
+        if (!personalTemplates.isEmpty()) {
+            List<Map<String, Object>> personalChildren = personalTemplates.stream().map(this::createTemplateNode).collect(Collectors.toList());
+            personalTemplate.put("children", personalChildren);
+        }
+
+        result.add(personalTemplate);
+        resultMap.put("data", result);
+        return resultMap;
+    }
+
+    // 创建模板节点的辅助方法
+    private Map<String, Object> createTemplateNode(NutritionEducationTemplateVo template) {
+        Map<String, Object> node = new HashMap<>();
+        node.put("id", template.getId());
+        node.put("label", template.getTemplateName());
+        node.put("template", template.getContent());
+        node.put("description", template.getDescription());
+        // 可以添加其他需要的字段
+        return node;
+    }
+}

+ 299 - 0
ruoyi-admin/src/main/java/org/dromara/web/service/impl/NutritionSettingServiceImpl.java

@@ -0,0 +1,299 @@
+package org.dromara.web.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.system.domain.SysUser;
+import org.dromara.system.mapper.SysUserMapper;
+import org.dromara.system.service.impl.SysDictDataServiceImpl;
+import org.dromara.web.domain.NutritionEducation;
+import org.dromara.web.domain.NutritionSetting;
+import org.dromara.web.domain.bo.NutritionSettingBo;
+import org.dromara.web.domain.vo.NutritionSettingVo;
+import org.dromara.web.mapper.NutritionSettingMapper;
+import org.dromara.web.service.INutritionSettingService;
+import org.dromara.web.service.NutritionDataUtil;
+import org.springframework.stereotype.Service;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 营养设定Service业务层处理
+ *
+ * @author Lion Li
+ * @date 2025-07-21
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class NutritionSettingServiceImpl implements INutritionSettingService {
+
+    private final NutritionSettingMapper baseMapper;
+
+    private final SysUserMapper userMapper;
+
+    private final SysDictDataServiceImpl dictDataService;
+
+    /**
+     * 查询营养设定
+     *
+     * @param id 主键
+     * @return 营养设定
+     */
+    @Override
+    public NutritionSettingVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询营养设定列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 营养设定分页列表
+     */
+    @Override
+    public TableDataInfo<NutritionSettingVo> queryPageList(NutritionSettingBo bo, PageQuery pageQuery) {
+        List<SysUser> userList = userMapper.selectList(Wrappers.lambdaQuery(SysUser.class).select(SysUser::getUserId, SysUser::getUserName));
+        Map<Long, String> userMap = userList.stream().collect(Collectors.toMap(k1 -> k1.getUserId(), k2 -> String.valueOf(k2.getUserName()), (k1, k2) -> k1));
+
+        LambdaQueryWrapper<NutritionSetting> lqw = buildQueryWrapper(bo);
+        Page<NutritionSettingVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        List<NutritionSettingVo> records = result.getRecords();
+        if (CollUtil.isNotEmpty(records)) {
+            for (NutritionSettingVo record : records) {
+                record.setCreateByUser(userMap.get(record.getCreateBy()));
+            }
+        }
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的营养设定列表
+     *
+     * @param bo 查询条件
+     * @return 营养设定列表
+     */
+    @Override
+    public List<NutritionSettingVo> queryList(NutritionSettingBo bo) {
+        LambdaQueryWrapper<NutritionSetting> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<NutritionSetting> buildQueryWrapper(NutritionSettingBo bo) {
+        Map<String, Object> params = bo.getParams();
+        List<Date> dateRange = bo.getDateRange();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+
+        List<SysUser> userList = userMapper.selectList(Wrappers.lambdaQuery(SysUser.class).select(SysUser::getUserId, SysUser::getUserName));
+        Map<String, Long> userMap = userList.stream().collect(Collectors.toMap(k1 -> String.valueOf(k1.getUserName()), k2 -> k2.getUserId(), (k1, k2) -> k1));
+        LambdaQueryWrapper<NutritionSetting> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(NutritionSetting::getId);
+
+        lqw.eq(bo.getPatientId() != null, NutritionSetting::getPatientId, bo.getPatientId());
+        lqw.eq(StringUtils.isNotBlank(bo.getSettingType()), NutritionSetting::getSettingType, bo.getSettingType());
+        lqw.eq(StringUtils.isNotBlank(bo.getType()), NutritionSetting::getType, bo.getType());
+        lqw.eq(StringUtils.isNotBlank(bo.getOutpatientNo()), NutritionSetting::getOutpatientNo, bo.getOutpatientNo());
+        if (StringUtils.isNotBlank(bo.getSearchValue())) {
+            lqw.and(wrapper -> wrapper.like(NutritionSetting::getCreateBy, userMap.get(bo.getSearchValue())).or().like(NutritionSetting::getOutpatientNo, bo.getSearchValue()));
+        }
+        if (dateRange != null && dateRange.size() == 2) {
+            String startTime = sdf.format(dateRange.get(0)) + " 00:00:00";  // 开始时间
+            String endTime = sdf.format(dateRange.get(1)) + " 23:59:59";    // 结束时间
+            if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
+                lqw.between(NutritionSetting::getCreateTime, startTime, endTime);
+
+            }
+        }
+        return lqw;
+    }
+
+    /**
+     * 新增营养设定
+     *
+     * @param bo 营养设定
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(NutritionSettingBo bo) {
+        NutritionSetting add = MapstructUtils.convert(bo, NutritionSetting.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改营养设定
+     *
+     * @param bo 营养设定
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(NutritionSettingBo bo) {
+        NutritionSetting update = MapstructUtils.convert(bo, NutritionSetting.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(NutritionSetting entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除营养设定信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+
+    public Map<String, String> calculateEnergyRequirements(
+        String gender, int age, double height, double weight,
+        Integer activity, Integer stressType) {
+
+        Map<String, String> activityMap = Optional.ofNullable(dictDataService.selectMapByType("physical_activity").getData())
+            .orElseGet(MapUtil::newHashMap)
+            .entrySet().stream()
+            .collect(Collectors.toMap(
+                Map.Entry::getKey,
+                entry -> entry.getValue().getDictLabel()
+            ));
+
+// 2. 保持一致的Map方向(根据业务需求选择一种)
+        Map<String, String> stressTypeMap = Optional.ofNullable(dictDataService.selectMapByType("stress_level").getData())
+            .orElseGet(MapUtil::newHashMap)
+            .entrySet().stream()
+            .collect(Collectors.toMap(
+                Map.Entry::getKey,
+                entry -> entry.getValue().getDictLabel()
+            ));
+        String activityLevel = null;
+        String stressLevel = null;
+        if (null != activity) {
+            activityLevel = activityMap.get(Integer.toString(activity));
+        }
+        if (null != stressType) {
+            stressLevel = stressTypeMap.get(Integer.toString(stressType));
+
+        }
+
+        Map<String, String> results = new HashMap<>();
+
+        // 1. 计算基础代谢率 (BEE) - 使用毛德倩公式
+        double bee;
+        if ("男".equals(gender)) {
+            bee = 48.5 * weight + 2954.7;
+        } else {
+            bee = 41.9 * weight + 2869.1;
+        }
+
+        // 2. 活动系数转换
+        double activityFactor = 1.2; // 默认静态
+        if (null != activityLevel) {
+            if (activityLevel.contains("低")) {
+                activityFactor = 1.375;
+            } else if (activityLevel.contains("中")) {
+                activityFactor = 1.55;
+            } else if (activityLevel.contains("重")) {
+                activityFactor = 1.725;
+            }
+        }
+
+        // 3. 应激系数转换
+        double stressFactor = 1.0; // 默认基础状态
+        if (null != stressLevel) {
+            if (stressLevel.contains("低度")) {
+                stressFactor = 1.1;
+            } else if (stressLevel.contains("中度")) {
+                stressFactor = 1.2;
+            } else if (stressLevel.contains("严重")) {
+                stressFactor = 1.3;
+            } else if (stressLevel.contains("恶性")) {
+                stressFactor = 1.4;
+            }
+        }
+
+        // 4. 计算总热量需求 (TDEE)
+        double tdeeKcal = bee * activityFactor * stressFactor;
+        double tdeeKj = tdeeKcal * 4.184; // 1 kcal = 4.184 kJ
+        double kcalPerKg = tdeeKcal / weight;
+
+        double proteinCaloriePercentage = 20;
+        double fatCaloriePercentage = 20;
+        double carbohydrateCaloriePercentage = 50;
+
+        // 5. 设置计算结果
+        results.put("caloriesKcalPerDay", String.format("%.2f", tdeeKcal));
+        results.put("caloriesKjPerDay", String.format("%.2f", tdeeKj));
+        results.put("caloriesKcalPerKgDay", String.format("%.2f", kcalPerKg));
+
+        results.put("proteinCaloriePercentage", String.format("%.2f", proteinCaloriePercentage));//蛋白质热量占比
+        results.put("proteinGPerKgDay", String.format("%.2f", tdeeKj));
+        results.put("proteinGPerDay", String.format("%.2f", kcalPerKg));
+
+        results.put("fatCaloriePercentage", String.format("%.2f", fatCaloriePercentage));//脂肪热量占比
+        results.put("fatGPerKgDay", String.format("%.2f", kcalPerKg));
+        results.put("fatGPerDay", String.format("%.2f", tdeeKj));
+
+        results.put("carbohydrateCaloriePercentage", String.format("%.2f", carbohydrateCaloriePercentage));//碳水化合物占比
+        results.put("carbohydrateGPerKgDay", String.format("%.2f", kcalPerKg));
+        results.put("carbohydrateGPerDay", String.format("%.2f", tdeeKj));
+
+        results.put("calcium", NutritionDataUtil.getValueByAge("钙", null, age));
+        results.put("potassium", NutritionDataUtil.getValueByAge("钾", null, age));
+        results.put("sodium", NutritionDataUtil.getValueByAge("钠", null, age));
+        results.put("magnesium", NutritionDataUtil.getValueByAge("镁", null, age));
+        results.put("phosphorus", NutritionDataUtil.getValueByAge("磷", null, age));
+        results.put("chloride", NutritionDataUtil.getValueByAge("氯", null, age));
+        results.put("iron", NutritionDataUtil.getValueByAge("铁", gender, age));
+        results.put("selenium", NutritionDataUtil.getValueByAge("硒", null, age));
+        results.put("manganese", NutritionDataUtil.getValueByAge("锰", null, age));
+        results.put("fluoride", NutritionDataUtil.getValueByAge("氟", null, age));
+        results.put("molybdenum", NutritionDataUtil.getValueByAge("钼", null, age));
+        results.put("zinc", NutritionDataUtil.getValueByAge("锌", gender, age));
+        results.put("copper", NutritionDataUtil.getValueByAge("铜", null, age));
+        results.put("iodine", NutritionDataUtil.getValueByAge("碘", null, age));
+        results.put("chromium", NutritionDataUtil.getValueByAge("铬", null, age));
+        results.put("vitaminA", NutritionDataUtil.getValueByAge("维生素A", null, age));
+        results.put("vitaminD", NutritionDataUtil.getValueByAge("维生素D", null, age));
+        results.put("vitaminE", NutritionDataUtil.getValueByAge("维生素E", null, age));
+        results.put("vitaminK", NutritionDataUtil.getValueByAge("维生素K", null, age));
+        results.put("vitaminBOne", NutritionDataUtil.getValueByAge("维生素B1", gender, age));
+        results.put("vitaminBTwo", NutritionDataUtil.getValueByAge("维生素B2", gender, age));
+        results.put("vitaminBSix", NutritionDataUtil.getValueByAge("维生素B6", gender, age));
+        results.put("vitaminBTwelve", NutritionDataUtil.getValueByAge("维生素B12", null, age));
+        results.put("niacin", NutritionDataUtil.getValueByAge("烟酸", gender, age));
+        results.put("vitaminC", NutritionDataUtil.getValueByAge("维生素C", null, age));
+        results.put("folicAcid", NutritionDataUtil.getValueByAge("叶酸", null, age));
+        results.put("choline", NutritionDataUtil.getValueByAge("胆碱", null, age));
+        results.put("biotin", NutritionDataUtil.getValueByAge("生物素", null, age));
+        results.put("pantothenicAcid", NutritionDataUtil.getValueByAge("泛酸", null, age));
+        results.put("dietaryFiber", NutritionDataUtil.getValueByAge("膳食纤维", null, age));
+
+
+        return results;
+    }
+}

+ 7 - 0
ruoyi-admin/src/main/resources/mapper/parameter/NutritionEducationMapper.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.dromara.web.mapper.NutritionEducationMapper">
+
+</mapper>

+ 7 - 0
ruoyi-admin/src/main/resources/mapper/parameter/NutritionSettingMapper.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.dromara.web.mapper.NutritionSettingMapper">
+
+</mapper>