在这里插入图片描述

在这里插入图片描述

目录

  1. 概述
  2. 工具功能
  3. 核心实现
  4. Kotlin 源代码
  5. JavaScript 编译代码
  6. ArkTS 调用代码
  7. 实战案例
  8. 最佳实践

概述

本文档介绍如何在 Kotlin Multiplatform (KMP) 鸿蒙跨端开发中实现一个完整的健身房管理系统,特别是会员健身计划生成器。健身房管理涉及会员信息管理、身体评估、个性化训练计划生成、热量管理和营养建议等多个方面。这个案例展示了如何使用 Kotlin 的数据处理、算法设计和字符串生成来创建一个功能丰富的健身管理工具。

会员健身计划生成器是健身房管理系统的核心功能,它能够根据会员的基本信息(体重、身高、年龄)和健身等级(初级、中级、高级),自动生成个性化的训练计划、营养建议和健身指导。通过 KMP,这个工具可以无缝编译到 JavaScript,在 OpenHarmony 应用中运行,为健身房管理者和会员提供专业的健身指导。

工具的特点

  • 会员管理:完整的会员信息管理,包括会员ID、入会日期、到期日期等
  • 身体评估:综合评估会员的体质状况,计算BMI和目标体重
  • 个性化计划:根据健身等级生成不同的训练计划
  • 热量管理:精确计算每日热量需求和训练消耗
  • 营养指导:提供科学的营养建议(蛋白质、碳水化合物、脂肪)
  • 跨端兼容:一份 Kotlin 代码可同时服务多个平台

工具功能

1. 会员信息管理

系统为每个会员生成唯一的会员ID,格式为 GYM 加上随机数字。同时记录会员的入会日期和到期日期,帮助管理者追踪会员的有效期。会员信息包括:

  • 姓名:会员的真实姓名
  • 会员ID:唯一标识,用于系统管理
  • 入会日期:会员加入健身房的日期
  • 到期日期:会员卡的到期日期
  • 等级:会员的健身等级(初级、中级、高级)

2. 身体评估系统

系统通过计算 BMI(身体质量指数)来评估会员的体质状况,并根据体质状况确定目标体重。BMI 的计算公式为:BMI = 体重(kg) / 身高²(m²)。

根据 BMI 值的不同范围,系统将会员分为四个体质等级:

  • 偏瘦 (BMI < 18.5):目标体重为正常范围的中间值
  • 正常 (18.5 ≤ BMI < 24.9):目标体重等于当前体重
  • 超重 (24.9 ≤ BMI < 29.9):目标体重为正常范围的上限
  • 肥胖 (BMI ≥ 29.9):目标体重为正常范围的上限

系统还会计算会员需要调整的体重,帮助会员了解自己的目标。

3. 个性化训练计划

系统根据会员的健身等级生成不同的训练计划:

初级 (Beginner)
  • 每周训练:3 天
  • 每次时长:45 分钟
  • 重点:有氧运动、基础力量、柔韧性
  • 训练安排
    • 周一:有氧运动(跑步/骑车)30分钟 + 拉伸 15分钟
    • 周三:基础力量训练(上身)45分钟
    • 周五:有氧运动(游泳/椭圆机)30分钟 + 拉伸 15分钟
中级 (Intermediate)
  • 每周训练:4 天
  • 每次时长:60 分钟
  • 重点:力量训练、有氧运动、核心训练
  • 训练安排
    • 周一:胸部和三头肌 + 有氧 20分钟
    • 周二:有氧运动(HIIT)30分钟
    • 周三:背部和二头肌 + 核心训练
    • 周四:腿部训练 + 有氧 20分钟
高级 (Advanced)
  • 每周训练:5 天
  • 每次时长:90 分钟
  • 重点:高强度间歇、肌肉增长、功能性训练
  • 训练安排
    • 周一:胸部爆发力训练 + HIIT 30分钟
    • 周二:背部和核心 + 功能性训练
    • 周三:腿部力量 + 有氧冲刺
    • 周四:肩部和手臂 + 代谢训练
    • 周五:全身功能性训练

4. 心率管理

系统根据会员的年龄计算最大心率(220 - 年龄),并进一步计算训练心率范围(最大心率的 60%-85%)。这个范围是进行有效训练时的理想心率范围,可以帮助会员更科学地进行运动训练。

5. 热量管理

系统计算会员的基础代谢率(BMR)和每日热量需求,然后根据健身等级计算训练消耗的热量:

  • 初级:每日热量需求的 20%
  • 中级:每日热量需求的 35%
  • 高级:每日热量需求的 50%

这些数据可以帮助会员了解自己的热量摄入和消耗情况。

6. 营养建议

系统根据会员的体重提供科学的营养建议:

  • 蛋白质:体重 × 1.6 克/天(用于肌肉合成和修复)
  • 碳水化合物:体重 × 3.0 克/天(用于能量供应)
  • 脂肪:体重 × 0.8 克/天(用于激素合成和吸收)

系统还会计算这些营养物质提供的热量,帮助会员制定合理的饮食计划。


核心实现

算法原理

健身房管理系统的核心算法包括:

  1. BMI 计算和体质评估:快速评估会员的体质状况
  2. 目标体重计算:根据体质状况确定科学的目标体重
  3. 训练计划生成:根据健身等级生成个性化的训练计划
  4. 心率区间计算:基于年龄的科学训练指导
  5. 热量计算:精确计算基础代谢率和训练消耗
  6. 营养建议生成:根据体重的科学营养指导

数据验证

系统对输入数据进行严格的验证:

  • 检查输入格式是否正确(必须包含 5 个字段)
  • 检查数值是否有效(体重、身高、年龄都必须大于 0)
  • 检查健身等级是否有效(必须是 beginner、intermediate 或 advanced)

这些验证确保了计算的准确性和系统的稳定性。

个性化计划生成

系统根据会员的具体情况生成个性化的训练计划和建议:

  • 根据体质状况提供体重调整建议
  • 根据健身等级提供不同的训练计划
  • 根据年龄和体重提供心率和热量指导
  • 根据体重提供营养建议

Kotlin 源代码

// 案例 32: 健身房管理系统 - 会员健身计划生成器
@OptIn(ExperimentalJsExport::class)
@JsExport
fun gymMembershipPlanner(inputData: String = "张三 75 1.75 30 beginner"): String {
    if (inputData.isEmpty()) {
        return "❌ 错误: 输入不能为空\n请输入: 姓名 体重(kg) 身高(m) 年龄(岁) 等级(beginner/intermediate/advanced)"
    }
    
    val parts = inputData.trim().split(" ")
    if (parts.size != 5) {
        return "❌ 错误: 输入格式不正确\n请输入: 姓名 体重(kg) 身高(m) 年龄(岁) 等级"
    }
    
    val memberName = parts[0]
    val weight = parts[1].toDoubleOrNull()
    val height = parts[2].toDoubleOrNull()
    val age = parts[3].toIntOrNull()
    val level = parts[4].lowercase()
    
    if (weight == null || height == null || age == null) {
        return "❌ 错误: 数值输入无效"
    }
    
    if (weight <= 0 || height <= 0 || age <= 0) {
        return "❌ 错误: 输入值必须大于 0"
    }
    
    if (level !in listOf("beginner", "intermediate", "advanced")) {
        return "❌ 错误: 等级必须是 beginner/intermediate/advanced"
    }
    
    // 1. 计算 BMI
    val bmi = weight / (height * height)
    val bmiCategory = when {
        bmi < 18.5 -> "偏瘦"
        bmi < 24.9 -> "正常"
        bmi < 29.9 -> "超重"
        else -> "肥胖"
    }
    
    // 2. 确定目标体重
    val targetWeight = when (bmiCategory) {
        "偏瘦" -> (18.5 * height * height + 24.9 * height * height) / 2
        "正常" -> weight
        "超重", "肥胖" -> 24.9 * height * height
        else -> weight
    }
    
    // 3. 计算需要调整的体重
    val weightDifference = targetWeight - weight
    
    // 4. 根据等级设置训练计划
    val (weeklyTraining, dailyDuration, focusAreas) = when (level) {
        "beginner" -> Triple(3, 45, listOf("有氧运动", "基础力量", "柔韧性"))
        "intermediate" -> Triple(4, 60, listOf("力量训练", "有氧运动", "核心训练"))
        "advanced" -> Triple(5, 90, listOf("高强度间歇", "肌肉增长", "功能性训练"))
        else -> Triple(3, 45, listOf("有氧运动", "基础力量", "柔韧性"))
    }
    
    // 5. 计算每周训练量
    val weeklyMinutes = weeklyTraining * dailyDuration
    
    // 6. 根据年龄和等级计算最大心率和训练心率
    val maxHeartRate = 220 - age
    val trainingHeartRateMin = (maxHeartRate * 0.6).toInt()
    val trainingHeartRateMax = (maxHeartRate * 0.85).toInt()
    
    // 7. 计算每日热量消耗
    val bmr = 10 * weight + 6.25 * height * 100 - 5 * age + 5
    val dailyCalories = bmr * 1.5
    val trainingCalories = when (level) {
        "beginner" -> dailyCalories * 0.2
        "intermediate" -> dailyCalories * 0.35
        "advanced" -> dailyCalories * 0.5
        else -> dailyCalories * 0.2
    }
    
    // 8. 生成营养建议
    val proteinGrams = (weight * 1.6).toInt()
    val carbsGrams = (weight * 3.0).toInt()
    val fatsGrams = (weight * 0.8).toInt()
    
    // 9. 生成训练计划
    val trainingPlan = mutableListOf<String>()
    when (level) {
        "beginner" -> {
            trainingPlan.add("周一: 有氧运动 (跑步/骑车) 30分钟 + 拉伸 15分钟")
            trainingPlan.add("周三: 基础力量训练 (上身) 45分钟")
            trainingPlan.add("周五: 有氧运动 (游泳/椭圆机) 30分钟 + 拉伸 15分钟")
        }
        "intermediate" -> {
            trainingPlan.add("周一: 胸部和三头肌 + 有氧 20分钟")
            trainingPlan.add("周二: 有氧运动 (HIIT) 30分钟")
            trainingPlan.add("周三: 背部和二头肌 + 核心训练")
            trainingPlan.add("周四: 腿部训练 + 有氧 20分钟")
        }
        "advanced" -> {
            trainingPlan.add("周一: 胸部爆发力训练 + HIIT 30分钟")
            trainingPlan.add("周二: 背部和核心 + 功能性训练")
            trainingPlan.add("周三: 腿部力量 + 有氧冲刺")
            trainingPlan.add("周四: 肩部和手臂 + 代谢训练")
            trainingPlan.add("周五: 全身功能性训练")
        }
        else -> trainingPlan.add("请选择有效的等级")
    }
    
    // 10. 生成会员卡信息
    val memberId = "GYM${(kotlin.random.Random.nextDouble() * 100000).toInt()}"
    val joinDate = "2024-01-15"
    val expiryDate = "2025-01-15"
    
    return "🏋️ 健身房会员管理系统\n" +
           "━━━━━━━━━━━━━━━━━━━━━\n" +
           "1️⃣ 会员信息:\n" +
           "  姓名: $memberName\n" +
           "  会员ID: $memberId\n" +
           "  入会日期: $joinDate\n" +
           "  到期日期: $expiryDate\n" +
           "  等级: ${level.uppercase()}\n\n" +
           "2️⃣ 身体评估:\n" +
           "  体重: $weight kg\n" +
           "  身高: $height m\n" +
           "  年龄: $age 岁\n" +
           "  BMI: ${(bmi * 10).toInt() / 10.0}\n" +
           "  体质: $bmiCategory\n" +
           "  目标体重: ${(targetWeight * 10).toInt() / 10.0} kg\n" +
           "  需要调整: ${if (weightDifference > 0) "增加 ${(weightDifference * 10).toInt() / 10.0} kg" else "减少 ${(-weightDifference * 10).toInt() / 10.0} kg"}\n\n" +
           "3️⃣ 训练计划:\n" +
           "  等级: ${level.uppercase()}\n" +
           "  每周训练: $weeklyTraining 天\n" +
           "  每次时长: $dailyDuration 分钟\n" +
           "  每周总量: $weeklyMinutes 分钟\n" +
           "  训练心率: $trainingHeartRateMin - $trainingHeartRateMax bpm\n" +
           "  重点: ${focusAreas.joinToString(", ")}\n\n" +
           "4️⃣ 详细训练安排:\n" +
           trainingPlan.mapIndexed { index, plan -> "  ${index + 1}. $plan" }.joinToString("\n") + "\n\n" +
           "5️⃣ 热量管理:\n" +
           "  基础代谢率: ${(bmr * 10).toInt() / 10.0} kcal/天\n" +
           "  每日需求: ${(dailyCalories * 10).toInt() / 10.0} kcal\n" +
           "  训练消耗: ${(trainingCalories * 10).toInt() / 10.0} kcal/天\n\n" +
           "6️⃣ 营养建议 (每日):\n" +
           "  蛋白质: $proteinGrams g (${(proteinGrams * 4)} kcal)\n" +
           "  碳水化合物: $carbsGrams g (${(carbsGrams * 4)} kcal)\n" +
           "  脂肪: $fatsGrams g (${(fatsGrams * 9)} kcal)\n\n" +
           "7️⃣ 健身建议:\n" +
           "  • 每周坚持 $weeklyTraining 天训练\n" +
           "  • 每次训练后进行 10-15 分钟拉伸\n" +
           "  • 保证充足睡眠 (7-9 小时)\n" +
           "  • 定期补充水分\n" +
           "  • 每月复测一次身体指标\n\n" +
           "━━━━━━━━━━━━━━━━━━━━━\n" +
           "✅ 会员计划生成完成!"
}

Kotlin 代码详解

这个 Kotlin 函数实现了一个完整的健身房会员管理系统。函数接收一个字符串参数,包含五个用空格分隔的数据:姓名、体重(kg)、身高(m)、年龄(岁)和健身等级(beginner/intermediate/advanced)。

首先,函数进行严格的输入验证。它检查输入是否为空,是否包含正确数量的字段,以及这些字段是否有效。这确保了后续计算的准确性。

接下来,函数计算 BMI 值,并根据 BMI 值将会员分为四个体质等级。同时,它根据体质等级确定目标体重,并计算会员需要调整的体重。

然后,函数根据健身等级设置训练计划,包括每周训练天数、每次时长和训练重点。它还计算最大心率和训练心率范围,这对会员的安全训练很重要。

函数还计算会员的基础代谢率和每日热量需求,然后根据健身等级计算训练消耗的热量。这些数据可以帮助会员制定合理的饮食计划。

最后,函数生成详细的训练计划、营养建议和健身指导,并返回一个格式化的结果字符串。


JavaScript 编译代码

// 编译后的 JavaScript 代码(部分示例)
function gymMembershipPlanner(inputData) {
    if (inputData === undefined) {
        inputData = "张三 75 1.75 30 beginner";
    }
    
    if (inputData.length === 0) {
        return "❌ 错误: 输入不能为空\n请输入: 姓名 体重(kg) 身高(m) 年龄(岁) 等级(beginner/intermediate/advanced)";
    }
    
    var parts = inputData.trim().split(" ");
    if (parts.length !== 5) {
        return "❌ 错误: 输入格式不正确\n请输入: 姓名 体重(kg) 身高(m) 年龄(岁) 等级";
    }
    
    var memberName = parts[0];
    var weight = parseFloat(parts[1]);
    var height = parseFloat(parts[2]);
    var age = parseInt(parts[3]);
    var level = parts[4].toLowerCase();
    
    if (isNaN(weight) || isNaN(height) || isNaN(age)) {
        return "❌ 错误: 数值输入无效";
    }
    
    if (weight <= 0 || height <= 0 || age <= 0) {
        return "❌ 错误: 输入值必须大于 0";
    }
    
    if (!["beginner", "intermediate", "advanced"].includes(level)) {
        return "❌ 错误: 等级必须是 beginner/intermediate/advanced";
    }
    
    // 计算 BMI
    var bmi = weight / (height * height);
    var bmiCategory;
    
    if (bmi < 18.5) {
        bmiCategory = "偏瘦";
    } else if (bmi < 24.9) {
        bmiCategory = "正常";
    } else if (bmi < 29.9) {
        bmiCategory = "超重";
    } else {
        bmiCategory = "肥胖";
    }
    
    // 确定目标体重
    var targetWeight;
    if (bmiCategory === "偏瘦") {
        targetWeight = (18.5 * height * height + 24.9 * height * height) / 2;
    } else if (bmiCategory === "正常") {
        targetWeight = weight;
    } else {
        targetWeight = 24.9 * height * height;
    }
    
    var weightDifference = targetWeight - weight;
    
    // 根据等级设置训练计划
    var weeklyTraining, dailyDuration, focusAreas;
    
    if (level === "beginner") {
        weeklyTraining = 3;
        dailyDuration = 45;
        focusAreas = ["有氧运动", "基础力量", "柔韧性"];
    } else if (level === "intermediate") {
        weeklyTraining = 4;
        dailyDuration = 60;
        focusAreas = ["力量训练", "有氧运动", "核心训练"];
    } else {
        weeklyTraining = 5;
        dailyDuration = 90;
        focusAreas = ["高强度间歇", "肌肉增长", "功能性训练"];
    }
    
    var weeklyMinutes = weeklyTraining * dailyDuration;
    
    // 计算心率
    var maxHeartRate = 220 - age;
    var trainingHeartRateMin = Math.floor(maxHeartRate * 0.6);
    var trainingHeartRateMax = Math.floor(maxHeartRate * 0.85);
    
    // 计算热量
    var bmr = 10 * weight + 6.25 * height * 100 - 5 * age + 5;
    var dailyCalories = bmr * 1.5;
    var trainingCalories;
    
    if (level === "beginner") {
        trainingCalories = dailyCalories * 0.2;
    } else if (level === "intermediate") {
        trainingCalories = dailyCalories * 0.35;
    } else {
        trainingCalories = dailyCalories * 0.5;
    }
    
    // 营养建议
    var proteinGrams = Math.floor(weight * 1.6);
    var carbsGrams = Math.floor(weight * 3.0);
    var fatsGrams = Math.floor(weight * 0.8);
    
    // 生成训练计划
    var trainingPlan = [];
    
    if (level === "beginner") {
        trainingPlan.push("周一: 有氧运动 (跑步/骑车) 30分钟 + 拉伸 15分钟");
        trainingPlan.push("周三: 基础力量训练 (上身) 45分钟");
        trainingPlan.push("周五: 有氧运动 (游泳/椭圆机) 30分钟 + 拉伸 15分钟");
    } else if (level === "intermediate") {
        trainingPlan.push("周一: 胸部和三头肌 + 有氧 20分钟");
        trainingPlan.push("周二: 有氧运动 (HIIT) 30分钟");
        trainingPlan.push("周三: 背部和二头肌 + 核心训练");
        trainingPlan.push("周四: 腿部训练 + 有氧 20分钟");
    } else {
        trainingPlan.push("周一: 胸部爆发力训练 + HIIT 30分钟");
        trainingPlan.push("周二: 背部和核心 + 功能性训练");
        trainingPlan.push("周三: 腿部力量 + 有氧冲刺");
        trainingPlan.push("周四: 肩部和手臂 + 代谢训练");
        trainingPlan.push("周五: 全身功能性训练");
    }
    
    // 会员信息
    var memberId = "GYM" + Math.floor(Math.random() * 100000);
    var joinDate = "2024-01-15";
    var expiryDate = "2025-01-15";
    
    // 构建结果字符串
    var trainingPlanStr = trainingPlan.map(function(plan, index) {
        return "  " + (index + 1) + ". " + plan;
    }).join("\n");
    
    var result = "🏋️ 健身房会员管理系统\n" +
                 "━━━━━━━━━━━━━━━━━━━━━\n" +
                 "1️⃣ 会员信息:\n" +
                 "  姓名: " + memberName + "\n" +
                 "  会员ID: " + memberId + "\n" +
                 "  入会日期: " + joinDate + "\n" +
                 "  到期日期: " + expiryDate + "\n" +
                 "  等级: " + level.toUpperCase() + "\n\n" +
                 "2️⃣ 身体评估:\n" +
                 "  体重: " + weight + " kg\n" +
                 "  身高: " + height + " m\n" +
                 "  年龄: " + age + " 岁\n" +
                 "  BMI: " + (Math.floor(bmi * 10) / 10) + "\n" +
                 "  体质: " + bmiCategory + "\n" +
                 "  目标体重: " + (Math.floor(targetWeight * 10) / 10) + " kg\n" +
                 "  需要调整: " + (weightDifference > 0 ? "增加 " + (Math.floor(weightDifference * 10) / 10) + " kg" : "减少 " + (Math.floor(-weightDifference * 10) / 10) + " kg") + "\n\n" +
                 "3️⃣ 训练计划:\n" +
                 "  等级: " + level.toUpperCase() + "\n" +
                 "  每周训练: " + weeklyTraining + " 天\n" +
                 "  每次时长: " + dailyDuration + " 分钟\n" +
                 "  每周总量: " + weeklyMinutes + " 分钟\n" +
                 "  训练心率: " + trainingHeartRateMin + " - " + trainingHeartRateMax + " bpm\n" +
                 "  重点: " + focusAreas.join(", ") + "\n\n" +
                 "4️⃣ 详细训练安排:\n" +
                 trainingPlanStr + "\n\n" +
                 "5️⃣ 热量管理:\n" +
                 "  基础代谢率: " + (Math.floor(bmr * 10) / 10) + " kcal/天\n" +
                 "  每日需求: " + (Math.floor(dailyCalories * 10) / 10) + " kcal\n" +
                 "  训练消耗: " + (Math.floor(trainingCalories * 10) / 10) + " kcal/天\n\n" +
                 "6️⃣ 营养建议 (每日):\n" +
                 "  蛋白质: " + proteinGrams + " g (" + (proteinGrams * 4) + " kcal)\n" +
                 "  碳水化合物: " + carbsGrams + " g (" + (carbsGrams * 4) + " kcal)\n" +
                 "  脂肪: " + fatsGrams + " g (" + (fatsGrams * 9) + " kcal)\n\n" +
                 "7️⃣ 健身建议:\n" +
                 "  • 每周坚持 " + weeklyTraining + " 天训练\n" +
                 "  • 每次训练后进行 10-15 分钟拉伸\n" +
                 "  • 保证充足睡眠 (7-9 小时)\n" +
                 "  • 定期补充水分\n" +
                 "  • 每月复测一次身体指标\n\n" +
                 "━━━━━━━━━━━━━━━━━━━━━\n" +
                 "✅ 会员计划生成完成!";
    
    return result;
}

JavaScript 代码详解

Kotlin 代码编译到 JavaScript 后,保留了原有的逻辑结构,但使用 JavaScript 的语法和 API。主要的转换包括:

  1. 类型转换:Kotlin 的 toDoubleOrNull()toIntOrNull() 转换为 JavaScript 的 parseFloat()parseInt(),并使用 isNaN() 检查转换是否成功。

  2. 条件语句:Kotlin 的 when 表达式转换为 JavaScript 的 if-else 链。

  3. 集合操作:Kotlin 的 in 操作符转换为 JavaScript 的 includes() 方法。

  4. 字符串处理:Kotlin 的字符串模板转换为 JavaScript 的字符串拼接操作。

  5. 数组操作:Kotlin 的 mutableListOf()mapIndexed() 转换为 JavaScript 的数组和 map() 方法。

这个 JavaScript 版本可以直接在浏览器或 Node.js 环境中运行,并且功能与 Kotlin 版本完全相同。


ArkTS 调用代码

import { gymMembershipPlanner } from './hellokjs';

@Entry
@Component
struct Index {
  @State message: string = '准备就绪';
  @State memberName: string = '张三';
  @State weight: string = '75';
  @State height: string = '1.75';
  @State age: string = '30';
  @State level: string = 'beginner';
  @State resultText: string = '';
  @State isLoading: boolean = false;

  aboutToAppear(): void {
    this.generateNewCase();
  }

  generateNewCase(): void {
    this.resultText = '';
    this.message = '准备就绪';
    
    const samples = [
      { name: '张三', w: '75', h: '1.75', a: '30', l: 'beginner' },
      { name: '李四', w: '68', h: '1.80', a: '25', l: 'intermediate' },
      { name: '王五', w: '82', h: '1.78', a: '35', l: 'advanced' },
      { name: '赵六', w: '60', h: '1.65', a: '28', l: 'beginner' },
      { name: '孙七', w: '90', h: '1.85', a: '40', l: 'intermediate' }
    ];
    
    const random = samples[Math.floor(Math.random() * samples.length)];
    this.memberName = random.name;
    this.weight = random.w;
    this.height = random.h;
    this.age = random.a;
    this.level = random.l;
  }

  generatePlan(): void {
    this.isLoading = true;
    try {
      const input: string = `${this.memberName} ${this.weight} ${this.height} ${this.age} ${this.level}`;
      const result: string = gymMembershipPlanner(input);
      this.resultText = result;
      console.log(result);
      this.message = '✓ 健身计划生成完成';
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      this.message = `✗ 错误: ${errorMessage}`;
    } finally {
      this.isLoading = false;
    }
  }

  build() {
    Column() {
      // ===== 顶部标题栏 - 橙色主题 =====
      Column() {
        Text('🏋️ Gym Membership Planner')
          .fontSize(28)
          .fontWeight(FontWeight.Bold)
          .fontColor(Color.White)
          .margin({ bottom: 8 })
        
        Text('Personalized Fitness Plan Generator')
          .fontSize(13)
          .fontColor('#FFE0B2')
      }
      .width('100%')
      .padding(24)
      .backgroundColor('#E65100')
      .alignItems(HorizontalAlign.Start)

      // ===== 主内容区域 =====
      Scroll() {
        Column() {
          // 输入卡片
          Column() {
            Row() {
              Text('📋 Member Info')
                .fontSize(16)
                .fontWeight(FontWeight.Bold)
                .fontColor('#FFFFFF')
              
              Blank()
              
              Text('🎲 Random')
                .fontSize(12)
                .fontColor(Color.White)
                .padding({ left: 10, right: 10, top: 6, bottom: 6 })
                .backgroundColor('#BF360C')
                .borderRadius(12)
                .onClick(() => {
                  this.generateNewCase();
                })
            }
            .width('100%')
            .margin({ bottom: 18 })

            // 姓名输入
            TextInput({ placeholder: 'Member Name', text: this.memberName })
              .width('100%')
              .height(50)
              .padding(14)
              .fontSize(15)
              .fontColor('#000000')
              .placeholderColor('#999999')
              .border({ width: 2, color: '#E65100' })
              .borderRadius(12)
              .backgroundColor('#FFF3E0')
              .onChange((value: string) => {
                this.memberName = value;
              })
              .margin({ bottom: 14 })

            // 体重输入
            TextInput({ placeholder: 'Weight (kg)', text: this.weight })
              .width('100%')
              .height(50)
              .padding(14)
              .fontSize(15)
              .fontColor('#000000')
              .placeholderColor('#999999')
              .border({ width: 2, color: '#E65100' })
              .borderRadius(12)
              .backgroundColor('#FFF3E0')
              .onChange((value: string) => {
                this.weight = value;
              })
              .margin({ bottom: 14 })

            // 身高输入
            TextInput({ placeholder: 'Height (m)', text: this.height })
              .width('100%')
              .height(50)
              .padding(14)
              .fontSize(15)
              .fontColor('#000000')
              .placeholderColor('#999999')
              .border({ width: 2, color: '#E65100' })
              .borderRadius(12)
              .backgroundColor('#FFF3E0')
              .onChange((value: string) => {
                this.height = value;
              })
              .margin({ bottom: 14 })

            // 年龄输入
            TextInput({ placeholder: 'Age (years)', text: this.age })
              .width('100%')
              .height(50)
              .padding(14)
              .fontSize(15)
              .fontColor('#000000')
              .placeholderColor('#999999')
              .border({ width: 2, color: '#E65100' })
              .borderRadius(12)
              .backgroundColor('#FFF3E0')
              .onChange((value: string) => {
                this.age = value;
              })
              .margin({ bottom: 14 })

            // 等级选择
            TextInput({ placeholder: 'Level (beginner/intermediate/advanced)', text: this.level })
              .width('100%')
              .height(50)
              .padding(14)
              .fontSize(15)
              .fontColor('#000000')
              .placeholderColor('#999999')
              .border({ width: 2, color: '#E65100' })
              .borderRadius(12)
              .backgroundColor('#FFF3E0')
              .onChange((value: string) => {
                this.level = value;
              })
              .margin({ bottom: 20 })

            // 生成按钮
            Button(this.isLoading ? 'Generating...' : 'Generate Plan')
              .width('100%')
              .height(54)
              .fontSize(16)
              .fontWeight(FontWeight.Bold)
              .fontColor(Color.White)
              .backgroundColor(this.isLoading ? '#BF360C' : '#E65100')
              .borderRadius(14)
              .onClick(() => {
                if (!this.isLoading) {
                  this.generatePlan();
                }
              })
          }
          .width('90%')
          .padding(20)
          .backgroundColor('#FFFFFF')
          .borderRadius(16)
          .margin({ top: 20, bottom: 20, left: 'auto', right: 'auto' })
          .border({ width: 2, color: '#E65100' })

          // 状态提示卡片
          if (this.message !== '准备就绪') {
            Row() {
              Text(this.message.startsWith('✓') ? '✅' : '⚠️')
                .fontSize(20)
                .margin({ right: 12 })

              Text(this.message)
                .fontSize(14)
                .fontColor(this.message.startsWith('✓') ? '#4ECDC4' : '#FF6B6B')
                .fontWeight(FontWeight.Bold)
                .layoutWeight(1)
            }
            .width('90%')
            .padding(16)
            .backgroundColor(this.message.startsWith('✓') ? '#1a3a3a' : '#3a1a1a')
            .border({ width: 2, color: this.message.startsWith('✓') ? '#4ECDC4' : '#FF6B6B' })
            .borderRadius(14)
            .margin({ bottom: 20, left: 'auto', right: 'auto' })
            .alignItems(VerticalAlign.Center)
          }

          // 结果卡片
          if (this.resultText) {
            Column() {
              Row() {
                Text('📊 Fitness Plan Results')
                  .fontSize(14)
                  .fontWeight(FontWeight.Bold)
                  .fontColor('#E65100')
              }
              .width('100%')
              .padding(14)
              .backgroundColor('#FFF8F0')
              .borderRadius(12)
              .margin({ bottom: 14 })
              .border({ width: 1, color: '#E65100' })

              Text(this.resultText)
                .fontSize(12)
                .fontFamily('monospace')
                .fontColor('#BF360C')
                .width('100%')
                .padding(14)
                .backgroundColor('#FFF8F0')
                .borderRadius(12)
                .border({ width: 1, color: '#FF6F00' })
            }
            .width('90%')
            .padding(16)
            .backgroundColor('#FFF3E0')
            .borderRadius(16)
            .margin({ bottom: 20, left: 'auto', right: 'auto' })
            .border({ width: 2, color: '#E65100' })
          }

          // 底部提示
          Column() {
            Row() {
              Text('💡')
                .fontSize(18)
                .margin({ right: 10 })
              
              Text('🏋️ Fitness Tips')
                .fontSize(14)
                .fontWeight(FontWeight.Bold)
                .fontColor('#E65100')
            }
            .width('100%')
            .margin({ bottom: 12 })

            Text('• Input member information\n• Select fitness level\n• Get personalized plan\n• Track progress monthly')
              .fontSize(12)
              .fontColor('#BF360C')
              .lineHeight(1.6)
          }
          .width('90%')
          .padding(16)
          .backgroundColor('#FFF3E0')
          .borderRadius(16)
          .margin({ bottom: 20, left: 'auto', right: 'auto' })
          .border({ width: 2, color: '#E65100' })

          Blank()
            .height(20)
        }
        .width('100%')
      }
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FFF3E0')
  }
}

ArkTS 代码详解

这个 ArkTS 组件实现了健身房会员管理系统的用户界面。组件使用了 OpenHarmony 的 ArkTS 语言,提供了一个现代化的、橙色主题的用户界面。

组件定义了六个 @State 属性来存储用户输入的数据:姓名、体重、身高、年龄和等级。这些属性与输入框绑定,当用户输入数据时,这些属性会自动更新。

generateNewCase() 方法生成随机的会员数据样本,帮助用户快速测试应用。用户可以点击"Random"按钮来生成随机数据。

generatePlan() 方法调用 Kotlin 编译的 JavaScript 函数 gymMembershipPlanner(),并将用户输入的数据作为参数传递。函数返回的分析结果会显示在结果卡片中。

用户界面包括五个输入框(姓名、体重、身高、年龄、等级)、一个生成按钮、一个状态提示卡片、一个结果卡片和一个提示卡片。所有元素都使用了橙色主题,与健身房的活力主题相符。


实战案例

案例 1:初级会员的健身计划

假设一个 30 岁的初级会员张三,体重 75 kg,身高 1.75 m。输入数据:张三 75 1.75 30 beginner

系统会生成:

  • 会员ID:GYM12345
  • BMI = 24.49(正常范围)
  • 目标体重:75 kg(保持不变)
  • 每周训练:3 天,每次 45 分钟
  • 训练心率:114-161 bpm
  • 基础代谢率:约 1700 kcal/天
  • 每日热量需求:约 2550 kcal
  • 训练消耗:约 510 kcal/天
  • 营养建议:蛋白质 120g,碳水化合物 225g,脂肪 60g

训练计划包括有氧运动、基础力量训练和拉伸。

案例 2:中级会员的健身计划

假设一个 25 岁的中级会员李四,体重 68 kg,身高 1.80 m。输入数据:李四 68 1.80 25 intermediate

系统会生成:

  • 会员ID:GYM54321
  • BMI = 20.99(正常范围)
  • 目标体重:68 kg(保持不变)
  • 每周训练:4 天,每次 60 分钟
  • 训练心率:117-175 bpm
  • 基础代谢率:约 1650 kcal/天
  • 每日热量需求:约 2475 kcal
  • 训练消耗:约 866 kcal/天
  • 营养建议:蛋白质 109g,碳水化合物 204g,脂肪 54g

训练计划包括力量训练、有氧运动和核心训练。

案例 3:高级会员的健身计划

假设一个 35 岁的高级会员王五,体重 82 kg,身高 1.78 m。输入数据:王五 82 1.78 35 advanced

系统会生成:

  • 会员ID:GYM98765
  • BMI = 25.87(超重)
  • 目标体重:78.5 kg(需要减少 3.5 kg)
  • 每周训练:5 天,每次 90 分钟
  • 训练心率:111-166 bpm
  • 基础代谢率:约 1750 kcal/天
  • 每日热量需求:约 2625 kcal
  • 训练消耗:约 1313 kcal/天
  • 营养建议:蛋白质 131g,碳水化合物 246g,脂肪 66g

训练计划包括高强度间歇训练、肌肉增长训练和功能性训练。


最佳实践

1. 会员信息管理

健身房管理者应该定期更新会员信息:

  • 定期体测:每月为会员进行一次身体测量,记录体重和身体围度的变化
  • 更新计划:根据会员的进度调整训练计划
  • 跟踪进度:使用系统记录会员的训练历史和成果

2. 训练计划执行

会员应该认真执行系统生成的训练计划:

  • 按时训练:每周按照计划进行规定次数的训练
  • 循序渐进:逐步增加训练强度和难度
  • 记录训练:记录每次训练的内容和感受

3. 营养管理

会员应该根据系统的营养建议调整饮食:

  • 均衡饮食:按照建议的蛋白质、碳水化合物和脂肪比例进食
  • 定时进食:建立规律的进食时间表
  • 水分补充:在训练前后充分补充水分

4. 安全训练

会员应该注意训练的安全性:

  • 热身准备:训练前进行 5-10 分钟的热身
  • 正确姿态:学习正确的运动姿态,避免受伤
  • 心率监测:使用心率表监测训练心率,确保在安全范围内
  • 冷却放松:训练后进行 10-15 分钟的拉伸和放松

5. 定期评估

健身房管理者应该定期评估会员的进度:

  • 月度评估:每月评估会员的训练完成情况和身体变化
  • 季度复测:每季度进行一次全面的身体评估
  • 调整计划:根据评估结果调整训练计划和营养建议

总结

健身房管理系统 - 会员健身计划生成器展示了如何使用 Kotlin Multiplatform 技术创建一个功能丰富、跨端兼容的健身管理应用。通过综合考虑会员的体重、身高、年龄和健身等级,系统能够自动生成个性化的训练计划、营养建议和健身指导。

这个案例不仅展示了 KMP 的强大功能,还演示了如何将复杂的健身科学知识转化为实用的应用功能。无论是健身房管理者还是健身爱好者,都可以使用这个系统来制定科学的训练计划,并根据建议调整生活方式。

健身是一个长期的过程,需要坚持和科学的指导。通过使用这个健身房管理系统,会员可以更有效地实现自己的健身目标,获得更好的训练效果。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐