当前位置: 首页 > news >正文

网站快速备案被退回的几种原因分析企业网站建设的步骤过程

网站快速备案被退回的几种原因分析,企业网站建设的步骤过程,建设网站如何挣钱,seo网络优化是什么工作介绍 本篇Codelab介绍了如何实现一个简单的健康生活应用#xff0c;主要功能包括#xff1a; 用户可以创建最多6个健康生活任务#xff08;早起#xff0c;喝水#xff0c;吃苹果#xff0c;每日微笑#xff0c;刷牙#xff0c;早睡#xff09;#xff0c;并设置任…介绍 本篇Codelab介绍了如何实现一个简单的健康生活应用主要功能包括 用户可以创建最多6个健康生活任务早起喝水吃苹果每日微笑刷牙早睡并设置任务目标、是否开启提醒、提醒时间、每周任务频率。用户可以在主页面对设置的健康生活任务进行打卡其中早起、每日微笑、刷牙和早睡只需打卡一次即可完成任务喝水、吃苹果需要根据任务目标量多次打卡完成。主页可显示当天的健康生活任务完成进度当天所有任务都打卡完成后进度为100%并且用户的连续打卡天数加一。当用户连续打卡天数达到3、7、30、50、73、99天时可以获得相应的成就。成就在获得时会以动画形式弹出并可以在“成就”页面查看。用户可以查看以前的健康生活任务完成情况。 本应用的运行效果如下图所示 相关概念 Observed 和 ObjectLinkObserved适用于类表示类中的数据变化由UI页面管理ObjectLink应用于被Observed装饰类的对象。Consume 和 ProvideProvide作为数据提供者可以更新子节点的数据触发页面渲染。Consume检测到Provide数据更新后会发起当前视图的重新渲染。Flex一个功能强大的容器组件支持横向布局竖向布局子组件均分和流式换行布局。ListList是很常用的滚动类容器组件之一它按照水平或者竖直方向线性排列子组件 List的子组件必须是ListItem它的宽度默认充满List的宽度。TimePickerTimePicker是选择时间的滑动选择器组件默认以00:00至23:59的时间区创建滑动选择器。Toggle组件提供勾选框样式、状态按钮样式及开关样式。后台代理提醒使用后台代理提醒能力后应用可以被冻结或退出计时和弹出提醒的功能将被后台系统服务代理。关系型数据库Relational DatabaseRDB一种基于关系模型来管理数据的数据库。 环境搭建 软件要求 DevEco Studio版本DevEco Studio 3.1 Release。OpenHarmony SDK版本API version 9。 硬件要求 开发板类型润和RK3568开发板。OpenHarmony系统3.2 Release。 环境搭建 完成本篇Codelab我们首先要完成开发环境的搭建本示例以RK3568开发板为例参照以下步骤进行 获取OpenHarmony系统版本标准系统解决方案二进制。以3.2 Release版本为例 2.搭建烧录环境。 完成DevEco Device Tool的安装完成RK3568开发板的烧录 3.搭建开发环境。 开始前请参考工具准备完成DevEco Studio的安装和开发环境配置。开发环境配置完成后请参考使用工程向导创建工程模板选择“Empty Ability”选择JS或者eTS语言开发。 工程创建完成后选择使用真机进行调测。 代码结构解读 本篇Codelab只对核心代码进行讲解。 ├─entry/src/main/ets // 代码区 │ ├─common │ │ ├─constants │ │ │ └─CommonConstants.ets // 公共常量 │ │ ├─database │ │ │ ├─rdb // 数据库 │ │ │ │ ├─RdbHelper.ets │ │ │ │ ├─RdbHelperImp.ets │ │ │ │ ├─RdbUtil.ets │ │ │ │ └─TableHelper.ets │ │ │ └─tables // 数据库接口 │ │ │ ├─DayInfoApi.ets │ │ │ ├─GlobalInfoApi.ets │ │ │ └─TaskInfoApi.ets │ │ └─utils │ │ ├─BroadCast.ets // 通知 │ │ ├─GlobalContext.ets // 全局上下文 │ │ ├─HealthDataSrcMgr.ets // 数据管理单例 │ │ ├─Logger.ets // 日志类 │ │ └─Utils.ets // 工具类 │ ├─entryability │ │ └─EntryAbility.ets // 程序入口类 │ ├─model // model │ │ ├─AchieveModel.ets │ │ ├─DatabaseModel.ets // 数据库model │ │ ├─Mine.ets │ │ ├─NavItemModel.ets // 菜单栏model │ │ ├─RdbColumnModel.ets // 数据库表数据 │ │ ├─TaskInitList.ets │ │ └─WeekCalendarModel.ets // 日历model │ ├─pages │ │ ├─AdvertisingPage.ets // 广告页 │ │ ├─MainPage.ets // 应用主页面 │ │ ├─MinePage.ets // 我的页面 │ │ ├─SplashPage.ets // 启动页 │ │ ├─TaskEditPage.ets // 任务编辑页面 │ │ └─TaskListPage.ets // 任务列表页面 │ ├─service │ │ └─ReminderAgent.ets // 后台提醒 │ ├─view │ │ ├─dialog // 弹窗组件 │ │ │ ├─AchievementDialog.ets // 成就弹窗 │ │ │ ├─CustomDialogView.ets // 自定义弹窗 │ │ │ ├─TaskDetailDialog.ets // 打卡弹窗 │ │ │ ├─TaskDialogView.ets // 任务对话框 │ │ │ ├─TaskSettingDialog.ets // 任务编辑相关弹窗 │ │ │ └─UserPrivacyDialog.ets │ │ ├─home // 主页面相关组件 │ │ │ ├─AddBtnComponent.ets // 添加任务按钮组件 │ │ │ ├─HomeTopComponent.ets // 首页顶部组件 │ │ │ ├─TaskCardComponent.ets // 任务item组件件 │ │ │ └─WeekCalendarComponent.ets // 日历组件 │ │ ├─task // 任务相关组件 │ │ │ ├─TaskDetailComponent.ets // 任务编辑详情组件 │ │ │ ├─TaskEditListItem.ets // 任务编辑行内容 │ │ │ └─TaskListComponent.ets // 任务列表组件 │ │ ├─AchievementComponent.ets // 成就页面 │ │ ├─BadgeCardComponent.ets // 勋章卡片组件 │ │ ├─BadgePanelComponent.ets // 勋章面板组件 │ │ ├─HealthTextComponent.ets // 自定义text组件 │ │ ├─HomeComponent.ets // 首页页面 │ │ ├─ListInfo.ets // 用户信息列表 │ │ ├─TitleBarComponent.ets // 成就标题组件 │ │ └─UserBaseInfo.ets // 用户基本信息 │ └─viewmodel // viewmodel │ ├─AchievementInfo.ets // 成就信息 │ ├─AchievementMapInfo.ets // 成就map信息 │ ├─AchievementViewModel.ets // 成就相关模块 │ ├─BroadCastCallBackInfo.ets // 通知回调信息 │ ├─CalendarViewModel.ets // 日历相关模块 │ ├─CardInfo.ets // 成就卡片信息 │ ├─ColumnInfo.ets // 数据库表结构 │ ├─CommonConstantsInfo.ets // 公共常量信息 │ ├─DayInfo.ets // 每日信息 │ ├─GlobalInfo.ets // 全局信息 │ ├─HomeViewModel.ets // 首页相关模块 │ ├─PublishReminderInfo.ets // 发布提醒信息 │ ├─ReminderInfo.ets // 提醒信息 │ ├─TaskInfo.ets // 任务信息 │ ├─TaskViewModel.ets // 任务设置相关模块 │ ├─WeekCalendarInfo.ets // 日历信息 │ └─WeekCalendarMethodInfo.ets // 日历方法信息 └─entry/src/main/resources // 资源文件夹 应用架构分析 本应用的基本架构如下图所示数据库为其他服务提供基础的用户数据主要业务包括用户可以查看和编辑自己的健康任务并进行打卡、查看成就。UI层提供了承载上述业务的UI界面。 应用主页面 本节将介绍如何给应用添加一个启动页设计应用的主界面以及首页的界面开发和数据展示。 启动页 首先我们需要给应用添加一个启动页启动页里我们需要用到一个定时器来实现启动页展示固定时间后跳转应用主页的功能效果图如下 打开应用时会进入此页面具体实现逻辑是 通过修改/entry/src/main/ets/entryability里的loadContent路径可以改变应用的入口文件我们需要把入口文件改为我们写的SplashPage启动页面。 // EntryAbility.ets windowStage.loadContent(pages/SplashPage, (err, data) { if (err.code) {...} Logger.info(windowStage,Succeeded in loading the content. Data: JSON.stringify(data)); }); 在SplashPage启动页的文件里通过首选项来实现是否需要弹“权限管理”的弹窗如果需要弹窗的情况下用户点击同意权限后通过首选项对用户的操作做持久化保存。相关代码如下 // SplashPage.ets import data_preferences from ohos.data.preferences; onConfirm() {let preferences data_preferences.getPreferences(this.context, H_STORE);preferences.then((res) {res.put(IS_PRIVACY, true).then(() {res.flush();Logger.info(SplashPage,isPrivacy is put success);}).catch((err: Error) {Logger.info(SplashPage,isPrivacy put failed. Cause: err);});})this.jumpAdPage(); } exitApp() {this.context.terminateSelf(); } jumpAdPage() {setTimeout(() {router.replaceUrl({ url: pages/AdvertisingPage });}, Const.LAUNCHER_DELAY_TIME); } aboutToAppear() {let preferences data_preferences.getPreferences(this.context, H_STORE);preferences.then((res) {res.get(IS_PRIVACY, false).then((isPrivate) {if (isPrivate true) {this.jumpAdPage();} else {this.dialogController.open();}});}); } APP功能入口 我们需要给APP添加底部菜单栏用于切换不同的应用模块由于各个模块之间属于完全独立的情况并且不需要每次切换都进行界面的刷新所以我们用到了TabsTabContent组件。 本应用一共有首页HomeIndex成就AchievementIndex和我的MineIndex三个模块分别对应Tabs组件的三个子组件TabContent。 // MainPage.ets TabContent() {HomeIndex({ homeStore: $homeStore, editedTaskInfo: $editedTaskInfo, editedTaskID: $editedTaskID }).borderWidth({ bottom: 1 }).borderColor($r(app.color.primaryBgColor)) } .tabBar(this.TabBuilder(TabId.HOME)) .align(Alignment.Start) TabContent() {AchievementIndex() } .tabBar(this.TabBuilder(TabId.ACHIEVEMENT)) TabContent() {MineIndex().borderWidth({ bottom: 1 }).borderColor($r(app.color.primaryBgColor)) } .tabBar(this.TabBuilder(TabId.MINE)) 首页 首页包含了任务信息的所有入口包含任务列表的展示任务的编辑和新增上下滚动的过程中顶部导航栏的渐变日期的切换以及随着日期切换界面任务列表跟着同步的功能效果图如下 具体代码实现我们将在下边分模块进行说明 导航栏背景渐变 Scroll滚动的过程中在它的onScroll方法里我们通过计算它Y轴的偏移量来改变当前界面的State修饰的naviAlpha变量值进而改变顶部标题的背景色代码实现如下 // HomeComponent.ets // 视图滚动的过程中处理导航栏的透明度 onScrollAction() { this.yOffset this.scroller.currentOffset().yOffset; if (this.yOffset Const.DEFAULT_56) { this.naviAlpha 1; } else { this.naviAlpha this.yOffset / Const.DEFAULT_56;} } 2.日历组件 日历组件主要用到的是一个横向滑动的Scroll组件。 // WeekCalendarComponent.etsbuild() { Row() { Column() { Row() {...} Scroll(this.scroller) { Row() { ForEach(this.homeStore.dateArr, (item: WeekDateModel, index?: number) { Column() { Text(item.weekTitle) .fontColor(sameDate(item.date, this.homeStore.showDate) ? $r(app.color.blueColor) : $r(app.color.titleColor)) Divider().color(sameDate(item.date, this.homeStore.showDate) ? $r(app.color.blueColor) : $r(app.color.white)) Image(this.getProgressImg(item)) } .onClick(() WeekCalendarMethods.calenderItemClickAction(item, index, this.homeStore)) }) } }... .onScrollEdge((event) this.onScrollEdgeAction(event)) }... }... } 手动滑动页面时我们通过在onScrollEnd方法里计算Scroll的偏移量来实现分页的效果同时Scroll有提供scrollPage()方法可供我们点击左右按钮的时候来进行页面切换。 // WeekCalendarComponent.ets import display from ohos.display; ... // scroll滚动停止时通过判断偏移量进行分页处理 onScrollEndAction() {if (this.isPageScroll false) {let page Math.round(this.scroller.currentOffset().xOffset / this.scrollWidth);page (this.isLoadMore true) ? page 1 : page;if (this.scroller.currentOffset().xOffset % this.scrollWidth ! 0 || this.isLoadMore true) {let xOffset page * this.scrollWidth;this.scroller.scrollTo({ xOffset, yOffset: 0 } as ScrollTo);this.isLoadMore false;}this.currentPage this.homeStore.dateArr.length / Const.WEEK_DAY_NUM - page - 1;Logger.info(HomeIndex, onScrollEnd: page page , listLength this.homeStore.dateArr.length);let dayModel: WeekDateModel this.homeStore.dateArr[Const.WEEK_DAY_NUM * pagethis.homeStore.selectedDay];Logger.info(HomeIndex, currentItem: JSON.stringify(dayModel) , selectedDay this.homeStore.selectedDay);this.homeStore!.setSelectedShowDate(dayModel!.date!.getTime());}this.isPageScroll false; } 我们在需要在Scroll滑动到左边边缘的时候去请求更多的历史数据以便Scroll能一直滑动通过Scroll的onScrollEdge方法我们可以判断它是否已滑到边缘位置。 // WeekCalendarComponent.ets onScrollEdgeAction(side: Edge) {if (side Edge.Top this.isPageScroll false) {Logger.info(HomeIndex, onScrollEdge: currentPage this.currentPage);if ((this.currentPage 2) * Const.WEEK_DAY_NUM this.homeStore.dateArr.length) {Logger.info(HomeIndex, onScrollEdge: load more data);let date: Date new Date(this.homeStore.showDate);date.setDate(date.getDate() - Const.WEEK_DAY_NUM);this.homeStore.getPreWeekData(date, () {});this.isLoadMore true;}} } homeStore主要是请求数据库的数据并对数据进行处理进而渲染到界面上。 // HomeViewModel.ets public getPreWeekData(date: Date, callback: Function) {let weekCalendarInfo: WeekCalendarInfo getPreviousWeek(date);// 请求数据库数据DayInfoApi.queryList(weekCalendarInfo.strArr, (res: DayInfo[]) {// 数据处理... this.dateArr weekCalendarInfo.arr.concat(...this.dateArr);}) } 同时我们还需要知道怎么根据当天的日期计算出本周内的所有日期数据。 // WeekCalendarModel.ets export function getPreviousWeek(showDate: Date): WeekCalendarInfo {Logger.debug(WeekCalendarModel, get week date by date: showDate.toDateString());let weekCalendarInfo: WeekCalendarInfo new WeekCalendarInfo();let arr: ArrayWeekDateModel [];let strArr: Arraystring [];let currentDay showDate.getDay() - 1;// 由于date的getDay()方法返回的是0-6代表周日到周六我们界面上展示的周一-周日为一周所以这里要将getDay()数据偏移一天let currentDay showDate.getDay() - 1;if (showDate.getDay() 0) {currentDay 6;}// 将日期设置为当前周第一天的数据周一showDate.setDate(showDate.getDate() - currentDay);for (let index WEEK_DAY_NUM; index 0; index--) {let tempDate new Date(showDate);tempDate.setDate(showDate.getDate() - index);let dateStr dateToStr(tempDate);strArr.push(dateStr);arr.push(new WeekDateModel(WEEK_TITLES[tempDate.getDay()], dateStr, tempDate));}Logger.debug(WeekCalendarModel, JSON.stringify(arr));weekCalendarInfo.arr arr;weekCalendarInfo.strArr strArr;return weekCalendarInfo; } 悬浮按钮 由于首页右下角有一个悬浮按钮所以首页整体我们用了一个Stack组件将右下角的悬浮按钮和顶部的title放在滚动组件层的上边。 // HomeComponent.ets build() { Stack() { Scroll(this.scroller) { Column() { ... // 上部界面组件Column() { ForEach(this.homeStore.getTaskListOfDay(), (item: TaskInfo) { TaskCard({taskInfoStr: JSON.stringify(item),clickAction: (isClick: boolean) this.taskItemAction(item, isClick)})...}, (item: TaskInfo) JSON.stringify(item))} } }}.onScroll(() {this.onScrollAction()})// 悬浮按钮AddBtn({ clickAction: () {this.editTaskAction()} }) // 顶部title Row() {Text($r(app.string.EntryAbility_label)).titleTextStyle().fontSize($r(app.float.default_24)).padding({ left: Const.THOUSANDTH_66 })}.width(Const.THOUSANDTH_1000).height(Const.DEFAULT_56).position({ x: 0, y: 0 }).backgroundColor(rgba(${WHITE_COLOR_0X},${WHITE_COLOR_0X},${WHITE_COLOR_0X},${this.naviAlpha}))CustomDialogView() } .allSize() .backgroundColor($r(app.color.primaryBgColor)) 4.界面跳转及传参 首页任务列表长按时需要跳转到对应的任务编辑界面同时点击悬浮按钮时需要跳转到任务列表页面。 页面跳转需要在头部引入router。 // HomeComponent.ets import router from ohos.router; 任务item的点击事件代码如下 // HomeComponent.ets taskItemAction(item: TaskInfo, isClick: boolean): void { if (!this.homeStore.checkCurrentDay()) { return; } if (isClick) { // 点击任务打卡 let callback: CustomDialogCallback { confirmCallback: (taskTemp: TaskInfo) { this.onConfirm(taskTemp) }, cancelCallback: () { } }; this.broadCast.emit(BroadCastType.SHOW_TASK_DETAIL_DIALOG, [item, callback]); } else { // 长按编辑任务 let editTaskStr: string JSON.stringify(TaskMapById[item.taskID - 1]); let editTask: ITaskItem JSON.parse(editTaskStr); ... router.pushUrl({ url: pages/TaskEditPage, params: { params: JSON.stringify(editTask) } }); } } 任务创建与编辑 本节将介绍如何创建和编辑健康生活任务。 功能概述 用户点击悬浮按钮进入任务列表页点击任务列表可进入对应任务编辑的页面中对任务进行详细的设置之后点击完成按钮编辑任务后将返回首页。实现效果如下图 任务列表与编辑任务 这里主要为大家介绍添加任务列表页的实现、任务编辑的实现、以及具体弹窗设置和编辑完成功能的逻辑实现。 任务列表页 任务列表页由包括上部分的标题、返回按钮以及正中间的任务列表组成。实现效果如图 使用Navigation以及List组件构成元素ForEach遍历生成具体列表。这里是Navigation构成页面导航 // TaskListPage.ets Navigation() {Column() {// 页面中间的列表TaskList() }.width(Const.THOUSANDTH_1000).justifyContent(FlexAlign.Center) } .size({ width: Const.THOUSANDTH_1000, height: Const.THOUSANDTH_1000 }) .title(Const.ADD_TASK_TITLE) .titleMode(NavigationTitleMode.Mini) 列表右侧有一个判断是否开启的文字标识点击某个列表需要跳转到对应的任务编辑页里。具体的列表实现如下 // TaskListComponent.etsComponent export default struct TaskList {...build() {List({ space: Const.LIST_ITEM_SPACE }) {ForEach(this.taskList, (item: ITaskItem) {ListItem() {Row() {Row() {Image(item?.icon)...Text(item?.taskName).fontSize(Const.DEFAULT_20).fontColor($r(app.color.titleColor))}.width(Const.THOUSANDTH_500)Blank()...// 状态改变if (item?.isOpen) {Text($r(app.string.already_open))...}Image($r(app.media.ic_right_grey))...}...}....onClick(() {router.pushUrl({url: pages/TaskEditPage,params: {params: formatParams(item),}})})...}, (item: ITaskItem) JSON.stringify(item))}...} } 任务编辑页 任务编辑页由上方的“编辑任务”标题以及返回按钮主体内容的List配置项和下方的完成按钮组成实现效果如图 由于每一个配置项功能不相同且逻辑复杂故将其拆分为五个独立的组件。 这是任务编辑页面由Navigation和一个自定义组件TaskDetail构成 // TaskEditPage.ets Navigation() {Column() {TaskDetail()}.width(Const.THOUSANDTH_1000).height(Const.THOUSANDTH_1000) } .size({ width: Const.THOUSANDTH_1000, height: Const.THOUSANDTH_1000 }) .title(Const.EDIT_TASK_TITLE) .titleMode(NavigationTitleMode.Mini) 自定义组件由List以及其子组件ListItem构成 // TaskDetailComponent.ets List({ space: Const.LIST_ITEM_SPACE }) {ListItem() {TaskChooseItem()}...ListItem() {TargetSetItem()}...ListItem() {OpenRemindItem()}...ListItem() {RemindTimeItem()}...ListItem() {FrequencyItem()}... } .width(Const.THOUSANDTH_940) 其中做了禁用判断需要任务打开才可以点击编辑 // TaskDetailComponent.ets .enabled(this.settingParams?.isOpen ) 一些特殊情况的禁用如每日微笑、每日刷牙的目标设置不可编辑 // TaskDetailComponent.ets .enabled(this.settingParams?.isOpen this.settingParams?.taskID ! taskType.smile this.settingParams?.taskID ! taskType.brushTeeth ) 提醒时间在开启提醒打开之后才可以编辑 // TaskDetailComponent.ets .enabled(this.settingParams?.isOpen this.settingParams?.isAlarm) 设置完成之后点击完成按钮会向数据库更新现在进行改变的状态信息并执行之后的逻辑判断 // TaskDetailComponent.ets addTask(taskInfo, context).then((res: number) {GlobalContext.getContext().setObject(taskListChange, true);// 成功的状态成功后跳转首页router.back({url: pages/MainPage, params: {editTask: this.backIndexParams(),}})Logger.info(addTaskFinished, JSON.stringify(res)); }).catch((error: Error) {// 失败的状态失败后弹出提示并打印错误日志prompt.showToast({message: Const.SETTING_FINISH_FAILED_MESSAGE})Logger.error(addTaskFailed, JSON.stringify(error)); }) 任务编辑弹窗 弹窗由封装的自定义组件CustomDialogView注册事件并在点击对应的编辑项时进行触发从而打开弹窗。 CustomDialogView引入实例并注册事件 // TaskDialogView.ets targetSettingDialog: CustomDialogController new CustomDialogController({ builder: TargetSettingDialog(),autoCancel: true,alignment: DialogAlignment.Bottom,offset: { dx: Const.ZERO, dy: Const.MINUS_20 } }); ...// 注册事件 this.broadCast.on(BroadCastType.SHOW_TARGET_SETTING_DIALOG, () {this.targetSettingDialog.open(); }) 点击对应的编辑项进行触发 // TaskDetailComponent.ets .onClick(() {this.broadCast.emit(BroadCastType.SHOW_TARGET_SETTING_DIALOG); }) 自定义弹窗的实现 任务目标设置的弹窗较为特殊故单独拿出来说明。 因为任务目标设置有三种类型 早睡早起的时间喝水的量度吃苹果的个数 如下图所示 故根据任务的ID进行区分将同一弹窗复用 // TaskSettingDialog.ets if ([taskType.getup, taskType.sleepEarly].indexOf(this.settingParams?.taskID) Const.HAS_NO_INDEX) {TimePicker({selected: new Date(${new Date().toDateString()} 8:00:00),}).height(Const.THOUSANDTH_800).useMilitaryTime(true).onChange((value: TimePickerResult) {this.currentTime formatTime(value);}) } else {TextPicker({ range: this.settingParams?.taskID taskType.drinkWater ? this.drinkRange : this.appleRange }).width(Const.THOUSANDTH_900,).height(Const.THOUSANDTH_800,).onChange((value) {this.currentValue value?.split( )[0];}) } 弹窗确认的时候将修改好的值赋予该项设置如不符合规则将弹出提示 // TaskSettingDialog.ets // 校验规则 compareTime(startTime: string, endTime: string) {if (returnTimeStamp(this.currentTime) returnTimeStamp(startTime) ||returnTimeStamp(this.currentTime) returnTimeStamp(endTime)) {prompt.showToast({message: Const.CHOOSE_TIME_OUT_RANGE})return false;}return true; } // 设置修改项 setTargetValue() {if (this.settingParams?.taskID taskType.getup) {if (!this.compareTime(Const.GET_UP_EARLY_TIME, Const.GET_UP_LATE_TIME)) {return;}this.settingParams.targetValue this.currentTime;return;}if (this.settingParams?.taskID taskType.sleepEarly) {if (!this.compareTime(Const.SLEEP_EARLY_TIME, Const.SLEEP_LATE_TIME)) {return;}this.settingParams.targetValue this.currentTime;return;}this.settingParams.targetValue this.currentValue; } 其余弹窗实现基本类似这里不再赘述。 后台代理提醒 健康生活App中提供了任务提醒功能我们用系统提供的后台代理提醒reminderAgent接口完成相关的开发。 说明 后台代理提醒接口需要在module.json5中申请ohos.permission.PUBLISH_AGENT_REMINDER权限代码如下 // module.json5 requestPermissions: [{name: ohos.permission.PUBLISH_AGENT_REMINDER} ] 后台代理提醒entry\src\main\ets\service\ReminderAgent.ts文件中提供了发布提醒任务、查询提醒任务、删除提醒任务三个接口供任务编辑页面调用跟随任务提醒的开关增加、更改、删除相关后台代理提醒代码如下 // ReminderAgent.ets import reminderAgent from ohos.reminderAgentManager; import notification from ohos.notificationManager; import preferences from ohos.data.preferences; import Logger from ../common/utils/Logger; import { CommonConstants as Const } from ../common/constants/CommonConstants; import ReminderInfo from ../viewmodel/ReminderInfo; import PublishReminderInfo from ../viewmodel/PublishReminderInfo;// 发布提醒 function publishReminder(params: PublishReminderInfo, context: Context) {if (!params) {Logger.error(Const.REMINDER_AGENT_TAG, publishReminder params is empty);return;}let notifyId: string params.notificationId.toString();hasPreferencesValue(context, notifyId, (preferences: preferences.Preferences, hasValue: boolean) {if (hasValue) {preferences.get(notifyId, -1, (error: Error, value: preferences.ValueType) {if (typeof value ! number) {return;}if (value 0) {reminderAgent.cancelReminder(value).then(() {processReminderData(params, preferences, notifyId);}).catch((err: Error) {Logger.error(Const.REMINDER_AGENT_TAG, cancelReminder err: ${err});});} else {Logger.error(Const.REMINDER_AGENT_TAG, preferences get value error JSON.stringify(error));}});} else {processReminderData(params, preferences, notifyId);}}); }// 取消提醒 function cancelReminder(reminderId: number, context: Context) {if (!reminderId) {Logger.error(Const.REMINDER_AGENT_TAG, cancelReminder reminderId is empty);return;}let reminder: string reminderId.toString();hasPreferencesValue(context, reminder, (preferences: preferences.Preferences, hasValue: boolean) {if (!hasValue) {Logger.error(Const.REMINDER_AGENT_TAG, cancelReminder preferences value is empty);return;}getPreferencesValue(preferences, reminder);}); }// 可通知ID function hasNotificationId(params: number) {if (!params) {Logger.error(Const.REMINDER_AGENT_TAG, hasNotificationId params is undefined);return;}return reminderAgent.getValidReminders().then((reminders) {if (!reminders.length) {return false;}let notificationIdList: Arraynumber [];for (let i 0; i reminders.length; i) {let notificationId reminders[i].notificationId;if (notificationId) {notificationIdList.push(notificationId);}}const flag notificationIdList.indexOf(params);return flag -1 ? false : true;}); }function hasPreferencesValue(context: Context, hasKey: string, callback: Function) {let preferencesPromise preferences.getPreferences(context, Const.H_STORE);preferencesPromise.then((preferences: preferences.Preferences) {preferences.has(hasKey).then((hasValue: boolean) {callback(preferences, hasValue);});}); }// 进程提醒数据 function processReminderData(params: PublishReminderInfo, preferences: preferences.Preferences, notifyId: string) {let timer fetchData(params);reminderAgent.publishReminder(timer).then((reminderId: number) {putPreferencesValue(preferences, notifyId, reminderId);}).catch((err: Error) {Logger.error(Const.REMINDER_AGENT_TAG, publishReminder err: ${err});}); }// 获取数据 function fetchData(params: PublishReminderInfo): reminderAgent.ReminderRequestAlarm {return {reminderType: reminderAgent.ReminderType.REMINDER_TYPE_ALARM,hour: params.hour || 0,minute: params.minute || 0,daysOfWeek: params.daysOfWeek || [],wantAgent: {pkgName: Const.PACKAGE_NAME,abilityName: Const.ENTRY_ABILITY},title: params.title || ,content: params.content || ,notificationId: params.notificationId || -1,slotType: notification.SlotType.SOCIAL_COMMUNICATION} }function putPreferencesValue(preferences: preferences.Preferences, putKey: string, putValue: number) {preferences.put(putKey, putValue).then(() {preferences.flush();}).catch((error: Error) {Logger.error(Const.REMINDER_AGENT_TAG, preferences put value error JSON.stringify(error));}); }function getPreferencesValue(preferences: preferences.Preferences, getKey: string) {preferences.get(getKey, -1).then((value: preferences.ValueType) {if (typeof value ! number) {return;}if (value 0) {reminderAgent.cancelReminder(value).then(() {Logger.info(Const.REMINDER_AGENT_TAG, cancelReminder promise success);}).catch((err: Error) {Logger.error(Const.REMINDER_AGENT_TAG, cancelReminder err: ${err});});}}).catch((error: Error) {Logger.error(Const.REMINDER_AGENT_TAG, preferences get value error JSON.stringify(error));}); }const reminder {publishReminder: publishReminder,cancelReminder: cancelReminder,hasNotificationId: hasNotificationId } as ReminderInfoexport default reminder; 实现打卡功能 首页会展示当前用户已经开启的任务列表每条任务会显示对应的任务名称以及任务目标、当前任务完成情况。用户只可对当天任务进行打卡操作用户可以根据需要对任务列表中相应的任务进行点击打卡。如果任务列表中的每个任务都在当天完成则为连续打卡一天连续打卡多天会获得成就徽章。打卡效果如下图所示 任务列表 使用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; } // HomeViewModel.ets // 更新当天任务列表 updateTask(task: TaskInfo): PromiseTaskInfo {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 NEXT学习资源获取完整版方式请点击→《HarmonyOS教学视频》 HarmonyOS教学视频语法ArkTS、TypeScript、ArkUI等…视频教程 鸿蒙生态应用开发白皮书V2.0PDF 获取完整版白皮书方式请点击→《鸿蒙生态应用开发白皮书V2.0PDF》 鸿蒙 (Harmony OS)开发学习手册 一、入门必看 应用开发导读(ArkTS).…… 二、HarmonyOS 概念 系统定义技术架构技术特性系统安全… 三、如何快速入门《鸿蒙基础入门学习指南》 基本概念构建第一个ArkTS应用.…… 四、开发基础知识 应用基础知识配置文件应用数据管理应用安全管理应用隐私保护三方应用调用管控机制资源分类与访问学习ArkTS语言.…… 五、基于ArkTS 开发 Ability开发UI开发公共事件与通知窗口管理媒体安全7.网络与链接电话服务数据管理后台任务(Background Task)管理设备管理设备使用信息统计DFX国际化开发折叠屏系列.…… 更多了解更多鸿蒙开发的相关知识可以参考《鸿蒙 (Harmony OS)开发学习手册》
http://www.zqtcl.cn/news/19678/

相关文章:

  • 电销系统软件信阳seo优化顾问
  • 秦皇岛住房建设网站网站怎么盈利
  • 潜江做网站十元精品店做网站
  • 做学分网站广西住房和城乡建设厅官方网站
  • 青岛网站建设网址工商网站注册公司
  • 网站建设过程小结建立多多少钱
  • 网站图片展示方式有哪些搬家网站建设案例说明
  • 佛山网站建设联系无锡网站建设 首选无锡立威云商
  • 手怎么搭建网站网站创建怎么做
  • 木樨园网站建设公司wordpress访问慢
  • 合肥做微网站如何做自动网站
  • 郑州阿里巴巴网站建设百度开户多少钱
  • 广西网站建设价格多少长春站最新通知
  • 深圳百度网站推广学历提升的重要性
  • 全美网站建设wordpress codecolorer
  • 茂名模板建站哪家好摄影标志logo设计欣赏
  • 免费网站模板的制作方法中小企业生产管理系统
  • 企业网站做几个合适手机版网址
  • 企业网站建设不要空间可以吗网站搭建制作免费
  • 固镇网站建设哪家好?钻磊二级域名分发
  • 物流行业网站模板沧州企业网站建设
  • 子网站怎么做网站内容计划
  • 清远网站制作招聘网站维护什么内容
  • 软件园做网站温岭市建设规划局网站
  • 为什么做网站必须用服务器大英县住房和城乡建设局网站
  • 网站开发专业优势主要干啥
  • 做网站需要办什么证件河北项目网官网
  • 景安企业网站建设工作室主题网站
  • 制作视频网站教程dw下载免费中文版
  • 门户网站的大数据应用wordpress 百度 插件怎么用