一、对统计页面进行修改
将收入和支出分为了两类展示,这两类中有相同的类别,为了避免混淆,方便后续保存和数据同步等操作。具体修改如下:
import router from '@ohos.router'
import classInfo from '../viewmodel/classInfo'
import budgetPanel from '../views/budgetPanel'
@Entry
@Component
struct statistics {
//支出选项
payout: classInfo[] = [
new classInfo('餐饮',$r('app.media.img1')),
new classInfo('购物',$r('app.media.img2')),
new classInfo('日用',$r('app.media.img3')),
new classInfo('交通',$r('app.media.img4')),
new classInfo('零食',$r('app.media.img5')),
new classInfo('运动',$r('app.media.img6')),
new classInfo('娱乐',$r('app.media.img7')),
new classInfo('通讯',$r('app.media.img8')),
new classInfo('服饰',$r('app.media.img9')),
new classInfo('美容',$r('app.media.img10')),
new classInfo('住房',$r('app.media.img11')),
new classInfo('家庭',$r('app.media.img12')),
new classInfo('社交',$r('app.media.img13')),
new classInfo('医疗',$r('app.media.img14')),
new classInfo('学习',$r('app.media.img15')),
new classInfo('宠物',$r('app.media.img16')),
new classInfo('礼品',$r('app.media.img17')),
new classInfo('办公',$r('app.media.img18')),
new classInfo('维修',$r('app.media.img19')),
new classInfo('捐赠',$r('app.media.img20')),
new classInfo('红包',$r('app.media.img21')),
new classInfo('还款',$r('app.media.img22')),
new classInfo('借出',$r('app.media.img23')),
new classInfo('其它',$r('app.media.img24'))
]
//收入选项
income: classInfo[] = [
new classInfo('工资',$r('app.media.img25')),
new classInfo('红包',$r('app.media.img21')),
new classInfo('礼金',$r('app.media.img26')),
new classInfo('分红',$r('app.media.img27')),
new classInfo('理财',$r('app.media.img28')),
new classInfo('借入',$r('app.media.img29')),
new classInfo('收款',$r('app.media.img30')),
new classInfo('其它',$r('app.media.img24'))
]
//展示支出统计
@State showPayoutPanel: boolean = true
//收入文本颜色
@State incomeColor: string = '#ff000000'
//支出文本颜色
@State payoutColor: string = '#ffff0000'
build() {
Column(){
//标题栏,包括返回按钮和标题
Row(){
Image($r('app.media.back'))
.width(50)
.borderRadius(50)
.onClick(() => {
router.pushUrl(
{
url: 'pages/Index'
},
router.RouterMode.Single,
err => {
if(err){
console.log('返回主页失败')
}
}
)
})
Text('类别收支统计')
.fontSize(30)
.margin({left: 10})
}
.width('100%')
.margin({bottom: 20})
//收入支出切换设置
Row(){
Text('支出')
.fontSize(25)
.fontColor(this.payoutColor)
.onClick(() => {
this.payoutColor = '#ffff0000'
this.incomeColor = '#ff000000'
this.showPayoutPanel = true
})
Text(' | ')
.fontSize(25)
Text('收入')
.fontSize(25)
.fontColor(this.incomeColor)
.onClick(() => {
this.payoutColor = '#ff000000'
this.incomeColor = '#ffff0000'
this.showPayoutPanel = false
})
}
.width('100%')
.justifyContent(FlexAlign.End)
.padding({right: 20})
.margin({bottom: 20})
Row(){
//显示支出面板
if(this.showPayoutPanel){
List(){
ForEach(
this.payout,
(item: classInfo) => {
ListItem(){
Row(){
Row(){
Image(item.img)
.width(50)
.borderRadius(20)
Text(item.name)
.fontSize(20)
.margin({left: 5})
}
.margin({left: 10})
//支出类别金额为负
Text('-¥' + item.money.toFixed(2))
.fontSize(20)
.fontColor(Color.Red)
}
.width('90%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({top: 15})
}
}
)
}
//显示收入面板
} else {
List(){
ForEach(
this.income,
(item: classInfo) => {
ListItem(){
Row(){
Row(){
Image(item.img)
.width(50)
.borderRadius(20)
Text(item.name)
.fontSize(20)
.margin({left: 5})
}
.margin({left: 10})
//收入类别金额为正
Text('¥' + item.money.toFixed(2))
.fontSize(20)
.fontColor(Color.Red)
}
.width('90%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({top: 15})
}
}
)
}
}
}
.width('90%')
.layoutWeight(1)
.backgroundColor(Color.White)
.borderRadius(10)
.shadow({radius: 20, color: Color.Black, offsetX: 0, offsetY: 0})
.alignItems(VerticalAlign.Top)
}
.width('100%')
.height('100%')
.backgroundColor('#ffbfe8fd')
}
}
二、添加数据库实现持久化保存
将每次支出收入的明细都存储到数据库中的明细表中,以便退出应用后可以保存,下次打开时仍然存在,于是单独编写了一个数据库操作类,以及对明细页面和添加页面实现了数据库的交互。具体代码如下:
数据库操作类:
import relationalStore from '@ohos.data.relationalStore' //导入关系型数据库模板
import detailedInfo from '../viewmodel/detailedInfo'
class DetailedModel{
//定义关系型数据库存储对象
private rdbStore: relationalStore.RdbStore
//表名
private tableName: string = 'DETAILED'
//初始化
initTaskDB(context){
const config = {
name: 'MyApplication.db', //数据库名
securityLevel: relationalStore.SecurityLevel.S1 //安全级别为S1
}
//创建表的SQL语句
const sql = `CREATE TABLE IF NOT EXISTS DETAILED (
NAME TEXT PRIMARY KEY,
IMG TEXT,
AMOUNT DOUBLE,
DATE TEXT
)`
//获取数据库存储对象并执行初始化
relationalStore.getRdbStore(context,config,(err,rdbStore) => {
if(err){
console.log('textTag','获取rdbStore失败!') //获取失败信息
return
}
rdbStore.executeSql(sql) //执行sql语句创建表
console.log('textTag','创建detailed成功!') //创建成功提示信息
//将数据库存储对象赋值给私有变量
this.rdbStore = rdbStore
})
}
//查询
async getTaskList(){
//创建查询谓词对象
let predicates = new relationalStore.RdbPredicates(this.tableName)
//执行查询操作
let result = await this.rdbStore.query(predicates,['NAME','IMG','AMOUNT','DATE'])
//存储查询结果的数组
let detailed: detailedInfo[] = []
//循环终止条件,遍历到结果集最后一行
while(!result.isAtLastRow){
//移动到结果集的下一行
result.goToNextRow()
let name = result.getString(result.getColumnIndex('NAME')) //获取name值
let img = result.getString(result.getColumnIndex('IMG')) //获取img值
let amount = result.getDouble(result.getColumnIndex('AMOUNT')) //获取amount值
let date = result.getString(result.getColumnIndex('DATE')) //获取date值
//将查询结果存入数组
detailed.push({name,img,amount,date})
}
console.log('taskTag','查询到数据:',JSON.stringify(detailed))
return detailed //返回查询结果数组
}
//添加
addTask(name: string, img: string, amount: number, date: string): Promise<number>{
//执行插入操作并返回插入的行数
return this.rdbStore.insert(this.tableName,{name,img,amount,date})
}
//更新——待实现(目前未用到)
//删除——待实现(目前未用到)
}
//创建DetailedModel类的实例
let detailedModel = new DetailedModel();
//导出DetailedModel类的实例作为默认导出
export default detailedModel as DetailedModel
添加页面的数据库操作语句:
明细展示页面添加的数据库操作语句:
其中数据库的初始化操作均在entryability目录下的EntryAbility.ets文件中实现。
这里在写的时候发现了一些小问题。
我们在存储类别图片时使用的是ResourceStr类型,但是数据库基本类型中没有这种类型,所以在存储到数据库中时只能通过string类型,SQL语句中为TEXT,在存储时没有问题,但是当从数据库导出时,在页面上不会展示效果。所以这里为图片路径进行了更改。将类别图片放到了ResourceStr目录下的rawfile文件夹中,通过image($rawfile{'image.png'})的形式进行调用,最终实现预期效果。
效果实现:
添加明细持久化实现