HarmonyOS APP应用开发项目- MCA助手(持续更新中~)

简言:

gitee地址:https://gitee.com/whltaoin_admin/money-controller-app.git
端云一体化开发在线文档:
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/agc-harmonyos-clouddev-view-0000001700053733-V5

注:此App参照此教程进行二次修改:https://www.bilibili.com/video/BV1q5411v7o7

一、简介

moneyControllerApp(MCA)

这款精心打造的个人财务管理应用,是您理财路上的智慧伙伴。凭借前沿的智能化技术与直观易用的界面设计,它将化繁为简,让您的财务状况一目了然。无论是日常收支的记录,还是复杂财务的分析,都能轻松应对。它不仅帮助您有效掌控每一笔收入与支出,更助您洞悉财务趋势,科学规划未来,让财富增长之路更加清晰可见。从此,财务管理不再是难题,而是通往财务自由的桥梁。
在鸿蒙HarmonyOS Next版本的加持下,这款个人财务管理应用的性能与体验再度升级,成为您理财旅程中的超级智慧伙伴。鸿蒙系统的分布式技术,使得应用运行更加流畅稳定,数据同步更加快速准确,即使在多设备间切换,也能无缝衔接,确保您的财务信息实时更新,安全无忧。

二、什么是端云一体化开发

为丰富HarmonyOS对云端开发的支持、实现端云联动,DevEco Studio以Cloud Foundation Kit(云开发服务)为底座、在传统的“端开发”基础上新增“云开发”能力,开发者在创建工程时选择合适的云开发工程模板,即可在DevEco Studio内同时完成HarmonyOS应用的端侧与云侧开发,体验端云一体化协同开发。

三、开发环境介绍

编辑器DevEco Studio NEXT Developer Beta1
SDK11
操作系统Window 10 专业版
模拟器HarmonyOS Emulator Version: 5.0.3.405
HarmonyOS Version: HarmonyOS NEXT Developer Beta1

四、项目初始化

  • 步骤一:
/*
1 create project
2 application选择>>>[cloudDev] Empty Ability>>>Next
*/
  • 步骤二:输入图中信息后>>>点击Finish
    • 注意:存放路径不建议使用中文字符

image.png

  • 步骤三:进入项目主页>>>点击右上角的头像进行用户登录。

image.png

  • 步骤四:
// 1 进入网址并进行登录:https://developer.huawei.com/consumer/cn/
// 2 登录后在网站首页点击管理中心
// 3 点击左侧边栏(生态服务-应用服务)>>>点击AppGallery Connect
// 4 进入到以下页面

image.png

  • 步骤四:
// 1 点击我的项目>>>新建项目
// 2 数据处理位置选择中国并设置为默认
// 3 点击完成后并添加应用
// 4 注意:创建应用时如果想要自定义包名的话,定义的包名必须和新建项目时写的包名一致。
// 5 创建应用完成后,点击Next后,新建项目既可创建完成。

image.png

五、项目构建静态页面

登录注册页面

  • 效果图

image.png
image.png
结构:

// 一个页面:Login.etc
// 两个组件:
// 头部标题组件:titleComponent.ets
// 表单组件:InputComponent.ets

image.png

  • 代码
// Login.ets
import InputComponent from '../components/InputComponent';
import TitleComponent from '../components/TitleComponent';
import { typeNode } from '@ohos.arkui.node';
import { TESTTYPE } from '@ohos/hypium/src/main/Constant';@Entry
@Component
struct Login {@State message: string = 'Login';// 倒计时@State countDown :number = 60timer :number=0@State isRegister:boolean= false// 发送验证码sendCode(){this.startCountDown()}// 开始倒计时startCountDown(){this.timer =   setInterval(()=>{this.countDown--if(this.countDown===0){this.countDown=60clearInterval(this.timer)}},1000)}build() {Column(){// titleTitleComponent({title:"登录"})// login_contentStack({alignContent:Alignment.Top}){Image($r("app.media.Login_icon")).width(88).height(88).offset({y:-44}).zIndex(999)Column({space:10}){// emialInputComponent({title:"电子邮箱",inputIcon:$r("app.media.mail_icon"),placeholder:"请输入邮箱信息"})// pwdInputComponent({title:"密码",inputIcon:$r("app.media.pwd_icon"),placeholder:"请输入密码",inputType:InputType.Password})// VCodeif(this.isRegister){Column(){Text("验证码").width("100%").textAlign(TextAlign.Start).fontWeight(500).fontSize(16).fontColor(Color.Black).margin({bottom:14})Row(){TextInput({placeholder:"请输入验证码"}).layoutWeight(1).backgroundColor(Color.Transparent).border({width:1,color:"#ff9b9b9b"}).borderRadius(10)Button(this.countDown==60?"点击获取验证码":`${this.countDown}s`).fontSize("10").margin({left:10}).width(100).padding(0).onClick((event: ClickEvent) => {if(this.countDown===60){this.sendCode()}else{AlertDialog.show({message:"正在获取验证码,请等待..."})}})}.width("100%").height(50)}}// login_btnButton(this.isRegister?"注册":"登录").width(228).backgroundColor("#ff09b19d").margin({top:50}).onClick(()=>{// 登录方法})// re_btnRow(){Text(this.isRegister?"去登录":"去注册").fontSize(12).onClick(()=>{this.isRegister= !this.isRegister})Text("|").padding({left:10,right:10})Text("忘记密码").fontSize(12)}.width("100%").layoutWeight(1).justifyContent(FlexAlign.Center)}.width("100%").height("100%").padding({left:14,right:14}).margin({top:44})}.width("90%").backgroundColor(Color.White).margin({top:44}).layoutWeight(1).borderRadius(20)}.width("100%").height("100%").backgroundColor($r("app.color.page_Color"))}
}
// InputComponent.ets@Component
export  default struct InputComponent {@Prop title:string@Prop inputIcon:Resource@Prop placeholder:string@Prop  inputType:InputType=InputType.Normal@State changeStatus:boolean =falsebuild() {Column(){Text(this.title).width("100%").textAlign(TextAlign.Start).fontWeight(500).fontSize(16).fontColor(Color.Black).margin({bottom:14})Row(){Image(this.inputIcon).width(40).aspectRatio(1)TextInput({placeholder:this.placeholder}).onFocus(()=>{// 聚焦this.changeStatus=trueconsole.log("result>>>",this.changeStatus)}).onBlur(()=>{// 失去this.changeStatus=falseconsole.log("result>>>",this.changeStatus)}).layoutWeight(1).backgroundColor(Color.Transparent).type(this.inputType)}.width("100%").height(50).padding({left:10,right:10}).borderRadius(10).border({width:2,color:this.changeStatus?"#002884":Color.White})}}
}
// 页面标题组件 TitleComponent.ets@Component
export  default struct TitleComponent {@Prop title :stringbuild() {Row(){Image($r("app.media.Button_left")).width("44").height(41).objectFit(ImageFit.ScaleDown)Text(this.title).fontColor("#ff403f3f").fontWeight(700).fontSize(20).height(40)Text("")}.width("100%").justifyContent(FlexAlign.SpaceBetween).padding({left:20,right:20,top:12,bottom:12})}
}

主页框架及底部导航栏

  • 效果图(点击底部图标后,可以切换到对应页面并修改选中图标的底色。)

image.png
image.png

  • 功能点及编写思路
1 看着效果图像是多个页面编写而成的,其实就只有一个页面,通过tabs组件框架,嵌套其他组件从而形成多页面效果
2 框架编写思路:
整理和页面通用的数据并提取,在主页定义一个tabs组件,
分别定义5个页面的组件,和底部导航栏的组件
3 图标切换状态思路:
因为底部导航栏的数据是封装到了一个数组中,可以给每个对象定义一个ID属性,同时在主框架中定义一个
装饰器变量来监听tabs的onchange事件,因为ongchange事件会传递tab的下标,所有可以将传递的下标赋值给装饰器变量,
再将装饰器变量传递给底部导航栏图标组件,从而判断是否选中切换图标。
  • 结构:
  • image.png
实体类:BtnNavData
页面:MainPage
组件:CBtnNavImageDataStatisticsHomeMyWallet

代码:

// MainPage
import CBtnNavImage from './components/CBtnNavImage'
import { createBtnNavDataList,BtnNavData } from './model/BtnNavData'
@Entry
@Component
struct MainPage {@State btnNavItemid :number=0@State btnNavDataList:BtnNavData[] =createBtnNavDataList()// tabBar@BuildertabItemBar(item :BtnNavData){CBtnNavImage({btnNavData:item,isSelect:this.btnNavItemid})}build() {Tabs({barPosition:BarPosition.End}){ForEach(this.btnNavDataList,(item:BtnNavData,index)=>{TabContent(){Text(this.btnNavItemid.toString())}.tabBar(  this.tabItemBar(item))})}.onChange((index)=>{// 切换图标// console.log("result>>>>",index)if(index !=2){this.btnNavItemid =index}}).backgroundImage($r("app.media.Subtract")).backgroundImagePosition(Alignment.BottomEnd).backgroundImageSize({width:"100%",height:50})}
}
// BtnNavData
interface  IBtnNavData{selectIcon:ResourcenowIcon:Resourcetitle:stringid:number}
export   class BtnNavData{selectIcon:ResourcenowIcon:Resourcetitle:stringid:numberisQrcode:booleanconstructor(obj:IBtnNavData,isQrcode=false) {this.selectIcon=obj.selectIconthis.nowIcon=obj.nowIconthis.title=obj.titlethis.id=obj.idthis.isQrcode =isQrcode}
}export  const createBtnNavDataList =():BtnNavData[]=>{return [new BtnNavData({id:0,title:"首页",nowIcon:$r("app.media.home_icon_unselect"),selectIcon:$r("app.media.home_icon_select"),}),new BtnNavData({id:1,title:"数据展示",nowIcon:$r("app.media.data_icon_unselect"),selectIcon:$r("app.media.data_icon_select"),}),new BtnNavData({id:2,title:"扫一扫",nowIcon:$r("app.media.qrcode_icon"),selectIcon:$r("app.media.qrcode_icon"),},true),new BtnNavData({id:3,title:"钱包",nowIcon:$r("app.media.wallet_icon_unselect"),selectIcon:$r("app.media.wallet_icon_select"),}),new BtnNavData({id:4,title:"我的",nowIcon:$r("app.media.my_icon_unselect"),selectIcon:$r("app.media.my_icon_select"),})]
}
// CBtnNavImage
import { createBtnNavDataList,BtnNavData } from '../model/BtnNavData'
@Componentexport default struct CBtnNavImage {@Prop btnNavData:BtnNavData@Prop isSelect :number =0build() {Column(){Image(this.isSelect ==this.btnNavData.id ?this.btnNavData.selectIcon:this.btnNavData.nowIcon).width(20).height(20).offset({ y:this.btnNavData.isQrcode? -15 :0 })}.width("100%").justifyContent(FlexAlign.Center).height("100%")}
}
//  其余文件均为占位,并未编写

day01持续更新中…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/37722.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PyQt】20-QTimer(动态显示时间、定时关闭)

QTimer 前言一、QTimer介绍二、动态时间展示2.1 代码2.2 运行结果 三、定时关闭3.1 介绍他的两种用法1、使用函数或Lambda表达式2、带有定时器类型(高级) 3.2 代码3.3 运行结果 总结 前言 好久没学习了。 一、QTimer介绍 pyqt里面的多线程可以有两种实…

IOS Swift 从入门到精通: ios从服务器获取数据

文章目录 证书数据模型将数据添加到 Firestore进一步了解Combine创建 ViewModel证书数据模型 接下来,我们需要为证书创建一个模型。创建一个名为“Certificate.swift”的新文件,并添加以下模型: // Certificate.swiftstruct Certificate: Identifiable {var id: Stringvar…

微信内置H5支付

🧑‍💻 写在开头 点赞 收藏 学会🤣🤣🤣 场景是用户通过微信扫app内的收款码,跳到一个h5页面。然后完成支付。 代码实现的整体流程: 使用微信扫码,码是app内生成的,码…

Day38:LeedCode 1049. 最后一块石头的重量 II 494. 目标和 474.一和零

1049. 最后一块石头的重量 II 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果…

大数据面试题之MapReduce(2)

目录 shuffle为什么要排序? 说一下map是怎么到reduce的? 说一下你了解的用哪几种shuffle机制? MapReduce的数据处理过程 mapjoin的原理(实现)?应用场景? reducejoin如何执行(原理) MapReduce为什么不能产生过多小文件 MapReduce分区及作用 ReduceTask数量和分区数…

Java的NIO体系

目录 NIO1、操作系统级别下的IO模型有哪些&#xff1f;2、Java语言下的IO模型有哪些&#xff1f;3、Java的NIO应用场景&#xff1f;相比于IO的优势在哪&#xff1f;4、Java的IO、NIO、AIO 操作文件读写5、NIO的核心类 :Buffer&#xff08;缓冲区&#xff09;、Channel&#xff…

2024.06.29 刷题日记

739. 每日温度 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 示例 1: …

Linux下C/C++获得当前时间(秒/毫秒)

秒或者毫秒是根据当前时间到1970年1月1日计算&#xff0c;主要用于两个时间戳计算间隔时间 #include <iostream> using namespace std;#include <sys/time.h>int main() {struct timeval time_;gettimeofday(&time_, NULL);cout << time_.tv_sec <&…

【proteus 51单片机入门】8*8led点阵

文章目录 前言如何点亮led点阵仿真图代码点亮led核心代码解析 爱心代码 滚动总结 前言 在嵌入式系统的开发中&#xff0c;LED点阵显示器是一种常见的显示设备&#xff0c;它可以用来显示各种图形和文字&#xff0c;为用户提供直观的信息反馈。本文将介绍如何使用Proteus软件和…

使用 MongoDB 剖析开放银行:技术挑战和解决方案

开放银行&#xff08;或开放金融&#xff09;在银行业掀起了一股颠覆性浪潮&#xff0c;它迫使金融机构&#xff08;银行、保险公司、金融科技公司、企业甚至政府机构&#xff09;迎接一个透明、协作和创新的新时代。这种模式转变要求银行与第三方提供商&#xff08;TPP&#x…

如何在 SQL 中删除一条记录?

如何在 SQL 中删除一条记录&#xff1f; 在 SQL 中&#xff0c;您可以使用DELETE查询和WHERE子句删除表中的一条记录。在本文中&#xff0c;我将向您介绍如何使用DELETE查询和WHERE子句删除记录。我还将向您展示如何一次从表中删除多条记录 如何在 SQL 中使用 DELETE 这是使…

【计算机图形学】期末考试知识点汇总(上)

文章目录 视频教程第一章 计算机图形学概述计算机图形学的定义计算机图形学的应用计算机图形学 vs 图像处理 vs模式识别图形显示器的发展及工作原理理解三维渲染管线 第二章 基本图元的扫描转换扫描转换直线的扫描转换DDA算法Bresenham算法中点画线算法圆的扫描转换中点画圆算法…

react项目实现语音识别功能

需要调用后端接口将录音文件传给后端&#xff0c;由后端将录音内容转换成文字返回给前端&#xff0c;当然也有一些插件可以实现语音转文字功能&#xff0c;可以自行查找使用插件实现方法 有注释版本&#xff0c;下面还有 一个无注释版本。 import React, { useState, useEffe…

面试-J.U.C包的梳理

1.J.U.C包的梳理 Java.Util.Concurrent包简称JUC (1)JUC整体架构图 (2)分析 Executor&#xff1a;线程执行器&#xff0c;任务执行和调度的框架。Tools下存在executor相关的executors类&#xff0c;用于创建executorservice&#xff0c;scheduleexecutorservice&#xff0c;…

互斥锁(Mutex)和条件变量(Condition Variable)的作用

互斥锁&#xff08;Mutex&#xff09;的作用 互斥锁&#xff08;Mutex&#xff0c;全称Mutual Exclusion Lock&#xff09;是一种用于多线程编程中的同步原语&#xff0c;其主要作用是确保在任何给定时间只有一个线程可以访问共享资源&#xff0c;以避免多个线程同时对共享资源…

哪吒汽车,正在等待“太乙真人”的拯救

文丨刘俊宏 在360创始人、哪吒汽车股东周鸿祎近日连续且着急的“督战”中&#xff0c;哪吒汽车&#xff08;下简称哪吒&#xff09;终究还是顶不住了。 6月26日&#xff0c;哪吒通过母公司合众新能源在港交所提交了IPO文件&#xff0c;急迫地希望成为第五家登陆港股的造车新势力…

高精度除法的实现

高精度除法与高精度加法的定义、前置过程都是大致相同的&#xff0c;如果想了解具体内容&#xff0c;可以移步至我的这篇博客&#xff1a;高精度加法计算的实现 在这里就不再详细讲解&#xff0c;只讲解主体过程qwq 主体过程 高精度除法的原理和小学学习的竖式除法是一样的。 …

【Sklearn-驯化】一文搞懂机器学习树模型建模可视化过程

【Sklearn-驯化】一文搞懂机器学习树模型建模可视化过程 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注&#xff…

OpenCV学习之cv2.imshow()函数

OpenCV学习之cv2.imshow()函数 一、简介 cv2.imshow 是 OpenCV 库中用于显示图像的基本函数之一。在图像处理和计算机视觉的过程中&#xff0c;使用该函数可以快速预览处理后的图像&#xff0c;便于调试和结果展示。 二、基本语法 cv2.imshow(WindowName, Imgmat)三、参数说…

如何制作鼠标悬浮后伸缩的搜索框

引言 许多博客都在使用的伸缩搜索框制作教程 成品展示&#xff08;颜色自行搭配&#xff09; 初步布局 居中盒子&&初始化样式 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewpo…