在这里插入图片描述

目录

  1. 概述
  2. 功能设计
  3. Kotlin 实现代码(KMP)
  4. JavaScript 调用示例
  5. ArkTS 页面集成与调用
  6. 数据输入与交互体验
  7. 编译与自动复制流程
  8. 总结

概述

本案例在 Kotlin Multiplatform (KMP) 工程中实现了一个 根据每日学习时长评估学习状态工具

  • 输入:每日学习时长数据(单位:分钟),使用空格分隔,例如:120 90 150 60 180 45 200
  • 输出:
    • 基础统计:总学习时长、平均每日学习时长、最长学习时长、最短学习时长
    • 深度分析:学习状态评级、学习效率评分、学习坚持度评估
    • 个性化建议:根据学习数据给出改进建议和激励语
  • 技术路径:Kotlin → Kotlin/JS → JavaScript 模块 → ArkTS 页面调用。

这个案例延续了 KMP 跨端开发的核心理念:

把算法逻辑写在 Kotlin 里,一次实现,多端复用;把交互界面写在 ArkTS 里,专注 UI 和体验。

Kotlin 侧负责解析学习时长数据、计算统计指标、评估学习状态和生成建议文本;ArkTS 侧只需要把输入字符串传给 Kotlin 函数,并把返回结果原样展示出来即可。借助 KMP 的 Kotlin/JS 能力,这个学习评估工具可以在 Node.js、Web 前端以及 OpenHarmony 中复用相同的代码逻辑。


功能设计

输入数据格式

学习时长评估工具采用简单直观的输入格式:

  • 使用 空格分隔 每一天的学习时长。
  • 每个数字代表该天的学习时长(分钟)
  • 输入示例:
120 90 150 60 180 45 200

这可以理解为最近 7 天的学习情况:

  • 第 1 天:学习 120 分钟(2 小时)
  • 第 2 天:学习 90 分钟(1.5 小时)
  • 第 3 天:学习 150 分钟(2.5 小时)
  • 第 4 天:学习 60 分钟(1 小时)
  • 第 5 天:学习 180 分钟(3 小时)
  • 第 6 天:学习 45 分钟(45 分钟)
  • 第 7 天:学习 200 分钟(3.3 小时)

工具会基于这串数据计算出:

  • 一共学习了多少分钟(总时长)
  • 平均每天学习多少分钟
  • 最长的一天学习了多少分钟
  • 最短的一天学习了多少分钟
  • 学习状态评级(优秀/良好/中等/一般/需要改进)
  • 学习效率评分(0-100)
  • 学习坚持度评估(连续学习天数、学习稳定性等)

输出信息结构

为了便于在 ArkTS 页面以及终端中直接展示,Kotlin 函数返回的是一段结构化的多行文本,划分为几个分区:

  1. 标题区:例如"📚 每日学习时长评估分析",一眼看出工具用途。
  2. 基础统计:总学习时长、平均时长、最长时长、最短时长等指标。
  3. 学习评估:学习状态等级、效率评分、坚持度评估。
  4. 详细分析:根据数据给出的具体分析和对比。
  5. 个性化建议:根据学习数据给出改进建议和激励语。

这样的输出结构使得:

  • 在 ArkTS 中可以直接把整段文本绑定到 Text 组件,配合 monospace 字体,阅读体验类似终端报告。
  • 如果将来想把结果保存到日志或者后端,直接保存字符串即可。
  • 需要更精细的 UI 时,也可以在前端根据分隔符进行拆分,再按块展示。

Kotlin 实现代码(KMP)

核心代码在 src/jsMain/kotlin/App.kt 中,通过 @JsExport 导出。以下是完整的 Kotlin 实现:

@OptIn(ExperimentalJsExport::class)
@JsExport
fun dailyLearningTimeAssessor(inputData: String = "120 90 150 60 180 45 200"): String {
    // 输入格式: 一串用空格分隔的数字,代表每天的学习时长(分钟)
    val parts = inputData.trim().split(" ").filter { it.isNotEmpty() }

    if (parts.isEmpty()) {
        return "❌ 错误: 请输入至少一个学习时长数据,例如: 120 90 150 60 180 45 200"
    }

    val learningTimes = parts.mapNotNull { it.toIntOrNull() }.filter { it >= 0 }

    if (learningTimes.isEmpty()) {
        return "❌ 错误: 无法解析学习时长数据,请确保输入的都是非负整数"
    }

    // 基础统计
    val totalTime = learningTimes.sum()
    val averageTime = totalTime / learningTimes.size
    val maxTime = learningTimes.maxOrNull() ?: 0
    val minTime = learningTimes.minOrNull() ?: 0
    val daysCount = learningTimes.size

    // 计算学习状态等级
    val statusLevel = when {
        averageTime >= 180 -> "优秀"
        averageTime >= 120 -> "良好"
        averageTime >= 90 -> "中等"
        averageTime >= 60 -> "一般"
        else -> "需要改进"
    }

    // 计算学习效率评分(0-100)
    val efficiencyScore = when {
        averageTime >= 180 -> 95
        averageTime >= 150 -> 85
        averageTime >= 120 -> 75
        averageTime >= 90 -> 65
        averageTime >= 60 -> 55
        else -> 40
    }

    // 计算学习稳定性(标准差)
    val variance = learningTimes.map { (it - averageTime) * (it - averageTime) }.average()
    val stdDev = kotlin.math.sqrt(variance)
    val stability = when {
        stdDev <= 30 -> "很稳定"
        stdDev <= 60 -> "较稳定"
        stdDev <= 90 -> "一般"
        else -> "波动较大"
    }

    // 计算连续学习天数
    var maxConsecutiveDays = 1
    var currentConsecutiveDays = 1
    for (i in 1 until learningTimes.size) {
        if (learningTimes[i] > 0) {
            currentConsecutiveDays++
            maxConsecutiveDays = maxOf(maxConsecutiveDays, currentConsecutiveDays)
        } else {
            currentConsecutiveDays = 1
        }
    }

    // 计算学习坚持度(有效学习天数占比)
    val effectiveDays = learningTimes.count { it > 0 }
    val persistenceRate = (effectiveDays * 100) / daysCount

    // 生成建议
    val suggestions = when {
        averageTime >= 180 && stability == "很稳定" -> "🌟 学习状态非常优秀!你的学习时长充足且稳定,建议继续保持这个节奏,可以考虑提高学习深度和质量。"
        averageTime >= 120 && stability == "很稳定" -> "✨ 学习状态良好!你的学习时长达到了理想水平,学习习惯也很稳定,建议继续坚持。"
        averageTime >= 90 -> "👍 学习状态中等。你已经建立了基本的学习习惯,建议逐步增加每天的学习时长,目标是达到 120 分钟以上。"
        averageTime >= 60 -> "💪 学习状态一般。你的学习时长还需要提高,建议每天至少学习 90 分钟,可以将学习分成多个时间段进行。"
        else -> "⚠️ 学习状态需要改进。你的学习时长较短,建议制定更具体的学习计划,从每天 60 分钟开始逐步增加。"
    }

    // 生成激励语
    val motivation = when {
        persistenceRate >= 80 -> "你的学习坚持度很高,这是成功的关键!"
        persistenceRate >= 60 -> "你正在建立良好的学习习惯,继续加油!"
        else -> "建议增加学习的连贯性,不要中断学习计划。"
    }

    // 构建输出文本
    val result = StringBuilder()
    result.append("📚 每日学习时长评估分析\n")
    result.append("═".repeat(50)).append("\n\n")
    
    result.append("📊 基础统计\n")
    result.append("─".repeat(50)).append("\n")
    result.append("总学习时长: ${totalTime} 分钟 (${String.format("%.1f", totalTime / 60.0)} 小时)\n")
    result.append("平均每日学习: ${averageTime} 分钟\n")
    result.append("最长学习时长: ${maxTime} 分钟\n")
    result.append("最短学习时长: ${minTime} 分钟\n")
    result.append("统计天数: ${daysCount} 天\n\n")

    result.append("🎯 学习评估\n")
    result.append("─".repeat(50)).append("\n")
    result.append("学习状态等级: ${statusLevel}\n")
    result.append("学习效率评分: ${efficiencyScore}/100\n")
    result.append("学习稳定性: ${stability}\n")
    result.append("学习坚持度: ${persistenceRate}%\n")
    result.append("最长连续学习: ${maxConsecutiveDays} 天\n\n")

    result.append("💡 详细分析\n")
    result.append("─".repeat(50)).append("\n")
    result.append("你在过去 ${daysCount} 天内共学习了 ${totalTime} 分钟,平均每天 ${averageTime} 分钟。")
    result.append("这表明你的学习投入量处于${statusLevel}水平。\n")
    result.append("学习时长的波动程度为${stability},说明你的学习计划执行情况${if (stability == "很稳定") "非常规律" else "需要更加规律"}。\n")
    result.append("你有 ${effectiveDays} 天进行了学习,坚持度达到 ${persistenceRate}%,这${if (persistenceRate >= 80) "非常值得肯定" else "还有改进空间"}。\n\n")

    result.append("🚀 个性化建议\n")
    result.append("─".repeat(50)).append("\n")
    result.append("${suggestions}\n")
    result.append("${motivation}\n\n")

    result.append("📈 学习等级说明\n")
    result.append("─".repeat(50)).append("\n")
    result.append("• 优秀: 平均每天学习 ≥ 180 分钟\n")
    result.append("• 良好: 平均每天学习 120-179 分钟\n")
    result.append("• 中等: 平均每天学习 90-119 分钟\n")
    result.append("• 一般: 平均每天学习 60-89 分钟\n")
    result.append("• 需要改进: 平均每天学习 < 60 分钟\n\n")

    result.append("💪 学习建议\n")
    result.append("─".repeat(50)).append("\n")
    result.append("1. 制定明确的学习目标,建议每天至少学习 120 分钟\n")
    result.append("2. 将学习时间分成多个时间段,避免长时间疲劳\n")
    result.append("3. 定期评估学习效果,根据需要调整学习计划\n")
    result.append("4. 建立学习习惯,保持学习的连贯性和稳定性\n")
    result.append("5. 选择适合自己的学习方式,提高学习效率\n")

    return result.toString()
}

代码说明

这段 Kotlin 代码实现了完整的学习时长评估功能。让我详细解释关键部分:

数据解析:首先将输入字符串按空格分隔,过滤掉空字符串,然后转换为整数列表。这样可以处理各种格式的输入,包括多个空格的情况。

基础统计:计算总时长、平均时长、最大值和最小值。这些是评估学习状态的基础数据。

状态等级评估:根据平均每日学习时长来判断学习状态。平均时长越长,学习状态等级越高。这个分级标准是根据教育研究中的建议制定的。

效率评分:基于平均学习时长生成 0-100 的评分,用于量化学习效率。

稳定性计算:使用标准差来衡量学习时长的波动程度。标准差越小,说明学习时长越稳定,学习习惯越规律。

连续学习天数:通过遍历数据找出最长的连续学习天数,这反映了用户的学习坚持力。

坚持度评估:计算有效学习天数(学习时长 > 0)占总天数的比例,这反映了用户的学习连贯性。

个性化建议:根据多个维度的数据(平均时长、稳定性、坚持度等)生成相应的建议和激励语。


JavaScript 调用示例

编译后的 JavaScript 代码可以在 Node.js 或浏览器中直接调用。以下是 JavaScript 的使用示例:

// 导入编译后的 Kotlin/JS 模块
const { dailyLearningTimeAssessor } = require('./hellokjs.js');

// 示例 1:基础调用
const result1 = dailyLearningTimeAssessor("120 90 150 60 180 45 200");
console.log("示例 1 - 基础调用:");
console.log(result1);
console.log("\n");

// 示例 2:学习时长较长的情况
const result2 = dailyLearningTimeAssessor("200 210 190 220 200 210 200");
console.log("示例 2 - 优秀学习状态:");
console.log(result2);
console.log("\n");

// 示例 3:学习时长较短的情况
const result3 = dailyLearningTimeAssessor("30 45 20 50 40 35 25");
console.log("示例 3 - 需要改进的学习状态:");
console.log(result3);
console.log("\n");

// 示例 4:学习时长波动较大的情况
const result4 = dailyLearningTimeAssessor("180 60 200 50 190 40 210");
console.log("示例 4 - 学习时长波动较大:");
console.log(result4);
console.log("\n");

// 示例 5:使用默认参数
const result5 = dailyLearningTimeAssessor();
console.log("示例 5 - 使用默认参数:");
console.log(result5);

// 实际应用场景:从用户输入获取数据
function assessUserLearning(userInput) {
    try {
        const result = dailyLearningTimeAssessor(userInput);
        return {
            success: true,
            data: result
        };
    } catch (error) {
        return {
            success: false,
            error: error.message
        };
    }
}

// 测试实际应用
const userInput = "120 150 100 180 90 200 110";
const assessment = assessUserLearning(userInput);
if (assessment.success) {
    console.log("用户学习评估结果:");
    console.log(assessment.data);
} else {
    console.log("评估失败:", assessment.error);
}

JavaScript 代码说明

这段 JavaScript 代码展示了如何在 Node.js 环境中调用编译后的 Kotlin 函数。关键点包括:

模块导入:使用 require 导入编译后的 JavaScript 模块,获取导出的 dailyLearningTimeAssessor 函数。

直接调用:可以直接调用函数,传入学习时长数据字符串,函数返回评估结果。

多个示例:展示了不同场景下的调用方式,包括优秀学习状态、需要改进的状态、波动较大的情况等。

错误处理:在实际应用中,应该使用 try-catch 块来处理可能的错误,确保程序的稳定性。

实际应用assessUserLearning 函数展示了如何在实际应用中集成这个工具,返回结构化的结果对象。


ArkTS 页面集成与调用

在 OpenHarmony 的 ArkTS 页面中集成这个学习评估工具。以下是完整的 ArkTS 实现代码:

import { dailyLearningTimeAssessor } from './hellokjs';

@Entry
@Component
struct LearningAssessmentPage {
  @State learningData: string = "120 90 150 60 180 45 200";
  @State assessmentResult: string = "";
  @State isLoading: boolean = false;

  build() {
    Column() {
      // 顶部栏
      Row() {
        Text("📚 学习时长评估")
          .fontSize(24)
          .fontWeight(FontWeight.Bold)
          .fontColor(Color.White)
      }
      .width("100%")
      .height(60)
      .backgroundColor("#1B5E20")
      .justifyContent(FlexAlign.Center)
      .padding({ top: 10, bottom: 10 })

      // 主容器
      Scroll() {
        Column() {
          // 说明文字
          Text("请输入每日学习时长数据(单位:分钟,用空格分隔)")
            .fontSize(14)
            .fontColor("#666666")
            .margin({ top: 20, left: 15, right: 15 })

          // 输入框
          TextInput({
            placeholder: "例如: 120 90 150 60 180 45 200",
            text: this.learningData
          })
            .width("90%")
            .height(50)
            .margin({ top: 15, bottom: 15 })
            .padding({ left: 10, right: 10 })
            .backgroundColor("#F1F8E9")
            .border({ width: 1, color: "#2E7D32" })
            .onChange((value: string) => {
              this.learningData = value;
            })

          // 按钮区域
          Row() {
            Button("🔍 评估学习")
              .width("45%")
              .height(45)
              .backgroundColor("#2E7D32")
              .fontColor(Color.White)
              .fontSize(16)
              .fontWeight(FontWeight.Bold)
              .onClick(() => {
                this.isLoading = true;
                // 模拟异步处理
                setTimeout(() => {
                  this.assessmentResult = dailyLearningTimeAssessor(this.learningData);
                  this.isLoading = false;
                }, 300);
              })

            Blank()

            Button("🔄 重置")
              .width("45%")
              .height(45)
              .backgroundColor("#1565C0")
              .fontColor(Color.White)
              .fontSize(16)
              .fontWeight(FontWeight.Bold)
              .onClick(() => {
                this.learningData = "120 90 150 60 180 45 200";
                this.assessmentResult = "";
                this.isLoading = false;
              })
          }
          .width("90%")
          .margin({ top: 10, bottom: 20 })
          .justifyContent(FlexAlign.SpaceBetween)

          // 加载指示器
          if (this.isLoading) {
            Row() {
              LoadingProgress()
                .width(40)
                .height(40)
                .color("#2E7D32")
              Text("  正在评估中...")
                .fontSize(14)
                .fontColor("#666666")
            }
            .width("90%")
            .height(50)
            .margin({ bottom: 15 })
            .justifyContent(FlexAlign.Center)
            .backgroundColor("#F1F8E9")
            .borderRadius(8)
          }

          // 结果显示区域
          if (this.assessmentResult.length > 0) {
            Column() {
              Text("📊 评估结果")
                .fontSize(16)
                .fontWeight(FontWeight.Bold)
                .fontColor("#1B5E20")
                .margin({ bottom: 10 })

              Text(this.assessmentResult)
                .width("100%")
                .fontSize(12)
                .fontFamily("monospace")
                .fontColor("#333333")
                .lineHeight(1.6)
                .padding(10)
                .backgroundColor("#FAFAFA")
                .border({ width: 1, color: "#E0E0E0" })
                .borderRadius(8)
            }
            .width("90%")
            .margin({ top: 20, bottom: 30 })
            .padding(15)
            .backgroundColor("#F1F8E9")
            .borderRadius(8)
            .border({ width: 1, color: "#2E7D32" })
          }
        }
        .width("100%")
      }
      .layoutWeight(1)
      .backgroundColor("#FFFFFF")
    }
    .width("100%")
    .height("100%")
    .backgroundColor("#F5F5F5")
  }
}

ArkTS 代码说明

这段 ArkTS 代码实现了完整的用户界面和交互逻辑。关键点包括:

导入函数:从编译后的 JavaScript 模块中导入 dailyLearningTimeAssessor 函数。

状态管理:使用 @State 装饰器管理三个状态:

  • learningData:用户输入的学习时长数据
  • assessmentResult:评估结果
  • isLoading:加载状态

UI 布局

  • 顶部栏:显示页面标题,使用深绿色背景
  • 输入框:允许用户输入学习时长数据
  • 按钮区域:包含"评估学习"和"重置"两个按钮
  • 加载指示器:在评估过程中显示加载动画
  • 结果显示区域:以 monospace 字体显示评估结果

交互逻辑

  • 点击"评估学习"按钮时,调用 Kotlin 函数进行评估,并显示结果
  • 点击"重置"按钮时,清空输入和结果
  • 使用 setTimeout 模拟异步处理,提供更好的用户体验

样式设计:使用绿色主题,与学习相关的主题相符。输入框、按钮和结果显示区域都有相应的样式设置,提供清晰的视觉层次。


数据输入与交互体验

输入数据格式规范

为了确保工具能够正确处理用户输入,用户应该遵循以下规范:

  1. 数字格式:每个学习时长应该是非负整数,单位为分钟。
  2. 分隔符:使用空格分隔不同天的学习时长。
  3. 数据量:至少输入一个数据点,建议输入 7 天以上的数据以获得更准确的评估。
  4. 范围:学习时长通常在 0-480 分钟之间(0-8 小时)。

示例输入

  • 优秀学习状态200 210 190 220 200 210 200
  • 良好学习状态150 140 160 130 170 140 150
  • 中等学习状态100 90 110 80 120 85 95
  • 一般学习状态60 50 70 40 80 45 55
  • 需要改进30 20 40 15 35 25 30

交互流程

  1. 用户打开应用,看到输入框和默认数据
  2. 用户可以修改输入框中的数据,或清空后输入自己的数据
  3. 点击"评估学习"按钮,应用调用 Kotlin 函数进行评估
  4. 应用显示加载动画,表示正在处理
  5. 评估完成后,显示详细的评估结果
  6. 用户可以点击"重置"按钮清空数据,重新开始

编译与自动复制流程

编译步骤

  1. 编译 Kotlin 代码

    ./gradlew build
    
  2. 生成 JavaScript 文件
    编译过程会自动生成 hellokjs.d.tshellokjs.js 文件。

  3. 复制到 ArkTS 项目
    使用提供的脚本自动复制生成的文件到 ArkTS 项目的 pages 目录:

    ./build-and-copy.bat
    

文件结构

编译完成后,项目结构如下:

kmp_openharmony/
├── src/
│   └── jsMain/
│       └── kotlin/
│           └── App.kt (包含 dailyLearningTimeAssessor 函数)
├── build/
│   └── js/
│       └── packages/
│           └── hellokjs/
│               ├── hellokjs.d.ts
│               └── hellokjs.js
└── kmp_ceshiapp/
    └── entry/
        └── src/
            └── main/
                └── ets/
                    └── pages/
                        ├── hellokjs.d.ts (复制后)
                        ├── hellokjs.js (复制后)
                        └── Index.ets (ArkTS 页面)

总结

这个案例展示了如何使用 Kotlin Multiplatform 技术实现一个跨端的学习评估工具。通过将核心逻辑写在 Kotlin 中,然后编译为 JavaScript,最后在 ArkTS 中调用,我们实现了代码的一次编写、多端复用。

核心优势

  1. 代码复用:Kotlin 代码可以在 JVM、JavaScript 和其他平台上运行,避免重复开发。
  2. 类型安全:Kotlin 的类型系统确保了代码的安全性和可维护性。
  3. 性能优化:Kotlin 编译为 JavaScript 后,性能与手写 JavaScript 相当。
  4. 易于维护:集中管理业务逻辑,使得维护和更新变得更加容易。

扩展方向

  1. 数据持久化:将评估结果保存到本地存储或云端。
  2. 数据可视化:使用图表库展示学习时长的趋势。
  3. 多用户支持:支持多个用户的学习数据管理。
  4. 智能推荐:根据学习数据推荐学习计划和资源。
  5. 社交功能:允许用户分享学习成果和相互鼓励。

通过这个案例,开发者可以学到如何在 KMP 项目中实现复杂的业务逻辑,以及如何在 OpenHarmony 平台上构建高效的跨端应用。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐