当前位置: 首页 > news >正文

鸿蒙OS个人记账App毕设源码包(DevEco Studio可直接运行)

本文还有配套的精品资源,点击获取

简介:一套开箱即用的鸿蒙系统个人收支管理应用源码,专为毕业设计和HarmonyOS开发入门准备。项目基于OpenHarmony标准构建,使用DevEco Studio开发环境,已通过真机与模拟器调试验证,导入后无需额外配置即可编译安装。包含完整的entry模块结构,支持手机和平板等多设备UI适配;采用Preferences实现本地数据持久化,涵盖收入支出分类录入、账单列表展示、月份筛选、基础统计逻辑等功能;配套标准Gradle构建体系(build.gradle、settings.gradle、gradlew等)、IDE配置文件(.idea、.deveco)、代码混淆规则(proguard-rules.pro)及预览资源(previewer),满足高校毕设对工程规范性、可复现性和技术完整性要求。适合学习鸿蒙应用生命周期管理、页面导航机制、响应式状态更新与轻量级数据存储实践。

1. 项目概述:为什么这个鸿蒙记账App源码值得你花时间细读

我带过三届鸿蒙方向的毕业设计,每年都有学生卡在“从零写一个能跑起来的完整App”这一步——不是不会写单个页面,而是搞不清模块怎么组织、数据怎么存、页面怎么跳、状态怎么同步,更别说满足毕设答辩对工程规范性的硬性要求。直到去年我把这个记账App源码包作为参考模板发给几个学生,情况才真正改观。它不是那种只有一两个Activity、连数据库都没配好的“教学Demo”,而是一个真实可交付、结构清晰、边界明确、细节到位的轻量级生产级雏形。关键词里说的“鸿蒙记账App”“HarmonyOS毕设”“收支管理源码”,每一个都不是虚词:它用的是OpenHarmony标准API(非私有API),所有UI组件都基于ArkTS声明式语法,数据层严格遵循Preferences轻量级存储规范,连gradle构建脚本里的签名配置、混淆规则、多设备适配开关都已预置妥当。你导入DevEco Studio后点一下“Run”,真机上立刻弹出首页,不是报错、不是白屏、不是缺资源——是真正能记一笔收入、筛选上个月支出、看到柱状图统计的完整闭环。它解决的不是“能不能跑”的问题,而是“怎么跑得规范、怎么让老师一眼看出你掌握了鸿蒙开发的核心脉络”。尤其适合两类人:一类是刚学完《ArkTS基础》但还没碰过真实项目的学生,另一类是想快速验证某个技术点(比如页面传参、Preference键值设计、图表渲染时机)的开发者。它不炫技,不堆砌高级特性,但每行代码都在回答一个关键问题:“在鸿蒙生态里,这件事,标准做法是什么?”

2. 整体架构与设计思路拆解:为什么选这个结构,而不是别的

2.1 模块划分逻辑:entry是唯一入口,也是最佳教学切口

整个项目只有一个模块——entry。这看似简单,实则是刻意为之的教学设计。鸿蒙应用的模块化(Feature Ability / Particle Ability)对初学者来说是个认知门槛,而毕设项目又不需要微服务级别的复杂度。所以这里采用最直白的单模块结构:所有页面(首页、记账页、统计页)、所有业务逻辑(收支计算、分类管理)、所有数据访问(Preferences封装类)全部放在entry/src/main/ets下,目录层级清晰到近乎“教科书式”:

entry/ ├── src/ │ └── main/ │ └── ets/ │ ├── MainAbility/ // 应用生命周期入口 │ ├── pages/ // 所有UI页面 │ │ ├── HomePage.ets // 首页:账单列表+筛选栏 │ │ ├── AddRecordPage.ets // 记账页:表单录入+分类选择 │ │ └── StatsPage.ets // 统计页:月度汇总+图表 │ ├── model/ // 数据模型层 │ │ ├── Record.ets // 收支记录实体类(含type, amount, date等字段) │ │ └── Category.ets // 分类枚举(收入/餐饮/交通/娱乐等) │ ├── data/ // 数据访问层 │ │ └── PreferenceManager.ets // Preferences封装:统一读写key、类型安全 │ └── utils/ // 工具类 │ └── DateUtils.ets // 日期格式化、月份范围计算(关键!统计逻辑依赖它)

提示:这种扁平化结构极大降低了理解成本。你看HomePage.ets里调用PreferenceManager.getAllRecords(),再看PreferenceManager.ets里如何用preferences.get()读取字符串数组并反序列化为Record[],整个数据流一目了然。没有LiveData、没有StateProvider绕弯子,就是最朴素的“存-取-展示”链路,但恰恰覆盖了毕设要求的“本地数据持久化”核心考点。

2.2 UI适配策略:响应式布局不是玄学,而是几行代码的事

很多学生以为“多设备适配”等于写一堆@ohos:screenWidth判断,其实鸿蒙的FlexColumn/Row配合百分比单位就能解决80%场景。这个项目里,HomePage.ets的账单列表区域是典型范例:

// HomePage.ets 片段 Column() { // 筛选栏:固定高度,宽度占满 Row() { Text('本月').fontSize(16).fontWeight(FontWeight.Bold) // ...其他筛选按钮 } .width('100%').height(56) // 固定高度,宽度自适应 // 账单列表:占据剩余全部空间,支持滚动 List() { ForEach(this.records, (item: Record) => { ListItem() { RecordItem(item) // 自定义组件,内部用Flex布局 } }, item => item.id.toString()) } .layoutWeight(1) // 关键!占满剩余空间 } .width('100%').height('100%') // 页面根容器撑满

layoutWeight(1)这行代码,就是鸿蒙响应式布局的“定海神针”。它告诉系统:“这个List,把父容器剩下的所有高度都给我,别管我内容多少”。配合List自身的滚动能力,无论手机小屏还是平板大屏,列表都能完美填充可用区域,且滚动流畅。而RecordItem组件内部用Flex做左右分栏(左侧图标+文字,右侧金额),用flexBasis控制图标大小、flexGrow分配文字区域宽度,一套组合拳下来,不同屏幕尺寸下元素比例始终协调。这比写死px值或频繁监听窗口变化要稳健得多,也更符合鸿蒙“一次开发,多端部署”的设计哲学。

2.3 数据持久化选型:为什么是Preferences,而不是SQLite或关系型数据库

毕设项目的数据量级决定了技术选型——你的记账App,一年最多几千条记录,每条就几个字段(ID、类型、金额、日期、备注)。这时候上SQLite,就像用起重机搬一盒图钉:功能过剩,维护成本陡增。项目选用Preferences,是经过权衡的务实之选:

  • 轻量无依赖Preferences是鸿蒙系统级API,无需额外引入库,@ohos.app.ability.common导入即用;
  • 读写极快:键值对存储,get()/put()操作毫秒级,远超SQLite建表、插入、查询的开销;
  • 天然防错PreferencesputString()putNumber()等方法强制类型,避免JSON序列化时的undefined陷阱;
  • 毕设友好:老师检查代码时,看到preferences.putNumber('balance', newBalance)比看到一堆SQL语句更易理解你的数据流向。

当然,Preferences也有局限:不支持复杂查询(如“查2023年所有餐饮支出”需全量遍历)。但项目通过巧妙设计规避了这点——所有记录以Record对象序列化为JSON字符串数组存储(key为'records'),查询时只需getAllRecords()取出全部,再用Array.filter()按月份、类型筛选。对于毕设体量,内存占用和性能完全可控。我在实际测试中,模拟5000条记录,首页加载时间仍稳定在120ms内(华为Mate 50真机)。

2.4 构建体系完整性:Gradle脚本里的“隐形考题”

毕设答辩常被忽略却极其关键的一环,是工程的可复现性。这个源码包的build.gradle文件,藏着几个容易被学生忽略的“隐形考点”:

// build.gradle (Module: entry) 片段 android { compileSdkVersion 10 // OpenHarmony SDK版本,必须与DevEco Studio匹配 defaultConfig { applicationId "com.example.hongmengaccount" // 包名,答辩PPT里要写清楚 minSdkVersion 9 // 最低兼容版本,决定API可用范围 targetSdkVersion 10 versionCode 1 versionName "1.0" } } // 签名配置(毕设必须!否则无法安装到真机) signingConfigs { release { storeFile file("../keystore/debug.keystore") // 预置调试密钥 storePassword "123456" keyAlias "androiddebugkey" keyPassword "123456" } } buildTypes { release { signingConfig signingConfigs.release // 发布版自动签名 minifyEnabled true // 启用混淆 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } }

这些配置意味着:你导出的.hap包,可以直接双击安装到任何鸿蒙设备,无需手动签名;混淆规则proguard-rules.pro里已排除Record等实体类(防止反序列化失败),确保代码压缩后功能不崩。很多学生交稿前才发现build.gradleminSdkVersion写错了,导致老师用旧版DevEco打不开——这种低级失误,这个源码包已帮你踩平。

3. 核心细节解析与实操要点:从代码到运行的关键节点

3.1 页面导航机制:router.pushUrl()背后的生命周期真相

鸿蒙的页面跳转不是简单的“打开新页面”,而是涉及Ability生命周期的精密协作。AddRecordPage.ets里点击“保存”后的跳转逻辑,是理解鸿蒙应用架构的绝佳入口:

// AddRecordPage.ets 保存按钮点击事件 saveRecord() { const record = new Record( this.selectedType, this.amount, this.date, this.remark ); // 1. 先存数据 PreferenceManager.saveRecord(record); // 2. 再跳转回首页,并触发刷新 router.pushUrl({ url: 'pages/HomePage', params: { refresh: true } // 关键!传递刷新标识 }); }

这里有两个易错点:第一,数据必须先存,再跳转。如果顺序颠倒,用户在HomePageonPageShow()时尝试读取最新数据,可能拿到旧缓存(因为HomePage实例可能还活着,只是被push到了后台)。第二,params: { refresh: true }不是可有可无的装饰——它直接关联到HomePage.etsonPageShow()钩子:

// HomePage.ets onPageShow() { console.info('HomePage onPageShow called'); // 检查是否需要强制刷新 if (this.$rawArgs?.refresh === true) { this.loadRecords(); // 重新从Preferences读取全部数据 } }

onPageShow()是鸿蒙页面显示时的必经之路,比onPageAppear()更可靠(后者在页面部分可见时也会触发)。利用这个钩子+参数传递,实现了“跳转即刷新”的无缝体验。很多学生用router.replaceUrl()想“替换掉当前页”,结果首页数据没更新——根本原因是没理解replaceUrl会销毁原页面实例,而HomePageonPageShow()replace后并不会被调用。

3.2 状态管理实践:@State@Observed的精准使用边界

ArkTS的状态管理不像React那样有useState/useEffect的强约束,初学者极易滥用@State导致性能问题。这个项目里,HomePage.ets的状态设计堪称教科书:

@Entry @Component struct HomePage { // 1. @State 用于驱动UI局部更新的简单状态 @State selectedMonth: string = DateUtils.getCurrentMonth(); // 当前选中月份,改变时仅重绘筛选栏 @State records: Record[] = []; // 账单列表,改变时重绘整个List // 2. @Observed 用于复杂对象的深度响应式 @Observed statsData: StatsData = new StatsData(); // 统计数据对象,含income/expense/total等属性 build() { Column() { // 筛选栏:绑定selectedMonth MonthSelector({ month: $selectedMonth }) // 账单列表:绑定records List() { ForEach(this.records, (item: Record) => { ListItem() { RecordItem(item) } }) } // 统计卡片:绑定statsData.income等 StatsCard({ income: this.statsData.income, expense: this.statsData.expense }) } } // 页面显示时加载数据 onPageShow() { this.loadRecords(); } loadRecords() { this.records = PreferenceManager.getRecordsByMonth(this.selectedMonth); this.statsData = PreferenceManager.calculateStats(this.selectedMonth); // 返回新StatsData实例 } }

关键点在于:@State只用于原始类型(string,number)或数组(Record[]),而StatsData这种含多个属性的对象,用@Observed修饰。这样做的好处是——当calculateStats()返回一个全新的StatsData实例时,StatsCard组件才会整体重绘;如果StatsData是普通类,this.statsData.income++这种修改不会触发UI更新。@Observed确保了对象内部属性变更也能被侦测。我在指导学生时反复强调:不要把所有变量都标@State,那会导致不必要的全量重绘;@Observed也不是万能药,它只对类实例有效,对普通对象字面量无效。

3.3 图表统计逻辑:用纯ArkTS实现月度汇总,避开第三方库陷阱

毕设项目引入ECharts等第三方图表库,常因鸿蒙兼容性问题翻车(JSBridge不稳定、Canvas渲染异常)。这个项目用纯ArkTS+Canvas组件手绘柱状图,虽不如专业库炫酷,但绝对稳定、可控、易讲解:

// StatsPage.ets 中的柱状图组件 @Component struct BarChart { @Prop income: number = 0; @Prop expense: number = 0; build() { Canvas(this.context) .width('100%') .height(200) .onReady(() => { const canvas = this.context; const ctx = canvas.getContext('2d'); // 计算坐标系(简化版) const chartWidth = canvas.width; const chartHeight = canvas.height; const barWidth = chartWidth * 0.3; const maxVal = Math.max(this.income, this.expense) || 100; // 绘制收入柱(蓝色) ctx.fillStyle = '#4A90E2'; ctx.fillRect( chartWidth * 0.2, chartHeight - (this.income / maxVal) * chartHeight * 0.7, barWidth, (this.income / maxVal) * chartHeight * 0.7 ); // 绘制支出柱(红色) ctx.fillStyle = '#E74C3C'; ctx.fillRect( chartWidth * 0.6, chartHeight - (this.expense / maxVal) * chartHeight * 0.7, barWidth, (this.expense / maxVal) * chartHeight * 0.7 ); }) } }

这段代码的价值不在美术效果,而在可解释性。答辩时你可以指着ctx.fillRect()说:“这是鸿蒙Canvas API的矩形绘制方法,参数分别是x,y,width,height;y坐标用chartHeight - valueRatio * height实现‘底部对齐’,这是图表渲染的基本数学原理”。老师听到这里,就知道你不是调包侠,而是理解底层逻辑的开发者。而且,所有计算都在onReady回调里完成,确保Canvas上下文就绪,避免getContext返回null的常见错误。

3.4 多设备预览配置:.previewer/config.json里的适配玄机

DevEco Studio的预览器是毕设演示利器,但很多人不知道如何让它精准模拟不同设备。项目根目录下的.previewer/config.json文件,就是预览器的“设备说明书”:

{ "devices": [ { "name": "phone", "deviceType": "phone", "screenWidth": 360, "screenHeight": 640, "density": 2.0, "orientation": "portrait" }, { "name": "tablet", "deviceType": "tablet", "screenWidth": 720, "screenHeight": 1280, "density": 2.0, "orientation": "portrait" } ], "defaultDevice": "phone" }

这个配置让预览器左上角出现设备切换按钮,点击即可实时查看同一份代码在手机和平板上的渲染效果。更重要的是,它强制指定了screenWidth/screenHeight,确保你在Column里写的layoutWeight(1)能按预期分配空间。很多学生抱怨“预览器里布局乱了”,根源往往是没配这个文件,导致预览器用默认分辨率(可能是1080p)渲染,而你的Flex计算基于360px宽度——数值对不上,布局必然崩。配好它,答辩时切换设备演示,瞬间提升专业感。

4. 实操过程与核心环节实现:从导入到真机运行的全流程详解

4.1 DevEco Studio环境准备:版本匹配是成功的第一道门槛

别急着导入项目,先确认你的DevEco Studio版本与源码包兼容。这个项目基于OpenHarmony SDK 4.0(对应DevEco Studio 4.1),如果你用的是3.x版本,大概率会遇到compileSdkVersion 10报错。正确步骤如下:

  1. 下载匹配版本:访问华为开发者联盟官网,下载DevEco Studio 4.1 Release(注意不是Beta版);
  2. 安装SDK:启动DevEco后,进入Settings > SDK Manager,勾选OpenHarmony SDK 4.0及配套工具链(HUAWEI DevEco SDK Tools);
  3. 配置Node.js:鸿蒙项目依赖Node.js 18.x,DevEco会自动检测,若提示缺失,请单独安装Node.js 18.18.2(LTS版),并在Settings > Languages & Frameworks > Node.js and NPM中指定路径;
  4. 验证环境:新建一个空的“Empty Ability”项目,能正常编译运行,说明环境就绪。

注意:千万别用VS Code装鸿蒙插件来替代DevEco Studio!鸿蒙的.hap包签名、真机调试、预览器联动等功能,只有官方IDE能完整支持。我见过太多学生因贪图VS Code熟悉感,最后卡在签名失败上,白白浪费三天。

4.2 项目导入与首次构建:三步走,避开90%的构建错误

导入不是简单拖拽,而是有明确顺序的标准化流程:

第一步:关闭所有已打开项目
DevEco Studio不支持多项目并存,务必先File > Close Project,确保工作区干净。

第二步:选择“Import Project”而非“Open”
点击File > Import Project,定位到你解压后的源码根目录(即包含build.gradlesettings.gradleentry文件夹的目录),不要选到entry子目录settings.gradle里的include ':entry'指令,正是告诉Gradle“这个模块才是主应用”。

第三步:等待Gradle同步,再执行构建
导入后,DevEco会自动触发Gradle Sync(右下角有进度条)。此时不要点击Run按钮!必须等Sync完成(状态栏显示“Gradle sync finished”),再点击顶部工具栏的Build > Build HAP(s)。首次构建耗时约2-3分钟(下载依赖、编译ArkTS),完成后会在entry/build/default/outputs/default/下生成entry-default-unsigned.hap

实操心得:如果Sync卡在Resolving Dependencies,大概率是网络问题。此时不要慌,打开gradle.properties,将mavenCentral()仓库地址注释掉,换成华为镜像:
// mavenCentral() maven { url 'https://developer.huawei.com/repo/' }
华为镜像速度稳定,能解决95%的依赖拉取失败。

4.3 真机调试配置:从USB连接到应用安装的完整链路

模拟器虽方便,但毕设答辩必须真机演示。鸿蒙真机调试需四步认证:

  1. 开启开发者模式:手机设置 > 关于手机 > 连续点击“版本号”7次;
  2. 启用USB调试:设置 > 系统和更新 > 开发人员选项 > 打开“USB调试”;
  3. 安装HiSuite(可选但推荐):华为电脑管家自带HiSuite,连接手机后自动安装HDC调试桥接工具;
  4. DevEco中配置设备:点击Tools > Device Manager,在“Local Device”标签页应看到你的手机型号。若显示“Offline”,拔插USB线或重启手机USB调试。

配置完成后,在DevEco顶部工具栏选择你的设备(而非“Emulator”),点击绿色三角形Run。系统会自动:
- 将entry-default-unsigned.hap推送到手机;
- 调用hdc install命令安装应用;
- 启动MainAbility,首页立即呈现。

常见问题:安装失败报错INSTALL_FAILED_INVALID_APK。这是因为未签名。解决方案:在Build Variants面板(左下角)将Build Variantdebug切换为release,再Build HAP(s),生成的entry-default-signed.hap即可直接安装。

4.4 功能验证清单:一份答辩前必须跑通的Checklist

别等到答辩现场才试功能!按此清单逐项验证,确保万无一失:

功能模块验证步骤预期结果常见陷阱
首页展示打开App,观察账单列表显示至少3条示例数据(源码预置),无空白或报错PreferenceManager未初始化,getAllRecords()返回空数组
新增记账点击“+”按钮 > 选择收入 > 输入金额100 > 保存自动跳转回首页,列表顶部新增一条“收入 100元”router.pushUrl()参数url写错(如漏掉pages/前缀)
月份筛选点击筛选栏“本月” > 切换为“上月”列表清空,显示“暂无记录”(因预置数据全在本月)DateUtils.getMonthRange()计算错误,返回空字符串
统计图表进入“统计”页柱状图正常渲染,收入柱高于支出柱(预置数据中收入更多)Canvas.onReady()未触发,getContext('2d')返回null
数据持久化新增一笔支出50元 > 退出App > 重新打开新增的50元支出仍在列表中PreferenceManager.saveRecord()未调用flush(),数据滞留在内存

这份清单覆盖了毕设答辩所有关键演示点。我建议学生打印出来,每验证一项就打钩,全部通过再提交——比临时救火强十倍。

5. 常见问题与排查技巧实录:那些让你熬夜的坑,我都替你踩过了

5.1 “页面白屏/黑屏”问题:90%源于资源路径或组件命名错误

这是新手最高频的崩溃点。现象:App启动后一片空白,控制台无报错。排查路径如下:

第一步:检查MainAbility配置
打开entry/src/main/config.json,确认module.mainElement指向正确的页面:

"module": { "mainElement": "pages/HomePage" // 必须与HomePage.ets文件名、组件名完全一致! }

常见错误:文件名是homePage.ets(小写h),但配置里写pages/homePage;或组件名是@Component struct HomePage,但配置里写pages/homepage。鸿蒙路径区分大小写,错一个字母就白屏。

第二步:检查HomePage.ets@Entry装饰
确保首页文件顶部有且只有一个@Entry

@Entry // 必须存在! @Component struct HomePage { ... }

漏掉@Entry,DevEco不会报错,但页面无法作为入口加载。

第三步:检查import路径
HomePage.ets里如果有import { Record } from '../model/Record';,确认../model/Record.ets文件真实存在,且文件名拼写准确(.ets后缀不能少)。

我的避坑技巧:在DevEco中按Ctrl+Click(Windows)或Cmd+Click(Mac)点击import语句中的路径,如果能跳转到目标文件,说明路径正确;如果提示“Cannot find declaration”,立刻修正。

5.2 “数据不更新”问题:状态驱动失效的三大元凶

现象:新增记录后,首页列表没变,但PreferenceManager里数据已写入。本质是UI状态未响应数据变更。

元凶一:@State变量未在build()中使用

@State records: Record[] = []; loadData() { this.records = PreferenceManager.getAllRecords(); // ✅ 正确赋值 } // ❌ 错误:build()里没用到this.records,状态变更不触发重绘 build() { Column() { Text('Hello World') // 只写了静态文本! } }

元凶二:ForEachkeyGenerator函数返回重复key

// ❌ 危险!如果多条记录date相同,key会重复,导致UI错乱 ForEach(this.records, (item: Record) => { ... }, item => item.date) // ✅ 安全!用唯一ID作key ForEach(this.records, (item: Record) => { ... }, item => item.id.toString())

元凶三:异步操作后未在主线程更新状态

// ❌ 错误!setTimeout在子线程,this.records赋值不触发UI更新 setTimeout(() => { this.records = newData; }, 1000); // ✅ 正确!用@ohos.app.ability.common的delayCallback common.delayCallback(() => { this.records = newData; // 此时在UI线程 }, 1000);

5.3 “真机安装失败”问题:签名与权限的硬性门槛

现象:hdc install报错INSTALL_FAILED_NO_MATCHING_ABISINSTALL_FAILED_INVALID_SIGNATURE

解决方案矩阵:

报错信息根本原因解决方案
INSTALL_FAILED_NO_MATCHING_ABIS手机芯片架构(arm64)与HAP包架构不匹配build-profile.json5中,abiFilters必须包含['arm64-v8a'],且target设为"default"(非"debug"
INSTALL_FAILED_INVALID_SIGNATUREHAP包未签名或签名证书不匹配切换Build Variantrelease,确保build.gradlesigningConfigs路径正确指向debug.keystore
INSTALL_FAILED_USER_RESTRICTED手机开启了“安装外部来源应用”限制设置 > 安全 > 更多安全设置 > 打开“安装外部来源应用”(针对当前DevEco Studio)

个人经验:每次更换电脑或重装DevEco,务必重新生成debug.keystore,并更新build.gradle中的storeFile路径。用旧密钥在新环境签名,必然失败。

5.4 “预览器不显示”问题:配置文件与组件语法的双重校验

现象:预览器窗口空白,或提示“Preview failed”。

双保险排查法:

  1. 检查.previewer/config.json是否存在且语法正确
    文件必须位于项目根目录,且JSON格式合法(可用在线JSON校验工具验证)。常见错误:末尾多逗号、引号用中文符号、deviceType写成"phone"(正确)而非"Phone"(错误)。

  2. 检查组件是否符合预览器语法限制
    预览器不支持某些动态语法:
    - ❌if (this.showHeader) { Header() }→ 预览器无法解析条件渲染
    - ✅ 改为Header({ visible: this.showHeader }),在Header组件内部用if控制显示

  • this.records.map(...)→ 预览器不支持复杂表达式
  • ✅ 改为this.recordList = this.records;,在build()中用ForEach(this.recordList, ...)

预览器本质是静态分析器,越接近“纯声明式”,兼容性越好。

6. 毕设扩展与进阶建议:让项目从“合格”走向“优秀”

这个源码包是扎实的起点,但若想在答辩中脱颖而出,可以基于它做三个低成本、高价值的扩展:

6.1 增加“数据导出”功能:用@ohos.fileio实现CSV导出

毕设常被问“数据怎么备份?”,一句“存在本地”显得单薄。增加导出功能,瞬间体现工程思维:

// 在HomePage.ets中添加 exportData() { const records = PreferenceManager.getAllRecords(); const csvContent = '类型,金额,日期,备注\n' + records.map(r => `${r.type},${r.amount},${r.date},${r.remark}`).join('\n'); // 使用fileio写入沙箱目录 const path = getContext().filesDir + '/export.csv'; fileio.writeTextSync(path, csvContent); // 弹出Toast提示 showToast({ message: '导出成功!路径:' + path }); }

只需10行代码,就实现了数据可迁移性。答辩时演示“导出CSV→用Excel打开”,老师会眼前一亮。

6.2 实现“夜间模式”切换:用@ohos.app.ability.common监听系统主题

鸿蒙原生支持深色模式,接入它成本极低,却能展示你对系统能力的理解:

// 在MainAbility中监听主题变化 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { // 监听系统主题变更 common.theme.onThemeChange((theme: common.Theme) => { this.isDarkMode = theme === common.Theme.DARK; // 通知所有页面更新UI eventHub.publish('themeChange', this.isDarkMode); }); }

然后在各页面build()中,根据this.isDarkMode动态设置backgroundColor。全程无需第三方库,纯鸿蒙API。

6.3 添加“手势删除”交互:用Gesture增强用户体验

List组件支持onDelete,但默认是长按弹菜单。升级为左滑删除,体验更原生:

// HomePage.ets List中 List() { ForEach(this.records, (item: Record) => { ListItem() { RecordItem(item) } .onDelete(() => { PreferenceManager.deleteRecord(item.id); this.records = this.records.filter(r => r.id !== item.id); }) }) }

配合ListItemswipeAction属性,就能实现iOS风格的滑动操作。代码量少,但演示效果惊艳。

最后分享一个小技巧:答辩PPT里,不要只放代码截图。把PreferenceManager.ets的类图、HomePage的组件树、build.gradle的关键配置项,用简洁的框图画出来。老师扫一眼,就能判断你是否真正理解了项目结构——这比讲十分钟API细节更有说服力。

本文还有配套的精品资源,点击获取

简介:一套开箱即用的鸿蒙系统个人收支管理应用源码,专为毕业设计和HarmonyOS开发入门准备。项目基于OpenHarmony标准构建,使用DevEco Studio开发环境,已通过真机与模拟器调试验证,导入后无需额外配置即可编译安装。包含完整的entry模块结构,支持手机和平板等多设备UI适配;采用Preferences实现本地数据持久化,涵盖收入支出分类录入、账单列表展示、月份筛选、基础统计逻辑等功能;配套标准Gradle构建体系(build.gradle、settings.gradle、gradlew等)、IDE配置文件(.idea、.deveco)、代码混淆规则(proguard-rules.pro)及预览资源(previewer),满足高校毕设对工程规范性、可复现性和技术完整性要求。适合学习鸿蒙应用生命周期管理、页面导航机制、响应式状态更新与轻量级数据存储实践。


本文还有配套的精品资源,点击获取

http://www.jsqmd.com/news/956384/

相关文章:

  • 别再死记ResNet结构图了!用PyTorch手写一个18层残差网络(附代码逐行解析)
  • EmojiOne Color彩色表情字体:3步实现跨平台表情符号统一设计
  • 深度探索:揭秘AMD处理器底层调校的5个突破性技巧
  • 信号完整性基石:深入解析返回损耗与阻抗匹配原理及工程实践
  • 技术生涯规划:从嵌入式到系统级挑战的七年成长路径
  • 你还在手动改简历、筛需求、写SOW?这8个AI工具已让头部自由职业者实现「零人工介入式接单」,最后1个国内可用率不足11%
  • 2026年三门峡市民高频选择的5家实体黄金回收白银回收铂金回收门店实地测评整理 - 中安检金银铂钻回收
  • 终极指南:如何利用Gemma-4-31B-JANG_4M-CRACK进行渗透测试与漏洞利用
  • PCL环境下单点坡度快速计算C++实现(含法向量估计与输出)
  • HSPF模型实践技术应用
  • 5步轻松获取国家中小学智慧教育平台电子课本PDF:教师家长必备下载工具
  • LinkSwift网盘直链下载助手:彻底告别网盘限速的完整教程
  • VHDL全加器实现:从逻辑门到模块化设计的数字电路实践
  • 实战演练:基于Spring Boot和MySQL,用快马快速构建个人博客系统数据库与API
  • 3步完成小说离线保存:开源工具novel-downloader终极指南
  • HSTracker终极指南:如何用macOS卡组跟踪器轻松提升炉石传说胜率
  • 别再手动复制了!Typora、VS Code、Obsidian里Markdown Emoji的快速输入与自动补全技巧
  • MuleSoft+LLM企业级AI编排:构建可审计、可治理、可降级的语义中间件
  • 限时公开:头部AI公司内部反馈看板架构图(含实时情感热力图+归因路径追踪模块)
  • 如何快速管理Switch游戏文件?NS-USBLoader终极指南:3分钟上手文件传输、RCM注入与文件处理
  • Standalone Migrations最佳实践:避免常见陷阱的10个技巧
  • RetroBar终极指南:让现代Windows重拾经典任务栏的完整方案
  • 华硕笔记本终极性能管家:GHelper完整指南,让你的ROG设备焕发新生
  • 问答系统开发实战:基于BERT-large-uncased-whole-word-masking-finetuned-squad的企业级应用
  • C++成员初始化列表:嵌入式开发中提升性能与可靠性的关键
  • 终极免费数字标牌系统:LibreSignage开源方案完全指南
  • 终极WarcraftHelper使用指南:如何让魔兽争霸III在现代电脑上焕发新生
  • 10张图看懂 AI Agent
  • 智能M3U8下载器:3分钟掌握跨平台视频保存技术
  • 【限时解密】红杉/DCM/A16Z最新AI工具尽调SOP(含NDA版技术验证Checklist):仅开放72小时》