KMP OpenHarmony 营养热量计算器 - 食物热量和营养成分分析
摘要: 本文介绍了基于Kotlin Multiplatform(KMP)的鸿蒙跨平台营养热量计算器实现方案。该工具提供全面的营养分析功能,包括热量计算、宏量营养素(蛋白质/脂肪/碳水化合物)分析、微量营养素追踪、每日摄入评估等核心模块。通过KMP实现跨平台逻辑复用,支持鸿蒙、Android等多端部署。 核心功能: 科学计算模型:采用Mifflin-St Jeor公式计算基础代谢率,结合活动水平动态

目录
概述
本文档介绍如何在 Kotlin Multiplatform (KMP) 鸿蒙跨端开发中实现一个功能完整的营养热量计算器系统。营养热量分析是现代健康管理和健身应用中的核心需求,广泛应用于减肥管理、健身计划、营养咨询、医疗诊断等领域。这个工具提供了对食物热量和营养成分的全面分析支持,包括热量计算、宏量营养素分析(蛋白质、脂肪、碳水化合物)、微量营养素追踪、每日摄入量评估等功能。
在实际应用中,营养热量计算器广泛应用于以下场景:个人健康管理应用、健身房管理系统、营养咨询平台、医疗诊断系统、食品标签分析、膳食计划制定等。通过 KMP 框架的跨端能力,我们可以在不同平台上使用相同的营养分析逻辑,确保热量计算的准确性和一致性。
工具的特点
- 全面的营养分析:支持热量、蛋白质、脂肪、碳水化合物等多维度营养分析
- 食物数据库:包含常见食物的营养信息
- 每日摄入追踪:记录和分析每日营养摄入
- 个性化建议:根据用户目标提供营养建议
- 营养平衡评估:评估营养摄入是否均衡
- 跨端兼容:一份 Kotlin 代码可同时服务多个平台
工具功能
1. 食物热量计算
热量是衡量食物能量含量的重要指标。不同的食物含有不同的热量,准确计算食物热量对于健康管理和减肥计划至关重要。热量计算需要考虑食物的类型、重量和烹饪方式。在营养应用中,热量计算是用户最关注的信息之一。
- 基础热量查询:查询常见食物的热量含量
- 重量调整:根据实际食用量调整热量
- 烹饪方式影响:考虑不同烹饪方式对热量的影响
- 食物组合分析:计算多种食物组合的总热量
2. 宏量营养素分析
宏量营养素(蛋白质、脂肪、碳水化合物)是人体所需的主要营养物质。不同的宏量营养素对人体有不同的作用。宏量营养素分析需要考虑各种营养素的比例和总摄入量。
- 蛋白质分析:计算蛋白质含量和摄入比例
- 脂肪分析:区分饱和脂肪、不饱和脂肪等
- 碳水化合物分析:区分简单碳水和复杂碳水
- 营养素比例:计算各营养素的摄入比例
3. 微量营养素追踪
微量营养素(维生素、矿物质等)虽然需要量少,但对人体健康至关重要。微量营养素追踪需要监测维生素、矿物质、纤维素等的摄入。
- 维生素追踪:追踪各种维生素的摄入
- 矿物质监测:监测钙、铁、锌等矿物质
- 纤维素计算:计算膳食纤维的摄入量
- 缺乏风险评估:评估营养素缺乏的风险
4. 每日摄入评估
每日摄入评估是将用户的营养摄入与推荐摄入量进行比较。这需要考虑用户的年龄、性别、活动水平等因素。每日摄入评估帮助用户了解自己的营养摄入是否符合健康标准。
- 推荐摄入量:根据用户信息计算推荐摄入量
- 摄入对比:将实际摄入与推荐摄入进行比较
- 超标警告:警告营养摄入过量
- 不足提醒:提醒营养摄入不足
5. 营养平衡评估
营养平衡评估是综合考虑各种营养素摄入的评估。营养平衡对于健康和疾病预防很重要。营养平衡评估需要考虑营养素之间的相互作用。
- 平衡指数:计算营养摄入的平衡指数
- 营养评级:根据平衡指数给出评级
- 改善建议:提供改善营养平衡的建议
- 风险评估:评估营养不平衡带来的健康风险
6. 膳食计划建议
根据用户的目标和当前营养摄入,提供个性化的膳食计划建议。膳食计划建议需要考虑用户的饮食偏好和健康目标。
- 减肥计划:为减肥用户提供低热量膳食建议
- 增肌计划:为健身用户提供高蛋白膳食建议
- 健康维持:为普通用户提供均衡膳食建议
- 特殊饮食:支持素食、无麸质等特殊饮食
7. 食物替代建议
根据用户的营养目标,提供食物替代建议。食物替代建议帮助用户在保持营养的同时改变饮食习惯。
- 热量相近食物:推荐热量相近的替代食物
- 营养相近食物:推荐营养成分相近的替代食物
- 更健康选择:推荐更健康的食物替代
- 口味偏好:考虑用户的口味偏好
核心实现
1. 食物热量计算
data class Food(
val name: String,
val caloriesPer100g: Double,
val protein: Double,
val fat: Double,
val carbs: Double,
val fiber: Double
)
fun calculateFoodCalories(food: Food, weight: Double): Double {
return (food.caloriesPer100g / 100) * weight
}
fun calculateNutrients(food: Food, weight: Double): Map<String, Double> {
val multiplier = weight / 100
return mapOf(
"calories" to food.caloriesPer100g * multiplier,
"protein" to food.protein * multiplier,
"fat" to food.fat * multiplier,
"carbs" to food.carbs * multiplier,
"fiber" to food.fiber * multiplier
)
}
代码说明: 食物热量计算使用食物的基础营养数据和实际食用量进行计算。通过定义 Food 数据类,可以方便地存储和管理食物信息。计算时使用比例法,根据实际重量调整营养值。
2. 每日摄入评估
data class UserProfile(
val age: Int,
val gender: String,
val weight: Double,
val height: Double,
val activityLevel: String
)
fun calculateDailyCalorieNeeds(user: UserProfile): Double {
// 使用 Mifflin-St Jeor 公式计算基础代谢率
val bmr = if (user.gender.lowercase() == "male") {
(10 * user.weight) + (6.25 * user.height) - (5 * user.age) + 5
} else {
(10 * user.weight) + (6.25 * user.height) - (5 * user.age) - 161
}
// 根据活动水平调整
val activityMultiplier = when (user.activityLevel.lowercase()) {
"sedentary" -> 1.2
"light" -> 1.375
"moderate" -> 1.55
"active" -> 1.725
"veryactive" -> 1.9
else -> 1.5
}
return bmr * activityMultiplier
}
fun calculateMacroNeeds(dailyCalories: Double, goal: String): Map<String, Double> {
return when (goal.lowercase()) {
"weight_loss" -> mapOf(
"protein" to dailyCalories * 0.30 / 4, // 30% from protein
"fat" to dailyCalories * 0.25 / 9, // 25% from fat
"carbs" to dailyCalories * 0.45 / 4 // 45% from carbs
)
"muscle_gain" -> mapOf(
"protein" to dailyCalories * 0.35 / 4,
"fat" to dailyCalories * 0.25 / 9,
"carbs" to dailyCalories * 0.40 / 4
)
else -> mapOf(
"protein" to dailyCalories * 0.25 / 4,
"fat" to dailyCalories * 0.30 / 9,
"carbs" to dailyCalories * 0.45 / 4
)
}
}
代码说明: 每日摄入评估使用科学的公式计算用户的热量需求。Mifflin-St Jeor 公式是目前最准确的基础代谢率计算方法。根据用户的活动水平调整,可以得到更准确的每日热量需求。
3. 营养平衡评估
fun assessNutritionBalance(dailyIntake: Map<String, Double>, dailyNeeds: Map<String, Double>): Map<String, Any> {
var balanceScore = 100
val issues = mutableListOf<String>()
for ((nutrient, intake) in dailyIntake) {
val need = dailyNeeds[nutrient] ?: continue
val percentage = (intake / need) * 100
when {
percentage < 80 -> {
balanceScore -= 10
issues.add("$nutrient 摄入不足 (${percentage.toInt()}%)")
}
percentage > 120 -> {
balanceScore -= 5
issues.add("$nutrient 摄入过量 (${percentage.toInt()}%)")
}
}
}
balanceScore = balanceScore.coerceIn(0, 100)
val rating = when {
balanceScore >= 80 -> "优秀"
balanceScore >= 60 -> "良好"
balanceScore >= 40 -> "一般"
else -> "需要改善"
}
return mapOf(
"score" to balanceScore,
"rating" to rating,
"issues" to issues
)
}
代码说明: 营养平衡评估通过比较实际摄入与推荐摄入来计算平衡指数。通过识别摄入不足或过量的营养素,可以提供具体的改善建议。
4. 膳食计划建议
fun generateDietPlan(user: UserProfile, goal: String, preferences: List<String>): List<String> {
val dailyCalories = calculateDailyCalorieNeeds(user)
val macroNeeds = calculateMacroNeeds(dailyCalories, goal)
val recommendations = mutableListOf<String>()
when (goal.lowercase()) {
"weight_loss" -> {
recommendations.add("每日热量摄入: ${dailyCalories.toInt()} 卡路里")
recommendations.add("蛋白质: ${(macroNeeds["protein"] ?: 0).toInt()} 克 (帮助保持肌肉)")
recommendations.add("多吃低热量、高纤维的食物")
recommendations.add("避免高糖、高脂肪的食物")
recommendations.add("每天喝足够的水")
}
"muscle_gain" -> {
recommendations.add("每日热量摄入: ${(dailyCalories * 1.1).toInt()} 卡路里")
recommendations.add("蛋白质: ${(macroNeeds["protein"] ?: 0).toInt()} 克 (每公斤体重1.6-2.2克)")
recommendations.add("增加复杂碳水化合物的摄入")
recommendations.add("选择优质蛋白质来源")
recommendations.add("配合力量训练")
}
else -> {
recommendations.add("每日热量摄入: ${dailyCalories.toInt()} 卡路里")
recommendations.add("保持营养均衡")
recommendations.add("多吃蔬菜和水果")
recommendations.add("选择全谷物食品")
recommendations.add("限制盐和糖的摄入")
}
}
return recommendations
}
代码说明: 膳食计划建议根据用户的目标和需求提供个性化的建议。通过考虑用户的目标(减肥、增肌或维持),可以提供针对性的营养建议。
Kotlin 源代码
// NutritionCalculator.kt
data class Food(
val name: String,
val caloriesPer100g: Double,
val protein: Double,
val fat: Double,
val carbs: Double,
val fiber: Double
)
data class UserProfile(
val age: Int,
val gender: String,
val weight: Double,
val height: Double,
val activityLevel: String
)
class NutritionCalculator {
private val foodDatabase = mapOf(
"鸡胸肉" to Food("鸡胸肉", 165.0, 31.0, 3.6, 0.0, 0.0),
"鸡蛋" to Food("鸡蛋", 155.0, 13.0, 11.0, 1.1, 0.0),
"牛奶" to Food("牛奶", 61.0, 3.2, 3.3, 4.8, 0.0),
"米饭" to Food("米饭", 130.0, 2.7, 0.3, 28.0, 0.4),
"面包" to Food("面包", 265.0, 9.0, 3.3, 49.0, 2.7),
"苹果" to Food("苹果", 52.0, 0.3, 0.2, 14.0, 2.4),
"香蕉" to Food("香蕉", 89.0, 1.1, 0.3, 23.0, 2.6),
"西兰花" to Food("西兰花", 34.0, 2.8, 0.4, 7.0, 2.4),
"胡萝卜" to Food("胡萝卜", 41.0, 0.9, 0.2, 10.0, 2.8),
"三文鱼" to Food("三文鱼", 208.0, 20.0, 13.0, 0.0, 0.0)
)
fun getFood(name: String): Food? = foodDatabase[name]
fun calculateFoodCalories(food: Food, weight: Double): Double {
return (food.caloriesPer100g / 100) * weight
}
fun calculateNutrients(food: Food, weight: Double): Map<String, Double> {
val multiplier = weight / 100
return mapOf(
"calories" to food.caloriesPer100g * multiplier,
"protein" to food.protein * multiplier,
"fat" to food.fat * multiplier,
"carbs" to food.carbs * multiplier,
"fiber" to food.fiber * multiplier
)
}
fun calculateDailyCalorieNeeds(user: UserProfile): Double {
val bmr = if (user.gender.lowercase() == "male") {
(10 * user.weight) + (6.25 * user.height) - (5 * user.age) + 5
} else {
(10 * user.weight) + (6.25 * user.height) - (5 * user.age) - 161
}
val activityMultiplier = when (user.activityLevel.lowercase()) {
"sedentary" -> 1.2
"light" -> 1.375
"moderate" -> 1.55
"active" -> 1.725
"veryactive" -> 1.9
else -> 1.5
}
return bmr * activityMultiplier
}
fun calculateMacroNeeds(dailyCalories: Double, goal: String): Map<String, Double> {
return when (goal.lowercase()) {
"weight_loss" -> mapOf(
"protein" to dailyCalories * 0.30 / 4,
"fat" to dailyCalories * 0.25 / 9,
"carbs" to dailyCalories * 0.45 / 4
)
"muscle_gain" -> mapOf(
"protein" to dailyCalories * 0.35 / 4,
"fat" to dailyCalories * 0.25 / 9,
"carbs" to dailyCalories * 0.40 / 4
)
else -> mapOf(
"protein" to dailyCalories * 0.25 / 4,
"fat" to dailyCalories * 0.30 / 9,
"carbs" to dailyCalories * 0.45 / 4
)
}
}
fun assessNutritionBalance(dailyIntake: Map<String, Double>, dailyNeeds: Map<String, Double>): Map<String, Any> {
var balanceScore = 100
val issues = mutableListOf<String>()
for ((nutrient, intake) in dailyIntake) {
val need = dailyNeeds[nutrient] ?: continue
val percentage = (intake / need) * 100
when {
percentage < 80 -> {
balanceScore -= 10
issues.add("$nutrient 摄入不足 (${percentage.toInt()}%)")
}
percentage > 120 -> {
balanceScore -= 5
issues.add("$nutrient 摄入过量 (${percentage.toInt()}%)")
}
}
}
balanceScore = balanceScore.coerceIn(0, 100)
val rating = when {
balanceScore >= 80 -> "优秀"
balanceScore >= 60 -> "良好"
balanceScore >= 40 -> "一般"
else -> "需要改善"
}
return mapOf(
"score" to balanceScore,
"rating" to rating,
"issues" to issues
)
}
fun generateDietPlan(user: UserProfile, goal: String): List<String> {
val dailyCalories = calculateDailyCalorieNeeds(user)
val macroNeeds = calculateMacroNeeds(dailyCalories, goal)
val recommendations = mutableListOf<String>()
when (goal.lowercase()) {
"weight_loss" -> {
recommendations.add("每日热量摄入: ${dailyCalories.toInt()} 卡路里")
recommendations.add("蛋白质: ${(macroNeeds["protein"] ?: 0).toInt()} 克")
recommendations.add("多吃低热量、高纤维的食物")
recommendations.add("避免高糖、高脂肪的食物")
recommendations.add("每天喝足够的水")
}
"muscle_gain" -> {
recommendations.add("每日热量摄入: ${(dailyCalories * 1.1).toInt()} 卡路里")
recommendations.add("蛋白质: ${(macroNeeds["protein"] ?: 0).toInt()} 克")
recommendations.add("增加复杂碳水化合物的摄入")
recommendations.add("选择优质蛋白质来源")
recommendations.add("配合力量训练")
}
else -> {
recommendations.add("每日热量摄入: ${dailyCalories.toInt()} 卡路里")
recommendations.add("保持营养均衡")
recommendations.add("多吃蔬菜和水果")
recommendations.add("选择全谷物食品")
recommendations.add("限制盐和糖的摄入")
}
}
return recommendations
}
fun analyzeMeal(foods: List<Pair<String, Double>>): Map<String, Any> {
var totalCalories = 0.0
var totalProtein = 0.0
var totalFat = 0.0
var totalCarbs = 0.0
var totalFiber = 0.0
for ((foodName, weight) in foods) {
val food = getFood(foodName) ?: continue
val nutrients = calculateNutrients(food, weight)
totalCalories += nutrients["calories"] ?: 0.0
totalProtein += nutrients["protein"] ?: 0.0
totalFat += nutrients["fat"] ?: 0.0
totalCarbs += nutrients["carbs"] ?: 0.0
totalFiber += nutrients["fiber"] ?: 0.0
}
return mapOf(
"calories" to String.format("%.1f", totalCalories),
"protein" to String.format("%.1f", totalProtein),
"fat" to String.format("%.1f", totalFat),
"carbs" to String.format("%.1f", totalCarbs),
"fiber" to String.format("%.1f", totalFiber)
)
}
}
fun main() {
val calculator = NutritionCalculator()
val user = UserProfile(age = 30, gender = "male", weight = 75.0, height = 180.0, activityLevel = "moderate")
println("=== 营养热量计算器演示 ===\n")
// 计算每日热量需求
val dailyCalories = calculator.calculateDailyCalorieNeeds(user)
println("每日热量需求: ${dailyCalories.toInt()} 卡路里\n")
// 分析一餐
val meal = listOf(
"鸡胸肉" to 150.0,
"米饭" to 150.0,
"西兰花" to 100.0
)
val mealAnalysis = calculator.analyzeMeal(meal)
println("一餐营养分析: $mealAnalysis\n")
// 生成膳食计划
val dietPlan = calculator.generateDietPlan(user, "weight_loss")
println("减肥膳食计划:")
dietPlan.forEach { println("• $it") }
}
Kotlin 代码说明: 这个实现提供了完整的营养计算功能。NutritionCalculator 类包含了食物数据库、热量计算、营养分析等多个方法。通过使用数据类存储食物和用户信息,代码更加清晰易维护。食物数据库可以根据需要扩展。
JavaScript 编译代码
// NutritionCalculator.js
class Food {
constructor(name, caloriesPer100g, protein, fat, carbs, fiber) {
this.name = name;
this.caloriesPer100g = caloriesPer100g;
this.protein = protein;
this.fat = fat;
this.carbs = carbs;
this.fiber = fiber;
}
}
class UserProfile {
constructor(age, gender, weight, height, activityLevel) {
this.age = age;
this.gender = gender;
this.weight = weight;
this.height = height;
this.activityLevel = activityLevel;
}
}
class NutritionCalculator {
constructor() {
this.foodDatabase = {
"鸡胸肉": new Food("鸡胸肉", 165, 31, 3.6, 0, 0),
"鸡蛋": new Food("鸡蛋", 155, 13, 11, 1.1, 0),
"牛奶": new Food("牛奶", 61, 3.2, 3.3, 4.8, 0),
"米饭": new Food("米饭", 130, 2.7, 0.3, 28, 0.4),
"面包": new Food("面包", 265, 9, 3.3, 49, 2.7),
"苹果": new Food("苹果", 52, 0.3, 0.2, 14, 2.4),
"香蕉": new Food("香蕉", 89, 1.1, 0.3, 23, 2.6),
"西兰花": new Food("西兰花", 34, 2.8, 0.4, 7, 2.4),
"胡萝卜": new Food("胡萝卜", 41, 0.9, 0.2, 10, 2.8),
"三文鱼": new Food("三文鱼", 208, 20, 13, 0, 0)
};
}
getFood(name) {
return this.foodDatabase[name] || null;
}
calculateFoodCalories(food, weight) {
return (food.caloriesPer100g / 100) * weight;
}
calculateNutrients(food, weight) {
const multiplier = weight / 100;
return {
calories: food.caloriesPer100g * multiplier,
protein: food.protein * multiplier,
fat: food.fat * multiplier,
carbs: food.carbs * multiplier,
fiber: food.fiber * multiplier
};
}
calculateDailyCalorieNeeds(user) {
let bmr;
if (user.gender.toLowerCase() === "male") {
bmr = (10 * user.weight) + (6.25 * user.height) - (5 * user.age) + 5;
} else {
bmr = (10 * user.weight) + (6.25 * user.height) - (5 * user.age) - 161;
}
let activityMultiplier;
switch (user.activityLevel.toLowerCase()) {
case "sedentary": activityMultiplier = 1.2; break;
case "light": activityMultiplier = 1.375; break;
case "moderate": activityMultiplier = 1.55; break;
case "active": activityMultiplier = 1.725; break;
case "veryactive": activityMultiplier = 1.9; break;
default: activityMultiplier = 1.5;
}
return bmr * activityMultiplier;
}
calculateMacroNeeds(dailyCalories, goal) {
switch (goal.toLowerCase()) {
case "weight_loss":
return {
protein: (dailyCalories * 0.30) / 4,
fat: (dailyCalories * 0.25) / 9,
carbs: (dailyCalories * 0.45) / 4
};
case "muscle_gain":
return {
protein: (dailyCalories * 0.35) / 4,
fat: (dailyCalories * 0.25) / 9,
carbs: (dailyCalories * 0.40) / 4
};
default:
return {
protein: (dailyCalories * 0.25) / 4,
fat: (dailyCalories * 0.30) / 9,
carbs: (dailyCalories * 0.45) / 4
};
}
}
assessNutritionBalance(dailyIntake, dailyNeeds) {
let balanceScore = 100;
const issues = [];
for (const nutrient in dailyIntake) {
const intake = dailyIntake[nutrient];
const need = dailyNeeds[nutrient];
if (!need) continue;
const percentage = (intake / need) * 100;
if (percentage < 80) {
balanceScore -= 10;
issues.push(`${nutrient} 摄入不足 (${Math.floor(percentage)}%)`);
} else if (percentage > 120) {
balanceScore -= 5;
issues.push(`${nutrient} 摄入过量 (${Math.floor(percentage)}%)`);
}
}
balanceScore = Math.max(0, Math.min(100, balanceScore));
let rating;
if (balanceScore >= 80) rating = "优秀";
else if (balanceScore >= 60) rating = "良好";
else if (balanceScore >= 40) rating = "一般";
else rating = "需要改善";
return {
score: balanceScore,
rating: rating,
issues: issues
};
}
generateDietPlan(user, goal) {
const dailyCalories = this.calculateDailyCalorieNeeds(user);
const macroNeeds = this.calculateMacroNeeds(dailyCalories, goal);
const recommendations = [];
switch (goal.toLowerCase()) {
case "weight_loss":
recommendations.push(`每日热量摄入: ${Math.floor(dailyCalories)} 卡路里`);
recommendations.push(`蛋白质: ${Math.floor(macroNeeds.protein)} 克`);
recommendations.push("多吃低热量、高纤维的食物");
recommendations.push("避免高糖、高脂肪的食物");
recommendations.push("每天喝足够的水");
break;
case "muscle_gain":
recommendations.push(`每日热量摄入: ${Math.floor(dailyCalories * 1.1)} 卡路里`);
recommendations.push(`蛋白质: ${Math.floor(macroNeeds.protein)} 克`);
recommendations.push("增加复杂碳水化合物的摄入");
recommendations.push("选择优质蛋白质来源");
recommendations.push("配合力量训练");
break;
default:
recommendations.push(`每日热量摄入: ${Math.floor(dailyCalories)} 卡路里`);
recommendations.push("保持营养均衡");
recommendations.push("多吃蔬菜和水果");
recommendations.push("选择全谷物食品");
recommendations.push("限制盐和糖的摄入");
}
return recommendations;
}
analyzeMeal(foods) {
let totalCalories = 0;
let totalProtein = 0;
let totalFat = 0;
let totalCarbs = 0;
let totalFiber = 0;
for (const [foodName, weight] of foods) {
const food = this.getFood(foodName);
if (!food) continue;
const nutrients = this.calculateNutrients(food, weight);
totalCalories += nutrients.calories;
totalProtein += nutrients.protein;
totalFat += nutrients.fat;
totalCarbs += nutrients.carbs;
totalFiber += nutrients.fiber;
}
return {
calories: totalCalories.toFixed(1),
protein: totalProtein.toFixed(1),
fat: totalFat.toFixed(1),
carbs: totalCarbs.toFixed(1),
fiber: totalFiber.toFixed(1)
};
}
}
// 使用示例
const calculator = new NutritionCalculator();
const user = new UserProfile(30, "male", 75, 180, "moderate");
console.log("=== 营养热量计算器演示 ===\n");
const dailyCalories = calculator.calculateDailyCalorieNeeds(user);
console.log(`每日热量需求: ${Math.floor(dailyCalories)} 卡路里\n`);
const meal = [
["鸡胸肉", 150],
["米饭", 150],
["西兰花", 100]
];
const mealAnalysis = calculator.analyzeMeal(meal);
console.log("一餐营养分析:", mealAnalysis);
const dietPlan = calculator.generateDietPlan(user, "weight_loss");
console.log("\n减肥膳食计划:");
dietPlan.forEach(item => console.log("• " + item));
JavaScript 代码说明: JavaScript 版本是 Kotlin 代码的直接转译。由于 JavaScript 和 Kotlin 在语法上有差异,我们使用 class 定义数据类,使用 switch 语句替代 when 表达式。整体逻辑和算法与 Kotlin 版本保持一致,确保跨平台的一致性。
ArkTS 调用代码
// NutritionCalculatorPage.ets
import { NutritionCalculator } from './NutritionCalculator';
@Entry
@Component
struct NutritionCalculatorPage {
@State selectedFoods: Array<{ name: string, weight: number }> = [];
@State mealAnalysis: string = '';
@State userAge: number = 30;
@State userGender: string = 'male';
@State userWeight: number = 75;
@State userHeight: number = 180;
@State userActivity: string = 'moderate';
@State goal: string = 'weight_loss';
@State showResult: boolean = false;
@State isLoading: boolean = false;
private calculator: NutritionCalculator = new NutritionCalculator();
private foodList = [
'鸡胸肉', '鸡蛋', '牛奶', '米饭', '面包',
'苹果', '香蕉', '西兰花', '胡萝卜', '三文鱼'
];
private genderOptions = [
{ label: '男性', value: 'male' },
{ label: '女性', value: 'female' }
];
private activityOptions = [
{ label: '久坐', value: 'sedentary' },
{ label: '轻度活动', value: 'light' },
{ label: '中度活动', value: 'moderate' },
{ label: '活跃', value: 'active' },
{ label: '非常活跃', value: 'veryactive' }
];
private goalOptions = [
{ label: '减肥', value: 'weight_loss' },
{ label: '增肌', value: 'muscle_gain' },
{ label: '维持', value: 'maintain' }
];
performAnalysis() {
this.isLoading = true;
try {
const user = {
age: this.userAge,
gender: this.userGender,
weight: this.userWeight,
height: this.userHeight,
activityLevel: this.userActivity
};
const dailyCalories = this.calculator.calculateDailyCalorieNeeds(user);
const dietPlan = this.calculator.generateDietPlan(user, this.goal);
let resultText = "🥗 营养分析结果\n";
resultText += "━━━━━━━━━━━━━━━━━━━━━\n";
resultText += `每日热量需求: ${Math.floor(dailyCalories)} 卡路里\n`;
resultText += `目标: ${this.goal === 'weight_loss' ? '减肥' : this.goal === 'muscle_gain' ? '增肌' : '维持'}\n\n`;
resultText += "📋 膳食建议:\n";
dietPlan.forEach((item: string) => {
resultText += `• ${item}\n`;
});
this.mealAnalysis = resultText;
this.showResult = true;
} catch (error) {
this.mealAnalysis = '分析失败: ' + (error instanceof Error ? error.message : String(error));
this.showResult = true;
} finally {
this.isLoading = false;
}
}
build() {
Column() {
// 标题
Text('营养热量计算器')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 })
.textAlign(TextAlign.Center)
.width('100%')
// 用户信息输入
Scroll() {
Column() {
// 年龄
Column() {
Text(`年龄: ${this.userAge}岁`)
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 10 })
Slider({ value: this.userAge, min: 18, max: 80, step: 1 })
.onChange((value: number) => {
this.userAge = value;
})
.width('100%')
}
.width('100%')
.padding(12)
.backgroundColor('#f5f5f5')
.borderRadius(8)
.margin({ bottom: 15 })
// 性别
Column() {
Text('性别')
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 10 })
Select(this.genderOptions)
.value(this.userGender)
.onSelect((index: number, value?: string) => {
this.userGender = value || 'male';
})
.width('100%')
.height(40)
}
.width('100%')
.padding(12)
.backgroundColor('#f5f5f5')
.borderRadius(8)
.margin({ bottom: 15 })
// 体重
Column() {
Text(`体重: ${this.userWeight}kg`)
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 10 })
Slider({ value: this.userWeight, min: 40, max: 150, step: 1 })
.onChange((value: number) => {
this.userWeight = value;
})
.width('100%')
}
.width('100%')
.padding(12)
.backgroundColor('#f5f5f5')
.borderRadius(8)
.margin({ bottom: 15 })
// 身高
Column() {
Text(`身高: ${this.userHeight}cm`)
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 10 })
Slider({ value: this.userHeight, min: 140, max: 220, step: 1 })
.onChange((value: number) => {
this.userHeight = value;
})
.width('100%')
}
.width('100%')
.padding(12)
.backgroundColor('#f5f5f5')
.borderRadius(8)
.margin({ bottom: 15 })
// 活动水平
Column() {
Text('活动水平')
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 10 })
Select(this.activityOptions)
.value(this.userActivity)
.onSelect((index: number, value?: string) => {
this.userActivity = value || 'moderate';
})
.width('100%')
.height(40)
}
.width('100%')
.padding(12)
.backgroundColor('#f5f5f5')
.borderRadius(8)
.margin({ bottom: 15 })
// 目标
Column() {
Text('目标')
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 10 })
Select(this.goalOptions)
.value(this.goal)
.onSelect((index: number, value?: string) => {
this.goal = value || 'weight_loss';
})
.width('100%')
.height(40)
}
.width('100%')
.padding(12)
.backgroundColor('#f5f5f5')
.borderRadius(8)
}
.width('100%')
.padding(15)
.backgroundColor('#ffffff')
.borderRadius(10)
.border({ width: 1, color: '#eeeeee' })
}
.height('50%')
.margin({ bottom: 20 })
// 分析按钮
Button('分析营养')
.width('100%')
.height(45)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.backgroundColor('#1B7837')
.fontColor('#ffffff')
.onClick(() => {
this.performAnalysis();
})
.margin({ bottom: 20 })
// 结果显示
if (this.showResult) {
Column() {
Scroll() {
Text(this.mealAnalysis)
.fontSize(12)
.fontColor('#333333')
.width('100%')
.padding(12)
.fontFamily('monospace')
.textAlign(TextAlign.Start)
}
.width('100%')
.height('100%')
}
.width('100%')
.height('45%')
.padding(15)
.backgroundColor('#ffffff')
.borderRadius(10)
.border({ width: 1, color: '#eeeeee' })
}
Blank()
}
.width('100%')
.height('100%')
.padding(15)
.backgroundColor('#f5f5f5')
}
}
ArkTS 代码说明: ArkTS 调用代码展示了如何在 OpenHarmony 应用中使用营养计算器。页面包含用户信息输入(年龄、性别、体重、身高、活动水平、目标)、分析按钮和结果显示区域。通过 @State 装饰器管理状态,实现了完整的用户交互流程。用户可以输入个人信息,选择健身目标,然后点击分析按钮获得个性化的营养建议。
实战案例
案例1:健身房管理系统
在健身房管理系统中,需要为会员提供个性化的营养计划。
fun createMemberNutritionPlan(memberId: String, goal: String, preferences: List<String>): Map<String, Any> {
val calculator = NutritionCalculator()
val member = getMemberProfile(memberId)
val dailyCalories = calculator.calculateDailyCalorieNeeds(member)
val macroNeeds = calculator.calculateMacroNeeds(dailyCalories, goal)
val dietPlan = calculator.generateDietPlan(member, goal)
return mapOf(
"memberId" to memberId,
"dailyCalories" to dailyCalories,
"macroNeeds" to macroNeeds,
"dietPlan" to dietPlan,
"createdDate" to System.currentTimeMillis()
)
}
案例2:营养咨询应用
在营养咨询应用中,需要分析用户的膳食并提供改善建议。
fun analyzeDailyDiet(meals: List<List<Pair<String, Double>>>): Map<String, Any> {
val calculator = NutritionCalculator()
var totalCalories = 0.0
var totalProtein = 0.0
var totalFat = 0.0
var totalCarbs = 0.0
for (meal in meals) {
val analysis = calculator.analyzeMeal(meal)
totalCalories += (analysis["calories"] as? String)?.toDoubleOrNull() ?: 0.0
totalProtein += (analysis["protein"] as? String)?.toDoubleOrNull() ?: 0.0
totalFat += (analysis["fat"] as? String)?.toDoubleOrNull() ?: 0.0
totalCarbs += (analysis["carbs"] as? String)?.toDoubleOrNull() ?: 0.0
}
return mapOf(
"totalCalories" to totalCalories,
"totalProtein" to totalProtein,
"totalFat" to totalFat,
"totalCarbs" to totalCarbs
)
}
案例3:医疗诊断系统
在医疗诊断系统中,需要根据患者的营养摄入评估健康状况。
fun assessPatientNutrition(patientId: String, dailyIntake: Map<String, Double>): String {
val calculator = NutritionCalculator()
val patient = getPatientProfile(patientId)
val dailyCalories = calculator.calculateDailyCalorieNeeds(patient)
val dailyNeeds = calculator.calculateMacroNeeds(dailyCalories, "maintain")
val assessment = calculator.assessNutritionBalance(dailyIntake, dailyNeeds)
return when (assessment["rating"]) {
"优秀" -> "营养摄入均衡,继续保持"
"良好" -> "营养摄入基本均衡,可适当调整"
"一般" -> "营养摄入不够均衡,建议改善"
else -> "营养摄入严重不均衡,需要专业指导"
}
}
最佳实践
1. 数据准确性
使用准确的食物营养数据。建议从官方营养数据库获取数据,而不是使用估计值。
2. 个性化计算
根据用户的个人信息(年龄、性别、体重、身高、活动水平)进行计算,确保结果的准确性。
3. 定期更新
定期更新食物数据库和营养建议,确保信息的最新性。
4. 用户教育
提供清晰的解释和教育内容,帮助用户理解营养信息。
5. 隐私保护
妥善处理用户的个人健康信息,确保隐私安全。
6. 专业指导
对于特殊情况(如医学饮食、过敏症等),建议用户咨询专业营养师。
总结
营养热量计算器是现代健康管理应用中的重要组件。通过 KMP 框架,我们可以创建一个跨端的营养分析系统,在 Kotlin、JavaScript 和 ArkTS 中使用相同的计算逻辑。这不仅提高了代码的可维护性,还确保了不同平台上计算结果的一致性。
在实际应用中,合理使用营养热量计算器可以帮助用户更好地管理健康。无论是减肥、增肌还是维持健康,营养计算器都能提供科学的指导。通过提供个性化的营养建议和详细的营养分析,我们可以帮助用户制定更加科学的膳食计划,实现健康目标。
更多推荐


所有评论(0)