一、通用DB工具
完成饮食记录操作和model的开发。
在RecordModel中
//关系型数据库
import relationalStore from '@ohos.data.relationalStore'
import data from '@ohos.telephony.data'
import { ColumnInfo, ColumnType } from '../common/bean/ColumnInfo'
import RecordPO from '../common/bean/RecordPO'
import DbUtil from '../common/utils/DbUtil'
//数据库建表语句
const CREATE_TABLE_SQL: string = `
CREATE TABLE IF NOT EXISTS record (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type_id INTEGER NOT NULL,
item_id INTEGER NOT NULL,
amount DOUBLE NOT NULL,
create_time INTEGER NOT NULL
)
`
const COLUMNS:ColumnInfo[]=[
{name:'id',columnName:'id',type:ColumnType.LONG},
{name:'typeId',columnName:'id',type:ColumnType.LONG},
{name:'itemId',columnName:'id',type:ColumnType.LONG},
{name:'amount',columnName:'id',type:ColumnType.DOUBLE},
{name:'createTime',columnName:'id',type:ColumnType.LONG}
]
const TABLE_NAME = 'record'
const ID_COLUMN = 'id'
const DATE_COLUMN = 'create_time'
class RecordModel {
getCreateTableSql():string{
return CREATE_TABLE_SQL
}
insert(record:RecordPO):Promise<number>{
return DbUtil.insert(TABLE_NAME,record,COLUMNS)
}
deleteById(id:number){
//1.删除条件
let predicates = new relationalStore.RdbPredicates(TABLE_NAME)
predicates.equalTo('ID_COLUMN',id)
//2.删除
return DbUtil.delete(predicates)
}
listByDate(date:number) :Promise<RecordPO[]>{
//1.查询条件
let predicates = new relationalStore.RdbPredicates(TABLE_NAME)
predicates.equalTo('DATE_COLUMN',date)
//2.查询
return DbUtil.queryForList(predicates,COLUMNS)
}
}
let recordModel = new RecordModel()
export default recordModel as RecordModel
在EntryAbility中调用数据库操作
async onCreate(want, launchParam) {
//1.加载用户首选项
PreferenceUtil.loadPreference(this.context)
//2.初始化日期
AppStorage.SetOrCreate(CommonConstants.RECORD_DATE,DateUtil.beginTimeOfDay(new Date()))
//3.初始化RDB工具
await DbUtil.initDB(this.context)
//4.创建record表
DbUtil.createTable(RecordModel.getCreateTableSql())
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
数据库中增删查的通用方法的定义
//新增
insert(tableName: string, obj: any, columns: ColumnInfo[]): Promise<number> {
return new Promise((resolve, reject) => {
// 1.构建新增数据
let value = this.buildValueBucket(obj, columns)
// 2.新增
this.rdbStore.insert(tableName, value, (err, id) => {
if (err) {
Logger.error('新增失败!', JSON.stringify(err))
reject(err)
} else {
Logger.debug('新增成功!新增id:', id.toString())
resolve(id)
}
})
})
}
//删除
delete(predicates: relationalStore.RdbPredicates): Promise<number> {
return new Promise((resolve, reject) => {
this.rdbStore.delete(predicates, (err, rows) => {
if (err) {
Logger.error('删除失败!', JSON.stringify(err))
reject(err)
} else {
Logger.debug('删除成功!删除行数:', rows.toString())
resolve(rows)
}
})
})
}
//查询
queryForList<T>(predicates: relationalStore.RdbPredicates, columns: ColumnInfo[]): Promise<T[]> {
return new Promise((resolve, reject) => {
this.rdbStore.query(predicates, columns.map(info => info.columnName), (err, result) => {
if (err) {
Logger.error('查询失败!', JSON.stringify(err))
reject(err)
} else {
Logger.debug('查询成功!查询行数:', result.rowCount.toString())
resolve(this.parseResultSet(result, columns))
}
})
})
}
调用增删查的函数
insert(record:RecordPO):Promise<number>{
return DbUtil.insert(TABLE_NAME,record,COLUMNS)
}
deleteById(id:number){
//1.删除条件
let predicates = new relationalStore.RdbPredicates(TABLE_NAME)
predicates.equalTo('ID_COLUMN',id)
//2.删除
return DbUtil.delete(predicates)
}
listByDate(date:number) :Promise<RecordPO[]>{
//1.查询条件
let predicates = new relationalStore.RdbPredicates(TABLE_NAME)
predicates.equalTo('DATE_COLUMN',date)
//2.查询
return DbUtil.queryForList(predicates,COLUMNS)
}
二、饮食记录业务层开发
GroupInfo
将GroupInfo中type和items只想的类型改为泛型。
import ItemCategory from './ItemCategory'
import RecordItem from './RecordItem'
export default class GroupInfo<TYPE,ELEMENT>{
//分组类型
type:TYPE
//组内数据集合
items:ELEMENT[]
//组内记录总热量
calorie:number = 0
constructor(type:TYPE,items:ELEMENT[]) {
this.type = type
this.items = items
}
}
完成增删查功能
饮食记录相关那个的业务封装到RecordServer中,从中完成增删查的业务。
import DateUtil from '../common/utils/DateUtil'
import ItemModel from '../model/ItemModel'
import RecordModel from '../model/RecordModel'
import { RecordTypeEnum, RecordTypes } from '../model/RecordTypeModel'
import GroupInfo from '../viewmodel/GroupInfo'
import RecordType from '../viewmodel/RecordType'
import RecordVO from '../viewmodel/RecordVO'
import StatsInfo from '../viewmodel/StatsInfo'
class RecordService{
insert(typeId: number, itemId: number, amount: number): Promise<number>{
// 1.获取时间
let createTime = (AppStorage.Get('selectedDate') || DateUtil.beginTimeOfDay(new Date())) as number
// 2.新增
return RecordModel.insert({typeId, itemId, amount, createTime})
}
async queryRecordByDate(date:number):Promise<RecordVO[]>{
//1.查询数据库的RecordPO
let rps = await RecordModel.listByDate(date)
//2.将RecordPO转为RecordVO
return rps.map(rp =>{
//2.1获取po中的基本属性
let rv = {id:rp.id,typeId:rp.typeId,amount:rp.amount} as RecordVO
//2.2查询记录项
rv.recordItem = ItemModel.getById(rp.itemId,rp.typeId !== RecordTypeEnum.WORKOUT)
//2.3计算热量
rv.calorie = rp.amount * rv.recordItem.calorie
return rv
})
}
calculateStatsInfo(records:RecordVO[]):StatsInfo{
//1.准备结果
let info = new StatsInfo()
if(!records || records.length <= 0){
return info
}
//2.计算统计数据
records.forEach(r => {
if (r.typeId === RecordTypeEnum.WORKOUT) {
//运动,累加消耗热量、蛋白质、碳水、脂肪
info.intake += r.calorie
info.carbon += r.recordItem.carbon
info.protein += r.recordItem.protein
info.fat += r.recordItem.fat
}
})
//3.返回
return info
}
calculateGroupInfo(records:RecordVO[]):GroupInfo<RecordType,RecordVO>[]{
//1.创建空的记录型分组
let groups = RecordTypes.map(RecordType => new GroupInfo(RecordType,[]))
if(!records || records.length <= 0){
return groups
}
//2.遍历所有饮食记录
records.forEach(record =>{
//2.1把每个记录存入其对应的分组中
groups[record.typeId].items.push(record)
//2.2计算该组的总热量
groups[record.typeId].calorie += record.calorie
})
return groups
}
}
let recordService = new RecordService()
export default recordService as RecordService
查询记录项在ItemModel中
getById(id:number,isFood:boolean = true){
return isFood ? foods[id] : workouts[id - 10000]
}
三、实现数据持久化和页面交互
在RecordIndex中完成查询
handlePageShow(){
if (this.isPageShow) {
this.aboutToAppear()
}
}
async aboutToAppear(){
this.records = await RecordService.queryRecordByDate(this.selectedDate)
}
StatsCard数据操作
@StorageProp('selectedDate') selectedDate: number =DateUtil.beginTimeOfDay(new Date())
@Consume records:RecordVO[]
@State info:StatsInfo = new StatsInfo()
handleRecordsChange(){
this.info = RecordService.calculateStatsInfo(this.records)
}
controller:CustomDialogController = new CustomDialogController({
builder:DatePickDialog({selectedDate:new Date(this.selectedDate)})
})
页面跳转
在RecordList中添加点击事件
.onClick(()=>{
router.pushUrl({
url:'pages/ItemIndex',
params:{type:group.type}
})
})
生命周期函数
在ItemIndex中写生命周期函数,取出跳转时传的参数。
//生命周期钩子
onPageShow(){
//1.获取跳转时参数
let params:any = router.getParams()
//2.获取点击饮食记录类型
this.type = params.type
this.isFood = this.type.id !== RecordTypeEnum.WORKOUT
}
到这我的鸿蒙项目就该一段落了,其中还有很多不足,还需要日后更多知识的补充。