好的如果你看到本篇文章你就可以开心一下了,因为这是此次实战项目开发的最后一篇文章了(完结撒花)
我会在这篇文章的最上方附上我的鸿蒙开发文件和实验报告,有需要的同学可以参考
那么本篇文章要继续完成饮食记录页面的交互部分并完成最终的数据持久化保存
正式开发
回到开发工具我们先找到饮食记录的页面,并进行修改
@component
export default struct recordindex {
@storageprop('selecteddate')
@watch('abouttoappear')
selecteddate: number = dateutil.begintimeofday(new date())
@provide records: recordvo[] = []
@prop @watch('handlepageshow') ispageshow: boolean
handlepageshow(){
if(this.ispageshow){
this.abouttoappear()
}
}
async abouttoappear(){
this.records = await recordservice.queryrecordbydate(this.selecteddate)
}
build() {
column(){
// 1.头部搜索栏
searchheader()
// 2.统计卡片
statscard()
// 3.记录列表
recordlist()
.layoutweight(1)
}
.width('100%')
.height('100%')
.backgroundcolor($r('app.color.index_page_background'))
}
}
并且对statscard、calorstats、recordlist的参数等进行修改
import breakpointtype from '../../common/bean/breanpointtype'
import breakpointconstants from '../../common/constants/breakpointconstants'
import { commonconstants } from '../../common/constants/commonconstants'
import dateutil from '../../common/utils/dateutil'
import recordservice from '../../service/recordservice'
import recordvo from '../../viewmodel/recordvo'
import statsinfo from '../../viewmodel/statsinfo'
import caloriestats from './caloriestats'
import datepickdialog from './datepickdialog'
import nutrientstats from './nutrientstats'
@component
export default struct statscard {
@storageprop('selecteddate') selecteddate: number = dateutil.begintimeofday(new date())
@storageprop('currentbreakpoint') currentbreakpoint: string = breakpointconstants.breakpoint_sm
@consume @watch('handlerecordschange') 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)})//回写到弹窗
})
build() {
column(){
// 1.日期信息
row(){
text(dateutil.formatdate(this.selecteddate))
.fontcolor($r('app.color.secondary_color'))
image($r('app.media.ic_public_spinner'))
.width(20)
.fillcolor($r('app.color.secondary_color'))
}
.padding(commonconstants.space_8)
.onclick(() => this.controller.open())
// 2.统计信息
swiper(){
// 2.1.热量统计
caloriestats({intake: this.info.intake, expend: this.info.expend})
// 2.2.营养素统计
nutrientstats({carbon: this.info.carbon, protein: this.info.protein, fat: this.info.fat})
}
.width('100%')
.backgroundcolor(color.white)
.borderradius(commonconstants.default_18)
.indicatorstyle({selectedcolor: $r('app.color.primary_color')})
.displaycount(new breakpointtype({
sm: 1,
md: 1,
lg: 2
}).getvalue(this.currentbreakpoint))
}
.width(commonconstants.thousandth_940)
.backgroundcolor($r('app.color.stats_title_bgc'))
.borderradius(commonconstants.default_18)
}
}
import { commonconstants } from '../../common/constants/commonconstants'
@component
export default struct caloriestats {
@prop intake: number//摄入
@prop expend: number//消耗
recommend: number = commonconstants.recommend_calorie//推荐
remaincalorie(){
return this.recommend - this.intake + this.expend
}
build() {
row({space: commonconstants.space_6}){
// 1.饮食摄入
this.statsbuilder({label: '饮食摄入', value: this.intake})
// 2.还可以吃
stack(){
// 2.1.进度条
progress({
value: this.intake,
total: this.recommend,
type: progresstype.ring
})
.width(120)
.style({strokewidth: commonconstants.default_10})
.color($r('app.color.primary_color'))
// 2.2.统计数据
this.statsbuilder({label: '还可以吃', value: this.remaincalorie(),tips: `推荐${this.recommend}`})
}
// 3.运动消耗
this.statsbuilder({label: '运动消耗', value: this.expend})
}
.width('100%')
.justifycontent(flexalign.spaceevenly)
.padding({top: 30, bottom: 35})
}
@builder statsbuilder($$:{label: string, value: number, tips?: string}){
column({space: commonconstants.space_6}){
text($$.label)
.fontcolor($r('app.color.gray'))
.fontweight(commonconstants.font_weight_600)
text($$.value.tofixed(0))
.fontsize(20)
.fontweight(commonconstants.font_weight_700)
if($$.tips){
text($$.tips)
.fontsize(12)
.fontcolor($r('app.color.light_gray'))
}
}
}
}
@extend(text) function graytext(){
.fontsize(14)
.fontcolor($r('app.color.light_gray'))
}
@component
export default struct recordlist {
@consume @watch('handlerecordschange') records: recordvo[]
@state groups: groupinfo<recordtype, recordvo>[] = []
handlerecordschange(){
this.groups = recordservice.calculategroupinfo(this.records)
}
build() {
list({space: commonconstants.space_10}){
foreach(this.groups, (group: groupinfo<recordtype, recordvo>) => {
listitem(){
column({space: commonconstants.space_8}){
// 1.分组的标题
row({space: commonconstants.space_4}){
image(group.type.icon).width(24)
text(group.type.name).fontsize(18).fontweight(commonconstants.font_weight_700)
text(`建议${group.type.min}~${group.type.max}千卡`).graytext()
blank()//空白
text(group.calorie.tofixed(0)).fontsize(14).fontcolor($r('app.color.primary_color'))
text('千卡').graytext()
image($r('app.media.ic_public_add_norm_filled'))
.width(20)
.fillcolor($r('app.color.primary_color'))
}
.width('100%')
.onclick(() => {
router.pushurl({
url: 'pages/itemindex',
params: {type: group.type}
})
})
// 2.组内记录列表
list(){
foreach(group.items, (item: recordvo) => {
listitem(){
row({space: commonconstants.space_6}){
image(item.recorditem.image).width(50)
column({space: commonconstants.space_4}){
text(item.recorditem.name).fontweight(commonconstants.font_weight_500)
text(`${item.amount}${item.recorditem.unit}`).graytext()
}
blank()
text(`${item.calorie.tofixed(0)}千卡`).graytext()
}
.width('100%')
.padding(commonconstants.space_6)
}.swipeaction({end: this.deletebutton.bind(this)})
})
}
.width('100%')
}
.width('100%')
.backgroundcolor(color.white)
.borderradius(commonconstants.default_18)
.padding(commonconstants.space_12)
}
})
}
.width(commonconstants.thousandth_940)
.height('100%')
.margin({top: 10})
}
@builder deletebutton(){
image($r('app.media.ic_public_delete_filled'))
.width(20)
.fillcolor(color.red)
.margin(5)
}
}
完成跳转部分后进入itemindex
同样进行修改
@extend(button) function panelbuttonstyle(){
.width(120)
.type(buttontype.normal)
.borderradius(6)
}
@entry
@component
struct itemindex {
@state amount: number = 1
@state value: string = ''
@state showpanel: boolean = false
@state item: recorditem = null
@state type: recordtype = recordtypes[0]
@state isfood: boolean = true
onpanelshow(item: recorditem) {
this.amount = 1
this.value = ''
this.item = item
this.showpanel = true
}
onpageshow(){
// 1.获取跳转时的参数
let params: any = router.getparams()
// 2.获取点击的饮食记录类型
this.type = params.type
this.isfood = this.type.id !== recordtypeenum.workout
}
build() {
column() {
// 1.头部导航
this.header()
// 2.列表
itemlist({ showpanel: this.onpanelshow.bind(this), isfood: this.isfood })
.layoutweight(1)
// 3.底部面板
panel(this.showpanel) {
// 3.1.顶部日期
itempanelheader()
// 3.2.记录项卡片
if(this.item){
itemcard({amount: this.amount, item: $item})
}
// 3.3.数字键盘
numberkeyboard({amount: $amount, value: $value})
// 3.4.按钮
this.panelbutton()
}
.mode(panelmode.full)//全部显示
.dragbar(false)//不可调整高度
.backgroundmask($r('app.color.light_gray'))//蒙版颜色浅灰
.backgroundcolor(color.white)//背景颜色
}
.width('100%')
.height('100%')
}
@builder panelbutton(){
row({space: commonconstants.space_6}){
button('取消')
.panelbuttonstyle()
.backgroundcolor($r('app.color.light_gray'))
.onclick(() => this.showpanel = false)
button('提交')
.panelbuttonstyle()
.backgroundcolor($r('app.color.primary_color'))
.onclick(() => {
// 1.持久化保存
recordservice.insert(this.type.id, this.item.id, this.amount)
.then(() => {
// 2.关闭弹窗
this.showpanel = false
})
})
}
.margin({top: 10})
}
@builder header() {
row() {
image($r('app.media.ic_public_back'))
.width(24)
.onclick(() => router.back())
blank()
text(this.type.name).fontsize(18).fontweight(commonconstants.font_weight_600)
}
.width(commonconstants.thousandth_940)
.height(32)
}
}
修改饮食列表页
@component
export default struct itemlist {
showpanel: (item: recorditem) => void
@prop isfood: boolean
build() {
tabs() {
tabcontent() {
this.tabcontentbuilder(itemmodel.list(this.isfood))
}
.tabbar('全部')
foreach(
itemmodel.listitemgroupbycategory(this.isfood),
(group: groupinfo<itemcategory, recorditem>) => {
tabcontent() {
this.tabcontentbuilder(group.items)
}
.tabbar(group.type.name)
})
}
.width(commonconstants.thousandth_940)
.height('100%')
.barmode(barmode.scrollable)
}
@builder tabcontentbuilder(items: recorditem[]) {
list({ space: commonconstants.space_10 }) {
foreach(items, (item: recorditem) => {
listitem() {
row({ space: commonconstants.space_6 }) {
image(item.image).width(50)
column({ space: commonconstants.space_4 }) {
text(item.name).fontweight(commonconstants.font_weight_500)
text(`${item.calorie}千卡/${item.unit}`).fontsize(14).fontcolor($r('app.color.light_gray'))
}.alignitems(horizontalalign.start)
blank()
image($r('app.media.ic_public_add_norm_filled'))
.width(18)
.fillcolor($r('app.color.primary_color'))
}
.width('100%')
.padding(commonconstants.space_6)
}
.onclick(() => this.showpanel(item))
})
}
.width('100%')
.height('100%')
}
}
营养素统计同样修改
@component
export default struct nutrientstats {
@prop carbon: number
@prop protein: number
@prop fat: number
recommendcarbon: number = commonconstants.recommend_carbon
recommendprotein: number = commonconstants.recommend_protein
recommendfat: number = commonconstants.recommend_fat
build() {
row({space: commonconstants.space_6}){
this.statsbuilder({
label: '碳水化合物',
value: this.carbon,
recommend: this.recommendcarbon,
color: $r('app.color.carbon_color')
})
this.statsbuilder({
label: '蛋白质',
value: this.protein,
recommend: this.recommendprotein,
color: $r('app.color.protein_color')
})
this.statsbuilder({
label: '脂肪',
value: this.fat,
recommend: this.recommendfat,
color: $r('app.color.fat_color')
})
}
.width('100%')
.justifycontent(flexalign.spaceevenly)
.padding({top: 30, bottom: 35})
}
@builder statsbuilder($$:{label: string, value: number, recommend: number, color: resourcestr}){
column({space: commonconstants.space_6}){
stack(){
progress({
value: $$.value,
total: $$.recommend,
type: progresstype.ring
})
.width(95)
.style({strokewidth: commonconstants.default_6})
.color($$.color)
column({space: commonconstants.space_6}){
text('摄入推荐')
.fontsize(12)
.fontcolor($r('app.color.gray'))
text(`${$$.value.tofixed(0)}/${$$.recommend.tofixed(0)}`)
.fontsize(18)
.fontweight(commonconstants.font_weight_600)
}
}
text(`${$$.label}(克)`)
.fontsize(12)
.fontcolor($r('app.color.light_gray'))
}
}
}
最终测试
经过我们的测试,实战项目开发的数据持久化和页面交互功能同预期一样正常使用
小结
那么本项目到此就算彻底结束了,我在这里也附上我的全部代码
ok,我们这里附上黑马程序员实现数据持久化和页面交互的视频链接,文章配合视频更好理解哦。
发表评论