黑马健康期末项目2
文章目录
前言
综合运用本学期所学内容及个人自学知识,使用HarmonyOS 4.0及以上版本开发一款具有实用性和创新性的移动应用软件
一、项目名称:黑马健康
黑马健康是一款面向健康管理机构及用户的软件,它提供了丰富的健康管理功能,旨在提高健康管理师的工作效率,加强与患者间的互动,并增强管理者对健康管理机构运营情况的了解。
二、运行过程
1.饮食记录——顶部搜索栏
思维导图:
运行截图:
代码如下(部分):
import DateUtil from '../../common/utils/DateUtil'
import RecordService from '../../service/RecordService'
import RecordVO from '../../viewmodel/RecordVO'
import RecordList from './RecordList'
import SearchHeader from './SearchHeader'
import StatsCard from './StatsCard'
@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'))
}
}
2.饮食记录——统计卡片
思维导图:
运行截图:
代码如下(部分):
import { CommonConstants } from '../../common/constants/CommonConstants'
@CustomDialog
export default struct DatePickDialog {
controller: CustomDialogController
selectedDate: Date = new Date()
build() {
Column({space: CommonConstants.SPACE_12}){
// 1.日期选择器
DatePicker({
start: new Date('2020-01-01'),
end: new Date(),
selected: this.selectedDate
})
.onChange((value: DatePickerResult) => {
this.selectedDate.setFullYear(value.year, value.month, value.day)
})
// 2.按钮
Row({space:CommonConstants.SPACE_12}){
Button('取消')
.width(120)
.backgroundColor($r('app.color.light_gray'))
.onClick(() => this.controller.close())
Button('确定')
.width(120)
.backgroundColor($r('app.color.primary_color'))
.onClick(() => {
// 1.保存日期到全局存储
AppStorage.SetOrCreate('selectedDate', this.selectedDate.getTime())
// 2.关闭窗口
this.controller.close()
})
}
}
.padding(CommonConstants.SPACE_12)
}
}
3.饮食记录——记录列表
思维导图:
运行截图:
代码如下(部分):
import router from '@ohos.router'
import { CommonConstants } from '../../common/constants/CommonConstants'
import RecordService from '../../service/RecordService'
import GroupInfo from '../../viewmodel/GroupInfo'
import RecordType from '../../viewmodel/RecordType'
import RecordVO from '../../viewmodel/RecordVO'
@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)
}
}
总结
1.饮食记录——顶部搜索栏
设置一个顶部搜索栏,用于搜索饮食或运动信息,这样可以提高用户体验,帮助用户快速定位到他们感兴趣的内容,而无需手动浏览整个页面或应用。同时简化操作,通过输入关键词进行搜索,用户能够以最简单直接的方式获取所需信息,减少操作步骤。
2.饮食记录——统计卡片
使用 Column 组件垂直排列内容,并设置了间距为 CommonConstants.SPACE_12。
包含一个 DatePicker 组件,用于选择日期。这个日期选择器限制了用户可以选择的日期范围(从 2020 年 1 月 1 日起至当前日期)。
当日期选择器中的日期发生变化时,会触发 onChange 事件处理器,该处理器会更新 selectedDate 的值。
还有一个 Row 组件,其中包含了两个 Button 组件,分别用于“取消”和“确定”操作。
“取消”按钮有固定的宽度(120 单位),背景色为应用定义的浅灰色,点击时调用 this.controller.close() 关闭对话框。
“确定”按钮也有固定的宽度(120 单位),背景色为应用定义的主色,点击时会执行两个操作:首先,将选择的日期(转换为时间戳)保存到全局存储(可能是使用 AppStorage.SetOrCreate 方法);然后,关闭对话框。
总的来说,DatePickDialog 结构体实现了一个自定义的日期选择器对话框,用户可以在其中选择日期,并通过“确定”按钮将选择的日期保存到全局存储中。同时,提供了“取消”按钮供用户取消操作。代码结构清晰,遵循了组件化的开发思想,易于维护和扩展。
3.饮食记录——记录列表
总体布局设计:
根据上图,可设计出完整的饮食记录