楼主: 萌犸
941 0

[其他] KMP 实现鸿蒙跨端:Kotlin 贷款等额本息还款计算器 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
20 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2018-9-12
最后登录
2018-11-6

楼主
萌犸 发表于 2025-11-28 16:36:29 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

概述

本案例基于 Kotlin Multiplatform (KMP) 工程,实现了一个贷款等额本息还款计算器。该工具支持以下功能:

  • 输入参数:贷款金额(单位:元)、年利率(%)、还款期数(月)
  • 输出结果
    • 每月固定的等额本息还款金额
    • 总支付利息与累计还款总额
    • 前若干期(最多显示6期)的详细还款计划,包括每期偿还的本金、利息及剩余未还本金

技术实现路径为:使用 Kotlin 编写核心算法 → 通过 Kotlin/JS 编译为 JavaScript 模块 → 在 ArkTS 页面中进行集成调用。

此方案延续了此前 BMI 计算器的设计思路,体现了“算法逻辑由 Kotlin 实现,前端界面由 ArkTS 承载”的典型跨平台开发模式。

等额本息计算原理

等额本息是房贷、车贷中最常见的还款方式之一,其核心特点是每月还款额固定。计算公式如下:

每月还款额 = 本金 × 月利率 × (1 + 月利率)^n / ((1 + 月利率)^n - 1)

其中:
- 本金:Loan Principal
- 月利率:年利率 / 12
- n:还款总期数(单位:月)

在每一期还款过程中:

  • 当期产生的利息 = 当前剩余本金 × 月利率
  • 当期归还的本金 = 每月固定还款额 - 当期利息
  • 更新后的剩余本金 = 上一期剩余本金 - 当期归还的本金

通过循环迭代上述过程,即可生成完整的分期还款明细表。

Kotlin 多平台代码实现(KMP)

在 KMP 项目结构中,新增一个用于贷款计算的方法,并通过注解将其导出为可供 JS 调用的形式。

src/jsMain/kotlin/App.kt
loanRepaymentCalculator
@JsExport

import kotlin.math.pow

@OptIn(ExperimentalJsExport::class)
@JsExport
fun loanRepaymentCalculator(inputText: String = "100000 3.85 12"): String {
    // 输入格式: "贷款总额(元) 年利率(%) 期数(月)", 示例: "100000 3.85 12"
    val parts = inputText.trim().split(" ").filter { it.isNotEmpty() }
    if (parts.size < 3) {
        return "? 错误: 请按 '金额 年利率 月数' 的格式输入,例如: 100000 3.85 12"
    }
    
    val principal = parts[0].toDoubleOrNull()
    val annualRate = parts[1].toDoubleOrNull()
    val months = parts[2].toIntOrNull()

    if (principal == null || annualRate == null || months == null || 
        principal <= 0 || annualRate <= 0 || months <= 0) {
        return "? 错误: 金额 / 利率 / 月数 无效\n请输入正确的正数,例如: 100000 3.85 12"
    }

    // 1. 计算月利率
    val monthlyRate = annualRate / 100.0 / 12.0

    // 2. 应用等额本息公式计算每月还款额
    val factor = (1 + monthlyRate).pow(months.toDouble())
    val monthlyPayment = principal * monthlyRate * factor / (factor - 1)

    // 辅助函数:保留两位小数
    fun round2(v: Double): Double = (v * 100).toInt() / 100.0
    val monthlyPaymentRounded = round2(monthlyPayment)

    // 3. 构建前几期还款计划(最多前6期)
    var remaining = principal
    var totalInterest = 0.0
    val schedule = mutableListOf<String>()
    val showMonths = if (months < 6) months else 6

    for (m in 1..months) {
        val interest = remaining * monthlyRate
        val principalPart = monthlyPayment - interest
        remaining -= principalPart
        totalInterest += interest

        if (m <= showMonths) {
            schedule.add(
                "  第${m}期: 本金 ${round2(principalPart)} 元, 利息 ${round2(interest)} 元, 剩余本金 ${round2(remaining.coerceAtLeast(0.0))} 元"
            )
        }
    }

    val totalPayment = principal + totalInterest

    return "???? 贷款等额本息还款计算器\n" +
           "━━━━━━━━━━━━━━━━━━━━━\n" +
           "贷款金额: ${principal} 元\n" +
           "年利率: ${annualRate}%\n" +
           "还款期数: ${months} 个月\n" +
           "───────────────────────\n" +
           "每月还款额: ${monthlyPaymentRounded} 元\n" +
           "总支付利息: ${round2(totalInterest)} 元\n" +
           "还款总额: ${round2(totalPayment)} 元\n" +
           "───────────────────────\n" +
           "前 ${showMonths} 期还款计划:\n" +
           "${schedule.joinToString("\n")}\n" +
           "━━━━━━━━━━━━━━━━━━━━━\n" +
           "注: 数据已四舍五入至两位小数"
}

JavaScript 编译输出与类型定义

借助 Kotlin/JS 插件配置,将上述 Kotlin 函数编译为标准 JavaScript 模块。生成的 JS 文件可直接被前端工程引用。

由于使用了 @JsExport 注解,在编译后会自动生成对应的类型声明文件(.d.ts),便于在 TypeScript 环境中安全调用。

最终输出的模块包含一个名为 loanRepaymentCalculator 的全局函数,接受字符串输入并返回格式化文本结果。

ArkTS 页面集成与调用

将编译后的 JavaScript 文件嵌入到 ArkTS 支持的前端页面中,通过简单的脚本调用即可完成交互。

示例调用方式:

const result = loanRepaymentCalculator("800000 4.9 360");

返回值为结构化文本,可在 UI 中以预格式化形式展示,适用于移动端或轻量级 Web 应用场景。

交互示例

用户输入示例:500000 4.5 240

系统输出:

???? 贷款等额本息还款计算器
━━━━━━━━━━━━━━━━━━━━━
贷款金额: 500000.0 元
年利率: 4.5%
还款期数: 240 个月
───────────────────────
每月还款额: 3164.57 元
总支付利息: 259496.8 元
还款总额: 759496.8 元
───────────────────────
前 6 期还款计划:
  第1期: 本金 1041.07 元, 利息 1875.0 元, 剩余本金 498958.93 元
  第2期: 本金 1045.42 元, 利息 1870.65 元, 剩余本金 497913.51 元
  第3期: 本金 1049.79 元, 利息 1866.28 元, 剩余本金 496863.72 元
  第4期: 本金 1054.18 元, 利息 1861.89 元, 剩余本金 495809.54 元
  第5期: 本金 1058.59 元, 利息 1857.48 元, 剩余本金 494750.95 元
  第6期: 本金 1063.02 元, 利息 1853.05 元, 剩余本金 493687.93 元
━━━━━━━━━━━━━━━━━━━━━
注: 数据已四舍五入至两位小数

编译与自动复制流程

构建流程可通过 Gradle 配置自动化完成:

  1. 执行 Kotlin 编译任务,生成 JS 输出文件
  2. 将生成的 JS 文件自动拷贝至 ArkTS 项目的静态资源目录
  3. 触发前端资源刷新,确保最新逻辑生效

该流程可集成进 CI/CD 流水线,实现算法更新后的一键发布。

总结

本文展示了如何利用 Kotlin Multiplatform 技术栈实现一个实用的金融计算器,并成功将其部署至 ArkTS 前端环境。整个链路验证了 Kotlin 算法模块在多平台间的复用能力,尤其适合需要统一业务逻辑、降低维护成本的跨端应用场景。

关键优势包括:

  • 算法一次编写,多端共享
  • 类型安全且具备良好可读性
  • 易于测试和调试
  • 无缝对接现代前端框架

未来可扩展方向:增加更多贷款模式(如等额本金)、支持汇率换算或多币种计价等高级功能。

输入参数:金额 ${principal} 元,年利率 ${annualRate}%,贷款期限 ${months} 个月

1. 每月还款金额

每月固定还款:${monthlyPaymentRounded} 元

2. 还款总体情况

  • 累计支付利息总额:${round2(totalInterest)} 元
  • 本息合计还款总额:${round2(totalPayment)} 元

3. 前 ${showMonths} 期详细还款计划

${schedule.joinToString("\n")}

4. 计算说明与注意事项

  • 本计算基于等额本息还款方式,仅用于学习和演示用途
  • 实际贷款业务中可能涉及服务费、管理费或浮动利率等额外因素,结果仅供参考

? 计算已完成!

String

所有输入参数通过上方标记位置传入,便于 ArkTS 端直接拼接处理。

函数返回多行中文文本结果,适配 ArkTS 页面的展示需求。

幂运算逻辑使用

kotlin.math.pow
实现,确保在 Kotlin/JS 多平台环境下的兼容性。

JavaScript 构建输出与类型定义

执行构建脚本后,将在

build/js/packages/hellokjs/kotlin/
目录下生成相应的文件:

hellokjs.mjs   // ESModule 格式的 JS
hellokjs.d.ts  // TypeScript 类型定义

.d.ts
中将包含如下类型声明:

export declare function loanRepaymentCalculator(inputText?: string): string;

导入

hellokjs
模块时,TypeScript 和 ArkTS 可获得完整的类型提示支持。

ArkTS 页面集成实现

当前首页

Index.ets
已调整为“贷款等额本息还款计算器”界面,核心代码结构(简化版)如下:

import { loanRepaymentCalculator } from './hellokjs';
@Entry
@Component
struct Index {
  @State message: string = '请输入贷款金额、年利率和期数';
  @State amount: string = '100000';
  @State annualRate: string = '3.85';
  @State months: string = '12';
  @State resultText: string = '';

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

  calculateLoan(): void {
    try {
      const input: string = `${this.amount} ${this.annualRate} ${this.months}`;
      const result: string = loanRepaymentCalculator(input);
      this.resultText = result;
      this.message = '? 计算完成';
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      this.message = `? 错误: ${errorMessage}`;
    }
  }

  build() {
    Column() {
      // 包含标题栏、输入控件区、结果显示区及操作按钮等组件
    }
  }
}

说明:

  • ArkTS 层负责用户输入收集与界面渲染
  • 全部计算逻辑,包括利息计算与还款计划生成,均由 Kotlin 实现

交互示例

示例一:10万元贷款,年利率3.85%,分12期偿还

输入界面示意:

金额: 100000 元
年利率: 3.85 %
期数: 12 月

部分输出结果示例:

1?? 每月还款额:
  每月需还: 8565.35 元

2?? 总体统计:
  支付总利息: xxxx.xx 元
  还款总金额: xxxxxx.xx 元

3?? 前 6 期还款计划:
  第1期: 本金 xxxx.xx 元, 利息 xxx.xx 元, 剩余本金 xxxxx.xx 元
  第2期: 本金 xxxx.xx 元, 利息 xxx.xx 元, 剩余本金 xxxxx.xx 元
  ...

示例二:较长期限贷款(如36期)

showMonths

  • 系统默认仅展示前6期明细,避免内容过长影响阅读
  • 随着期数增加,总利息与还款总额显著上升,可用于不同方案的成本对比分析

示例三:错误输入处理

例如输入非法字符或格式不正确:

输入: abc 3.85 12

系统将返回相应错误信息:

? 错误: 金额 / 利率 / 月数 无效
请输入正确的正数,例如: 100000 3.85 12

编译与自动化复制流程

参照 BMI 案例,采用统一构建脚本完成全流程:

在项目根目录执行:

build-and-copy.bat

该脚本将自动执行以下步骤:

  1. 调用
    gradlew build
    编译 Kotlin/JS 代码
  2. 检查
    hellokjs.mjs
    hellokjs.d.ts
    是否成功生成
  3. 将生成的文件复制至 ArkTS 的 pages 目录,并将
    .mjs
    重命名为
    .js
  4. 最终目标路径为:
    d:\flutter_Obj\kmp_openharmony\kmp_ceshiapp\entry\src\main\ets\pages\hellokjs.js
    d:\flutter_Obj\kmp_openharmony\kmp_ceshiapp\entry\src\main\ets\pages\hellokjs.d.ts

总结

通过“贷款等额本息还款计算器”这一实践案例,目前已建立两条完整的 KMP 到 ArkTS 的集成链路:

  • BMI 体质指数计算器
  • 贷款等额本息还款计算器

两者共有的技术特点包括:

  • 核心算法集中于 Kotlin 层:便于未来复用于 Web、桌面应用等多个平台
  • ArkTS 聚焦 UI 交互逻辑:专注于数据输入采集与结果可视化展示
  • 借助 Kotlin/JS 实现鸿蒙端集成:一套 Kotlin 代码,实现多端共享业务逻辑

通过这种模式,你可以进一步拓展更多实用的功能工具,例如:

  • 提前还款模拟器
  • 投资收益计算器(支持定投与单次投资)
  • 收支记账统计分析工具

实现这些功能的流程高度一致,只需按照以下步骤重复操作即可:

  1. 在项目中新增对应的函数模块
    App.kt
  2. 添加具体的逻辑处理函数
    @JsExport
  3. 运行构建脚本,完成 JS 文件的编译与复制
  4. 在 ArkTS 页面中引入新生成的脚本并进行调用

最后,建议撰写一篇技术记录文章,详细描述整个实现过程,包括架构设计思路、关键代码片段以及实际应用效果,便于后续维护和团队协作。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Lin 计算器 TLI Experimental calculator

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注jr
拉您进交流群
GMT+8, 2026-1-16 21:28