實現打卡功能
首頁會展示當前用戶已經開啟的任務列表,每條任務會顯示對應的任務名稱以及任務目標、當前任務完成情況。用戶只可對當天任務進行打卡操作,用戶可以根據需要對任務列表中相應的任務進行點擊打卡。如果任務列表中的每個任務都在當天完成則為連續打卡一天,連續打卡多天會獲得成就徽章。打卡效果如下圖所示:
開發前請熟悉鴻蒙開發指導文檔:[qr23.cn/FBD4cY
]。
任務列表
使用List組件展示用戶當前已經開啟的任務,每條任務對應一個TaskCard組件,clickAction包裝了點擊和長按事件,用戶點擊任務卡時會觸發彈起打卡彈窗,從而進行打卡操作;長按任務卡時會跳轉至任務編輯界面,對相應的任務進行編輯處理。代碼如下:
// HomeComponent.ets
// 任務列表
ForEach(this.homeStore.getTaskListOfDay(), (item: TaskInfo) = > {
TaskCard({
taskInfoStr: JSON.stringify(item),
clickAction: (isClick: boolean) = > this.taskItemAction(item, isClick)
})
.margin({ bottom: Const.DEFAULT_12 })
.height($r('app.float.default_64'))
}, (item: TaskInfo) = > JSON.stringify(item))
...
CustomDialogView() // 自定義彈窗中間件
自定義彈窗中間件CustomDialogView
在組件CustomDialogView的aboutToAppear生命周期中注冊SHOW_TASK_DETAIL_DIALOG的事件回調方法 ,當通過emit觸發此事件時即觸發回調方法執行。代碼如下:
// CustomDialogView.ets
export class CustomDialogCallback {
confirmCallback: Function = () = > {};
cancelCallback: Function = () = > {};
}
@Component
export struct CustomDialogView {
@State isShow: boolean = false;
@Provide achievementLevel: number = 0;
@Consume broadCast: BroadCast;
@Provide currentTask: TaskInfo = TaskItem;
@Provide dialogCallBack: CustomDialogCallback = new CustomDialogCallback();
// 成就對話框
achievementDialog: CustomDialogController = new CustomDialogController({
builder: AchievementDialog(),
autoCancel: true,
customStyle: true
});
// 任務時鐘對話框
taskDialog: CustomDialogController = new CustomDialogController({
builder: TaskDetailDialog(),
autoCancel: true,
customStyle: true
});
aboutToAppear() {
Logger.debug('CustomDialogView', 'aboutToAppear');
// 成就對話框
this.broadCast.on(BroadCastType.SHOW_ACHIEVEMENT_DIALOG, (achievementLevel: number) = > {
Logger.debug('CustomDialogView', 'SHOW_ACHIEVEMENT_DIALOG');
this.achievementLevel = achievementLevel;
this.achievementDialog.open();
});
// 任務時鐘對話框
this.broadCast.on(BroadCastType.SHOW_TASK_DETAIL_DIALOG,
(currentTask: TaskInfo, dialogCallBack: CustomDialogCallback) = > {
Logger.debug('CustomDialogView', 'SHOW_TASK_DETAIL_DIALOG');
this.currentTask = currentTask || TaskItem;
this.dialogCallBack = dialogCallBack;
this.taskDialog.open();
});
}
aboutToDisappear() {
Logger.debug('CustomDialogView', 'aboutToDisappear');
}
build() {
}
}
點擊任務卡片
點擊任務卡片會emit觸發 “SHOW_TASK_DETAIL_DIALOG” 事件,同時把當前任務,以及確認打卡回調方法傳遞下去。代碼如下:
// HomeComponent.ets
// 任務卡片事件
taskItemAction(item: TaskInfo, isClick: boolean): void {
...
if (isClick) {
// 點擊任務打卡
let callback: CustomDialogCallback = { confirmCallback: (taskTemp: TaskInfo) = > {
this.onConfirm(taskTemp)
}, cancelCallback: () = > {
} };
// 觸發彈出打卡彈窗事件 并透傳當前任務參數(item) 以及確認打卡回調
this.broadCast.emit(BroadCastType.SHOW_TASK_DETAIL_DIALOG, [item, callback]);
} else {
// 長按編輯任務
...
}
}
// 確認打卡
onConfirm(task) {
this.homeStore.taskClock(task).then((res: AchievementInfo) = > {
// 打卡成功后 根據連續打卡情況判斷是否 彈出成就勛章 以及成就勛章級別
if (res.showAchievement) {
// 觸發彈出成就勛章SHOW_ACHIEVEMENT_DIALOG 事件, 并透傳勛章類型級別
let achievementLevel = res.achievementLevel;
if (achievementLevel) {
this.broadCast.emit(BroadCastType.SHOW_ACHIEVEMENT_DIALOG, achievementLevel);
} else {
this.broadCast.emit(BroadCastType.SHOW_ACHIEVEMENT_DIALOG);
}
}
})
}
打卡彈窗組件TaskDetailDialog
打卡彈窗組件根據當前任務的ID獲取任務名稱以及彈窗背景圖片資源。
打卡彈窗組件由兩個小組件構成,代碼如下:
// TaskDetailDialog.ets
Column() {
// 展示任務的基本信息
TaskBaseInfo({
taskName: TaskMapById[this.currentTask?.taskID - 1].taskName // 根據當前任務ID獲取任務名稱
});
// 打卡功能組件 (任務打卡、關閉彈窗)
TaskClock({
confirm: () = > {
this.dialogCallBack.confirmCallback(this.currentTask);
this.controller.close();
},
cancel: () = > {
this.controller.close();
},
showButton: this.showButton
})
}
...
TaskBaseInfo組件代碼如下:
// TaskDetailDialog.ets
@Component
struct TaskBaseInfo {
taskName: string | Resource = '';
build() {
Column({ space: Const.DEFAULT_8 }) {
Text(this.taskName)
.fontSize($r('app.float.default_22'))
.fontWeight(FontWeight.Bold)
.fontFamily($r('app.string.HarmonyHeiTi_Bold'))
.taskTextStyle()
.margin({left: $r('app.float.default_12')})
}
.position({ y: $r('app.float.default_267') })
}
}
TaskClock組件代碼如下:
// TaskDetailDialog.ets
@Component
struct TaskClock {
confirm: Function = () = > {};
cancel: Function = () = > {};
showButton: boolean = false;
build() {
Column({ space: Const.DEFAULT_12 }) {
Button() {
Text($r('app.string.clock_in'))
.height($r('app.float.default_42'))
.fontSize($r('app.float.default_20'))
.fontWeight(FontWeight.Normal)
.textStyle()
}
.width($r('app.float.default_220'))
.borderRadius($r('app.float.default_24'))
.backgroundColor('rgba(255,255,255,0.40)')
.onClick(() = > {
GlobalContext.getContext().setObject('taskListChange', true);
this.confirm();
})
.visibility(!this.showButton ? Visibility.None : Visibility.Visible)
Text($r('app.string.got_it'))
.fontSize($r('app.float.default_14'))
.fontWeight(FontWeight.Regular)
.textStyle()
.onClick(() = > {
this.cancel();
})
}
}
}
打卡接口調用
// HomeViewModel.ets
public async taskClock(taskInfo: TaskInfo) {
let taskItem = await this.updateTask(taskInfo);
let dateStr = this.selectedDayInfo?.dateStr;
// 更新任務失敗
if (!taskItem) {
return {
achievementLevel: 0,
showAchievement: false
} as AchievementInfo;
}
// 更新當前時間的任務列表
this.selectedDayInfo.taskList = this.selectedDayInfo.taskList.map((item) = > {
return item.taskID === taskItem?.taskID ? taskItem : item;
});
let achievementLevel: number = 0;
if(taskItem.isDone) {
// 更新每日任務完成情況數據
let dayInfo = await this.updateDayInfo();
...
// 當日任務完成數量等于總任務數量時 累計連續打卡一天
// 更新成就勛章數據 判斷是否彈出獲得勛章彈出及勛章類型
if (dayInfo && dayInfo?.finTaskNum === dayInfo?.targetTaskNum) {
achievementLevel = await this.updateAchievement(this.selectedDayInfo.dayInfo);
}
}
...
return {
achievementLevel: achievementLevel,
showAchievement: ACHIEVEMENT_LEVEL_LIST.includes(achievementLevel)
} as AchievementInfo;
}
`HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`
// HomeViewModel.ets
// 更新當天任務列表
updateTask(task: TaskInfo): Promise< TaskInfo > {
return new Promise((resolve, reject) = > {
let taskID = task.taskID;
let targetValue = task.targetValue;
let finValue = task.finValue;
let updateTask = new TaskInfo(task.id, task.date, taskID, targetValue, task.isAlarm, task.startTime,
task.endTime, task.frequency, task.isDone, finValue, task.isOpen);
let step = TaskMapById[taskID - 1].step; // 任務步長
let hasExceed = updateTask.isDone;
if (step === 0) { // 任務步長為0 打卡一次即完成該任務
updateTask.isDone = true; // 打卡一次即完成該任務
updateTask.finValue = targetValue;
} else {
let value = Number(finValue) + step; // 任務步長非0 打卡一次 步長與上次打卡進度累加
updateTask.isDone = updateTask.isDone || value >= Number(targetValue); // 判斷任務是否完成
updateTask.finValue = updateTask.isDone ? targetValue : `${value}`;
}
TaskInfoTableApi.updateDataByDate(updateTask, (res: number) = > { // 更新數據庫
if (!res || hasExceed) {
Logger.error('taskClock-updateTask', JSON.stringify(res));
reject(res);
}
resolve(updateTask);
})
})
}
審核編輯 黃宇
-
HarmonyOS
+關注
關注
79文章
1979瀏覽量
30280 -
OpenHarmony
+關注
關注
25文章
3728瀏覽量
16395 -
鴻蒙OS
+關注
關注
0文章
189瀏覽量
4456
發布評論請先 登錄
相關推薦
評論