10000 5000 2000 1500
输出内容包括:
- 总收入、总支出与余额统计
- 各项支出占总收入的比例明细
- 简要的预算健康评语(如是否超支、结余情况)
技术路线采用:Kotlin → Kotlin/JS → JavaScript 模块 → ArkTS 页面调用。
相比此前开发的 BMI 计算器、等额本息贷款计算器和成绩排行榜工具,该案例更贴近日常理财需求,能直观反映用户的支出结构和预算合理性,充分体现了“**核心逻辑用 Kotlin 编写,一次编写多端复用;界面交互由 ArkTS 实现**”的设计理念。
完整链路涵盖以下关键环节:
- 如何在 KMP 的公共源集中实现业务算法,并通过特定注解导出供 JS 使用
jsMain
@JsExport
- Kotlin 代码如何被编译成 ES Module 格式的 JavaScript 文件
hellokjs.mjs,同时生成对应的类型声明文件
hellokjs.d.ts
- 在 OpenHarmony 的 ArkTS 页面中,如何像引入普通 JS 模块一样调用 Kotlin 导出函数,并结合状态管理机制将结果绑定至 UI 组件
10000 5000 2000 1500
可理解为:
- 月收入 10000 元
- 三项支出分别为 5000、2000 和 1500 元
系统将自动计算:
- 总支出 = 5000 + 2000 + 1500 = 8500 元
- 余额 = 10000 - 8500 = 1500 元
- 每项支出占比,如第一项:5000 / 10000 = 50%
Text
控件进行滚动展示
- 文本可轻松复制用于日志记录、调试输出或其他终端场景
- 若未来需支持富文本渲染,当前字符串结构也利于二次解析扩展
核心算法实现在共享源集的 Kotlin 文件中
src/jsMain/kotlin/App.kt,并通过注解导出给 JavaScript 调用
@JsExport:
@OptIn(ExperimentalJsExport::class)
@JsExport
fun personalBudgetAnalyzer(inputText: String = "10000 5000 2000 1500"): String {
// 输入格式: "总收入 支出1 支出2 ...",例如 "10000 5000 2000 1500"
val parts = inputText.trim().split(" ").filter { it.isNotEmpty() }
if (parts.size < 2) {
return "? 错误: 请按 '总收入 支出1 支出2 ...' 的格式输入,例如: 10000 5000 2000 1500"
}
val income = parts[0].toDoubleOrNull()
val expenses = parts.drop(1).mapNotNull { it.toDoubleOrNull() }
if (income == null || expenses.any { it <= 0 }) {
return "? 错误: 总收入或支出无效\n请输入正确的正数,例如: 10000 5000 2000 1500"
}
val totalExpense = expenses.sum()
val balance = income - totalExpense
val expenseRatios = expenses.map { (it / income * 100).toInt() / 10.0 }
该函数具备良好的容错机制:
- 对输入为空或格式不正确的情况进行提示
- 验证数值合法性,防止负数或非数字输入
- 自动计算总支出、余额及各项支出占比
- 返回结构化文本,适配前端展示需求
hellokjs.mjs
- 类型定义文件(`.d.ts`)
hellokjs.d.ts,提升 TypeScript 开发体验
- 可通过 Gradle 脚本将输出产物自动复制到 OpenHarmony 工程的指定目录,实现无缝集成
个人收支预算分析代码实现说明 本实现基于 Kotlin 语言,结合其强大的集合操作与字符串处理能力,完成一个简洁高效的预算分析工具。以下为各部分逻辑的详细解析:输入解析机制trim().split(" ")
通过简单的空格分隔方式对输入字符串进行拆分,并利用对分割后的结果执行过滤,去除多余的空白项,确保数据有效性。 首项被尝试转换为filter { it.isNotEmpty() }作为用户的总收入金额,后续所有项则依次视为各项支出金额。Double健壮性校验设计null
若输入内容不足两项(即无收入或无支出),系统将直接返回带有示例格式的错误提示信息,引导用户正确使用。 同时,任何一项金额(收入或支出)若小于等于零,则立即中断计算流程并反馈错误,防止出现非法数值运算,保障逻辑合理性。 核心计算逻辑
总支出采用 Kotlin 集合 API 中的 sum() 方法实现,一行代码即可完成累加,充分体现了语言层面的表达力与简洁性。 余额expenses.sum()由总收入减去总支出得出,是判断预算状态的核心指标。 在计算各项支出占比时,采用保留一位小数的方式balance避免浮点数过长影响输出可读性,提升用户体验。(it / income * 100).toInt() / 10.0跨平台复用优势@JsExport
得益于 Kotlin/JS 的多平台支持能力,该逻辑不仅可在 JVM 环境运行,还可编译为 JavaScript 模块供前端或其他环境调用,为此提供了技术基础,使得此段业务逻辑能无缝集成至 JS 或 ArkTS 项目中,实现真正的一次编写、多端复用。 输出构造策略@JsExport
最终结果通过字符串拼接生成结构化文本报告,使用 Emoji 与分隔线增强可视化效果,适用于终端打印或 UI 展示场景。整体结构清晰,包含: - 收支统计:展示总收入、总支出与余额 - 支出明细:列出每项支出及其占总支出的比例 - 预算评语:根据余额正负给出“预算良好”或“预算超支”的结论 ━━━━━━━━━━━━━━━━━━━━━ 示例输出格式如下: ???? 个人收支预算分析 ━━━━━━━━━━━━━━━━━━━━━ 原始输入: 10000 5000 2000 1500 1?? 收支统计: 总收入: 10000 元 总支出: 8500 元 余额: 1500 元 2?? 支出明细: 支出1: 5000 元 (58.8%) 支出2: 2000 元 (23.5%) 支出3: 1500 元 (17.6%) 3?? 预算评语: 预算良好,剩余 1500 元。 ━━━━━━━━━━━━━━━━━━━━━ ? 分析完成!JavaScript 调用方式build/js/packages/hellokjs/kotlin/
Kotlin/JS 编译后会在目录生成对应的模块文件build/js/packages/hellokjs/kotlin/和hellokjs.mjs。在标准 ES Module 环境中可直接导入使用: // 导入由 Kotlin 编译生成的模块 import { personalBudgetAnalyzer } from './hellokjs.mjs'; // 使用默认输入执行分析 const result1 = personalBudgetAnalyzer(); console.log(result1); // 自定义输入,例如增加更多支出项 const result2 = personalBudgetAnalyzer('12000 4000 3000 1000 800 600'); console.log(result2); 该调用方式兼容 Node.js 命令行工具、Web 页面脚本以及任意支持 ES Module 的运行环境。hellokjs.d.ts值得注意的是,在 TypeScript 或 ArkTS 中引用时,hellokjs.d.ts还能提供良好的类型推断与编辑器智能提示,使调用体验接近原生 JavaScript 函数。hellokjs.d.tsArkTS 页面集成方案kmp_ceshiapp
在 OpenHarmony 工程中,已将主页面kmp_ceshiapp重构为预算分析功能页。ArkTS 使用标准Index.ets语法导入 Kotlin 导出函数,并在组件生命周期或按钮事件中触发调用: import { personalBudgetAnalyzer } from './hellokjs'; @Entry @Component struct Index { @State message: string = '请输入总收入和各项支出'; @State inputText: string = '10000 5000 2000 1500'; } 通过这种方式,实现了原生前端框架与 Kotlin 业务逻辑的高效协同,充分发挥多语言混合开发的优势。import
let resultText: string = '';
aboutToAppear(): void {
this.calculateBudget();
}
calculateBudget(): void {
try {
const input: string = this.inputText;
const result: string = personalBudgetAnalyzer(input);
this.resultText = result;
this.message = ' 计算完成';
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.message = ` 错误: ${errorMessage}`;
}
}
build() {
// UI 结构省略,重点在于状态管理与函数调用逻辑
}
上述代码展示了一种典型的 KMP(Kotlin Multiplatform)与 ArkTS 协同开发模式:
personalBudgetAnalyzer
其中,核心算法由 Kotlin 模块实现,完整的功能开发与单元测试均在 Kotlin 工程中完成。ArkTS 页面仅需承担以下职责:
- 管理用户输入内容
inputText
- 展示处理结果
resultText
- 绑定界面状态
通过生命周期钩子(例如页面初始化时)
aboutToAppear
或用户触发的按钮事件来调用底层算法函数,并根据返回值更新界面上的状态提示信息
message
。
当需要优化预算计算逻辑、引入更复杂的统计分析时,绝大多数修改集中在 Kotlin 端进行,而 ArkTS 的调用代码几乎无需调整。这种设计显著提升了跨平台项目的可维护性与扩展能力。
TextInput
组件,用于接收用户的文本输入:
- 输入框内置占位提示文本
例如: 10000 5000 2000 1500
,提供清晰的格式示例,降低初次使用门槛。
- “默认示例”按钮会自动填充一组合法测试数据并立即启动分析流程,帮助用户快速了解工具功能。
- “清空”按钮则重置输入区和输出结果,同时将提示语恢复为初始状态:“请输入总收入和各项支出”,便于用户重新开始新的预算评估。
整体操作流程如下:
- 页面加载完成后,自动执行一次
calculateBudget()
,利用默认数据填充结果区域,直观呈现工具用途。
- 用户可自行编辑输入内容,点击“开始分析”按钮再次调用相同的 Kotlin 函数进行实时计算。
- 若输入不符合规范(如缺少必要数值、包含非法字符等),Kotlin 层将返回带有具体说明的错误信息,ArkTS 层只需原样显示即可,避免在前端重复编写校验逻辑。
该分层架构——即“后端负责严谨的数据验证与结果组织,前端专注交互呈现”——在多端协同项目中具备高度实用性,也为后续集成更多工具类功能奠定了良好基础。
build-and-copy.bat
PowerShell 命令:
build-and-copy.ps1
脚本将自动执行以下步骤:
- 启动
gradlew build
任务,编译 Kotlin/JS 模块,生成
hellokjs.mjs
和
hellokjs.d.ts
两个输出文件。
- 检查生成结果是否完整,并输出明确的成功或失败提示。
- 将生成的文件复制至
kmp_ceshiapp/entry/src/main/ets/pages/
目录:
hellokjs.d.ts
直接复制,保持原名不变。
hellokjs.mjs
复制后重命名为
hellokjs.js
,以便 ArkTS 能通过相对路径顺利导入。
如此一来,每当你在
App.kt
中新增或修改 Kotlin 函数,只需重新运行该脚本,ArkTS 端即可立即使用最新逻辑,无需手动搬运文件或调整引用路径。
@JsExport
注解暴露给 JavaScript 环境调用;
- 使用 Kotlin/JS 编译器生成符合 ES Module 规范的模块及类型声明文件,保障类型安全与模块化复用;
- 在 OpenHarmony 的 ArkTS 页面中,像引入普通 JS 库一样导入并调用 Kotlin 提供的功能;
- 通过多行文本形式,将结构化分析结果直接渲染到移动端界面。
结合此前实现的 BMI 计算、贷款分期、成绩统计、井字棋小游戏等案例,目前已形成一套较为完整的 KMP 跨端应用示例体系,覆盖算法工具、数据分析和轻量级互动场景等多个维度。
在此基础上,你可以进一步拓展功能,例如:
- 为每项支出添加类别标签,生成可视化预算报表;
- 引入“储蓄率”“投资占比”等进阶财务指标;
- 结合本地计算与远程服务,支持数据云端同步或多设备共享。
无论功能如何演进,其核心理念始终一致:使用 Kotlin 处理复杂的计算逻辑与核心业务规则,充分发挥其在性能与稳定性方面的优势;同时,借助 ArkTS 实现流畅的用户界面与细腻的交互设计,提升整体体验感。通过 KMP 技术将二者无缝整合,实现能力互补、协同开发的高效架构。
扫码加好友,拉您进群



收藏
